rsyslog-8.2412.0/0000775000175000017500000000000014723322661007223 5rsyslog-8.2412.0/README0000664000175000017500000000007714650736301010026 see README.md -- this file here is just required for autotools rsyslog-8.2412.0/outchannel.c0000664000175000017500000001560714650736301011457 /* 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(char **pp) { register char *p; assert(pp != NULL); assert(*pp != NULL); p = *pp; while(isspace((int)*p)) ++p; if(*p == ',') ++p; while(isspace((int)*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((char**)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((char**)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((char**)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.2412.0/m4/0000775000175000017500000000000014723322653007544 5rsyslog-8.2412.0/m4/lt~obsolete.m40000644000175000017500000001400714723322615012276 # 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.2412.0/m4/ltsugar.m40000644000175000017500000001045314723322615011406 # 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.2412.0/m4/atomic_operations_64bit.m40000664000175000017500000000244314650736301014456 # 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; if (__sync_fetch_and_add(&val, 1010) != 1010 || val != 2020) return 1; tmp = val; if (__sync_fetch_and_sub(mem, 1010) != tmp || val != 1010) return 1; if (__sync_sub_and_fetch(&val, 1010) != 0 || val != 0) return 1; tmp = 3030; if (__sync_val_compare_and_swap(mem, 0, tmp) != 0 || val != tmp) return 1; if (__sync_lock_test_and_set(&val, 4040) != 3030) return 1; mem = &tmp; if (__sync_val_compare_and_swap(&mem, &tmp, &val) != &tmp) return 1; __sync_synchronize(); if (mem != &val) 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.2412.0/m4/ac_check_define.m40000664000175000017500000000215514650736301012761 AC_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.2412.0/m4/atomic_operations.m40000664000175000017500000000356614650736301013455 # 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 int main() { unsigned long val = 1010, tmp, *mem = &val; time_t tval = 1010, ttmp, *tmem = &tval; if (__sync_fetch_and_add(&val, 1010) != 1010 || val != 2020) return 1; tmp = val; if (__sync_fetch_and_sub(mem, 1010) != tmp || val != 1010) return 1; if (__sync_sub_and_fetch(&val, 1010) != 0 || val != 0) return 1; tmp = 3030; if (__sync_val_compare_and_swap(mem, 0, tmp) != 0 || val != tmp) return 1; if (__sync_lock_test_and_set(&val, 4040) != 3030) return 1; mem = &tmp; if (__sync_val_compare_and_swap(&mem, &tmp, &val) != &tmp) return 1; if (__sync_fetch_and_add(&tval, 1010) != 1010 || tval != 2020) return 1; ttmp = tval; if (__sync_fetch_and_sub(tmem, 1010) != ttmp || tval != 1010) return 1; if (__sync_sub_and_fetch(&tval, 1010) != 0 || tval != 0) return 1; ttmp = 3030; if (__sync_val_compare_and_swap(tmem, 0, ttmp) != 0 || tval != ttmp) return 1; if (__sync_lock_test_and_set(&tval, 4040) != 3030) return 1; tmem = &ttmp; if (__sync_val_compare_and_swap(&tmem, &ttmp, &tval) != &ttmp) return 1; __sync_synchronize(); if (mem != &val) 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.2412.0/m4/libtool.m40000644000175000017500000113165214723322615011377 # 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.2412.0/m4/ltversion.m40000644000175000017500000000131214723322615011744 # 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.2412.0/m4/ltoptions.m40000644000175000017500000003427514723322615011770 # 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.2412.0/threads.c0000664000175000017500000002041514650736301010742 /* 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); *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); 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); pThis->bShallStop = RSTRUE; 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, 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.2412.0/test-driver0000755000175000017500000001141714723322621011337 #! /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.2412.0/platform/0000775000175000017500000000000014723322653011050 5rsyslog-8.2412.0/platform/README0000664000175000017500000000064014650736301011646 This 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.2412.0/platform/freebsd/0000775000175000017500000000000014723322653012462 5rsyslog-8.2412.0/platform/freebsd/rsyslogd0000775000175000017500000000405614650736301014201 #!/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.2412.0/platform/slackware/0000775000175000017500000000000014723322653013024 5rsyslog-8.2412.0/platform/slackware/rc.rsyslogd0000775000175000017500000000305214650736301015141 #!/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.2412.0/platform/redhat/0000775000175000017500000000000014723322653012317 5rsyslog-8.2412.0/platform/redhat/rsyslog.conf0000664000175000017500000000657114650736301014617 # 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.2412.0/template.c0000664000175000017500000023014214650736301011123 /* 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 "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" PRAGMA_INGORE_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.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 }, { "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? */ #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; iNewSize = (iMinSize / ALLOC_INC + 1) * ALLOC_INC; CHKmalloc(pNewBuf = (uchar*) realloc(iparam->param, iNewSize)); iparam->param = pNewBuf; iparam->lenBuf = iNewSize; finalize_it: RETiRet; } /* 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 >= (rs_size_t)iparam->lenBuf) /* we reserve one char for the final \0! */ CHKiRet(ExtendBuf(iparam, iLenVal + 1)); memcpy(iparam->param, pVal, iLenVal+1); FINALIZE; } /* we have a "regular" template with template entries */ /* 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 extra_space = (pTpl->optFormatEscape == JSONF) ? 1 : 3; if(pTpl->optFormatEscape == JSONF) { 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); /* 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 */ if(iLenVal > 0) { /* may be zero depending on property */ /* first, make sure buffer fits */ if(iBuf + iLenVal + extra_space >= iparam->lenBuf) /* we reserve one char for the final \0! */ CHKiRet(ExtendBuf(iparam, iBuf + iLenVal + 1)); if(need_comma) { memcpy(iparam->param + iBuf, ", ", 2); iBuf += 2; } memcpy(iparam->param + iBuf, pVal, iLenVal); iBuf += iLenVal; if(pTpl->optFormatEscape == JSONF) { need_comma = 1; } } if((pTpl->optFormatEscape == JSONF) && (pTpe->pNext == NULL)) { /* space was reserved while processing field above (via extra_space in ExtendBuf() new size formula. */ 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) { 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': i = 0; while(*p && isdigit((int)*p)) { i = i * 10 + *p++ - '0'; } 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; } else if(!strcmp((char*)Buf, "drop-cc")) { pTpe->data.field.options.bDropCC = 1; } else if(!strcmp((char*)Buf, "space-cc")) { pTpe->data.field.options.bSpaceCC = 1; } 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 { iNum = 0; while(isdigit((int)*p)) iNum = iNum * 10 + *p++ - '0'; 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; iNum = 0; while(isdigit((int)*p)) iNum = iNum * 10 + *p++ - '0'; 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) */ iNum = 0; while(isdigit((int)*p)) iNum = iNum * 10 + *p++ - '0'; 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) { iNum = 0; while(isdigit((int)*p)) iNum = iNum * 10 + *p++ - '0'; pTpe->data.field.iFieldNr = iNum; if(*p == ',') { /* get real toPos? */ ++p; iNum = 0; while(isdigit((int)*p)) iNum = iNum * 10 + *p++ - '0'; pTpe->data.field.iToPos = iNum; } } else { iNum = 0; while(isdigit((int)*p)) iNum = iNum * 10 + *p++ - '0'; 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 { dbgprintf("Invalid option '%s' ignored.\n", optBuf); } } *ppRestOfConfLine = p; apply_case_sensitivity(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; 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")) { 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 = (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); /* apply */ CHKmalloc(pTpe = tpeConstruct(pTpl)); es_unescapeStr(value); pTpe->eEntryType = CONSTANT; pTpe->fieldName = outname; if(outname != NULL) pTpe->lenFieldName = ustrlen(outname); if(is_jsonf) { CHKmalloc(json = json_object_new_object()); const char *sz = es_str2cstr(value, NULL); CHKmalloc(sz); CHKmalloc(jval = json_object_new_string(sz)); free((void*)sz); json_object_object_add(json, (char*)outname, jval); CHKmalloc(sz = json_object_get_string(json)); const size_t len_json = strlen(sz) - 4; CHKmalloc(pTpe->data.constant.pConstant = (uchar*) strndup(sz+2, len_json)); pTpe->data.constant.iLenConstant = ustrlen(pTpe->data.constant.pConstant); json_object_put(json); } else { pTpe->data.constant.iLenConstant = es_strlen(value); pTpe->data.constant.pConstant = (uchar*)es_str2cstr(value, NULL); } finalize_it: 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 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_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")) { 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 = (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 = (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, "spifno1stsp")) { spifno1stsp = pvals[i].val.d.n; bComplexProcessing = 1; } else if(!strcmp(pblkProperty.descr[i].name, "outname")) { 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")) { 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 = (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 = (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 = (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*)"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 = (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 = (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 = (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 = (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); } /* 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.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; } switch(controlchr) { case CC_NONE: /* all set ;) */ break; case CC_ESCAPE: pTpe->data.field.options.bEscapeCC = 1; break; case CC_SPACE: pTpe->data.field.options.bSpaceCC = 1; break; case CC_DROP: pTpe->data.field.options.bDropCC = 1; 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; } 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); 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_json=0, o_casesensitive=0; /* options */ int numopts; rsRetVal localRet; 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); 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 = (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")) { 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] != '!') { char *cstr = 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); free(cstr); free(name); /* overall assigned */ ABORT_FINALIZE(RS_RET_ERR); } else { uchar *cstr; cstr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); CHKiRet(msgPropDescrFill(&subtree, cstr, ustrlen(cstr))); free(cstr); bHaveSubtree = 1; } } else if(!strcmp(pblk.descr[i].name, "plugin")) { 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.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(numopts > 1) { LogError(0, RS_RET_ERR, "template '%s' has multiple incompatible " "options of sql, stdsql or json 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 = name; 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: createListTpl(pTpl, o); break; case T_SUBTREE: memcpy(&pTpl->subtree, &subtree, sizeof(msgPropDescr_t)); pTpl->bHaveSubtree = 1; 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) pTpl->optFormatEscape = JSONF; if(o_casesensitive) pTpl->optCaseSensitive = 1; apply_case_sensitivity(pTpl); finalize_it: 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; } free(pTpeDel->fieldName); free(pTpeDel); } pTplDel = pTpl; pTpl = pTpl->pNext; free(pTplDel->pszName); if(pTplDel->bHaveSubtree) msgPropDescrDestruct(&pTplDel->subtree); 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; } free(pTpeDel); } pTplDel = pTpl; pTpl = pTpl->pNext; free(pTplDel->pszName); if(pTplDel->bHaveSubtree) msgPropDescrDestruct(&pTplDel->subtree); 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; } 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; } 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.2412.0/outchannel.h0000664000175000017500000000235114650736301011454 /* 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.2412.0/COPYING.ASL200000664000175000017500000002166114650736301010763 Apache 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.2412.0/missing0000755000175000017500000001533614723322620010543 #! /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.2412.0/action.h0000664000175000017500000001211214650736301010565 /* 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-2018 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 ACTION_H_INCLUDED #define ACTION_H_INCLUDED 1 #include "syslogd-types.h" #include "queue.h" /* external data */ extern int glbliActionResumeRetryCount; /* the following struct defines the action object data structure */ 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; sbool bDisabled; 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 */ 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 */ 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(ctrFail, mutCtrFail) STATSCOUNTER_DEF(ctrSuspend, mutCtrSuspend) STATSCOUNTER_DEF(ctrSuspendDuration, mutCtrSuspendDuration) STATSCOUNTER_DEF(ctrResume, mutCtrResume) }; /* function prototypes */ rsRetVal actionConstruct(action_t **ppThis); rsRetVal actionConstructFinalize(action_t *pThis, struct nvlst *lst); rsRetVal actionDestruct(action_t *pThis); rsRetVal actionSetGlobalResumeInterval(int iNewVal); rsRetVal actionDoAction(action_t *pAction); rsRetVal actionWriteToAction(action_t *pAction, smsg_t *pMsg, wti_t*); rsRetVal actionCallHUPHdlr(action_t *pAction); rsRetVal actionClassInit(void); rsRetVal addAction(action_t **ppAction, modInfo_t *pMod, void *pModData, omodStringRequest_t *pOMSR, struct cnfparamvals *actParams, struct nvlst *lst); rsRetVal activateActions(void); rsRetVal actionNewInst(struct nvlst *lst, action_t **ppAction); rsRetVal actionProcessCnf(struct cnfobj *o); void actionCommitAllDirect(wti_t *pWti); void actionRemoveWorker(action_t *const pAction, void *const actWrkrData); void releaseDoActionParams(action_t * const pAction, wti_t * const pWti, int action_destruct); #endif /* #ifndef ACTION_H_INCLUDED */ rsyslog-8.2412.0/devtools/0000775000175000017500000000000014723322661011062 5rsyslog-8.2412.0/devtools/prep-mysql-db.sh0000775000175000017500000000040114650736301014027 #!/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.2412.0/devtools/prepare_clickhouse.sh0000775000175000017500000000120614650736301015206 #!/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.2412.0/COPYING.LESSER0000664000175000017500000001672714330725737011214 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.2412.0/Makefile.am0000664000175000017500000002546614650736301011213 sbin_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 SUBDIRS = compat runtime grammar . 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_OMFILE_HARDENED SUBDIRS += contrib/omfile-hardened 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_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_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_IMDOCKER SUBDIRS += contrib/imdocker endif if ENABLE_IMPTCP SUBDIRS += plugins/imptcp endif if ENABLE_IMDIAG SUBDIRS += plugins/imdiag 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_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_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_MMJSONPARSE SUBDIRS += plugins/mmjsonparse 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_MMRFC5424ADDHMAC SUBDIRS += contrib/mmrfc5424addhmac 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-imdiag \ --enable-testbench \ --enable-valgrind # 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_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_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_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 rsyslog-8.2412.0/config.guess0000755000175000017500000014051214723322620011457 #! /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.2412.0/tools/0000775000175000017500000000000014723322654010365 5rsyslog-8.2412.0/tools/recover_qi.pl0000775000175000017500000001372214650736301013005 #!/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.2412.0/tools/smtradfwd.h0000664000175000017500000000211414650736301012444 /* 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.2412.0/tools/smfwd.c0000664000175000017500000000760314650736301011574 /* 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.2412.0/tools/omdiscard.h0000664000175000017500000000224214650736301012420 /* 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.2412.0/tools/smtradfile.c0000664000175000017500000000711314650736301012602 /* 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.2412.0/tools/omfwd.c0000664000175000017500000022257214704407366011602 /* 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-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 #include #include #include #include #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 "tcpclt.h" #include "cfsysline.h" #include "module-template.h" #include "glbl.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; DEF_ATOMIC_HELPER_MUT64(mut_sentBytes) DEF_ATOMIC_HELPER_MUT64(mut_sentMsgs) } targetStats_t; typedef struct _instanceData { uchar *tplName; /* name of assigned template */ uchar *pszStrmDrvr; uchar *pszStrmDrvrAuthMode; uchar *pszStrmDrvrPermitExpiredCerts; permittedPeers_t *pPermPeers; int iStrmDrvrMode; 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 *pszStrmDrvrKeyFile; const uchar *pszStrmDrvrCertFile; int nTargets; int nActiveTargets; /* how many targets have been active the last time? */ char **target_name; int nPorts; char **ports; char *address; char *device; int compressionLevel; /* 0 - no compression, else level for zlib */ int protocol; char *networkNamespace; int originalNamespace; int iRebindInterval; /* rebind interval */ sbool bKeepAlive; int iKeepAliveIntvl; int iKeepAliveProbes; int iKeepAliveTime; 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; unsigned int ratelimitInterval; unsigned int ratelimitBurst; 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 bzInitDone; /* did we do an init of zstrm already? */ z_stream zstrm; /* zip stream to use for tcp compression */ /* 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) */ 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 */ 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 } }; static struct cnfparamblk modpblk = { CNFPARAMBLK_VERSION, sizeof(modpdescr)/sizeof(struct cnfparamdescr), modpdescr }; /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { { "target", eCmdHdlrArray, CNFPARAM_REQUIRED }, { "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.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 }, { "conerrskip", eCmdHdlrNonNegInt, 0 }, { "gnutlsprioritystring", eCmdHdlrString, 0 }, { "streamdriver", eCmdHdlrGetWord, 0 }, { "streamdrivermode", eCmdHdlrInt, 0 }, { "streamdriverauthmode", eCmdHdlrGetWord, 0 }, { "streamdriverpermittedpeers", eCmdHdlrGetWord, 0 }, { "streamdriver.permitexpiredcerts", eCmdHdlrGetWord, 0 }, { "streamdriver.CheckExtendedKeyPurpose", eCmdHdlrBinary, 0 }, { "streamdriver.PrioritizeSAN", eCmdHdlrBinary, 0 }, { "streamdriver.TlsVerifyDepth", eCmdHdlrPositiveInt, 0 }, { "streamdriver.cafile", eCmdHdlrString, 0 }, { "streamdriver.crlfile", 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 } }; 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 */ 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.bResendLastOnRecon = 0; /* should the last message be re-sent on a successful reconnect? */ cs.pszStrmDrvrAuthMode = NULL; /* authentication mode to use */ 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 doZipFinish(targetData_t *); /* 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; } /* 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; } /* Close the UDP sockets. * rgerhards, 2009-05-29 */ static rsRetVal closeUDPSockets(wrkrInstanceData_t *pWrkrData) { DEFiRet; if(pWrkrData->target[0].pSockArray != NULL) { net.closeUDPListenSockets(pWrkrData->target[0].pSockArray); pWrkrData->target[0].pSockArray = NULL; freeaddrinfo(pWrkrData->target[0].f_addr); pWrkrData->target[0].f_addr = NULL; } pWrkrData->target[0].bIsConnected = 0; RETiRet; } static void DestructTCPTargetData(targetData_t *const pTarget) { // TODO: do we need to do a final send? if so, old bug! doZipFinish(pTarget); if(pTarget->pNetstrm != NULL) { netstrm.Destruct(&pTarget->pNetstrm); } if(pTarget->pNS != NULL) { netstrms.Destruct(&pTarget->pNS); } /* set resume time for interal retries */ datetime.GetTime(&pTarget->ttResume); pTarget->ttResume += pTarget->pData->poolResumeInterval; pTarget->bIsConnected = 0; DBGPRINTF("omfwd: DestructTCPTargetData: %p %s:%s, connected %d, ttResume %lld\n", &pTarget, pTarget->target_name, pTarget->port, pTarget->bIsConnected, (long long) pTarget->ttResume); } /* destruct the TCP 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 DestructTCPInstanceData(wrkrInstanceData_t *pWrkrData) { LogMsg(0, RS_RET_DEBUG, LOG_DEBUG, "omfwd: Destructing TCP target pool of %d targets (DestructTCPInstanceData)", pWrkrData->pData->nTargets); for(int j = 0 ; j < pWrkrData->pData->nTargets ; ++j) { DestructTCPTargetData(&(pWrkrData->target[j])); } } BEGINbeginCnfLoad CODESTARTbeginCnfLoad loadModConf = pModConf; pModConf->pConf = pConf; pModConf->tplName = 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")) { 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 { 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); ENDfreeCnf BEGINcreateInstance CODESTARTcreateInstance /* We always have at least one target and port */ pData->nTargets = 1; pData->nActiveTargets = 0; pData->nPorts = 1; pData->target_name = NULL; if(cs.pszStrmDrvr != NULL) CHKmalloc(pData->pszStrmDrvr = (uchar*)strdup((char*)cs.pszStrmDrvr)); if(cs.pszStrmDrvrAuthMode != NULL) CHKmalloc(pData->pszStrmDrvrAuthMode = (uchar*)strdup((char*)cs.pszStrmDrvrAuthMode)); 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].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 BEGINfreeInstance CODESTARTfreeInstance free(pData->pszStrmDrvr); free(pData->pszStrmDrvrAuthMode); free(pData->pszStrmDrvrPermitExpiredCerts); free(pData->gnutlsPriorityString); 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->pszStrmDrvrKeyFile); free((void*)pData->pszStrmDrvrCertFile); net.DestructPermittedPeers(&pData->pPermPeers); if (pData->ratelimiter != NULL){ ratelimitDestruct(pData->ratelimiter); pData->ratelimiter = NULL; } ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance LogMsg(0, RS_RET_DEBUG, LOG_DEBUG, "omfwd: [wrkr %u/%" PRIuPTR "] Destructing worker instance", pWrkrData->wrkrID, (uintptr_t) pthread_self()); DestructTCPInstanceData(pWrkrData); closeUDPSockets(pWrkrData); 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 */ CHKiRet(closeUDPSockets(pWrkrData)); } if(pWrkrData->target[0].pSockArray == NULL) { CHKiRet(doTryResume(pTarget)); /* for UDP, we have only a single tartget! */ } 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) { lsent = sendto(pTarget->pSockArray[i+1], msg, lenThisTry, 0, r->ai_addr, r->ai_addrlen); if (lsent == (ssize_t) lenThisTry) { bSendSuccess = RSTRUE; ATOMIC_ADD_uint64(&pTargetStats->sentBytes, &pTargetStats->mut_sentBytes, lenThisTry); try_send = 0; runSockArrayLoop = 0; } else if(errno == 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 = errno; 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) { CHKiRet(closeUDPSockets(pWrkrData)); } /* 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); DestructTCPTargetData(pTarget); 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; CHKiRet(netstrm.Send(pTarget->pNetstrm, buf+alreadySent, &lenSend)); 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) { emitConnectionErrorMsg(pTarget, iRet); DestructTCPTargetData(pTarget); iRet = RS_RET_SUSPENDED; } RETiRet; } static rsRetVal TCPSendBufCompressed(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 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 doZipFinish(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; } /* 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.SetDrvrTlsKeyFile(pTarget->pNetstrm, pData->pszStrmDrvrKeyFile)); CHKiRet(netstrm.SetDrvrTlsCertFile(pTarget->pNetstrm, pData->pszStrmDrvrCertFile)); 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.Connect(pTarget->pNetstrm, glbl.GetDefPFFamily(runModConf->pConf), (uchar*)pTarget->port, (uchar*)pTarget->target_name, pData->device)); /* 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); DestructTCPTargetData(pTarget); } 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) { DestructTCPTargetData((targetData_t *) pvData); /* Even if the destruct fails, it does not help to provide this info to * the upper layer. Also, DestructTCPTargtData() 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 int iErr; int destinationNs = -1; char *nsPath = NULL; if(pData->networkNamespace) { /* keep file descriptor of original network namespace */ pData->originalNamespace = open("/proc/self/ns/net", O_RDONLY); if (pData->originalNamespace < 0) { LogError(0, RS_RET_IO_ERROR, "omfwd: could not read /proc/self/ns/net"); ABORT_FINALIZE(RS_RET_IO_ERROR); } /* build network namespace path */ if (asprintf(&nsPath, "/var/run/netns/%s", pData->networkNamespace) == -1) { LogError(0, RS_RET_OUT_OF_MEMORY, "omfwd: asprintf failed"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* keep file descriptor of destination network namespace */ destinationNs = open(nsPath, 0); if (destinationNs < 0) { LogError(0, RS_RET_IO_ERROR, "omfwd: could not change to namespace '%s'", pData->networkNamespace); ABORT_FINALIZE(RS_RET_IO_ERROR); } /* actually change in the destination network namespace */ if((iErr = (setns(destinationNs, CLONE_NEWNET))) != 0) { LogError(0, RS_RET_IO_ERROR, "could not change to namespace '%s': %s", pData->networkNamespace, gai_strerror(iErr)); ABORT_FINALIZE(RS_RET_IO_ERROR); } dbgprintf("omfwd: changed to network namespace '%s'\n", pData->networkNamespace); } finalize_it: free(nsPath); if(destinationNs >= 0) { close(destinationNs); } #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 int iErr; /* only in case a network namespace is given and a file descriptor to * the original namespace exists */ if(pData->networkNamespace && pData->originalNamespace >= 0) { /* actually change to the original network namespace */ if((iErr = (setns(pData->originalNamespace, CLONE_NEWNET))) != 0) { LogError(0, RS_RET_IO_ERROR, "could not return to original namespace: %s", gai_strerror(iErr)); ABORT_FINALIZE(RS_RET_IO_ERROR); } close(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++; } } if(activeTargets != pWrkrData->pData->nActiveTargets) { LogMsg(0, RS_RET_DEBUG, LOG_DEBUG, "omfwd: [wrkr %u] number of active targets changed from %d to %d", pWrkrData->wrkrID, pWrkrData->pData->nActiveTargets, activeTargets); pWrkrData->pData->nActiveTargets = 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; DBGPRINTF("doTryResume: isConnected: %d, ttResume %lld, LastActiveTargets: %d\n", pTarget->bIsConnected, (long long) pTarget->ttResume, pTarget->pData->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 && pTarget->pData->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); freeaddrinfo(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); } 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); 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(), pWrkrData->pData->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_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); DestructTCPTargetData(pTarget); 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 */ CODESTARTcommitTransaction /* if needed, rebind first. This ensure we can deliver to the rebound addresses. * Note that rebind requires reconnect to the new targets. This is done by the * poolTryResume(), which needs to be made in any case. */ 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 */ DestructTCPInstanceData(pWrkrData); initTCP(pWrkrData); 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: error during rate limit : %d.\n",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 { 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); DestructTCPTargetData(&(pWrkrData->target[j])); iRet = RS_RET_OK; } } } finalize_it: /* do pool stats */ countActiveTargets(pWrkrData); if(pWrkrData->pData->nActiveTargets == 0) { 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->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->iStrmDrvrMode = 0; pData->iStrmDrvrExtendedCertCheck = 0; pData->iStrmDrvrSANPreference = 0; pData->iStrmTlsVerifyDepth = 0; pData->pszStrmDrvrCAFile = NULL; pData->pszStrmDrvrCRLFile = NULL; pData->pszStrmDrvrKeyFile = NULL; pData->pszStrmDrvrCertFile = NULL; pData->iRebindInterval = 0; pData->bKeepAlive = 0; pData->iKeepAliveProbes = 0; pData->iKeepAliveIntvl = 0; pData->iKeepAliveTime = 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->strmCompFlushOnTxEnd = 1; pData->compressionMode = COMPRESS_NEVER; pData->ipfreebind = IPFREEBIND_ENABLED_WITH_LOG; pData->poolResumeInterval = 30; pData->ratelimiter = NULL; pData->ratelimitInterval = 0; pData->ratelimitBurst = 200; } /* 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))); CHKiRet(statsobj.ConstructFinalize(pData->target_stats[i].stats)); } 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) { pData->target_name[j] = (char*) es_str2cstr(pvals[i].val.d.ar->arr[j], NULL); } } else if(!strcmp(actpblk.descr[i].name, "address")) { pData->address = es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "device")) { 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) { 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; 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")) { 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; 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, "conerrskip")) { pData->iConErrSkip = (int) pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "gnutlsprioritystring")) { pData->gnutlsPriorityString = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "streamdriver")) { pData->pszStrmDrvr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "streamdrivermode")) { pData->iStrmDrvrMode = pvals[i].val.d.n; } 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")) { pData->pszStrmDrvrAuthMode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "streamdriver.permitexpiredcerts")) { uchar *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, "streamdriver.cafile")) { pData->pszStrmDrvrCAFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "streamdriver.crlfile")) { pData->pszStrmDrvrCRLFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "streamdriver.keyfile")) { pData->pszStrmDrvrKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "streamdriver.certfile")) { 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; 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")) { 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.mode")) { 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 = (unsigned int) pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "ratelimit.interval")) { pData->ratelimitInterval = (unsigned int) pvals[i].val.d.n; } else { LogError(0, RS_RET_INTERNAL_ERROR, "omfwd: program error, non-handled parameter '%s'", actpblk.descr[i].name); } } 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; } } 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"); } if( pData->ratelimitInterval > 0) { CHKiRet(ratelimitNew(&pData->ratelimiter, "omfwd", NULL)); ratelimitSetLinuxLike(pData->ratelimiter, pData->ratelimitInterval, 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; if(cs.pPermPeers != NULL) { pData->pPermPeers = cs.pPermPeers; cs.pPermPeers = NULL; } } 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.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_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.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; } BEGINmodInit(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, NULL, &cs.iStrmDrvrMode, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriverauthmode", 0, eCmdHdlrGetWord, NULL, &cs.pszStrmDrvrAuthMode, 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.2412.0/tools/Makefile.am0000664000175000017500000000604714660643541012351 sbin_PROGRAMS = bin_PROGRAMS = CLEANFILES = man1_MANS = man_MANS = rsyslogd.8 rsyslog.conf.5 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 \ \ ../dirty.h rsyslogd_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) 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) $(PTHREADS_LIBS) $(RSRT_LIBS) $(SOL_LIBS) $(LIBUUID_LIBS) $(HASH_XXHASH_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 = $(man_MANS) \ rscryutil.rst \ recover_qi.pl 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 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.2412.0/tools/omdiscard.c0000664000175000017500000000713114650736301012415 /* 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-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 "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 BEGINmodInit(Discard) CODESTARTmodInit *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr ENDmodInit /* * vi:set ai: */ rsyslog-8.2412.0/tools/smtradfile.h0000664000175000017500000000224014650736301012603 /* 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.2412.0/tools/smfile.c0000664000175000017500000000743514650736301011736 /* 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.2412.0/tools/pmrfc5424.h0000664000175000017500000000223714650736301012105 /* 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*); #endif /* #ifndef PMRFC54254_H_INCLUDED */ /* vi:set ai: */ rsyslog-8.2412.0/tools/syslogd.c0000664000175000017500000000710414650736301012134 /** * 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.2412.0/tools/ompipe.h0000664000175000017500000000214414650736301011745 /* 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.2412.0/tools/rsyslog.conf.50000664000175000017500000007422614650736301013031 .\" 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 "22 October 2012" "Version 7.2.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.2412.0/tools/pmrfc3164.h0000664000175000017500000000222614650736301012102 /* 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*); #endif /* #ifndef PMRFC3164_H_INCLUDED */ /* vi:set ai: */ rsyslog-8.2412.0/tools/rscryutil.rst0000664000175000017500000001355514704407366013113 ========= 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 intial 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.2412.0/tools/omusrmsg.c0000664000175000017500000003272314650736301012331 /* omusrmsg.c * This is the implementation of the build-in output module for sending * user messages. * * NOTE: read comments in module-template.h to understand how this file * works! * * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c, which at the * time of the fork from sysklogd was under BSD license) * * Copyright 2007-2018 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_UTMP_H # include # define STRUCTUTMP struct utmp # define UTNAME ut_name #else # include # define STRUCTUTMP struct utmpx # define UTNAME ut_user #endif #include #include #include #include #if HAVE_FCNTL_H #include #else #include #endif #ifdef HAVE_PATHS_H #include #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" /* 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; } 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 */ /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { { "users", eCmdHdlrString, CNFPARAM_REQUIRED }, { "template", eCmdHdlrGetWord, 0 } }; static struct cnfparamblk actpblk = { CNFPARAMBLK_VERSION, sizeof(actpdescr)/sizeof(struct cnfparamdescr), actpdescr }; BEGINinitConfVars /* (re)set config variables to default values */ CODESTARTinitConfVars ENDinitConfVars BEGINcreateInstance CODESTARTcreateInstance ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature if(eFeat == sFEATURERepeatedMsgReduction) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINfreeInstance CODESTARTfreeInstance free(pData->tplName); 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) # define setutent(void) setutxent(void) # define getutent(void) getutxent(void) # define endutent(void) endutxent(void) #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 */ static void sendwallmsg(const char *tty, uchar* pMsg) { uchar szErr[512]; int errnoSave; char p[sizeof(_PATH_DEV) + UNAMESZ]; int ttyf; struct stat statb; int wrRet; /* compute the device name */ strcpy(p, _PATH_DEV); strncat(p, tty, UNAMESZ); /* 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); } } /* WALLMSG -- Write a message to the world at large * * Write the specified message to either the entire * world, or a list of approved users. * * rgerhards, 2005-10-19: applying the following sysklogd patch: * Tue May 4 16:52:01 CEST 2004: Solar Designer * Adjust the size of a variable to prevent a buffer overflow * should _PATH_DEV ever contain something different than "/dev/". * rgerhards, 2008-07-04: changing the function to no longer use fork() but * continue run on its thread instead. */ 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; 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); user = pws->pw_name; /* DO NOT FREE, OS/LIB internal memory! */ if (user == NULL) { dbgprintf("failed to get username for userid '%d'\n", uid); continue; } } else { /* we record the state to the debug log */ rs_strerror_r(-sdRet, (char*)szErr, sizeof(szErr)); dbgprintf("get userid for session '%s' failed with [%d]:%s\n", sessions_list[j], -sdRet, szErr); 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)); dbgprintf("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"); iRet = wallmsg(ppString[0], pWrkrData->pData); ENDdoAction static void 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; } 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")) { pData->tplName = (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->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)); } 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_OMOD_QUERIES ENDqueryEtryPt BEGINmodInit(UsrMsg) CODESTARTmodInit INITLegCnfVars *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr ENDmodInit /* vim:set ai: */ rsyslog-8.2412.0/tools/rsyslogd.80000664000175000017500000002437314650736301012252 .\" Copyright 2004-2014 Rainer Gerhards and Adiscon for the rsyslog modifications .\" May be distributed under the GNU General Public License .\" .TH RSYSLOGD 8 "28 May 2014" "Version 8.1905.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 ", " INT ", " QUIT .B Rsyslogd will die. .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.2412.0/tools/smtradfwd.c0000664000175000017500000000755014650736301012450 /* 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.2412.0/tools/gethostn.c0000664000175000017500000000263714650736301012311 /* 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.2412.0/tools/omshell.h0000664000175000017500000000224314650736301012117 /* 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.2412.0/tools/smfwd.h0000664000175000017500000000207114650736301011573 /* 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.2412.0/tools/omusrmsg.h0000664000175000017500000000221714650736301012331 /* omusrmsg.c * These are the definitions for the build-in user message output module. * * File begun on 2007-07-13 by RGerhards * * Copyright 20072-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 */ rsRetVal modInitUsrMsg(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()), modInfo_t*); #endif /* #ifndef OMUSRMSG_H_INCLUDED */ /* vi:set ai: */ rsyslog-8.2412.0/tools/iminternal.c0000664000175000017500000001136614650736301012617 /* 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, 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.2412.0/tools/logctl.c0000664000175000017500000002636614723322534011747 /** * 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 #include #include 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.2412.0/tools/ompipe.c0000664000175000017500000002720014650736301011740 /* 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-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 "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")) { 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")) { pData->pipe = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "template")) { 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 BEGINmodInit(Pipe) CODESTARTmodInit INITLegCnfVars *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr ENDmodInit /* vi:set ai: */ rsyslog-8.2412.0/tools/smfile.h0000664000175000017500000000221414650736301011731 /* 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.2412.0/tools/pmrfc3164.c0000664000175000017500000003314414650736301012100 /* 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-2017 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 "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 "rsconf.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) /* static data */ static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */ /* 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}, }; 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; }; 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; bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf); *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 { 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 dbgprintf("pmrfc3164: free parser instance %p\n", pInst); ENDfreeParserInst /* parse a legay-formatted syslog message. */ 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 indicated * by spaces or tabs followed '{' or '['. */ 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 */ if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) { /* 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); /* we are done - parse pointer is moved by ParseTIMESTAMP3164 */; } else if(*p2parse == ' ' && lenMsg > 1) { /* try to see if it is slighly 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! */ /* 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(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(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 * envrionments, 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. */ 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 */ p2parse -= ( i + 1 ); lenMsg += ( i + 1 ); i = 0; /* Default TAG is dash (without ':') */ bufParseTAG[i++] = '-'; } /* no TAG can only be detected if the message immediatly 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 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_PMOD2_QUERIES CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES 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)); DBGPRINTF("rfc3164 parser init called\n"); bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf); /* cache value, is set only during rsyslogd option processing */ ENDmodInit /* vim:set ai: */ rsyslog-8.2412.0/tools/omshell.c0000664000175000017500000000766114650736301012123 /* 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-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 "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, ppString[0]) == 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 BEGINmodInit(Shell) CODESTARTmodInit *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr ENDmodInit /* * vi:set ai: */ rsyslog-8.2412.0/tools/omfile.c0000664000175000017500000016040014650736301011722 /* 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-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 #ifdef HAVE_ATOMIC_BUILTINS # include #endif #include "rsyslog.h" #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.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); /* internal structures */ DEF_OMOD_STATIC_DATA DEFobjCurrIf(strm) DEFobjCurrIf(statsobj) /* for our current LRU mechanism, we need a monotonically increasing counters. We use * it much like a "Lamport logical clock": we do not need the actual time, we just need * to know the sequence in which files were accessed. So we use a simple counter to * create that sequence. We use an unsigned 64 bit value which is extremely unlike to * wrap within the lifetime of a process. If we process 1,000,000 file writes per * second, the process could still exist over 500,000 years before a wrap to 0 happens. * That should be sufficient (and even than, there would no really bad effect ;)). * The variable below is the global counter/clock. */ #ifdef HAVE_ATOMIC_BUILTINS64 static uint64 clockFileAccess = 0; #else static unsigned clockFileAccess = 0; #endif /* and the "tick" function */ #ifndef HAVE_ATOMIC_BUILTINS static pthread_mutex_t mutClock; #endif 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 } /* The following structure is a dynafile name cache entry. */ 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 */ 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 */ 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 */ 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; 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; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; 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? */ EMPTY_STRUCT } configSettings_t; static configSettings_t cs; uchar *pszFileDfltTplName; /* name of the default template to use */ 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; strm_compressionDriver_t compressionDriver; int compressionDriver_workers; }; 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 }, { "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 }, { "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 */ { "sig.provider", eCmdHdlrGetWord, 0 }, { "cry.provider", eCmdHdlrGetWord, 0 }, { "closetimeout", eCmdHdlrPositiveInt, 0 }, { "rotation.sizelimit", eCmdHdlrSize, 0 }, { "rotation.sizelimitcommand", eCmdHdlrString, 0 }, { "template", eCmdHdlrGetWord, 0 } }; static struct cnfparamblk actpblk = { CNFPARAMBLK_VERSION, sizeof(actpdescr)/sizeof(struct cnfparamdescr), actpdescr }; /* 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(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("\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 /* 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); 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; } /* set the dynaFile cache size. Does some limit checking. * rgerhards, 2007-07-31 */ static rsRetVal setDynaFileCacheSize(void __attribute__((unused)) *pVal, int iNewVal) { DEFiRet; if(iNewVal < 1) { errno = 0; parser_errmsg( "DynaFileCacheSize must be greater 0 (%d given), changed to 1.", iNewVal); iRet = RS_RET_VAL_OUT_OF_RANGE; iNewVal = 1; } else if(iNewVal > 25000) { errno = 0; parser_warnmsg("DynaFileCacheSize is larger than 25,000 (%d given) - this looks very " "large. Is it intended?", iNewVal); } cs.iDynaFileCacheSize = iNewVal; DBGPRINTF("DynaFileCacheSize changed to %d.\n", iNewVal); RETiRet; } /* Helper to cfline(). Parses a output channel name up until the first * comma and then looks for the template specifier. Tries * to find that template. Maps the output channel to the * proper filed structure settings. Everything is stored in the * filed struct. Over time, the dependency on filed might be * removed. * rgerhards 2005-06-21 */ 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; /* WARNING: It is dangerous "just" to pass the pointer. As we * never rebuild the output channel description, this is acceptable here. */ pData->pszSizeLimitCmd = pOch->cmdOnSizeLimit; iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, getDfltTpl()); finalize_it: RETiRet; } /* This function deletes an entry from the dynamic file name * cache. A pointer to the cache must be passed in as well * as the index of the to-be-deleted entry. This index may * point to an unallocated entry, in whcih case the * function immediately returns. Parameter bFreeEntry is 1 * if the entry should be free()ed and 0 if not. */ 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; } /* This function frees all dynamic file name cache entries and closes the * relevant files. Part of Shutdown and HUP processing. * rgerhards, 2008-10-23 */ 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; } /* This function frees the dynamic file name cache. */ static void dynaFileFreeCache(instanceData *__restrict__ const pData) { assert(pData != NULL); dynaFileFreeCacheEntries(pData); if(pData->dynCache != NULL) free(pData->dynCache); } /* close current file */ static rsRetVal closeFile(instanceData *__restrict__ const pData) { DEFiRet; if(pData->useSigprov) { pData->sigprov.OnFileClose(pData->sigprovFileData); pData->sigprovFileData = NULL; } strm.Destruct(&pData->pStrm); RETiRet; } /* This prepares the signature provider to process a file */ static rsRetVal sigprovPrepare(instanceData *__restrict__ const pData, uchar *__restrict__ const fn) { DEFiRet; pData->sigprov.OnFileOpen(pData->sigprovData, fn, &pData->sigprovFileData); RETiRet; } /* This is now shared code for all types of files. It simply prepares * file access, which, among others, means the the file 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 prepareFile(instanceData *__restrict__ const pData, const uchar *__restrict__ const newFileName) { 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) */ fd = open((char*) newFileName, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY|O_CLOEXEC, 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 */ } } /* 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.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)); 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; } /* This function handles dynamic file names. It checks if the * requested file name is already open and, if not, does everything * needed to switch to the it. * Function returns 0 if all went well and non-zero otherwise. * On successful return pData->fd must point to the correct file to * be written. * This is a helper to writeFile(). rgerhards, 2007-07-03 */ 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; rsRetVal localRet; dynaFileCacheEntry **pCache; DEFiRet; assert(pData != NULL); assert(newFileName != NULL); pCache = pData->dynCache; /* first check, if we still have the current file */ if( (pData->iCurrElt != -1) && !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; } /* 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 */ 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++; STATSCOUNTER_SETMAX_NOMUT(pData->ctrMax, (unsigned) pData->iCurrCacheSize); } /* 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 ;) */ } else { /* 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); /* ignore exact error, we check fd below */ /* check if we had an error */ if(localRet != RS_RET_OK) { /* 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! */ 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; 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; } /* do the actual write process. This function is to be called once we are ready for writing. * It will do buffered writes and persist data only when the buffer is full. Note that we must * be careful to detect when the file handle changed. * rgerhards, 2009-06-03 */ static rsRetVal doWrite(instanceData *__restrict__ const pData, uchar *__restrict__ const pszBuf, const int lenBuf) { DEFiRet; assert(pData != NULL); assert(pszBuf != NULL); DBGPRINTF("omfile: write to stream, pData->pStrm %p, lenBuf %d, strt data %.128s\n", pData->pStrm, lenBuf, pszBuf); if(pData->pStrm != NULL){ CHKiRet(strm.Write(pData->pStrm, pszBuf, lenBuf)); if(pData->useSigprov) { CHKiRet(pData->sigprov.OnRecordWrite(pData->sigprovFileData, pszBuf, lenBuf)); } } finalize_it: RETiRet; } /* rgerhards 2004-11-11: write to a file output. */ 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); CHKiRet(prepareDynFile(pData, actParam(pParam, pData->iNumTpls, iMsg, 1).param)); } else { /* "regular", non-dynafile */ if(pData->pStrm == NULL) { CHKiRet(prepareFile(pData, pData->fname)); 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; 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")) { 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, "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 { dbgprintf("omfile: program error, non-handled " "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); } } finalize_it: if(pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf /* This function checks dynafile cache for janitor action */ 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; } } } /* callback for the janitor. This cleans out files (if so configured) */ 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; pthread_mutex_init(&pData->mutWrite, NULL); ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance ENDcreateWrkrInstance BEGINfreeInstance CODESTARTfreeInstance free(pData->tplName); free(pData->fname); 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 BEGINtryResume CODESTARTtryResume ENDtryResume BEGINbeginTransaction CODESTARTbeginTransaction /* we have nothing to do to begin a transaction */ ENDbeginTransaction BEGINcommitTransaction instanceData *__restrict__ const pData = pWrkrData->pData; unsigned i; CODESTARTcommitTransaction if(pData->isDevNull) { goto terminate; } pthread_mutex_lock(&pData->mutWrite); for(i = 0 ; i < nParams ; ++i) { writeFile(pData, pParams, i); } /* 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) { CHKiRet(strm.Flush(pData->pStrm)); } 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 static void setInstParamDefaults(instanceData *__restrict__ const pData) { pData->fname = NULL; pData->tplName = NULL; 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->sigprovName = NULL; pData->cryprovName = NULL; pData->useSigprov = 0; pData->useCryprov = 0; pData->iCloseTimeout = -1; pData->iSizeLimit = 0; pData->isDevNull = 0; pData->pszSizeLimitCmd = NULL; } 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; } 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; } 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; } 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, "file")) { 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"); } 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, "template")) { pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "sig.provider")) { pData->sigprovName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "cry.provider")) { 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")) { pData->pszSizeLimitCmd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } 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(*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_NO_RQD_TPL_OPTS)); 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)); 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_NO_RQD_TPL_OPTS)); /* 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 /* Reset config variables for this module to default values. * rgerhards, 2007-07-17 */ 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_doHUP ENDqueryEtryPt BEGINmodInit(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.2412.0/tools/pmrfc5424.c0000664000175000017500000002225614650736301012103 /* 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 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.2412.0/tools/rscryutil.c0000664000175000017500000004761014660643541012522 /* 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, nWritten; size_t toRead; size_t leftTillBlkEnd; char buf[64*1024]; 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; 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; } } } 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() { return 0; } static int rsgcryModename2Mode() { 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.2412.0/tools/Makefile.in0000664000175000017500000022413714723322621012355 # 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) bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_1 = $(LIBLOGGING_STDLOG_CFLAGS) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_LIBS) @ENABLE_DIAGTOOLS_TRUE@am__append_3 = rsyslog_diag_hostname msggen @ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_4 = logctl @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_5 = rscryutil @ENABLE_LIBGCRYPT_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_6 = $(LIBGCRYPT_CFLAGS) @ENABLE_LIBGCRYPT_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_7 = ../runtime/libgcry.la $(LIBGCRYPT_LIBS) @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_8 = $(OPENSSL_CFLAGS) @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_9 = ../runtime/libossl.la $(OPENSSL_LIBS) @ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_10 = rscryutil.1 @ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_11 = rscryutil.1 @ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_12 = 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_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)$(man1dir)" "$(DESTDIR)$(man5dir)" \ "$(DESTDIR)$(man8dir)" @ENABLE_DIAGTOOLS_TRUE@am__EXEEXT_3 = rsyslog_diag_hostname$(EXEEXT) \ @ENABLE_DIAGTOOLS_TRUE@ msggen$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS) am__logctl_SOURCES_DIST = logctl.c @ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@am_logctl_OBJECTS = logctl-logctl.$(OBJEXT) logctl_OBJECTS = $(am_logctl_OBJECTS) am__DEPENDENCIES_1 = @ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@logctl_DEPENDENCIES = $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__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_2 = ../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_3 = ../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_2) \ @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(am__DEPENDENCIES_3) 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) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__DEPENDENCIES_4 = \ @ENABLE_LIBLOGGING_STDLOG_TRUE@ $(am__DEPENDENCIES_1) rsyslogd_DEPENDENCIES = ../grammar/libgrammar.la \ ../runtime/librsyslog.la ../compat/compat.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_4) rsyslogd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(rsyslogd_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)/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 = $(logctl_SOURCES) $(msggen_SOURCES) rscryutil.c \ $(rsyslog_diag_hostname_SOURCES) $(rsyslogd_SOURCES) DIST_SOURCES = $(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 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; }; \ } man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man1_MANS) $(man_MANS) 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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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_11) man1_MANS = $(am__append_10) man_MANS = rsyslogd.8 rsyslog.conf.5 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 \ \ ../dirty.h rsyslogd_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(am__append_1) \ -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) $(PTHREADS_LIBS) $(RSRT_LIBS) \ $(SOL_LIBS) $(LIBUUID_LIBS) $(HASH_XXHASH_LIBS) \ $(am__append_2) @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 = $(man_MANS) rscryutil.rst recover_qi.pl $(am__append_12) EXTRA_rsyslogd_DEPENDENCIES = $(exports_list_file) @ENABLE_DIAGTOOLS_TRUE@rsyslog_diag_hostname_SOURCES = gethostn.c @ENABLE_DIAGTOOLS_TRUE@msggen_SOURCES = msggen.c @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_6) \ @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(am__append_8) @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil_LDADD = \ @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(am__append_7) \ @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(am__append_9) @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 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 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) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @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 $@ $< 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) $(man_MANS) @$(NORMAL_INSTALL) @list1='$(man1_MANS)'; \ list2='$(man_MANS)'; \ 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; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | 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: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ 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=''; test -n "$(man5dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.5[a-z]*$$/p'; \ } | 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: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ 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=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | 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) 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) $(MANS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(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-sbinPROGRAMS mostlyclean-am distclean: distclean-am -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 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-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)/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-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-generic clean-libtool \ clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-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-man uninstall-man1 uninstall-man5 uninstall-man8 \ uninstall-sbinPROGRAMS .PRECIOUS: Makefile @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.2412.0/tools/iminternal.h0000664000175000017500000000300014650736301012606 /* 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.2412.0/tools/omfile.h0000664000175000017500000000263714650736301011736 /* 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.2412.0/tools/syslogd.h0000664000175000017500000000221214650736301012134 /* 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; extern int Debug; #include "dirty.h" #endif /* #ifndef SYSLOGD_H_INCLUDED */ rsyslog-8.2412.0/tools/rsyslogd.c0000664000175000017500000021536614723322534012331 /* 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-2024 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 #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 "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 "rsconf.h" #include "cfsysline.h" #include "datetime.h" #include "operatingstate.h" #include "dirty.h" #include "janitor.h" #include "parserif.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; #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; reply.svrreply.rtncode = msgno; /* AIXPORT : srv was corrected to syslogd */ strcpy(reply.svrreply.objname, "syslogd"); snprintf(reply.svrreply.rtnmsg, SRCMIN(sizeof(reply.svrreply.rtnmsg)-1, strlen(txt)), "%s", txt); 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 */ DEFobjCurrIf(obj) DEFobjCurrIf(prop) DEFobjCurrIf(parser) DEFobjCurrIf(ruleset) DEFobjCurrIf(net) DEFobjCurrIf(rsconf) DEFobjCurrIf(module) DEFobjCurrIf(datetime) DEFobjCurrIf(glbl) extern int yydebug; /* interface to flex */ /* 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 pthread_mutex_t mutChildDied; static int bChildDied = 0; static pthread_mutex_t mutHadHUP; static int bHadHUP; static int doFork = 1; /* fork - run in daemon mode - read-only after startup */ int bFinished = 0; /* used by termination signal handler, read-only except there * is either 0 or the number of the signal that requested the * termination. */ 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 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. The mutex look is primarily to force * a memory barrier, so that we have a change to see changes already * written, but not present in the core's cache. * 2023-07-26 Rainer Gerhards */ int get_bHadHUP(void) { pthread_mutex_lock(&mutHadHUP); const int ret = bHadHUP; pthread_mutex_unlock(&mutHadHUP); /* 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; 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 rsRetVal writePidFile(void) { FILE *fp; DEFiRet; const char *tmpPidFile; if(!strcmp(PidFile, NO_PIDFILE)) { FINALIZE; } if(asprintf((char **)&tmpPidFile, "%s.tmp", PidFile) == -1) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if(tmpPidFile == NULL) tmpPidFile = PidFile; 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) { LogError(errno, iRet, "rsyslog: error writing pid file"); } fclose(fp); if(tmpPidFile != PidFile) { if(rename(tmpPidFile, PidFile) != 0) { perror("rsyslogd: error writing pid file (rename stage)"); } free((void*)tmpPidFile); } finalize_it: 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 strcpy(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)); 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 /* 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)); /* intialize 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, int *pbShutdownImmediate) { 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 && !*pbShutdownImmediate ; 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; } /* The consumer of dequeued messages. This function is called by the * queue engine on dequeueing of a message. It runs on a SEPARATE * THREAD. It receives an array of pointers, which it must iterate * over. We do not do any further batching, as this is of no benefit * for the main queue. */ static rsRetVal msgConsumer(void __attribute__((unused)) *notNeeded, batch_t *pBatch, wti_t *pWti) { DEFiRet; assert(pBatch != NULL); preprocessBatch(pBatch, pWti->pbShutdownImmediate); 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 && !*pWti->pbShutdownImmediate ; 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; static int qfn_renamenum = 0; uchar qfrenamebuf[1024]; DEFiRet; /* 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), pszQueueName); 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, (pszQueueName == NULL) ? "NONAME" : (char*)pszQueueName); 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); 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) 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; } /* submit a message to the main message queue. This is primarily * a hook to prevent the need for callers to know about the main message queue * rgerhards, 2008-02-13 */ 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); 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) { pthread_mutex_lock(&mutHadHUP); bHadHUP = 1; pthread_mutex_unlock(&mutHadHUP); /* 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) { pthread_mutex_lock(&mutChildDied); bChildDied = 1; pthread_mutex_unlock(&mutChildDied); } 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 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); /* first, parse the command line options. We do not carry out any actual work, just * see what we should do. This relieves us from certain anomalies and we can process * the parameters down below in the correct order. For example, we must know the * value of -M before we can do the init, but at the same time we need to have * the base classes init before we can process most of the options. Now, with the * split of functionality, this is no longer a problem. Thanks to varmofekoj for * suggesting this algo. * Note: where we just need to set some flags and can do so without knowledge * of other options, we do this during the inital option processing. * rgerhards, 2008-04-04 */ #if defined(_AIX) while((ch = getopt(argc, argv, "46ACDdf:hi:M:nN:o:qQS:T:u:vwxR")) != EOF) { #else while((ch = getopt(argc, argv, "46ACDdf:hi:M:nN:o:qQS:T:u:vwx")) != EOF) { #endif switch((char)ch) { case '4': case '6': case 'A': case 'f': /* configuration file */ 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 'o': if(fp_rs_full_conf_output != NULL) { fprintf(stderr, "warning: -o option given multiple times. Now " "using value %s\n", (arg == NULL) ? "-" : arg); fclose(fp_rs_full_conf_output); fp_rs_full_conf_output = NULL; } if(arg == NULL || !strcmp(arg, "-")) { fp_rs_full_conf_output = stdout; } else { fp_rs_full_conf_output = fopen(arg, "w"); } if(fp_rs_full_conf_output == NULL) { perror(arg); fprintf (stderr, "rsyslogd: cannot open config output file %s - " "-o option will be ignored\n", arg); } 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); } 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; 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; capabilities_t capabilities[] = { #define CAP_FIELD(code, type) { code, #code, 0 , type} CAP_FIELD(CAP_BLOCK_SUSPEND, CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_FIELD(CAP_NET_RAW, CAPNG_EFFECTIVE | CAPNG_PERMITTED ), CAP_FIELD(CAP_CHOWN, CAPNG_EFFECTIVE | CAPNG_PERMITTED ), CAP_FIELD(CAP_LEASE, CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_FIELD(CAP_NET_ADMIN, CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_FIELD(CAP_NET_BIND_SERVICE, CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_FIELD(CAP_DAC_OVERRIDE, CAPNG_EFFECTIVE | CAPNG_PERMITTED | CAPNG_BOUNDING_SET), CAP_FIELD(CAP_SETGID, CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_FIELD(CAP_SETUID, CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_FIELD(CAP_SYS_ADMIN, CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_FIELD(CAP_SYS_CHROOT, CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_FIELD(CAP_SYS_RESOURCE, CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_FIELD(CAP_SYSLOG, CAPNG_EFFECTIVE | CAPNG_PERMITTED) #undef CAP_FIELD }; 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); 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: 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; 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); } } } /* This takes a received message that must be decoded and submits it to * the main message queue. This is a legacy function which is being provided * to aid older input plugins that do not support message creation via * the new interfaces themselves. It is not recommended to use this * function for new plugins. -- rgerhards, 2009-10-12 */ 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. * rgerhards, 2008-10-22 */ DEFFUNC_llExecFunc(doHUPActions) { actionCallHUPHdlr((action_t*) pData); return RS_RET_OK; /* we ignore errors, we can not do anything either way */ } /* This function processes a HUP after one has been detected. Note that this * is *NOT* the sighup handler. The signal is recorded by the handler, that record * detected inside the mainloop and then this function is called to do the * real work. -- rgerhards, 2008-10-22 * Note: 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, 2012-04-11 */ static void doHUP(void) { char buf[512]; DBGPRINTF("doHUP: doing modules\n"); if(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 errmsgs\n"); errmsgDoHUP(); } /* rsyslogdDoDie() is a signal handler. If called, it sets the bFinished variable * to indicate the program should terminate. However, it does not terminate * it itself, because that causes issues with multi-threading. The actual * termination is then done on the main thread. This solution might introduce * a minimal delay, but it is much cleaner than the approach of doing everything * inside the signal handler. * rgerhards, 2005-10-26 * Note: * - we do not call DBGPRINTF() as this may cause us to block in case something * with the threading is wrong. * - we do not really care about the return state of write(), but we need this * strange check we do to silence compiler warnings (thanks, Ubuntu!) */ void rsyslogdDoDie(int sig) { # define MSG1 "DoDie called.\n" # define MSG2 "DoDie called 5 times - unconditional exit\n" static int 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 void wait_timeout(const sigset_t *sigmask) { struct timespec tvSelectTimeout; tvSelectTimeout.tv_sec = runConf->globals.janitorInterval * 60; /* interval is in minutes! */ tvSelectTimeout.tv_nsec = 0; #ifdef _AIX if(!src_exists) { /* it looks like select() is NOT interrupted by HUP, even though * SA_RESTART is not given in the signal setup. As this code is * not expected to be used in production (when running as a * service under src control), we simply make a kind of * "somewhat-busy-wait" algorithm. We compute our own * timeout value, which we count down to zero. We do this * in useful subsecond steps. */ const long wait_period = 500000000; /* wait period in nanoseconds */ int timeout = runConf->globals.janitorInterval * 60 * (1000000000 / wait_period); tvSelectTimeout.tv_sec = 0; tvSelectTimeout.tv_nsec = wait_period; do { pthread_mutex_lock(&mutHadHUP); if(bFinished || bHadHUP) { pthread_mutex_unlock(&mutHadHUP); break; } pthread_mutex_unlock(&mutHadHUP); pselect(1, NULL, NULL, NULL, &tvSelectTimeout, sigmask); } while(--timeout > 0); } else { char buf[256]; fd_set rfds; FD_ZERO(&rfds); FD_SET(SRC_FD, &rfds); if(pselect(SRC_FD + 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) { fprintf(stderr,"%s: ERROR: '%d' recvfrom\n", progname,errno); exit(1); //TODO: this needs to be handled gracefully } else { /* punt on short read */ return; } 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); return ; } 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 pselect(0, NULL, NULL, NULL, &tvSelectTimeout, sigmask); #endif /* AIXPORT : SRC end */ } 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); } /* This is the main processing loop. It is called after successful initialization. * When it returns, the syslogd terminates. * Its sole function is to provide some housekeeping things. The real work is done * by the other threads spawned. */ static void mainloop(void) { time_t tTime; sigset_t origmask; sigset_t sigblockset; int need_free_mutex; sigemptyset(&sigblockset); sigaddset(&sigblockset, SIGTERM); sigaddset(&sigblockset, SIGCHLD); sigaddset(&sigblockset, SIGHUP); do { pthread_sigmask(SIG_BLOCK, &sigblockset, &origmask); pthread_mutex_lock(&mutChildDied); need_free_mutex = 1; if(bChildDied) { bChildDied = 0; pthread_mutex_unlock(&mutChildDied); need_free_mutex = 0; reapChild(); } if(need_free_mutex) { pthread_mutex_unlock(&mutChildDied); } pthread_mutex_lock(&mutHadHUP); need_free_mutex = 1; if(bHadHUP) { need_free_mutex = 0; pthread_mutex_unlock(&mutHadHUP); doHUP(); pthread_mutex_lock(&mutHadHUP); bHadHUP = 0; pthread_mutex_unlock(&mutHadHUP); } if(need_free_mutex) { pthread_mutex_unlock(&mutHadHUP); } processImInternal(); if(bFinished) break; /* exit as quickly as possible */ wait_timeout(&origmask); pthread_sigmask(SIG_UNBLOCK, &sigblockset, NULL); janitorRun(); datetime.GetTime(&tTime); checkGoneAwaySenders(tTime); } while(!bFinished); /* end do ... while() */ } /* Finalize and destruct all actions. */ 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", 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(), 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(); } /* This is the main entry point into rsyslogd. This must be a function in its own * right in order to intialize the debug system in a portable way (otherwise we would * need to have a statement before variable definitions. * rgerhards, 20080-01-28 */ 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. */ pthread_mutex_init(&mutHadHUP, NULL); pthread_mutex_init(&mutChildDied, NULL); strncpy(progname,argv[0], sizeof(progname)-1); 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 sd_notify(0, "READY=1"); 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(); pthread_mutex_destroy(&mutChildDied); pthread_mutex_destroy(&mutHadHUP); return 0; } rsyslog-8.2412.0/tools/msggen.c0000664000175000017500000000207414650736301011731 /* 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.2412.0/tools/omfwd.h0000664000175000017500000000217714650736301011576 /* 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.2412.0/runtime/0000775000175000017500000000000014723322653010707 5rsyslog-8.2412.0/runtime/tcpclt.c0000664000175000017500000004015614704407366012276 /* 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 #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; 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)) { /* 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 */ iLenBuf = snprintf(szLenBuf, sizeof(szLenBuf), "%d ", (int) len); /* IETF20061218 iLenBuf = snprintf(szLenBuf, sizeof(szLenBuf), "%d ", len + iLenBuf);*/ if((buf = malloc(len + iLenBuf)) == 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 += iLenBuf; /* 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_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 ourselfs */ CHKiRet(tcpcltClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ ENDmodInit rsyslog-8.2412.0/runtime/zstdw.c0000664000175000017500000001233214650736301012145 /* 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) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit 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.2412.0/runtime/tcpclt.h0000664000175000017500000000476414704407366012310 /* 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-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 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 */ PROTOTYPEObj(tcpclt); /* the name of our library binary */ #define LM_TCPCLT_FILENAME "lmtcpclt" #endif /* #ifndef TCPCLT_H_INCLUDED */ rsyslog-8.2412.0/runtime/linkedlist.h0000664000175000017500000000563314650736301013147 /* 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)(), rsRetVal (*pKeyDestructor)(), int (*pCmpOp)()); 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.2412.0/runtime/perctile_ringbuf.h0000664000175000017500000000154514650736301014326 #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.2412.0/runtime/nsdsel_gtls.c0000664000175000017500000002307614650736301013322 /* nsdsel_gtls.c * * An implementation of the nsd select() interface for GnuTLS. * * Copyright (C) 2008-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 #include #include #include "rsyslog.h" #include "module-template.h" #include "obj.h" #include "errmsg.h" #include "nsd.h" #include "nsd_gtls.h" #include "nsd_ptcp.h" #include "nsdsel_ptcp.h" #include "nsdsel_gtls.h" /* static data */ DEFobjStaticHelpers DEFobjCurrIf(glbl) DEFobjCurrIf(nsdsel_ptcp) static rsRetVal gtlsHasRcvInBuffer(nsd_gtls_t *pThis) { /* we have a valid receive buffer one such is allocated and * NOT exhausted! */ DBGPRINTF("hasRcvInBuffer on nsd %p: pszRcvBuf %p, lenRcvBuf %d\n", pThis, pThis->pszRcvBuf, pThis->lenRcvBuf); return(pThis->pszRcvBuf != NULL && pThis->lenRcvBuf != -1); } /* Standard-Constructor */ BEGINobjConstruct(nsdsel_gtls) /* be sure to specify the object type also in END macro! */ iRet = nsdsel_ptcp.Construct(&pThis->pTcp); ENDobjConstruct(nsdsel_gtls) /* destructor for the nsdsel_gtls object */ BEGINobjDestruct(nsdsel_gtls) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(nsdsel_gtls) if(pThis->pTcp != NULL) nsdsel_ptcp.Destruct(&pThis->pTcp); ENDobjDestruct(nsdsel_gtls) /* Add a socket to the select set */ static rsRetVal Add(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp) { DEFiRet; nsdsel_gtls_t *pThis = (nsdsel_gtls_t*) pNsdsel; nsd_gtls_t *pNsdGTLS = (nsd_gtls_t*) pNsd; ISOBJ_TYPE_assert(pThis, nsdsel_gtls); ISOBJ_TYPE_assert(pNsdGTLS, nsd_gtls); DBGPRINTF("Add on nsd %p:\n", pNsdGTLS); if(pNsdGTLS->iMode == 1) { if(waitOp == NSDSEL_RD && gtlsHasRcvInBuffer(pNsdGTLS)) { ++pThis->iBufferRcvReady; dbgprintf("nsdsel_gtls: data already present in buffer, initiating " "dummy select %p->iBufferRcvReady=%d\n", pThis, pThis->iBufferRcvReady); FINALIZE; } if(pNsdGTLS->rtryCall != gtlsRtry_None) { if(gnutls_record_get_direction(pNsdGTLS->sess) == 0) { CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, NSDSEL_RD)); } else { CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, NSDSEL_WR)); } FINALIZE; } } dbgprintf("nsdsel_gtls: reached end on nsd %p, calling nsdsel_ptcp.Add with waitOp %d... \n", pNsdGTLS, waitOp); /* if we reach this point, we need no special handling */ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, waitOp)); finalize_it: RETiRet; } /* perform the select() piNumReady returns how many descriptors are ready for IO * TODO: add timeout! */ static rsRetVal Select(nsdsel_t *pNsdsel, int *piNumReady) { DEFiRet; nsdsel_gtls_t *pThis = (nsdsel_gtls_t*) pNsdsel; ISOBJ_TYPE_assert(pThis, nsdsel_gtls); if(pThis->iBufferRcvReady > 0) { /* we still have data ready! */ *piNumReady = pThis->iBufferRcvReady; dbgprintf("nsdsel_gtls: doing dummy select for %p->iBufferRcvReady=%d, data present\n", pThis, pThis->iBufferRcvReady); } else { iRet = nsdsel_ptcp.Select(pThis->pTcp, piNumReady); } RETiRet; } /* retry an interrupted GTLS operation * rgerhards, 2008-04-30 */ static rsRetVal doRetry(nsd_gtls_t *pNsd) { DEFiRet; int gnuRet; dbgprintf("doRetry: GnuTLS 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 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); LogError(0, RS_RET_TLS_HANDSHAKE_ERR, "GnuTLS handshake retry returned error: %s\n", pGnuErr); free(pGnuErr); ABORT_FINALIZE(RS_RET_TLS_HANDSHAKE_ERR); } break; case gtlsRtry_recv: dbgprintf("doRetry: retrying gtls recv, nsd: %p\n", pNsd); iRet = gtlsRecordRecv(pNsd); if (iRet == RS_RET_RETRY) { // Check if there is pending data size_t stBytesLeft = gnutls_record_check_pending(pNsd->sess); if (stBytesLeft > 0) { // We are in retry and more data waiting, finalize it goto finalize_it; } else { dbgprintf("doRetry: gtlsRecordRecv returned RETRY, but there is no pending" "data on nsd: %p\n", pNsd); } } pNsd->rtryCall = gtlsRtry_None; /* no more data, we are done */ gnuRet = 0; break; case gtlsRtry_None: default: assert(0); /* this shall not happen! */ dbgprintf("ERROR: pNsd->rtryCall invalid in nsdsel_gtls.c:%d\n", __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; } /* check if a socket is ready for IO */ static rsRetVal IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady) { DEFiRet; nsdsel_gtls_t *pThis = (nsdsel_gtls_t*) pNsdsel; nsd_gtls_t *pNsdGTLS = (nsd_gtls_t*) pNsd; ISOBJ_TYPE_assert(pThis, nsdsel_gtls); ISOBJ_TYPE_assert(pNsdGTLS, nsd_gtls); if(pNsdGTLS->iMode == 1) { if(waitOp == NSDSEL_RD && gtlsHasRcvInBuffer(pNsdGTLS)) { *pbIsReady = 1; --pThis->iBufferRcvReady; /* one "pseudo-read" less */ dbgprintf("nsdl_gtls: dummy read, decermenting %p->iBufRcvReady, now %d\n", pThis, pThis->iBufferRcvReady); FINALIZE; } if(pNsdGTLS->rtryCall == gtlsRtry_handshake) { CHKiRet(doRetry(pNsdGTLS)); /* we used this up for our own internal processing, so the socket * is not ready from the upper layer point of view. */ *pbIsReady = 0; FINALIZE; } else if(pNsdGTLS->rtryCall == gtlsRtry_recv) { iRet = doRetry(pNsdGTLS); if(iRet == RS_RET_OK) { *pbIsReady = 0; FINALIZE; } } /* now we must ensure that we do not fall back to PTCP if we have * done a "dummy" select. In that case, we know when the predicate * is not matched here, we do not have data available for this * socket. -- rgerhards, 2010-11-20 */ if(pThis->iBufferRcvReady) { dbgprintf("nsd_gtls: dummy read, %p->buffer not available for this FD\n", pThis); *pbIsReady = 0; FINALIZE; } } CHKiRet(nsdsel_ptcp.IsReady(pThis->pTcp, pNsdGTLS->pTcp, waitOp, pbIsReady)); finalize_it: RETiRet; } /* ------------------------------ end support for the select() interface ------------------------------ */ /* queryInterface function */ BEGINobjQueryInterface(nsdsel_gtls) CODESTARTobjQueryInterface(nsdsel_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(*)(nsdsel_t**)) nsdsel_gtlsConstruct; pIf->Destruct = (rsRetVal(*)(nsdsel_t**)) nsdsel_gtlsDestruct; pIf->Add = Add; pIf->Select = Select; pIf->IsReady = IsReady; finalize_it: ENDobjQueryInterface(nsdsel_gtls) /* exit our class */ BEGINObjClassExit(nsdsel_gtls, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(nsdsel_gtls) /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); objRelease(nsdsel_ptcp, LM_NSD_PTCP_FILENAME); ENDObjClassExit(nsdsel_gtls) /* Initialize the nsdsel_gtls class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINObjClassInit(nsdsel_gtls, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(nsdsel_ptcp, LM_NSD_PTCP_FILENAME)); /* set our own handlers */ ENDObjClassInit(nsdsel_gtls) /* vi:set ai: */ rsyslog-8.2412.0/runtime/ruleset.c0000664000175000017500000010264314650736301012462 /* 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-2021 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 }; /* 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(stmt->d.act->bDisabled) { 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 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(scriptExec(pRuleset->root, 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(scriptExec(stmt->d.s_call.stmt, 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) { sbool 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<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_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(*pWti->pbShutdownImmediate) { 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) && !*(pWti->pbShutdownImmediate) ; ++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, 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.2412.0/runtime/objomsr.h0000664000175000017500000000416214650736301012454 /* 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 */ /* next option is 16, 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.2412.0/runtime/nssel.h0000664000175000017500000000403214650736301012121 /* Definitions for the nssel IO waiter. * * 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_NSSEL_H #define INCLUDED_NSSEL_H #include "netstrms.h" /* the nssel object */ struct nssel_s { BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */ nsd_t *pDrvrData; /**< the driver's data elements */ uchar *pBaseDrvrName; /**< nsd base driver name to use, or NULL if system default */ uchar *pDrvrName; /**< full base driver name (set when driver is loaded) */ nsdsel_if_t Drvr; /**< our stream driver */ }; /* interface */ BEGINinterface(nssel) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(nssel_t **ppThis); rsRetVal (*ConstructFinalize)(nssel_t *pThis); rsRetVal (*Destruct)(nssel_t **ppThis); rsRetVal (*Add)(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp); rsRetVal (*Wait)(nssel_t *pThis, int *pNumReady); rsRetVal (*IsReady)(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp, int *pbIsReady, int *piNumReady); /* v2 - 2013-09-17 by rgerhards */ rsRetVal (*SetDrvrName)(nssel_t *pThis, uchar *name); ENDinterface(nssel) #define nsselCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObj(nssel); /* the name of our library binary */ #define LM_NSSEL_FILENAME LM_NETSTRMS_FILENAME #endif /* #ifndef INCLUDED_NSSEL_H */ rsyslog-8.2412.0/runtime/batch.h0000664000175000017500000001244214650736301012062 /* 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!). */ }; /* 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; 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.2412.0/runtime/stream.h0000664000175000017500000003024614650736301012276 /* 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-2018 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 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 */ 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 (*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, 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*); /* 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 14 /* 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) */ #define strmGetCurrFileNum(pStrm) ((pStrm)->iCurrFNum) /* prototypes */ PROTOTYPEObjClassInit(strm); 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.2412.0/runtime/conf.h0000664000175000017500000000567214650736301011735 /* 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.2412.0/runtime/msg.h0000664000175000017500000003300614650736301011566 /* msg.h * Header file for all msg-related functions. * * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c) * * Copyright 2007-2018 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 */ uint16_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 */ 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; /* 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 */ /* (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); smsg_t *MsgAddRef(smsg_t *pM); void setProtocolVersion(smsg_t *pM, int iNewVersion); void MsgSetInputName(smsg_t *pMsg, prop_t*); 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 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); void MsgSetRcvFrom(smsg_t *pMsg, prop_t*); 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); 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); uchar *getRcvFrom(smsg_t *pM); 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); 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); 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.2412.0/runtime/nsd_ptcp.h0000664000175000017500000000362314650736301012614 /* An implementation of the nsd interface for plain tcp sockets. * * Copyright 2007-2020 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 */ }; /* interface is defined in nsd.h, we just implement it! */ #define nsd_ptcpCURR_IF_VERSION nsdCURR_IF_VERSION /* prototypes */ PROTOTYPEObj(nsd_ptcp); /* the name of our library binary */ #define LM_NSD_PTCP_FILENAME "lmnsd_ptcp" #endif /* #ifndef INCLUDED_NSD_PTCP_H */ rsyslog-8.2412.0/runtime/net.c0000664000175000017500000014645114650736301011572 /* 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) #ifndef HAVE_STRUCT_SOCKADDR_SA_LEN extern size_t SALEN(struct sockaddr *sa); #endif /* 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; } 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); } /* 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; } } } 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); } /* 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 isAllowedSender2(uchar *pszType, struct sockaddr *pFrom, const char *pszFromHost, int bChkDNS) { struct AllowedSenders *pAllow; struct AllowedSenders *pAllowRoot = NULL; int bNeededDNS = 0; /* partial check because we could not resolve DNS? */ int ret; assert(pFrom != NULL); if(setAllowRoot(&pAllowRoot, pszType) != RS_RET_OK) return 0; /* if something went wrong, we deny access - that's the better choice... */ 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; } /* 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) { strcpy(hnbuf, EMPTY_HOSTNAME_REPLACEMENT); } else { /* now guard against empty hostname * see https://github.com/rsyslog/rsyslog/issues/1040 */ if(hnbuf[0] == '\0') { strcpy(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->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->GetIFIPAddr = getIFIPAddr; 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.2412.0/runtime/errmsg.h0000664000175000017500000000256414650736301012304 /* 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 */ void errmsgExit(void); void errmsgDoHUP(void); void resetErrMsgsFlag(void); int hadErrMsgs(void); void __attribute__((format(printf, 3, 4))) LogError(const int iErrno, const int iErrCode, const char *fmt, ... ); void __attribute__((format(printf, 4, 5))) LogMsg(const int iErrno, const int iErrCode, const int severity, const char *fmt, ... ); rsRetVal ATTR_NONNULL() writeOversizeMessageLog(const smsg_t *const pMsg); #endif /* #ifndef INCLUDED_ERRMSG_H */ rsyslog-8.2412.0/runtime/nsd_ossl.c0000664000175000017500000013506014721360463012623 /* nsd_ossl.c * * An implementation of the nsd interface for OpenSSL. * * Copyright 2018-2023 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 "nsdsel_ossl.h" #include "nsd_ossl.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); /*--------------------------------------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; } #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); } /* 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) { 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) { /* Output error and abort */ nsd_ossl_lastOpenSSLErrorMsg(pThis, lenRcvd, pThis->pNetOssl->ssl, LOG_INFO, "osslRecordRecv", "SSL_read 1"); iRet = RS_RET_NO_ERRCODE; /* 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); } } // TODO: Check if MORE retry logic needed? finalize_it: dbgprintf("osslRecordRecv return. nsd %p, iRet %d, lenRcvd %zd, lenRcvBuf %d, ptrRcvBuf %d\n", pThis, iRet, lenRcvd, pThis->lenRcvBuf, pThis->ptrRcvBuf); 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_NO_ERRCODE); } // 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 */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) /* NOTE: do never use: +eNULL, it DISABLES encryption! */ strncpy(pristringBuf, "ALL:+COMPLEMENTOFDEFAULT:+ADH:+ECDH:+aNULL@SECLEVEL=0", sizeof(pristringBuf)); #else strncpy(pristringBuf, "ALL:+COMPLEMENTOFDEFAULT:+ADH:+ECDH:+aNULL", sizeof(pristringBuf)); #endif dbgprintf("osslInitSession: setting anon ciphers: %s\n", pristringBuf); if ( SSL_set_cipher_list(pThis->pNetOssl->ssl, pristringBuf) == 0 ){ dbgprintf("osslInitSession: Error setting ciphers '%s'\n", pristringBuf); ABORT_FINALIZE(RS_RET_SYS_ERR); } } /* Create BIO from ptcp socket! */ conn = BIO_new_socket(pPtcp->sock, BIO_CLOSE /*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; 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: FINALIZE; break; } finalize_it: 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; } /* ---------------------------- 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 */ PROTOTYPEobjDestruct(nsd_ossl); 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); 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); 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; } /* 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); } /* 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 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 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((nsd_t*)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 Server handshake does not complete " "immediately - setting to retry (this is OK and normal)\n"); FINALIZE; } else 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': " "Handshake failed with SSL_ERROR_SYSCALL", fromHostIP); 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': " "Handshake failed with error code: %d", fromHostIP, resErr); 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((nsd_t*)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"); 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"); LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "nsd_ossl:TLS session terminated with remote syslog server '%s':" "Handshake failed with error code: %d", fromHostIP, resErr); 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) { 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)); 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->DrvrVerifyDepth = pThis->DrvrVerifyDepth; 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 */ SSL_set_ex_data(pNew->pNetOssl->ssl, 0, pThis->pTcp); SSL_set_ex_data(pNew->pNetOssl->ssl, 1, &pThis->permitExpiredCerts); /* 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) { 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)); FINALIZE; } /* --- in TLS mode now --- */ /* 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)); } 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; 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; } 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, retry next time\n"); ABORT_FINALIZE(RS_RET_RETRY); } else if(err == SSL_ERROR_SYSCALL) { /* Output error and abort */ nsd_ossl_lastOpenSSLErrorMsg(pThis, iSent, pThis->pNetOssl->ssl, LOG_INFO, "Send", "SSL_write"); iRet = RS_RET_NO_ERRCODE; /* 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 { /* 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)); /* Store nsd_ossl_t* reference in SSL obj */ SSL_set_ex_data(pThis->pNetOssl->ssl, 0, pThis->pTcp); SSL_set_ex_data(pThis->pNetOssl->ssl, 1, &pThis->permitExpiredCerts); /* 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* pThis = (nsd_ossl_t*) pNsd; ISOBJ_TYPE_assert(pThis, nsd_ossl); #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER) 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 *const pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_ossl); #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER) /* 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 finalize_it: 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, for now it is empty wrapper. * TODO: implement openSSL version * 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 ossl netstream driver", prioritizeSan); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } 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; } 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); if(caFile == NULL) { pThis->pNetOssl->pszCAFile = NULL; } else { 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); if(crlFile == NULL) { pThis->pNetOssl->pszCRLFile = NULL; } else { CHKmalloc(pThis->pNetOssl->pszCRLFile = (const uchar*) strdup((const char*) crlFile)); } 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); if(pszFile == NULL) { pThis->pNetOssl->pszKeyFile = NULL; } else { 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); if(pszFile == NULL) { pThis->pNetOssl->pszCertFile = NULL; } else { CHKmalloc(pThis->pNetOssl->pszCertFile = (const uchar*) strdup((const char*) pszFile)); } finalize_it: RETiRet; } /* 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->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->SetGnutlsPriorityString = SetGnutlsPriorityString; /* we don't NEED this interface! */ pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage; /* we don't NEED this interface! */ pIf->SetPrioritizeSAN = SetPrioritizeSAN; /* we don't NEED this interface! */ pIf->SetTlsVerifyDepth = SetTlsVerifyDepth; pIf->SetTlsCAFile = SetTlsCAFile; pIf->SetTlsCRLFile = SetTlsCRLFile; pIf->SetTlsKeyFile = SetTlsKeyFile; pIf->SetTlsCertFile = SetTlsCertFile; 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 nsdsel_osslClassExit(); 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 */ CHKiRet(nsdsel_osslClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ ENDmodInit rsyslog-8.2412.0/runtime/prop.c0000664000175000017500000001662014650736301011756 /* 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.2412.0/runtime/lmcry_gcry.c0000664000175000017500000002231414660643541013151 /* 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")) { 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")) { 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")) { 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")) { 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")) { 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.2412.0/runtime/perctile_stats.h0000664000175000017500000000500714650736301014025 /* * 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 { 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.2412.0/runtime/cfsysline.h0000664000175000017500000000474314650736301013005 /* 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.2412.0/runtime/nsdsel_ossl.c0000664000175000017500000002072714650736301013331 /* nsdsel_ossl.c * * An implementation of the nsd select() interface for OpenSSL. * * Copyright (C) 2018-2018 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. */ #include "config.h" #include #include #include #include #include #include "rsyslog.h" #include "module-template.h" #include "obj.h" #include "errmsg.h" #include "net_ossl.h" // Include OpenSSL Helpers #include "nsd.h" #include "nsd_ossl.h" #include "nsd_ptcp.h" #include "nsdsel_ptcp.h" #include "nsdsel_ossl.h" /* static data */ DEFobjStaticHelpers DEFobjCurrIf(glbl) DEFobjCurrIf(nsdsel_ptcp) static rsRetVal osslHasRcvInBuffer(nsd_ossl_t *pThis) { /* we have a valid receive buffer one such is allocated and * NOT exhausted! */ DBGPRINTF("hasRcvInBuffer on nsd %p: pszRcvBuf %p, lenRcvBuf %d\n", pThis, pThis->pszRcvBuf, pThis->lenRcvBuf); return(pThis->pszRcvBuf != NULL && pThis->lenRcvBuf != -1); } /* Standard-Constructor */ BEGINobjConstruct(nsdsel_ossl) /* be sure to specify the object type also in END macro! */ iRet = nsdsel_ptcp.Construct(&pThis->pTcp); ENDobjConstruct(nsdsel_ossl) /* destructor for the nsdsel_ossl object */ BEGINobjDestruct(nsdsel_ossl) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(nsdsel_ossl) if(pThis->pTcp != NULL) nsdsel_ptcp.Destruct(&pThis->pTcp); ENDobjDestruct(nsdsel_ossl) /* Add a socket to the select set */ static rsRetVal Add(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp) { DEFiRet; nsdsel_ossl_t *pThis = (nsdsel_ossl_t*) pNsdsel; nsd_ossl_t *pNsdOSSL = (nsd_ossl_t*) pNsd; ISOBJ_TYPE_assert(pThis, nsdsel_ossl); ISOBJ_TYPE_assert(pNsdOSSL, nsd_ossl); DBGPRINTF("Add on nsd %p:\n", pNsdOSSL); if(pNsdOSSL->iMode == 1) { if(waitOp == NSDSEL_RD && osslHasRcvInBuffer(pNsdOSSL)) { ++pThis->iBufferRcvReady; dbgprintf("nsdsel_ossl: data already present in buffer, initiating " "dummy select %p->iBufferRcvReady=%d\n", pThis, pThis->iBufferRcvReady); FINALIZE; } if(pNsdOSSL->rtryCall != osslRtry_None) { /* // VERBOSE dbgprintf("nsdsel_ossl: rtryOsslErr=%d ... \n", pNsdOSSL->rtryOsslErr); */ if (pNsdOSSL->rtryOsslErr == SSL_ERROR_WANT_READ) { CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdOSSL->pTcp, NSDSEL_RD)); FINALIZE; } else if (pNsdOSSL->rtryOsslErr == SSL_ERROR_WANT_WRITE) { CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdOSSL->pTcp, NSDSEL_WR)); FINALIZE; } else { dbgprintf("nsdsel_ossl: rtryCall=%d, rtryOsslErr=%d, unexpected ... help?! ... \n", pNsdOSSL->rtryCall, pNsdOSSL->rtryOsslErr); ABORT_FINALIZE(RS_RET_NO_ERRCODE); } } else { dbgprintf("nsdsel_ossl: rtryCall=%d, nothing to do ... \n", pNsdOSSL->rtryCall); } } dbgprintf("nsdsel_ossl: reached end, calling nsdsel_ptcp.Add with waitOp %d... \n", waitOp); /* if we reach this point, we need no special handling */ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdOSSL->pTcp, waitOp)); finalize_it: RETiRet; } /* perform the select() piNumReady returns how many descriptors are ready for IO * TODO: add timeout! */ static rsRetVal Select(nsdsel_t *pNsdsel, int *piNumReady) { DEFiRet; nsdsel_ossl_t *pThis = (nsdsel_ossl_t*) pNsdsel; ISOBJ_TYPE_assert(pThis, nsdsel_ossl); if(pThis->iBufferRcvReady > 0) { /* we still have data ready! */ *piNumReady = pThis->iBufferRcvReady; dbgprintf("nsdsel_ossl: doing dummy select, data present\n"); } else { iRet = nsdsel_ptcp.Select(pThis->pTcp, piNumReady); } RETiRet; } /* retry an interrupted OSSL operation * rgerhards, 2008-04-30 */ 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); /* Do the handshake again*/ CHKiRet(osslHandshakeCheck(pNsdOSSL)); pNsd->rtryCall = osslRtry_None; /* we are done */ break; case osslRtry_recv: dbgprintf("doRetry: retrying ossl recv, nsd: %p\n", pNsd); CHKiRet(osslRecordRecv(pNsd)); pNsd->rtryCall = osslRtry_None; /* we are done */ break; 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; } /* check if a socket is ready for IO */ static rsRetVal IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady) { DEFiRet; nsdsel_ossl_t *pThis = (nsdsel_ossl_t*) pNsdsel; nsd_ossl_t *pNsdOSSL = (nsd_ossl_t*) pNsd; ISOBJ_TYPE_assert(pThis, nsdsel_ossl); ISOBJ_TYPE_assert(pNsdOSSL, nsd_ossl); DBGPRINTF("nsdsel_ossl IsReady EINTR\n"); if(pNsdOSSL->iMode == 1) { if(waitOp == NSDSEL_RD && osslHasRcvInBuffer(pNsdOSSL)) { *pbIsReady = 1; --pThis->iBufferRcvReady; /* one "pseudo-read" less */ FINALIZE; } if(pNsdOSSL->rtryCall == osslRtry_handshake) { CHKiRet(doRetry(pNsdOSSL)); /* we used this up for our own internal processing, so the socket * is not ready from the upper layer point of view. */ *pbIsReady = 0; FINALIZE; } else if(pNsdOSSL->rtryCall == osslRtry_recv) { iRet = doRetry(pNsdOSSL); if(iRet == RS_RET_OK) { *pbIsReady = 0; FINALIZE; } } /* now we must ensure that we do not fall back to PTCP if we have * done a "dummy" select. In that case, we know when the predicate * is not matched here, we do not have data available for this * socket. -- rgerhards, 2010-11-20 */ if(pThis->iBufferRcvReady) { *pbIsReady = 0; FINALIZE; } } /* // VERBOSE dbgprintf("nsdl_ossl: IsReady before nsdsel_ptcp.IsReady for %p\n", pThis); */ CHKiRet(nsdsel_ptcp.IsReady(pThis->pTcp, pNsdOSSL->pTcp, waitOp, pbIsReady)); finalize_it: RETiRet; } /* ------------------------------ end support for the select() interface ------------------------------ */ /* queryInterface function */ BEGINobjQueryInterface(nsdsel_ossl) CODESTARTobjQueryInterface(nsdsel_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(*)(nsdsel_t**)) nsdsel_osslConstruct; pIf->Destruct = (rsRetVal(*)(nsdsel_t**)) nsdsel_osslDestruct; pIf->Add = Add; pIf->Select = Select; pIf->IsReady = IsReady; finalize_it: ENDobjQueryInterface(nsdsel_ossl) /* exit our class */ BEGINObjClassExit(nsdsel_ossl, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(nsdsel_ossl) /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); objRelease(nsdsel_ptcp, LM_NSD_PTCP_FILENAME); ENDObjClassExit(nsdsel_ossl) /* Initialize the nsdsel_ossl class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINObjClassInit(nsdsel_ossl, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(nsdsel_ptcp, LM_NSD_PTCP_FILENAME)); /* set our own handlers */ ENDObjClassInit(nsdsel_ossl) /* vi:set ai: */ rsyslog-8.2412.0/runtime/nsdpoll_ptcp.h0000664000175000017500000000427714721401737013512 /* An implementation of the nsd poll interface for plain tcp sockets. * * Copyright 2009-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_NSDPOLL_PTCP_H #define INCLUDED_NSDPOLL_PTCP_H #include "nsd.h" #ifdef HAVE_SYS_EPOLL_H # include #endif typedef nsdpoll_if_t nsdpoll_ptcp_if_t; /* we just *implement* this interface */ /* a helper object to keep track of the epoll event records * Note that we need to keep track of that list because we need to * free the events when they are no longer needed. */ typedef struct nsdpoll_epollevt_lst_s nsdpoll_epollevt_lst_t; struct nsdpoll_epollevt_lst_s { #ifdef HAVE_SYS_EPOLL_H epoll_event_t event; #endif int id; void *pUsr; nsd_ptcp_t *pSock; /* our associated netstream driver data */ nsdpoll_epollevt_lst_t *pNext; }; /* the nsdpoll_ptcp object */ struct nsdpoll_ptcp_s { BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */ int efd; /* file descriptor used by epoll */ nsdpoll_epollevt_lst_t *pRoot; /* Root of the epoll event list */ pthread_mutex_t mutEvtLst; }; /* interface is defined in nsd.h, we just implement it! */ #define nsdpoll_ptcpCURR_IF_VERSION nsdCURR_IF_VERSION /* prototypes */ PROTOTYPEObj(nsdpoll_ptcp); #endif /* #ifndef INCLUDED_NSDPOLL_PTCP_H */ rsyslog-8.2412.0/runtime/wti.c0000664000175000017500000004330414650736301011600 /* 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 aquainted to the object. * * Copyright 2008-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. */ #include "config.h" #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; /* forward-definitions */ /* 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_FETCH_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"); } 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_0_TO_INT(&pThis->bIsRunning, &pThis->mutIsRunning); } else { ATOMIC_OR_INT_TO_INT(&pThis->bIsRunning, &pThis->mutIsRunning, newVal); } return RS_RET_OK; } /* 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; ISOBJ_TYPE_assert(pThis, wti); wtiJoinThrd(pThis); if(wtiGetState(pThis) != WRKTHRD_STOPPED) { LogMsg(0, RS_RET_ERR, LOG_WARNING, "%s: need to do cooperative cancellation " "- some data may be lost, increase timeout?", cancelobj); /* we first try the cooperative "cancel" interface */ pthread_kill(pThis->thrdID, SIGTTIN); DBGPRINTF("sent SIGTTIN to worker thread %p, giving it a chance to terminate\n", (void *) pThis->thrdID); srSleep(0, 50000); wtiJoinThrd(pThis); } if(wtiGetState(pThis) != WRKTHRD_STOPPED) { 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(pThis->thrdID); pthread_kill(pThis->thrdID, SIGTTIN); DBGPRINTF("cooperative worker termination failed, using cancellation...\n"); DBGOPRINT((obj_t*) pThis, "canceling worker thread\n"); pthread_cancel(pThis->thrdID); /* now wait until the thread terminates... */ while(wtiGetState(pThis) != WRKTHRD_STOPPED && wtiGetState(pThis) != WRKTHRD_WAIT_JOIN) { DBGOPRINT((obj_t*) pThis, "waiting on termination, state %d\n", wtiGetState(pThis)); srSleep(0, 10000); } } wtiJoinThrd(pThis); 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; int newMax; DEFiRet; if(wrkrInfo->p.tx.currIParam == wrkrInfo->p.tx.maxIParams) { /* we need to extend */ newMax = (wrkrInfo->p.tx.maxIParams == 0) ? CONF_IPARAMS_BUFSIZE : 2 * wrkrInfo->p.tx.maxIParams; CHKmalloc(iparams = realloc(wrkrInfo->p.tx.iparams, sizeof(actWrkrIParams_t) * pAction->iNumTpls * newMax)); memset(iparams + (wrkrInfo->p.tx.currIParam * pAction->iNumTpls), 0, sizeof(actWrkrIParams_t) * pAction->iNumTpls * (newMax - wrkrInfo->p.tx.maxIParams)); wrkrInfo->p.tx.iparams = iparams; wrkrInfo->p.tx.maxIParams = 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 { timeoutComp(&t, pWtp->toWrkShutdown);/* 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; 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 ourselfs, 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) { 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 */ DEFpropSetMeth(wti, pWtp, wtp_t*) /* 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(nsdsel_gtls) /* 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.2412.0/runtime/nspoll.c0000664000175000017500000001501114723310736012277 /* nspoll.c * * This is an io waiter interface utilizing the much-more-efficient poll/epoll API. * Note that it may not always be available for a given driver. If so, that is reported * back to the upper peer which then should consult a nssel-based io waiter. * * Work on this module begun 2009-11-18 by Rainer Gerhards. * * Copyright 2009-2014 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 "rsyslog.h" #include #include #include #include #include #include "rsyslog.h" #include "obj.h" #include "module-template.h" #include "netstrm.h" #include "nspoll.h" #include "rsconf.h" /* static data */ DEFobjStaticHelpers DEFobjCurrIf(glbl) /* 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. Please note that * we do some name-mangeling. We know that each nsd driver also needs * a nspoll driver. So we simply append "sel" to the nsd driver name: This, * of course, means that the driver name must match these rules, but that * shouldn't be a real problem. * WARNING: this code is mostly identical to similar code in * netstrms.c - TODO: abstract it and move it to some common place. * rgerhards, 2008-04-28 */ static rsRetVal loadDrvr(nspoll_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), "lmnsdpoll_%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, DONT_LOAD_LIB, (void*) &pThis->Drvr)); finalize_it: if(iRet != RS_RET_OK) { if(pThis->pDrvrName != NULL) { free(pThis->pDrvrName); pThis->pDrvrName = NULL; } } RETiRet; } /* Standard-Constructor */ BEGINobjConstruct(nspoll) /* be sure to specify the object type also in END macro! */ ENDobjConstruct(nspoll) /* destructor for the nspoll object */ BEGINobjDestruct(nspoll) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(nspoll) if(pThis->pDrvrData != NULL) pThis->Drvr.Destruct(&pThis->pDrvrData); /* 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 */ free(pThis->pBaseDrvrName); if(pThis->pDrvrName != NULL) { obj.ReleaseObj(__FILE__, pThis->pDrvrName+2, DONT_LOAD_LIB, (void*) &pThis->Drvr); free(pThis->pDrvrName); } ENDobjDestruct(nspoll) /* ConstructionFinalizer */ static rsRetVal ConstructFinalize(nspoll_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, nspoll); CHKiRet(loadDrvr(pThis)); CHKiRet(pThis->Drvr.Construct(&pThis->pDrvrData)); finalize_it: RETiRet; } /* Carries out the actual wait (all done in lower layers) */ static rsRetVal Wait(nspoll_t *pThis, int timeout, int *numEntries, nsd_epworkset_t workset[]) { DEFiRet; ISOBJ_TYPE_assert(pThis, nspoll); assert(workset != NULL); iRet = pThis->Drvr.Wait(pThis->pDrvrData, timeout, numEntries, workset); 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(nspoll_t *pThis, uchar *pszName) { DEFiRet; ISOBJ_TYPE_assert(pThis, nspoll); if(pThis->pBaseDrvrName != NULL) { free(pThis->pBaseDrvrName); pThis->pBaseDrvrName = NULL; } if(pszName != NULL) { CHKmalloc(pThis->pBaseDrvrName = (uchar*) strdup((char*) pszName)); } finalize_it: RETiRet; } /* semantics like the epoll_ctl() function, does the same thing. * rgerhards, 2009-11-18 */ static rsRetVal Ctl(nspoll_t *pThis, netstrm_t *pStrm, int id, void *pUsr, int mode, int op) { DEFiRet; ISOBJ_TYPE_assert(pThis, nspoll); iRet = pThis->Drvr.Ctl(pThis->pDrvrData, pStrm->pDrvrData, id, pUsr, mode, op); RETiRet; } /* queryInterface function */ BEGINobjQueryInterface(nspoll) CODESTARTobjQueryInterface(nspoll) if(pIf->ifVersion != nspollCURR_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 = nspollConstruct; pIf->ConstructFinalize = ConstructFinalize; pIf->SetDrvrName = SetDrvrName; pIf->Destruct = nspollDestruct; pIf->Wait = Wait; pIf->Ctl = Ctl; finalize_it: ENDobjQueryInterface(nspoll) /* exit our class */ BEGINObjClassExit(nspoll, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(nspoll) /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); ENDObjClassExit(nspoll) /* Initialize the nspoll class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINObjClassInit(nspoll, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ DBGPRINTF("doing nspollClassInit\n"); CHKiRet(objUse(glbl, CORE_COMPONENT)); /* set our own handlers */ ENDObjClassInit(nspoll) /* vi:set ai: */ rsyslog-8.2412.0/runtime/gss-misc.h0000664000175000017500000000273214650736301012527 /* 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 "obj.h" /* interfaces */ BEGINinterface(gssutil) /* name must also be changed in ENDinterface macro! */ int (*recv_token)(int s, gss_buffer_t tok); 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 1 /* 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.2412.0/runtime/timezones.h0000664000175000017500000000220314650736301013010 /* 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.2412.0/runtime/nssel.c0000664000175000017500000001711014650736301012115 /* nssel.c * * The io waiter is a helper object enabling us to wait on a set of streams to become * ready for IO - this is modelled after select(). We need this, because * stream drivers may have different concepts. Consequently, * the structure must contain nsd_t's from the same stream driver type * only. This is implemented as a singly-linked list where every * new element is added at the top of the list. * * Work on this module begun 2008-04-22 by Rainer Gerhards. * * Copyright 2008-2014 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 "rsyslog.h" #include "obj.h" #include "module-template.h" #include "netstrm.h" #include "nssel.h" #include "rsconf.h" /* static data */ DEFobjStaticHelpers DEFobjCurrIf(glbl) /* 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. Please note that * we do some name-mangeling. We know that each nsd driver also needs * a nssel driver. So we simply append "sel" to the nsd driver name: This, * of course, means that the driver name must match these rules, but that * shouldn't be a real problem. * WARNING: this code is mostly identical to similar code in * netstrms.c - TODO: abstract it and move it to some common place. * rgerhards, 2008-04-28 */ static rsRetVal loadDrvr(nssel_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), "lmnsdsel_%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, DONT_LOAD_LIB, (void*) &pThis->Drvr)); finalize_it: if(iRet != RS_RET_OK) { if(pThis->pDrvrName != NULL) { free(pThis->pDrvrName); pThis->pDrvrName = NULL; } } RETiRet; } /* Standard-Constructor */ BEGINobjConstruct(nssel) /* be sure to specify the object type also in END macro! */ ENDobjConstruct(nssel) /* destructor for the nssel object */ BEGINobjDestruct(nssel) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(nssel) if(pThis->pDrvrData != NULL) pThis->Drvr.Destruct(&pThis->pDrvrData); /* 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 */ free(pThis->pBaseDrvrName); if(pThis->pDrvrName != NULL) { obj.ReleaseObj(__FILE__, pThis->pDrvrName+2, DONT_LOAD_LIB, (void*) &pThis->Drvr); free(pThis->pDrvrName); } ENDobjDestruct(nssel) /* ConstructionFinalizer */ static rsRetVal ConstructFinalize(nssel_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, nssel); CHKiRet(loadDrvr(pThis)); CHKiRet(pThis->Drvr.Construct(&pThis->pDrvrData)); finalize_it: 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(nssel_t *pThis, uchar *pszName) { DEFiRet; ISOBJ_TYPE_assert(pThis, nssel); if(pThis->pBaseDrvrName != NULL) { free(pThis->pBaseDrvrName); pThis->pBaseDrvrName = NULL; } if(pszName != NULL) { CHKmalloc(pThis->pBaseDrvrName = (uchar*) strdup((char*) pszName)); } finalize_it: RETiRet; } /* Add a stream object to the current select() set. * Note that a single stream may have multiple "sockets" if * it is a listener. If so, all of them are begin added. */ static rsRetVal Add(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp) { DEFiRet; ISOBJ_TYPE_assert(pThis, nssel); ISOBJ_TYPE_assert(pStrm, netstrm); CHKiRet(pThis->Drvr.Add(pThis->pDrvrData, pStrm->pDrvrData, waitOp)); finalize_it: RETiRet; } /* wait for IO to happen on one of our netstreams. iNumReady has * the number of ready "sockets" after the call. This function blocks * until some are ready. EAGAIN is retried. */ static rsRetVal Wait(nssel_t *pThis, int *piNumReady) { DEFiRet; ISOBJ_TYPE_assert(pThis, nssel); assert(piNumReady != NULL); iRet = pThis->Drvr.Select(pThis->pDrvrData, piNumReady); RETiRet; } /* Check if a stream is ready for IO. *piNumReady contains the remaining number * of ready streams. Note that this function may say the stream is not ready * but still decrement *piNumReady. This can happen when (e.g. with TLS) the low * level driver requires some IO which is hidden from the upper layer point of view. * rgerhards, 2008-04-23 */ static rsRetVal IsReady(nssel_t *pThis, netstrm_t *pStrm, nsdsel_waitOp_t waitOp, int *pbIsReady, int __attribute__((unused)) *piNumReady) { DEFiRet; ISOBJ_TYPE_assert(pThis, nssel); ISOBJ_TYPE_assert(pStrm, netstrm); assert(pbIsReady != NULL); assert(piNumReady != NULL); iRet = pThis->Drvr.IsReady(pThis->pDrvrData, pStrm->pDrvrData, waitOp, pbIsReady); RETiRet; } /* queryInterface function */ BEGINobjQueryInterface(nssel) CODESTARTobjQueryInterface(nssel) if(pIf->ifVersion != nsselCURR_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 = nsselConstruct; pIf->ConstructFinalize = ConstructFinalize; pIf->Destruct = nsselDestruct; pIf->SetDrvrName = SetDrvrName; pIf->Add = Add; pIf->Wait = Wait; pIf->IsReady = IsReady; finalize_it: ENDobjQueryInterface(nssel) /* exit our class */ BEGINObjClassExit(nssel, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(nssel) /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); ENDObjClassExit(nssel) /* Initialize the nssel class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINObjClassInit(nssel, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ DBGPRINTF("doing nsselClassInit\n"); CHKiRet(objUse(glbl, CORE_COMPONENT)); /* set our own handlers */ ENDObjClassInit(nssel) /* vi:set ai: */ rsyslog-8.2412.0/runtime/rsconf.h0000664000175000017500000003101314704407366012274 /* The rsconf object. It models a complete rsyslog configuration. * * Copyright 2011-2023 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" /* --- 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 #ifndef DFLT_INT_MSGS_SEV_FILTER #define DFLT_INT_MSGS_SEV_FILTER 6 /* Warning level and more important */ #endif /* queue config parameters. TODO: move to queue.c? */ 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 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 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() */ 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; }; 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 */ }; /* 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 */ PROTOTYPEObj(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); /* some defaults (to be removed?) */ #define DFLT_bLogStatusMsgs 1 #endif /* #ifndef INCLUDED_RSCONF_H */ rsyslog-8.2412.0/runtime/glbl.c0000664000175000017500000015564114704407366011733 /* 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 "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) */ int glblUnloadModules = 1; int glblAbortOnProgramError = 0; char** glblDbgFiles = NULL; size_t glblDbgFilesNum = 0; int glblDbgWhitelist = 1; int glblPermitCtlC = 0; 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 */ /* tables for interfacing with the v6 config system */ static struct cnfparamdescr cnfparamdescr[] = { { "workdirectory", eCmdHdlrString, 0 }, { "operatingstatefile", eCmdHdlrString, 0 }, { "dropmsgswithmaliciousdnsptrrecords", eCmdHdlrBinary, 0 }, { "localhostname", eCmdHdlrGetWord, 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.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 }, { "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 (TODO: create interface?) */ 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) { return(cnf->globals.iGnuTLSLoglevel); } /* 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(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_FETCH_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) { ATOMIC_STORE_1_TO_INT(&bTerminateInputs, &mutTerminateInputs); } /* 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; int error = 0; free(loadConf->globals.pszNetstrmDrvrCAExtraFiles); token = strtok((char*)pNewVal, ","); // Here, fopen per strtok ... while(token != NULL) { 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); } token = strtok(NULL, ","); } if(!error) { loadConf->globals.pszNetstrmDrvrCAExtraFiles = pNewVal; } else { loadConf->globals.pszNetstrmDrvrCAExtraFiles = NULL; } 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; } 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 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; } 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) * TODO: we should set the FQDN ourselfs in here! */ 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->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; bPreserveFQDN = 0; loadConf->globals.iMaxLine = 8192; loadConf->globals.reportOversizeMsg = 1; loadConf->globals.parser.cCCEscapeChar = '#'; loadConf->globals.parser.bDropTrailingLF = 1; 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; } } 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, "defaultnetstreamdriver")) { cstr = (uchar*) es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setDfltNetstrmDrvr(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, "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, "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; LogError(0, RS_RET_OK, "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.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); } } LogError(0, RS_RET_OK, "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(!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; } 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)); /* intialize 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 *)"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.2412.0/runtime/atomic.h0000664000175000017500000002176114650736301012261 /* This header supplies atomic operations. So far, we rely on GCC's * atomic builtins. During configure, we check if atomic operatons 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 atomicitiy. * 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! * * 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 # define ATOMIC_SUB(data, val, phlpmut) __sync_fetch_and_sub(data, val) # define ATOMIC_SUB_unsigned(data, val, phlpmut) __sync_fetch_and_sub(data, val) # define ATOMIC_ADD(data, val) __sync_fetch_and_add(&(data), val) # define ATOMIC_INC(data, phlpmut) ((void) __sync_fetch_and_add(data, 1)) # define ATOMIC_INC_AND_FETCH_int(data, phlpmut) __sync_fetch_and_add(data, 1) # define ATOMIC_INC_AND_FETCH_unsigned(data, phlpmut) __sync_fetch_and_add(data, 1) # define ATOMIC_DEC(data, phlpmut) ((void) __sync_sub_and_fetch(data, 1)) # define ATOMIC_DEC_AND_FETCH(data, phlpmut) __sync_sub_and_fetch(data, 1) # define ATOMIC_FETCH_32BIT(data, phlpmut) ((int) __sync_fetch_and_and(data, 0xffffffff)) # define ATOMIC_FETCH_32BIT_unsigned(data, phlpmut) ((int) __sync_fetch_and_and(data, 0xffffffff)) # define ATOMIC_STORE_1_TO_32BIT(data) __sync_lock_test_and_set(&(data), 1) # define ATOMIC_STORE_0_TO_INT(data, phlpmut) __sync_fetch_and_and(data, 0) # define ATOMIC_STORE_1_TO_INT(data, phlpmut) __sync_fetch_and_or(data, 1) # define ATOMIC_OR_INT_TO_INT(data, phlpmut, val) __sync_fetch_and_or((data), (val)) # define ATOMIC_CAS(data, oldVal, newVal, phlpmut) __sync_bool_compare_and_swap(data, (oldVal), (newVal)) # define ATOMIC_CAS_time_t(data, oldVal, newVal, phlpmut) __sync_bool_compare_and_swap(data, (oldVal), (newVal)) # define ATOMIC_CAS_VAL(data, oldVal, newVal, phlpmut) __sync_val_compare_and_swap(data, (oldVal), (newVal)); /* 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 preferrably be done atomic, 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! */ # define PREFER_ATOMIC_INC(data) ((void) __sync_fetch_and_add(&(data), 1)) # define PREFER_FETCH_32BIT(data) ((unsigned) __sync_fetch_and_and(&(data), 0xffffffff)) # define PREFER_STORE_0_TO_INT(data) __sync_fetch_and_and(data, 0) # define PREFER_STORE_1_TO_INT(data) __sync_fetch_and_or(data, 1) #else /* note that we gained parctical 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_STORE_0_TO_INT(data, hlpmut) { \ pthread_mutex_lock(hlpmut); \ *(data) = 0; \ pthread_mutex_unlock(hlpmut); \ } # define ATOMIC_STORE_1_TO_INT(data, hlpmut) { \ pthread_mutex_lock(hlpmut); \ *(data) = 1; \ pthread_mutex_unlock(hlpmut); \ } # 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); if(*data == oldVal) { *data = newVal; } val = *data; 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_FETCH_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_FETCH_32BIT_unsigned(unsigned *data, pthread_mutex_t *phlpmut) { int val; pthread_mutex_lock(phlpmut); val = (*data); pthread_mutex_unlock(phlpmut); return(val); } 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); } # 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_FETCH_32BIT(data) ((unsigned) (data)) # 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) __sync_fetch_and_add(data, 1)) # define ATOMIC_ADD_uint64(data, phlpmut, value) ((void) __sync_fetch_and_add(data, value)) # define ATOMIC_DEC_uint64(data, phlpmut) ((void) __sync_sub_and_fetch(data, 1)) # define ATOMIC_INC_AND_FETCH_uint64(data, phlpmut) __sync_fetch_and_add(data, 1) # 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_DEC_uint64(data, phlpmut) { \ pthread_mutex_lock(phlpmut); \ --(*(data)); \ pthread_mutex_unlock(phlpmut); \ } static inline unsigned 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); } # 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.2412.0/runtime/debug.h0000664000175000017500000000572014650736301012070 /* 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.2412.0/runtime/Makefile.am0000664000175000017500000001764714660643541012704 sbin_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 \ 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 \ 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 \ ruleset.c \ ruleset.h \ prop.c \ prop.h \ ratelimit.c \ ratelimit.h \ lookup.c \ lookup.h \ cfsysline.c \ cfsysline.h \ \ ../action.h \ ../action.c \ ../threads.c \ ../threads.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 # the files with ../ we need to work on - so that they either become part of the # runtime or will no longer be needed. -- rgerhards, 2008-06-13 # #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 endif #librsyslog_la_LDFLAGS = -module -avoid-version librsyslog_la_CPPFLAGS += $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(LIBUUID_CFLAGS) $(LIBFASTJSON_CFLAGS) ${LIBESTR_CFLAGS} librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS) $(LIBUUID_LIBS) $(LIBFASTJSON_LIBS) ${LIBESTR_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 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 \ nssel.c nssel.h \ nspoll.c nspoll.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 \ nsdsel_ptcp.c nsdsel_ptcp.h \ nsdpoll_ptcp.c nsdpoll_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_OPENSSL # noinst_LTLIBRARIES += lmnsd_ossl.la pkglib_LTLIBRARIES += lmnsd_ossl.la lmnsd_ossl_la_SOURCES = net_ossl.c net_ossl.h nsd_ossl.c nsd_ossl.h nsdsel_ossl.c nsdsel_ossl.h lmnsd_ossl_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(OPENSSL_CFLAGS) lmnsd_ossl_la_LDFLAGS = -module -avoid-version lmnsd_ossl_la_LIBADD = $(OPENSSL_LIBS) endif # # GnuTLS netstream driver # if ENABLE_GNUTLS pkglib_LTLIBRARIES += lmnsd_gtls.la lmnsd_gtls_la_SOURCES = nsd_gtls.c nsd_gtls.h nsdsel_gtls.c nsdsel_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 # # 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 lmgssutil_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_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 lmtcpsrv_la_LIBADD = 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.2412.0/runtime/linkedlist.c0000664000175000017500000002326714650736301013145 /* 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.2412.0/runtime/dnscache.h0000664000175000017500000000211714650736301012547 /* 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.2412.0/runtime/modules.h0000664000175000017500000002205014650736301012445 /* 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-2018 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" /* 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); 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 (*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.2412.0/runtime/net_ossl.c0000664000175000017500000012605414660643541012633 /* 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 "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 "nsd_ptcp.h" #include "rsconf.h" /* 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) 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); rsRetVal net_ossl_chkpeername(net_ossl_t *pThis, X509* certpeer, uchar *fromHostIP); /*--------------------------------------MT OpenSSL helpers ------------------------------------------*/ 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; } /*-------------------------------------- MT OpenSSL helpers -----------------------------------------*/ /*--------------------------------------OpenSSL helpers ------------------------------------------*/ /* globally initialize OpenSSL */ void osslGlblInit(void) { DBGPRINTF("osslGlblInit: ENTER\n"); 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!"); } /* 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 // 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); PRAGMA_DIAGNOSTIC_POP } /* globally de-initialize OpenSSL */ void osslGlblExit(void) { DBGPRINTF("openssl: entering osslGlblExit\n"); ENGINE_cleanup(); ERR_free_strings(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); } /* initialize openssl context; called on * - listener creation * - outbound connection creation * Once created, the ctx object is used by-subobjects (accepted inbound connections) */ 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 *extraCaFiles, *extraCaFile; /* 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", caFile); 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", crlFile); 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", certFile); 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", keyFile); 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", extraCaFiles); bHaveExtraCAFiles = 1; } /* Create main CTX Object based on method parameter */ pThis->ctx = SSL_CTX_new(method); if(bHaveExtraCAFiles == 1) { while((extraCaFile = strsep(&extraCaFiles, ","))) { if(SSL_CTX_load_verify_locations(pThis->ctx, extraCaFile, NULL) != 1) { LogError(0, RS_RET_TLS_CERT_ERR, "Error: Extra 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"); net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "SSL_CTX_load_verify_locations"); ABORT_FINALIZE(RS_RET_TLS_CERT_ERR); } } } if(bHaveCA == 1 && SSL_CTX_load_verify_locations(pThis->ctx, caFile, NULL) != 1) { LogError(0, RS_RET_TLS_CERT_ERR, "Error: CA certificate 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", "SSL_CTX_load_verify_locations"); ABORT_FINALIZE(RS_RET_TLS_CERT_ERR); } if(bHaveCRL == 1) { #if 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 } if(bHaveCert == 1 && SSL_CTX_use_certificate_chain_file(pThis->ctx, certFile) != 1) { LogError(0, RS_RET_TLS_CERT_ERR, "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"); net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "SSL_CTX_use_certificate_chain_file"); ABORT_FINALIZE(RS_RET_TLS_CERT_ERR); } if(bHaveKey == 1 && SSL_CTX_use_PrivateKey_file(pThis->ctx, keyFile, SSL_FILETYPE_PEM) != 1) { LogError(0, RS_RET_TLS_KEY_ERR , "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"); net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "SSL_CTX_use_PrivateKey_file"); 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 >= 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 finalize_it: 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) /* 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 added Command: %s:'%s' " "in net_ossl_apply_tlscgfcmd with error '%d'", 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" "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; } /* 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 net_ossl_chkonepeername(net_ossl_t *pThis, X509 *certpeer, uchar *pszPeerID, int *pbFoundPositiveMatch) { permittedPeers_t *pPeer; #if OPENSSL_VERSION_NUMBER >= 0x10002000L int osslRet; #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); /* Obtain Namex509 name from subject */ x509name = X509_NAME_oneline(RSYSLOG_X509_NAME_oneline(certpeer), NULL, 0); if(pThis->pPermPeers) { /* do we have configured peer IDs? */ pPeer = pThis->pPermPeers; while(pPeer != NULL) { CHKiRet(net.PermittedPeerWildcardMatch(pPeer, pszPeerID, pbFoundPositiveMatch)); if(*pbFoundPositiveMatch) break; #if OPENSSL_VERSION_NUMBER >= 0x10002000L /* if we did not succeed so far, try ossl X509_check_host * ( Includes check against SubjectAlternativeName ) */ osslRet = X509_check_host( certpeer, (const char*)pPeer->pszID, strlen((const char*)pPeer->pszID), 0, NULL); if ( osslRet == 1 ) { /* Found Peer cert in allowed Peerslist */ dbgprintf("net_ossl_chkonepeername: 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_chkonepeername", "X509_check_host"); ABORT_FINALIZE(RS_RET_NO_ERRCODE); } #endif /* Check next peer */ pPeer = pPeer->pNext; } } 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; } /* 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); RETiRet; } /* Check the peer's ID in name auth mode. */ rsRetVal net_ossl_chkpeername(net_ossl_t *pThis, X509* certpeer, uchar *fromHostIP) { DEFiRet; uchar lnBuf[256]; int bFoundPositiveMatch; cstr_t *pStr = NULL; char *x509name = NULL; ISOBJ_TYPE_assert(pThis, net_ossl); bFoundPositiveMatch = 0; CHKiRet(rsCStrConstruct(&pStr)); /* Obtain Namex509 name from subject */ x509name = X509_NAME_oneline(RSYSLOG_X509_NAME_oneline(certpeer), NULL, 0); dbgprintf("net_ossl_chkpeername: checking - peername '%s' on server '%s'\n", x509name, fromHostIP); snprintf((char*)lnBuf, sizeof(lnBuf), "name: %s; ", x509name); CHKiRet(rsCStrAppendStr(pStr, lnBuf)); CHKiRet(net_ossl_chkonepeername(pThis, certpeer, (uchar*)x509name, &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); iVerErr = SSL_get_verify_result(ssl); 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; } /* 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); int err = X509_STORE_CTX_get_error(store); SSL* ssl = X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx()); 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); } return status; } #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); } #if OPENSSL_VERSION_NUMBER >= 0x10100000L // 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) { DEFiRet; 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 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) { #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 } /* ------------------------------ 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; #if OPENSSL_VERSION_NUMBER >= 0x10100000L 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); } 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) 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 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.2412.0/runtime/var.c0000664000175000017500000000765014650736301011571 /* 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.2412.0/runtime/nsdsel_ptcp.h0000664000175000017500000000306014650736301013313 /* An implementation of the nsd select interface for plain tcp sockets. * * Copyright 2008 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_NSDSEL_PTCP_H #define INCLUDED_NSDSEL_PTCP_H #include #include "nsd.h" typedef nsdsel_if_t nsdsel_ptcp_if_t; /* we just *implement* this interface */ /* the nsdsel_ptcp object */ struct nsdsel_ptcp_s { BEGINobjInstance; uint32_t maxfds; uint32_t currfds; struct pollfd *fds; }; /* interface is defined in nsd.h, we just implement it! */ #define nsdsel_ptcpCURR_IF_VERSION nsdCURR_IF_VERSION /* prototypes */ PROTOTYPEObj(nsdsel_ptcp); #endif /* #ifndef INCLUDED_NSDSEL_PTCP_H */ rsyslog-8.2412.0/runtime/regexp.h0000664000175000017500000000314514650736301012273 /* 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.2412.0/runtime/syslogd-types.h0000664000175000017500000000746314650736301013636 /* 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.2412.0/runtime/modules.c0000664000175000017500000013127314723322534012450 /* 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-2018 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*); /* 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 ressources */ 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 */ } 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); 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)); 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.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; } 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; } 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); 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; } 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 ... */ strncat((char *) pPathBuf, (char *) pModName, lenPathBuf - iPathLen - 1); /* 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 */ strncat((char *) pPathBuf, ".so", lenPathBuf - strlen((char*) pPathBuf) - 1); } /* 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.2412.0/runtime/tcpsrv.c0000664000175000017500000014325214723310736012322 /* 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-2022 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 HAVE_FCNTL_H #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 "nssel.h" #include "nspoll.h" #include "errmsg.h" #include "ruleset.h" #include "ratelimit.h" #include "unicode-helper.h" PRAGMA_INGORE_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(nssel) DEFobjCurrIf(nspoll) DEFobjCurrIf(prop) DEFobjCurrIf(statsobj) static void startWorkerPool(void); /* The following structure controls the worker threads. Global data is * needed for their access. */ static struct wrkrInfo_s { pthread_t tid; /* the worker's thread ID */ pthread_cond_t run; int idx; tcpsrv_t *pSrv; /* pSrv == NULL -> idle */ nspoll_t *pPoll; void *pUsr; sbool enabled; long long unsigned numCalled; /* how often was this called */ } wrkrInfo[4]; static sbool bWrkrRunning; /* are the worker threads running? */ static pthread_mutex_t wrkrMut; static pthread_cond_t wrkrIdle; static int wrkrMax = 4; static int wrkrRunning; /* add new listener port to listener port list * rgerhards, 2009-05-21 */ static rsRetVal ATTR_NONNULL(1, 2) 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; strcpy((char*)pEntry->cnf_params->dfltTZ, (char*)pThis->dfltTZ); pEntry->cnf_params->bSPFramingFix = pThis->bSPFramingFix; pEntry->cnf_params->bPreserveCase = pThis->bPreserveCase; pEntry->pSrv = pThis; /* support statistics gathering */ CHKiRet(ratelimitNew(&pEntry->ratelimiter, "tcperver", 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); CHKiRet(statsobj.AddCounter(pEntry->stats, UCHAR_CONSTANT("submitted"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pEntry->ctrSubmit))); 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->cnf_params->pInputName != NULL) { prop.Destruct(&pEntry->cnf_params->pInputName); } if(pEntry->ratelimiter != NULL) { ratelimitDestruct(pEntry->ratelimiter); } if(pEntry->stats != NULL) { statsobj.Destruct(&pEntry->stats); } 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(1,2) configureTCPListen(tcpsrv_t *const pThis, tcpLstnParams_t *const cnf_params) { assert(cnf_params->pszPort != NULL); int i; 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)); } else { LogError(0, NO_ERRCODE, "Invalid TCP listen port %s - ignored.\n", cnf_params->pszPort); } finalize_it: RETiRet; } /* Initialize the session table * returns 0 if OK, somewhat else otherwise */ static rsRetVal TCPSessTblInit(tcpsrv_t *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; } /* find a free spot in the session table. If the table * is full, -1 is returned, else the index of the free * entry (0 or higher). */ static int TCPSessTblFindFreeSpot(tcpsrv_t *pThis) { register int i; ISOBJ_TYPE_assert(pThis, tcpsrv); for(i = 0 ; i < pThis->iSessMax ; ++i) { if(pThis->pSessions[i] == NULL) break; } return((i < pThis->iSessMax) ? i : -1); } /* 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 TCPSessGetNxtSess(tcpsrv_t *pThis, int iCurr) { register int i; ISOBJ_TYPE_assert(pThis, tcpsrv); assert(pThis->pSessions != NULL); for(i = iCurr + 1 ; i < pThis->iSessMax ; ++i) { if(pThis->pSessions[i] != NULL) break; } return((i < pThis->iSessMax) ? i : -1); } /* De-Initialize TCP listner 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) { /* close all TCP connections! */ if(!pThis->bUsingEPoll) { i = TCPSessGetNxtSess(pThis, -1); while(i != -1) { tcps_sess.Destruct(&pThis->pSessions[i]); /* now get next... */ i = TCPSessGetNxtSess(pThis, i); } } /* 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) { prop.Destruct(&pEntry->cnf_params->pInputName); free((void*)pEntry->cnf_params->pszInputName); free((void*)pEntry->cnf_params->pszPort); free((void*)pEntry->cnf_params->pszAddr); free((void*)pEntry->cnf_params->pszLstnPortFileName); free((void*)pEntry->cnf_params); ratelimitDestruct(pEntry->ratelimiter); statsobj.Destruct(&(pEntry->stats)); 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 addTcpLstn(void *pUsr, netstrm_t *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 initTCPListener(tcpsrv_t *pThis, tcpLstnPortList_t *pPortEntry) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); assert(pPortEntry != NULL); // pPortEntry->pszAddr = NULL ==> bind to all interfaces 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 create_tcp_socket(tcpsrv_t *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) { LogError(0, localRet, "Could not create tcp listener, ignoring port " "%s bind-address %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); } 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 rsRetVal SessAccept(tcpsrv_t *pThis, tcpLstnPortList_t *pLstnInfo, tcps_sess_t **ppSess, netstrm_t *pStrm) { 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; ISOBJ_TYPE_assert(pThis, tcpsrv); assert(pLstnInfo != NULL); CHKiRet(netstrm.AcceptConnReq(pStrm, &pNewStrm)); /* Add to session list */ iSess = TCPSessTblFindFreeSpot(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)); 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)); CHKiRet(netstrm.GetRemAddr(pNewStrm, &addr)); /* TODO: check if we need to strip the domain name here -- rgerhards, 2008-04-24 */ /* 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 discarded", fromHostFQDN); } 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 */ CHKiRet(tcps_sess.SetHostIP(pSess, fromHostIP)); 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)); } *ppSess = pSess; if(!pThis->bUsingEPoll) pThis->pSessions[iSess] = pSess; 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", propGetSzStr(fromHostIP)); } finalize_it: if(iRet != RS_RET_OK) { if(iRet != RS_RET_HOST_NOT_PERMITTED && pThis->bEmitMsgOnOpen) { LogError(0, NO_ERRCODE, "imtcp: connection could not be " "established with host: %s", fromHostIP == NULL ? "(IP unknown)" : (const char*)propGetSzStr(fromHostIP)); } if(pSess != NULL) tcps_sess.Destruct(&pSess); if(pNewStrm != NULL) netstrm.Destruct(&pNewStrm); free(fromHostFQDN); } RETiRet; } static void RunCancelCleanup(void *arg) { nspoll_t **ppPoll = (nspoll_t**) arg; if (*ppPoll != NULL) nspoll.Destruct(ppPoll); /* Wait for any running workers to finish */ pthread_mutex_lock(&wrkrMut); DBGPRINTF("tcpsrv terminating, waiting for %d workers\n", wrkrRunning); while(wrkrRunning > 0) { pthread_cond_wait(&wrkrIdle, &wrkrMut); } pthread_mutex_unlock(&wrkrMut); } static void RunSelectCancelCleanup(void *arg) { nssel_t **ppSel = (nssel_t**) arg; if(*ppSel != NULL) nssel.Destruct(ppSel); } /* helper to close a session. Takes status of poll vs. select into consideration. * rgerhards, 2009-11-25 */ static rsRetVal closeSess(tcpsrv_t *pThis, tcps_sess_t **ppSess, nspoll_t *pPoll) { DEFiRet; if(pPoll != NULL) { CHKiRet(nspoll.Ctl(pPoll, (*ppSess)->pStrm, 0, *ppSess, NSDPOLL_IN, NSDPOLL_DEL)); } pThis->pOnRegularClose(*ppSess); tcps_sess.Destruct(ppSess); finalize_it: RETiRet; } /* process a receive request on one of the streams * If pPoll is non-NULL, we have a netstream in epoll mode, which means we need * to remove any descriptor we close from the epoll set. * rgerhards, 2009-07-020 */ static rsRetVal doReceive(tcpsrv_t *pThis, tcps_sess_t **ppSess, nspoll_t *pPoll) { char buf[128*1024]; /* reception buffer - may hold a partial or multiple messages */ ssize_t iRcvd; rsRetVal localRet; DEFiRet; uchar *pszPeer; int lenPeer; int oserr = 0; ISOBJ_TYPE_assert(pThis, tcpsrv); prop.GetString((*ppSess)->fromHostIP, &pszPeer, &lenPeer); DBGPRINTF("netstream %p with new data from remote peer %s\n", (*ppSess)->pStrm, pszPeer); /* Receive message */ iRet = pThis->pRcvData(*ppSess, buf, sizeof(buf), &iRcvd, &oserr); 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.\n", (*ppSess)->pStrm, pszPeer); } CHKiRet(closeSess(pThis, ppSess, pPoll)); break; case RS_RET_RETRY: /* we simply ignore retry - this is not an error, but we also have not received anything */ break; case RS_RET_OK: /* valid data received, process it! */ localRet = tcps_sess.DataRcvd(*ppSess, buf, iRcvd); if(localRet != RS_RET_OK && localRet != RS_RET_QUEUE_FULL) { /* in this case, something went awfully wrong. * We are instructed to terminate the session. */ LogError(oserr, localRet, "Tearing down TCP Session from %s", pszPeer); CHKiRet(closeSess(pThis, ppSess, pPoll)); } break; default: LogError(oserr, iRet, "netstream session %p from %s will be closed due to error", (*ppSess)->pStrm, pszPeer); CHKiRet(closeSess(pThis, ppSess, pPoll)); break; } finalize_it: RETiRet; } /* process a single workset item */ static rsRetVal ATTR_NONNULL(1) processWorksetItem(tcpsrv_t *const pThis, nspoll_t *pPoll, const int idx, void *pUsr) { tcps_sess_t *pNewSess = NULL; tcpLstnParams_t *cnf_params; DEFiRet; DBGPRINTF("tcpsrv: processing item %d, pUsr %p, bAbortConn\n", idx, pUsr); if(pUsr == pThis->ppLstn) { DBGPRINTF("New connect on NSD %p.\n", pThis->ppLstn[idx]); iRet = SessAccept(pThis, pThis->ppLstnPort[idx], &pNewSess, pThis->ppLstn[idx]); cnf_params = pThis->ppLstnPort[idx]->cnf_params; if(iRet == RS_RET_OK) { if(pPoll != NULL) { CHKiRet(nspoll.Ctl(pPoll, pNewSess->pStrm, 0, pNewSess, NSDPOLL_IN, NSDPOLL_ADD)); } DBGPRINTF("New session created with NSD %p.\n", pNewSess); } else { DBGPRINTF("tcpsrv: error %d during accept\n", iRet); } } else { pNewSess = (tcps_sess_t*) pUsr; cnf_params = pNewSess->pLstnInfo->cnf_params; doReceive(pThis, &pNewSess, pPoll); if(pPoll == NULL && pNewSess == NULL) { pThis->pSessions[idx] = NULL; } } finalize_it: if(iRet != RS_RET_OK) { LogError(0, iRet, "tcpsrv listener (inputname: '%s') failed " "to process incoming connection with error %d", (cnf_params->pszInputName == NULL) ? (uchar*)"*UNSET*" : cnf_params->pszInputName, iRet); srSleep(0,20000); /* Sleep 20ms */ } RETiRet; } /* worker to process incoming requests */ static void * ATTR_NONNULL(1) wrkr(void *const myself) { struct wrkrInfo_s *const me = (struct wrkrInfo_s*) myself; pthread_mutex_lock(&wrkrMut); while(1) { // wait for work, in which case pSrv will be populated while(me->pSrv == NULL && glbl.GetGlobalInputTermState() == 0) { pthread_cond_wait(&me->run, &wrkrMut); } if(me->pSrv == NULL) { // only possible if glbl.GetGlobalInputTermState() == 1 // we need to query me->opSrv to avoid clang static // analyzer false positive! -- rgerhards, 2017-10-23 assert(glbl.GetGlobalInputTermState() == 1); break; } pthread_mutex_unlock(&wrkrMut); ++me->numCalled; processWorksetItem(me->pSrv, me->pPoll, me->idx, me->pUsr); pthread_mutex_lock(&wrkrMut); me->pSrv = NULL; /* indicate we are free again */ --wrkrRunning; pthread_cond_broadcast(&wrkrIdle); } me->enabled = 0; /* indicate we are no longer available */ pthread_mutex_unlock(&wrkrMut); return NULL; } /* This has been factored out from processWorkset() because * pthread_cleanup_push() invokes setjmp() and this triggers the -Wclobbered * warning for the iRet variable. */ static void waitForWorkers(void) { pthread_mutex_lock(&wrkrMut); pthread_cleanup_push(mutexCancelCleanup, &wrkrMut); while(wrkrRunning > 0) { pthread_cond_wait(&wrkrIdle, &wrkrMut); } pthread_cleanup_pop(1); } /* Process a workset, that is handle io. We become activated * from either select 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 processWorkset(tcpsrv_t *pThis, nspoll_t *pPoll, int numEntries, nsd_epworkset_t workset[]) { int i; int origEntries = numEntries; DEFiRet; DBGPRINTF("tcpsrv: ready to process %d event entries\n", numEntries); while(numEntries > 0) { if(glbl.GetGlobalInputTermState() == 1) ABORT_FINALIZE(RS_RET_FORCE_TERM); if(numEntries == 1) { /* process self, save context switch */ iRet = processWorksetItem(pThis, pPoll, workset[numEntries-1].id, workset[numEntries-1].pUsr); } else { /* No cancel handler needed here, since no cancellation * points are executed while wrkrMut is locked. * * Re-evaluate this if you add a DBGPRINTF or something! */ pthread_mutex_lock(&wrkrMut); /* check if there is a free worker */ for(i = 0 ; (i < wrkrMax) && ((wrkrInfo[i].pSrv != NULL) || (wrkrInfo[i].enabled == 0)) ; ++i) /*do search*/; if(i < wrkrMax) { /* worker free -> use it! */ wrkrInfo[i].pSrv = pThis; wrkrInfo[i].pPoll = pPoll; wrkrInfo[i].idx = workset[numEntries -1].id; wrkrInfo[i].pUsr = workset[numEntries -1].pUsr; /* Note: we must increment wrkrRunning HERE and not inside the worker's * code. This is because a worker may actually never start, and thus * increment wrkrRunning, before we finish and check the running worker * count. We can only avoid this by incrementing it here. */ ++wrkrRunning; pthread_cond_signal(&wrkrInfo[i].run); pthread_mutex_unlock(&wrkrMut); } else { pthread_mutex_unlock(&wrkrMut); /* no free worker, so we process this one ourselfs */ iRet = processWorksetItem(pThis, pPoll, workset[numEntries-1].id, workset[numEntries-1].pUsr); } } --numEntries; } if(origEntries > 1) { /* we now need to wait until all workers finish. This is because the * rest of this module can not handle the concurrency introduced * by workers running during the epoll call. */ waitForWorkers(); } finalize_it: RETiRet; } /* This function is called to gather input. * This variant here is only used if we need to work with a netstream driver * that does not support epoll(). */ PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wempty_body static rsRetVal RunSelect(tcpsrv_t *pThis, nsd_epworkset_t workset[], size_t sizeWorkset) { DEFiRet; int nfds; int i; int iWorkset; int iTCPSess; int bIsReady; nssel_t *pSel = NULL; rsRetVal localRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pthread_cleanup_push(RunSelectCancelCleanup, (void*) &pSel); while(1) { CHKiRet(nssel.Construct(&pSel)); if(pThis->pszDrvrName != NULL) CHKiRet(nssel.SetDrvrName(pSel, pThis->pszDrvrName)); CHKiRet(nssel.ConstructFinalize(pSel)); /* Add the TCP listen sockets to the list of read descriptors. */ for(i = 0 ; i < pThis->iLstnCurr ; ++i) { CHKiRet(nssel.Add(pSel, pThis->ppLstn[i], NSDSEL_RD)); } /* do the sessions */ iTCPSess = TCPSessGetNxtSess(pThis, -1); while(iTCPSess != -1) { /* TODO: access to pNsd is NOT really CLEAN, use method... */ CHKiRet(nssel.Add(pSel, pThis->pSessions[iTCPSess]->pStrm, NSDSEL_RD)); DBGPRINTF("tcpsrv process session %d:\n", iTCPSess); /* now get next... */ iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess); } /* wait for io to become ready */ CHKiRet(nssel.Wait(pSel, &nfds)); if(glbl.GetGlobalInputTermState() == 1) break; /* terminate input! */ iWorkset = 0; for(i = 0 ; i < pThis->iLstnCurr ; ++i) { if(glbl.GetGlobalInputTermState() == 1) ABORT_FINALIZE(RS_RET_FORCE_TERM); CHKiRet(nssel.IsReady(pSel, pThis->ppLstn[i], NSDSEL_RD, &bIsReady, &nfds)); if(bIsReady) { workset[iWorkset].id = i; workset[iWorkset].pUsr = (void*) pThis->ppLstn; /* this is a flag to indicate listen sock */ ++iWorkset; if(iWorkset >= (int) sizeWorkset) { processWorkset(pThis, NULL, iWorkset, workset); 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); localRet = nssel.IsReady(pSel, pThis->pSessions[iTCPSess]->pStrm, NSDSEL_RD, &bIsReady, &nfds); if(bIsReady || localRet != RS_RET_OK) { workset[iWorkset].id = iTCPSess; workset[iWorkset].pUsr = (void*) pThis->pSessions[iTCPSess]; ++iWorkset; if(iWorkset >= (int) sizeWorkset) { processWorkset(pThis, NULL, iWorkset, workset); iWorkset = 0; } if(bIsReady) --nfds; /* indicate we have processed one */ } iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess); } if(iWorkset > 0) processWorkset(pThis, NULL, iWorkset, workset); /* we need to copy back close descriptors */ nssel.Destruct(&pSel); /* no iRet check as it is overriden at start of loop! */ 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 */ if(pSel != NULL) { /* cleanup missing? happens during err exit! */ nssel.Destruct(&pSel); } } pthread_cleanup_pop(1); /* execute and remove cleanup handler */ RETiRet; } PRAGMA_DIAGNOSTIC_POP static rsRetVal DoRun(tcpsrv_t *pThis, nspoll_t **ppPoll) { DEFiRet; int i; nsd_epworkset_t workset[128]; /* 128 is currently fixed num of concurrent requests */ int numEntries; nspoll_t *pPoll = NULL; rsRetVal localRet; if((localRet = nspoll.Construct(ppPoll)) == RS_RET_OK) { pPoll = *ppPoll; if(pThis->pszDrvrName != NULL) CHKiRet(nspoll.SetDrvrName(pPoll, pThis->pszDrvrName)); localRet = nspoll.ConstructFinalize(pPoll); } if(localRet != RS_RET_OK) { /* fall back to select */ DBGPRINTF("tcpsrv could not use epoll() interface, iRet=%d, using select()\n", localRet); iRet = RunSelect(pThis, workset, sizeof(workset)/sizeof(nsd_epworkset_t)); FINALIZE; } DBGPRINTF("tcpsrv uses epoll() interface, nsdpoll driver found\n"); /* flag that we are in epoll mode */ pThis->bUsingEPoll = RSTRUE; /* 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); CHKiRet(nspoll.Ctl(pPoll, pThis->ppLstn[i], i, pThis->ppLstn, NSDPOLL_IN, NSDPOLL_ADD)); DBGPRINTF("Added listener %d\n", i); } while(glbl.GetGlobalInputTermState() == 0) { numEntries = sizeof(workset)/sizeof(nsd_epworkset_t); localRet = nspoll.Wait(pPoll, -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... */ if(localRet != RS_RET_OK) continue; processWorkset(pThis, pPoll, numEntries, workset); } /* remove the tcp listen sockets from the epoll set */ for(i = 0 ; i < pThis->iLstnCurr ; ++i) { CHKiRet(nspoll.Ctl(pPoll, pThis->ppLstn[i], i, pThis->ppLstn, NSDPOLL_IN, NSDPOLL_DEL)); } finalize_it: RETiRet; } /* 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 Run(tcpsrv_t *pThis) { DEFiRet; nspoll_t *pPoll = NULL; ISOBJ_TYPE_assert(pThis, tcpsrv); if(pThis->iLstnCurr == 0) { dbgprintf("tcpsrv: no listeneres at all (probably init error), terminating\n"); RETiRet; /* somewhat "dirty" exit to avoid issue with cancel handler */ } /* check if we need to start the worker pool. Once it is running, all is * well. Shutdown is done on modExit. */ d_pthread_mutex_lock(&wrkrMut); if(!bWrkrRunning) { bWrkrRunning = 1; startWorkerPool(); } d_pthread_mutex_unlock(&wrkrMut); /* We try to terminate cleanly, but install a cancellation clean-up * handler in case we are cancelled. */ pthread_cleanup_push(RunCancelCleanup, (void*) &pPoll); iRet = DoRun(pThis, &pPoll); pthread_cleanup_pop(1); RETiRet; } /* Standard-Constructor */ BEGINobjConstruct(tcpsrv) /* be sure to specify the object type also in END macro! */ 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->DrvrTlsVerifyDepth = 0; ENDobjConstruct(tcpsrv) /* ConstructionFinalizer */ static rsRetVal tcpsrvConstructFinalize(tcpsrv_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); /* prepare network stream subsystem */ CHKiRet(netstrms.Construct(&pThis->pNS)); 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)); 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*))); iRet = pThis->OpenLstnSocks(pThis); finalize_it: if(iRet != RS_RET_OK) { if(pThis->pNS != NULL) netstrms.Destruct(&pThis->pNS); 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); 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->pszInputName); free(pThis->pszOrigin); 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 SetCBIsPermittedHost(tcpsrv_t *pThis, int (*pCB)(struct sockaddr *addr, char *fromHostFQDN, void*, void*)) { DEFiRet; pThis->pIsPermittedHost = pCB; RETiRet; } static rsRetVal SetCBRcvData(tcpsrv_t *pThis, rsRetVal (*pRcvData)(tcps_sess_t*, char*, size_t, ssize_t*, int*)) { DEFiRet; pThis->pRcvData = pRcvData; RETiRet; } static rsRetVal SetCBOnListenDeinit(tcpsrv_t *pThis, rsRetVal (*pCB)(void*)) { DEFiRet; pThis->pOnListenDeinit = pCB; RETiRet; } static rsRetVal SetCBOnSessAccept(tcpsrv_t *pThis, rsRetVal (*pCB)(tcpsrv_t*, tcps_sess_t*)) { DEFiRet; pThis->pOnSessAccept = pCB; RETiRet; } static rsRetVal SetCBOnDestruct(tcpsrv_t *pThis, rsRetVal (*pCB)(void*)) { DEFiRet; pThis->OnDestruct = pCB; RETiRet; } static rsRetVal SetCBOnSessConstructFinalize(tcpsrv_t *pThis, rsRetVal (*pCB)(void*)) { DEFiRet; pThis->OnSessConstructFinalize = pCB; RETiRet; } static rsRetVal SetCBOnSessDestruct(tcpsrv_t *pThis, rsRetVal (*pCB)(void*)) { DEFiRet; pThis->pOnSessDestruct = pCB; RETiRet; } static rsRetVal SetCBOnRegularClose(tcpsrv_t *pThis, rsRetVal (*pCB)(tcps_sess_t*)) { DEFiRet; pThis->pOnRegularClose = pCB; RETiRet; } static rsRetVal SetCBOnErrClose(tcpsrv_t *pThis, rsRetVal (*pCB)(tcps_sess_t*)) { DEFiRet; pThis->pOnErrClose = pCB; RETiRet; } static rsRetVal SetCBOpenLstnSocks(tcpsrv_t *pThis, rsRetVal (*pCB)(tcpsrv_t*)) { DEFiRet; pThis->OpenLstnSocks = pCB; RETiRet; } static rsRetVal SetUsrP(tcpsrv_t *pThis, void *pUsr) { DEFiRet; pThis->pUsr = pUsr; RETiRet; } static rsRetVal SetKeepAlive(tcpsrv_t *pThis, int iVal) { DEFiRet; DBGPRINTF("tcpsrv: keep-alive set to %d\n", iVal); pThis->bUseKeepAlive = iVal; RETiRet; } static rsRetVal SetKeepAliveIntvl(tcpsrv_t *pThis, int iVal) { DEFiRet; DBGPRINTF("tcpsrv: keep-alive interval set to %d\n", iVal); pThis->iKeepAliveIntvl = iVal; RETiRet; } static rsRetVal SetKeepAliveProbes(tcpsrv_t *pThis, int iVal) { DEFiRet; DBGPRINTF("tcpsrv: keep-alive probes set to %d\n", iVal); pThis->iKeepAliveProbes = iVal; RETiRet; } static rsRetVal SetKeepAliveTime(tcpsrv_t *pThis, int iVal) { DEFiRet; DBGPRINTF("tcpsrv: keep-alive timeout set to %d\n", iVal); pThis->iKeepAliveTime = iVal; RETiRet; } static rsRetVal 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 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 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 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 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 SetMaxFrameSize(tcpsrv_t *pThis, int maxFrameSize) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->maxFrameSize = maxFrameSize; RETiRet; } static rsRetVal SetDfltTZ(tcpsrv_t *const pThis, uchar *const tz) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); strncpy((char*)pThis->dfltTZ, (char*)tz, sizeof(pThis->dfltTZ)); pThis->dfltTZ[sizeof(pThis->dfltTZ)-1] = '\0'; RETiRet; } static rsRetVal SetbSPFramingFix(tcpsrv_t *pThis, const sbool val) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->bSPFramingFix = val; RETiRet; } static rsRetVal 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 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)); free(pThis->pszInputName); // TODO: REMOVE ME pThis->pszInputName = ustrdup("imtcp"); // TODO: REMOVE ME /* 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; } /* Set the linux-like ratelimiter settings */ static rsRetVal SetLinuxLikeRatelimiters(tcpsrv_t *pThis, unsigned int ratelimitInterval, unsigned int ratelimitBurst) { DEFiRet; pThis->ratelimitInterval = ratelimitInterval; pThis->ratelimitBurst = ratelimitBurst; RETiRet; } /* Set connection open notification */ static rsRetVal SetNotificationOnRemoteOpen(tcpsrv_t *pThis, const int bNewVal) { pThis->bEmitMsgOnOpen = bNewVal; return RS_RET_OK; } /* Set connection close notification */ static rsRetVal 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 SetDrvrMode(tcpsrv_t *pThis, const int iMode) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->iDrvrMode = iMode; RETiRet; } static rsRetVal 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 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 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 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 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 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 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 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 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 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 SetDrvrTlsVerifyDepth(tcpsrv_t *pThis, int verifyDepth) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->DrvrTlsVerifyDepth = verifyDepth; RETiRet; } /* End of methods to shuffle autentication 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 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 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 SetSessMax(tcpsrv_t *pThis, int iMax) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->iSessMax = iMax; RETiRet; } static rsRetVal SetPreserveCase(tcpsrv_t *pThis, int bPreserveCase) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis-> bPreserveCase = bPreserveCase; RETiRet; } /* 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->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->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; 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(nssel, DONT_LOAD_LIB); objRelease(netstrm, LM_NETSTRMS_FILENAME); objRelease(net, LM_NET_FILENAME); 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(nssel, DONT_LOAD_LIB)); CHKiRet(objUse(nspoll, 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)); /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, tcpsrvDebugPrint); OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, tcpsrvConstructFinalize); ENDObjClassInit(tcpsrv) /* start worker threads * Important: if we fork, this MUST be done AFTER forking */ static void startWorkerPool(void) { int i; int r; pthread_attr_t sessThrdAttr; /* We need to temporarily block all signals because the new thread * inherits our signal mask. There is a race if we do not block them * now, and we have seen in practice that this race causes grief. * So we 1. save the current set, 2. block evertyhing, 3. start * threads, and 4 reset the current set to saved state. * rgerhards, 2019-08-16 */ sigset_t sigSet, sigSetSave; sigfillset(&sigSet); pthread_sigmask(SIG_SETMASK, &sigSet, &sigSetSave); wrkrRunning = 0; pthread_cond_init(&wrkrIdle, NULL); pthread_attr_init(&sessThrdAttr); pthread_attr_setstacksize(&sessThrdAttr, 4096*1024); for(i = 0 ; i < wrkrMax ; ++i) { /* init worker info structure! */ pthread_cond_init(&wrkrInfo[i].run, NULL); wrkrInfo[i].pSrv = NULL; wrkrInfo[i].numCalled = 0; r = pthread_create(&wrkrInfo[i].tid, &sessThrdAttr, wrkr, &(wrkrInfo[i])); if(r == 0) { wrkrInfo[i].enabled = 1; } else { LogError(r, NO_ERRCODE, "tcpsrv error creating thread"); } } pthread_attr_destroy(&sessThrdAttr); pthread_sigmask(SIG_SETMASK, &sigSetSave, NULL); } /* destroy worker pool structures and wait for workers to terminate */ static void stopWorkerPool(void) { int i; for(i = 0 ; i < wrkrMax ; ++i) { pthread_mutex_lock(&wrkrMut); pthread_cond_signal(&wrkrInfo[i].run); /* awake wrkr if not running */ pthread_mutex_unlock(&wrkrMut); pthread_join(wrkrInfo[i].tid, NULL); DBGPRINTF("tcpsrv: info: worker %d was called %llu times\n", i, wrkrInfo[i].numCalled); pthread_cond_destroy(&wrkrInfo[i].run); } pthread_cond_destroy(&wrkrIdle); } /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit if(bWrkrRunning) { stopWorkerPool(); bWrkrRunning = 0; } /* de-init in reverse order! */ tcpsrvClassExit(); tcps_sessClassExit(); pthread_mutex_destroy(&wrkrMut); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt CODEqueryEtryPt_STD_LIB_QUERIES ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ /* we just init the worker mutex, but do not start the workers themselves. This is deferred * to the first call of Run(). Reasons for this: * 1. depending on load order, tcpsrv gets loaded during rsyslog startup BEFORE * it forks, in which case the workers would be running in the then-killed parent, * leading to a defuncnt child (we actually had this bug). * 2. depending on circumstances, Run() would possibly never be called, in which case * the worker threads would be totally useless. * Note that in order to guarantee a non-racy worker start, we need to guard the * startup sequence by a mutex, which is why we init it here (no problem with fork() * in this case as the mutex is a pure-memory structure). * rgerhards, 2012-05-18 */ pthread_mutex_init(&wrkrMut, NULL); bWrkrRunning = 0; /* Initialize all classes that are in our module - this includes ourselfs */ CHKiRet(tcps_sessClassInit(pModInfo)); CHKiRet(tcpsrvClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ ENDmodInit rsyslog-8.2412.0/runtime/wti.h0000664000175000017500000001412014650736301011577 /* 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. */ /* 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 *pbShutdownImmediate;/* end processing of this batch immediately if set to 1 */ 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) */ } execState; /* state for the execution engine */ }; /* 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 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); } rsRetVal wtiNewIParam(wti_t *const pWti, action_t *const pAction, actWrkrIParams_t **piparams); #endif /* #ifndef WTI_H_INCLUDED */ rsyslog-8.2412.0/runtime/strgen.h0000664000175000017500000000431014650736301012276 /* header for strgen.c * * 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 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 */ PROTOTYPEObj(strgen); #endif /* #ifndef INCLUDED_STRGEN_H */ rsyslog-8.2412.0/runtime/dnscache.c0000664000175000017500000003334114704407366012553 /* 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++; } 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)); 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[80]; /* large enough for IPv6 */ 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) { strcpy(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.2412.0/runtime/var.h0000664000175000017500000000333514650736301011572 /* The var object. * * 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_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 */ PROTOTYPEObj(var); #endif /* #ifndef INCLUDED_VAR_H */ rsyslog-8.2412.0/runtime/zstdw.h0000664000175000017500000000313514650736301012153 /* 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.2412.0/runtime/lmcry_ossl.c0000664000175000017500000002001614704407366013164 /* 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")) { 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")) { 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")) { 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.2412.0/runtime/dynstats.c0000664000175000017500000004477614650736301012664 /* * 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 "srUtils.h" #include "errmsg.h" #include "rsconf.h" #include "unicode-helper.h" /* definitions for objects we access */ DEFobjStaticHelpers DEFobjCurrIf(statsobj) #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_DEFAULT_RESETTABILITY 1 #define DYNSTATS_DEFAULT_MAX_CARDINALITY 2000 #define DYNSTATS_DEFAULT_UNUSED_METRIC_LIFE 3600 /* seconds */ #define DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH 100 #define DYNSTATS_METRIC_NAME_SEPARATOR '.' #define DYNSTATS_HASHTABLE_SIZE_OVERPROVISIONING 1.25 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 */ }; static struct cnfparamblk modpblk = { CNFPARAMBLK_VERSION, sizeof(modpdescr)/sizeof(struct cnfparamdescr), modpdescr }; rsRetVal dynstatsClassInit(void) { DEFiRet; CHKiRet(objGetObjInterface(&obj)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); finalize_it: RETiRet; } static void dynstats_destroyCtr(dynstats_ctr_t *ctr) { statsobj.DestructUnlinkedCounter(ctr->pCtr); free(ctr->metric); free(ctr); } 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 /* assumes exclusive access to bucket */ dynstats_destroyCounters(dynstats_bucket_t *b) { statsobj.UnlinkAllCounters(b->stats); dynstats_destroyCountersIn(b, b->table, b->ctrs); } static void dynstats_destroyBucket(dynstats_buckets_t *bkts, dynstats_bucket_t* b) { pthread_rwlock_wrlock(&b->lock); dynstats_destroyCounters(b); dynstats_destroyCountersIn(b, b->survivor_table, b->survivor_ctrs); statsobj.Destruct(&b->stats); free(b->name); pthread_rwlock_unlock(&b->lock); pthread_rwlock_destroy(&b->lock); pthread_mutex_destroy(&b->mutMetricCount); statsobj.DestructCounter(bkts->global_stats, b->pOpsOverflowCtr); statsobj.DestructCounter(bkts->global_stats, b->pNewMetricAddCtr); statsobj.DestructCounter(bkts->global_stats, b->pNoMetricCtr); statsobj.DestructCounter(bkts->global_stats, b->pMetricsPurgedCtr); statsobj.DestructCounter(bkts->global_stats, b->pOpsIgnoredCtr); statsobj.DestructCounter(bkts->global_stats, b->pPurgeTriggeredCtr); free(b); } static rsRetVal dynstats_addBucketMetrics(dynstats_buckets_t *bkts, dynstats_bucket_t *b, const uchar* name) { uchar *metric_name_buff, *metric_suffix; const uchar *suffix_litteral; int name_len; DEFiRet; name_len = ustrlen(name); CHKmalloc(metric_name_buff = malloc((name_len + DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH + 1) * sizeof(uchar))); strcpy((char*)metric_name_buff, (char*)name); metric_suffix = metric_name_buff + name_len; *metric_suffix = DYNSTATS_METRIC_NAME_SEPARATOR; metric_suffix++; suffix_litteral = UCHAR_CONSTANT("ops_overflow"); ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_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)); suffix_litteral = UCHAR_CONSTANT("new_metric_add"); ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrNewMetricAdd, b->mutCtrNewMetricAdd); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrNewMetricAdd), &b->pNewMetricAddCtr, 1)); suffix_litteral = UCHAR_CONSTANT("no_metric"); ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrNoMetric, b->mutCtrNoMetric); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrNoMetric), &b->pNoMetricCtr, 1)); suffix_litteral = UCHAR_CONSTANT("metrics_purged"); ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrMetricsPurged, b->mutCtrMetricsPurged); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrMetricsPurged), &b->pMetricsPurgedCtr, 1)); suffix_litteral = UCHAR_CONSTANT("ops_ignored"); ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrOpsIgnored, b->mutCtrOpsIgnored); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrOpsIgnored), &b->pOpsIgnoredCtr, 1)); suffix_litteral = UCHAR_CONSTANT("purge_triggered"); ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrPurgeTriggered, b->mutCtrPurgeTriggered); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrPurgeTriggered), &b->pPurgeTriggeredCtr, 1)); finalize_it: free(metric_name_buff); if (iRet != RS_RET_OK) { if (b->pOpsOverflowCtr != NULL) { statsobj.DestructCounter(bkts->global_stats, b->pOpsOverflowCtr); } if (b->pNewMetricAddCtr != NULL) { statsobj.DestructCounter(bkts->global_stats, b->pNewMetricAddCtr); } if (b->pNoMetricCtr != NULL) { statsobj.DestructCounter(bkts->global_stats, b->pNoMetricCtr); } if (b->pMetricsPurgedCtr != NULL) { statsobj.DestructCounter(bkts->global_stats, b->pMetricsPurgedCtr); } if (b->pOpsIgnoredCtr != NULL) { statsobj.DestructCounter(bkts->global_stats, b->pOpsIgnoredCtr); } if (b->pPurgeTriggeredCtr != NULL) { statsobj.DestructCounter(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"))); statsobj.SetReadNotifier(b->stats, dynstats_readCallback, b); CHKiRet(statsobj.ConstructFinalize(b->stats)); finalize_it: RETiRet; } static rsRetVal dynstats_newBucket(const uchar* name, uint8_t resettable, uint32_t maxCardinality, uint32_t unusedMetricLife) { dynstats_bucket_t *b; dynstats_buckets_t *bkts; uint8_t lock_initialized, metric_count_mutex_initialized; pthread_rwlockattr_t bucket_lock_attr; DEFiRet; lock_initialized = metric_count_mutex_initialized = 0; b = NULL; bkts = &loadConf->dynstats_buckets; if (bkts->initialized) { CHKmalloc(b = calloc(1, sizeof(dynstats_bucket_t))); b->resettable = resettable; b->maxCardinality = maxCardinality; b->unusedMetricLife = 1000 * unusedMetricLife; CHKmalloc(b->name = ustrdup(name)); 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; CHKiRet(dynstats_initNewBucketStats(b)); CHKiRet(dynstats_resetBucket(b)); CHKiRet(dynstats_addBucketMetrics(bkts, b, name)); 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 (metric_count_mutex_initialized) { pthread_mutex_destroy(&b->mutMetricCount); } if (lock_initialized) { pthread_rwlock_destroy(&b->lock); } if (b != NULL) { dynstats_destroyBucket(bkts, b); } } RETiRet; } rsRetVal dynstats_processCnf(struct cnfobj *o) { struct cnfparamvals *pvals; short i; uchar *name = NULL; uint8_t resettable = DYNSTATS_DEFAULT_RESETTABILITY; uint32_t maxCardinality = DYNSTATS_DEFAULT_MAX_CARDINALITY; uint32_t unusedMetricLife = DYNSTATS_DEFAULT_UNUSED_METRIC_LIFE; 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 { dbgprintf("dyn_stats: program error, non-handled " "param '%s'\n", modpblk.descr[i].name); } } if (name != NULL) { CHKiRet(dynstats_newBucket(name, resettable, maxCardinality, unusedMetricLife)); } finalize_it: free(name); 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; finalize_it: if (iRet != RS_RET_OK) { statsobj.Destruct(&bkts->global_stats); } RETiRet; } void dynstats_destroyAllBuckets(void) { dynstats_buckets_t *bkts; dynstats_bucket_t *b; bkts = &runConf->dynstats_buckets; if (bkts->initialized) { pthread_rwlock_wrlock(&bkts->lock); while(1) { b = bkts->list; if (b == NULL) { break; } else { bkts->list = b->next; dynstats_destroyBucket(bkts, b); } } statsobj.Destruct(&bkts->global_stats); pthread_rwlock_unlock(&bkts->lock); pthread_rwlock_destroy(&bkts->lock); } } 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; } #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) { dynstats_ctr_t *ctr; dynstats_ctr_t *found_ctr, *survivor_ctr, *effective_ctr; int created; uchar *copy_of_key = NULL; DEFiRet; created = 0; ctr = NULL; if ((unsigned) ATOMIC_FETCH_32BIT_unsigned(&b->metricCount, &b->mutMetricCount) >= b->maxCardinality) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } CHKiRet(dynstats_createCtr(b, metric, &ctr)); pthread_rwlock_wrlock(&b->lock); 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; } } if ((created = hashtable_insert(b->table, copy_of_key, effective_ctr))) { 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); } } } pthread_rwlock_unlock(&b->lock); 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 (((! created) || (effective_ctr != ctr)) && (ctr != NULL)) { dynstats_destroyCtr(ctr); } RETiRet; } #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop #endif rsRetVal dynstats_inc(dynstats_bucket_t *b, uchar* metric) { dynstats_ctr_t *ctr; 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)); } 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; } rsyslog-8.2412.0/runtime/strgen.c0000664000175000017500000001670114650736301012300 /* 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; /* intialize (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; } PROTOTYPEobjDestruct(strgen); 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.2412.0/runtime/netstrms.h0000664000175000017500000001051714656663250012671 /* Definitions for the stream-based netstrmsworking class. * * Copyright 2007-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. */ #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 */ uchar *pszDrvrPermitExpiredCerts; const uchar *pszDrvrCAFile; const uchar *pszDrvrCRLFile; const uchar *pszDrvrKeyFile; const uchar *pszDrvrCertFile; uchar *gnutlsPriorityString; /**< priorityString for connection */ 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); int (*GetDrvrTlsVerifyDepth)(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); ENDinterface(netstrms) #define netstrmsCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObj(netstrms); /* the name of our library binary */ #define LM_NETSTRMS_FILENAME "lmnetstrms" #endif /* #ifndef INCLUDED_NETSTRMS_H */ rsyslog-8.2412.0/runtime/tcps_sess.c0000664000175000017500000004564714650736301013017 /* 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-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. */ #include "config.h" #include #include #include #include #include #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) /* forward definitions */ static rsRetVal Close(tcps_sess_t *pThis); /* Standard-Constructor */ BEGINobjConstruct(tcps_sess) /* be sure to specify the object type also in END macro! */ 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... */ /* now allocate the message reception buffer */ CHKmalloc(pThis->pMsg = (uchar*) malloc(pThis->iMaxLine + 1)); finalize_it: ENDobjConstruct(tcps_sess) /* ConstructionFinalizer */ static rsRetVal tcps_sessConstructFinalize(tcps_sess_t __attribute__((unused)) *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); if(pThis->pSrv->OnSessConstructFinalize != NULL) { CHKiRet(pThis->pSrv->OnSessConstructFinalize(&pThis->pUsr)); } finalize_it: RETiRet; } /* 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) if(pThis->pStrm != NULL) netstrm.Destruct(&pThis->pStrm); if(pThis->pSrv->pOnSessDestruct != NULL) { pThis->pSrv->pOnSessDestruct(&pThis->pUsr); } /* now destruct our own properties */ if(pThis->fromHost != NULL) CHKiRet(prop.Destruct(&pThis->fromHost)); if(pThis->fromHostIP != NULL) CHKiRet(prop.Destruct(&pThis->fromHostIP)); free(pThis->pMsg); 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 SetStrm(tcps_sess_t *pThis, netstrm_t *pStrm) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); pThis->pStrm = pStrm; 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; 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; 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; MsgSetRcvFrom(pMsg, pThis->fromHost); CHKiRet(MsgSetRcvFromIP(pMsg, pThis->fromHostIP)); MsgSetRuleset(pMsg, cnf_params->pRuleset); STATSCOUNTER_INC(pThis->pLstnInfo->ctrSubmit, pThis->pLstnInfo->mutCtrSubmit); ratelimitAddMsg(pThis->pLstnInfo->ratelimiter, pMultiSub, pMsg); finalize_it: /* reset status variables */ pThis->iMsg = 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 * fragement. If evrything goes well, we must be right at the * beginnig 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); 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; } /* Closes a TCP session * No attention is paid to the return code * of close, so potential-double closes are not detected. */ static rsRetVal Close(tcps_sess_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); 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, const char c, struct syslogTime *stTime, const time_t ttGenTime, multi_submit_t *pMultiSub, unsigned *const __restrict__ pnMsgs) { DEFiRet; const tcpLstnParams_t *const cnf_params = pThis->pLstnInfo->cnf_params; ISOBJ_TYPE_assert(pThis, tcps_sess); if(pThis->inputState == eAtStrtFram) { if(c >= '0' && c <= '9' && pThis->bSuppOctetFram) { pThis->inputState = eInOctetCnt; 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->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? */ 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); 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 */ uchar *propPeerName = NULL; uchar *propPeerIP = NULL; int lenPeerName = 0; int lenPeerIP = 0; DBGPRINTF("TCP Message with octet-counter, size %d.\n", pThis->iOctetsRemain); prop.GetString(pThis->fromHost, &propPeerName, &lenPeerName); prop.GetString(pThis->fromHost, &propPeerIP, &lenPeerIP); if(c != ' ') { LogError(0, NO_ERRCODE, "imtcp %s: Framing Error in received TCP message from " "peer: (hostname) %s, (ip) %s: delimiter is not SP but has " "ASCII value %d.", cnf_params->pszInputName, propPeerName, propPeerIP, c); } if(pThis->iOctetsRemain < 1) { /* TODO: handle the case where the octet count is 0! */ LogError(0, NO_ERRCODE, "imtcp %s: Framing Error in received TCP message from " "peer: (hostname) %s, (ip) %s: invalid octet count %d.", cnf_params->pszInputName, propPeerName, propPeerIP, pThis->iOctetsRemain); pThis->eFraming = TCP_FRAMING_OCTET_STUFFING; } else if(pThis->iOctetsRemain > pThis->iMaxLine) { /* 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: size is %d bytes, max msg size " "is %d, truncating...", cnf_params->pszInputName, propPeerName, propPeerIP, 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: frame too large: %d, change " "to octet stuffing", cnf_params->pszInputName, propPeerName, propPeerIP, 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. Acutally, * 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 DataRcvd(tcps_sess_t *pThis, char *pData, const size_t iLen) { 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); 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 intensional */ while(pData < pEnd) { CHKiRet(processDataRcvd(pThis, *pData++, &stTime, ttGenTime, &multiSub, &nMsgs)); } iRet = multiSubmitFlush(&multiSub); if(runConf->globals.senderKeepTrack) statsRecordSender(propGetSzStr(pThis->fromHost), nMsgs, ttGenTime); finalize_it: RETiRet; } #undef NUM_MULTISUB /* 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->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); 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)); 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.2412.0/runtime/net.h0000664000175000017500000001604014650736301011565 /* 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 */ 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); 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 (*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 */ ENDinterface(net) #define netCURR_IF_VERSION 10 /* 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.2412.0/runtime/nsdsel_gtls.h0000664000175000017500000000273414650736301013325 /* An implementation of the nsd select interface for GnuTLS. * * Copyright (C) 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_NSDSEL_GTLS_H #define INCLUDED_NSDSEL_GTLS_H #include "nsd.h" typedef nsdsel_if_t nsdsel_gtls_if_t; /* we just *implement* this interface */ /* the nsdsel_gtls object */ struct nsdsel_gtls_s { BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */ nsdsel_t *pTcp; /* our aggregated ptcp sel handler (which does almost everything) */ int iBufferRcvReady; /* number of descriptiors where no RD select is needed because we have data in buf */ }; /* interface is defined in nsd.h, we just implement it! */ #define nsdsel_gtlsCURR_IF_VERSION nsdCURR_IF_VERSION /* prototypes */ PROTOTYPEObj(nsdsel_gtls); #endif /* #ifndef INCLUDED_NSDSEL_GTLS_H */ rsyslog-8.2412.0/runtime/obj.c0000664000175000017500000011540214723322534011546 /* 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-2019 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 /* TODO change to a linked list? info: 16 were currently in use 2008-02-29 */ #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" /* 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] != 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] = pConstruct; pThis->objMethods[1] = pDestruct; for(i = 2 ; i < OBJ_NUM_METHODS ; ++i) { pThis->objMethods[i] = 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] = 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), (long) *((short*) pUsr))); pszBuf = szBuf; lenBuf = ustrlen(szBuf); vType = VARTYPE_NUMBER; break; case PROPTYPE_INT: CHKiRet(srUtilItoA((char*) szBuf, sizeof(szBuf), (long) *((int*) pUsr))); pszBuf = szBuf; lenBuf = ustrlen(szBuf); vType = VARTYPE_NUMBER; break; case PROPTYPE_LONG: CHKiRet(srUtilItoA((char*) szBuf, sizeof(szBuf), *((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(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; } /* 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)(), 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)); /* re-init var object - TODO: method of var! */ rsCStrDestruct(&pVar->pcsName); /* no longer needed */ if(pVar->varType == VARTYPE_STR) { if(pVar->val.pStr != NULL) rsCStrDestruct(&pVar->val.pStr); } 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))) /* TODO: optimize strlen() - caller shall provide */ 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, 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)(), rsRetVal (*objConstructFinalize)(), rsRetVal (*objDeserialize)()) { 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(&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, 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 */ static rsRetVal UseObj(const char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf) { DEFiRet; objInfo_t *pObjInfo; #if DEV_DEBUG == 1 dbgprintf("source file %s requests object '%s', " " ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded); #endif pthread_mutex_lock(&mutObjGlobalOp); if(pIf->ifIsLoaded == 1) { ABORT_FINALIZE(RS_RET_OK); /* we are already set */ } if(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 */ 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 */ } CHKiRet(pObjInfo->QueryIF(pIf)); pIf->ifIsLoaded = 1; /* we are happy */ 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, 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(pIf->ifIsLoaded == 0) { FINALIZE; /* we are not loaded - this is perfectly OK... */ } else if(pIf->ifIsLoaded == 2) { pIf->ifIsLoaded = 0; /* clean up */ 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 */ pIf->ifIsLoaded = 0; /* indicated "no longer valid" */ 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.2412.0/runtime/cryprov.h0000664000175000017500000000406414650736301012506 /* 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.2412.0/runtime/lib_ksils12.h0000664000175000017500000002366014650736301013123 /* 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.2412.0/runtime/hashtable_itr.h0000664000175000017500000000753414650736301013620 /* 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.2412.0/runtime/lib_ksils12.c0000664000175000017500000016215014650736301013114 /* 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; 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; 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 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(rnd_device, O_RDONLY)) >= 0) { if(read(fd, ksi->IV, hashlen) == hashlen) {}; /* keep compiler happy */ 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); //TODO: maybe milli/nanoseconds should be used 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 */ /* TODO: this need more elegant solution, hash should be detached from creation context*/ 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.2412.0/runtime/hashtable_private.h0000664000175000017500000000526014650736301014466 /* 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.2412.0/runtime/rsconf.c0000664000175000017500000015360114723322534012271 /* 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 "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" extern char* yytext; /* 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!) */ /* 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"; /* 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 }; /* forward-definitions */ void cnfDoCfsysline(char *ln); 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.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->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.glblDevOptions = 0; pThis->globals.intMsgRateLimitItv = 5; pThis->globals.intMsgRateLimitBurst = 500; 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.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(llInit(&pThis->rulesets.llRulesets, rulesetDestructForLinkedList, rulesetKeyDestruct, 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 AND free the module entries themselfes. */ static void freeCnf(rsconf_t *pThis) { cfgmodules_etry_t *etry, *del; 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); } del = etry; etry = etry->next; free(del); } } /* destructor for the rsconf object */ PROTOTYPEobjDestruct(rsconf); BEGINobjDestruct(rsconf) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(rsconf) freeCnf(pThis); tplDeleteAll(pThis); dynstats_destroyAllBuckets(); 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(); llDestroy(&(pThis->rulesets.llRulesets)); 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(); // TODO: The following code needs to be "streamlined", so far just moved over... 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); /* TODO: add iActionRetryCount = 0; iActionRetryInterval = 30000; static int iMainMsgQtoWrkMinMsgs = 100; static int iMainMsgQbSaveOnShutdown = 1; iMainMsgQueMaxDiskSpace = 0; setQPROP(qqueueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", 100); setQPROP(qqueueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", 1); */ 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; } /*------------------------------ interface to flex/bison parser ------------------------------*/ extern int yylineno; 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; } 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_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) { dbgprintf("cnf:global:script\n"); ruleset.AddScript(ruleset.GetCurrent(loadConf), script); } void cnfDoCfsysline(char *ln) { DBGPRINTF("cnf:global:cfsysline: %s\n", ln); /* the legacy system needs the "$" stripped */ conf.cfsysline((uchar*) ln+1); free(ln); } void cnfDoBSDTag(char *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) { 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 * if something goes wrong, the function never returns */ 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"); 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()", 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 * if something goes wrong, the function never returns * Note that such an abort can cause damage to on-disk structures, so we should * re-design the "interface" in the long term. -- rgerhards, 2008-11-19 */ static void doDropPrivUid(rsconf_t *cnf) { int res; uchar szBuf[1024]; struct passwd *pw; gid_t gid; /* 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); 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) { /* if we can not set the userid, this is fatal, so let's unconditionally abort */ perror("could not set requested userid"); exit(1); } 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); } /* 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) { 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 */ } /* 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); /* 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); } /* 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, "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 -------------------- */ /* set the processes max number ob files (upon configuration request) * 2009-04-14 rgerhards */ static rsRetVal setMaxFiles(void __attribute__((unused)) *pVal, int iFiles) { // TODO this must use a local var, then carry out action during activate! struct rlimit maxFiles; char errStr[1024]; DEFiRet; 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! */ rs_strerror_r(errno, errStr, sizeof(errStr)); LogError(0, RS_RET_ERR_RLIM_NOFILE, "could not set process file limit to %d: %s " "[kernel max %ld]", iFiles, errStr, (long) maxFiles.rlim_max); ABORT_FINALIZE(RS_RET_ERR_RLIM_NOFILE); } #ifdef USE_UNLIMITED_SELECT glbl.SetFdSetSize(howmany(iFiles, __NFDBITS) * sizeof (fd_mask)); #endif DBGPRINTF("Max number of files set to %d [kernel max %ld].\n", iFiles, (long) maxFiles.rlim_max); finalize_it: RETiRet; } /* 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); 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; } /* intialize 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, eCmdHdlrInt, 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_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_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' 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' 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 */ r = cnfSetLexFile((char*)confFile); if(r == 0) { r = yyparse(); 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(validateConf(loadConf)); CHKiRet(loadMainQueue()); /* we are done checking the config - now validate if we should actually run or not. * If not, terminate. -- rgerhards, 2008-07-25 * TODO: iConfigVerify -- should it be pulled from the config, or leave as is (option)? */ if(iConfigVerify) { if(iRet == RS_RET_OK) iRet = RS_RET_VALIDATION_RUN; FINALIZE; } /* all OK, pass loaded conf to caller */ *cnf = loadConf; // TODO: enable this once all config code is moved to here! loadConf = NULL; 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.2412.0/runtime/zlibw.c0000664000175000017500000001626414650736301012131 /* 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 ressources - 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) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit 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.2412.0/runtime/objomsr.c0000664000175000017500000001011414650736301012441 /* 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; RETiRet; } /* vim:set ai: */ rsyslog-8.2412.0/runtime/wtp.c0000664000175000017500000005112614704407366011616 /* 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 aquainted to the object. * * Copyright 2008-2018 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 /// TODO: check on solaris if this is any longer needed - I don't think so - rgerhards, 2009-09-20 //#ifdef OS_SOLARIS //# 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! */ 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)); 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) /* Sent a specific state for the worker thread pool. -- rgerhards, 2008-01-21 * We do not need to do atomic instructions as set operations are only * called when terminating the pool, and then in strict sequence. So we * can never overwrite each other. On the other hand, it also doesn't * matter if the read operation obtains an older value, as we then simply * do one more iteration, what is perfectly legal (during shutdown * they are awoken in any case). -- rgerhards, 2009-07-20 */ rsRetVal wtpSetState(wtp_t *pThis, wtpState_t iNewState) { ISOBJ_TYPE_assert(pThis, wtp); pThis->wtpState = iNewState; // TODO: do we need a mutex here? 2010-04-26 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 fetch - then we simply do one more iteration in the worker */ wtpState = (wtpState_t) ATOMIC_FETCH_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; while(pThis->iCurNumWrkThrd > 0 && !bTimedOut) { wtpJoinTerminatedWrkr(pThis); DBGPRINTF("%s: waiting %ldms on worker thread termination, %d still running\n", wtpGetDbgHdr(pThis), timeoutVal(ptTimeout), ATOMIC_FETCH_32BIT(&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]); } } 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_FETCH_32BIT(&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); # 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); wtiSetState(pWti, WRKTHRD_RUNNING); pthread_cond_broadcast(&pThis->condThrdInitDone); d_pthread_mutex_unlock(&pThis->mutWtp); pthread_cleanup_push(wtpWrkrExecCancelCleanup, pWti); 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_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd)); } const wtpState_t wtpState = (wtpState_t) ATOMIC_FETCH_32BIT((int*)&pThis->wtpState, &pThis->mutWtpState); if(wtpState != wtpState_RUNNING && !permit_during_shutdown) { 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! */ } d_pthread_mutex_lock(&pThis->mutWtp); wtpJoinTerminatedWrkr(pThis); /* find free spot in thread table. */ for(i = 0 ; i < pThis->iNumWorkerThreads ; ++i) { if(wtiGetState(pThis->pWrkr[i]) == WRKTHRD_STOPPED) { break; } } if(i == pThis->iNumWorkerThreads) ABORT_FINALIZE(RS_RET_NO_MORE_THREADS); if(i == 0 || pThis->toWrkShutdown == -1) { wtiSetAlwaysRunning(pThis->pWrkr[i]); } pWti = pThis->pWrkr[i]; wtiSetState(pWti, WRKTHRD_INITIALIZING); iState = pthread_create(&(pWti->thrdID), &pThis->attrThrd, wtpWorker, (void*) pWti); 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_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd)); } DBGPRINTF("%s: started with state %d, num workers now %d\n", wtpGetDbgHdr(pThis), iState, ATOMIC_FETCH_32BIT(&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_FETCH_32BIT(&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_FETCH_32BIT(&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; nMissing = nMaxWrkr - ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd); if(nMissing > 0) { if(ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd) > 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, ATOMIC_FETCH_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd) ); } /* 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; } /* some simple object access methods */ DEFpropSetMeth(wtp, toWrkShutdown, 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*)) /* 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(nsdsel_gtls) /* 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.2412.0/runtime/lookup.c0000664000175000017500000007532014704407366012317 /* 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" PRAGMA_IGNORE_Wdeprecated_declarations /* definitions for objects we access */ DEFobjStaticHelpers DEFobjCurrIf(glbl) /* 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_tbl_reloader:"; static void * lookupTableReloader(void *self); static void lookupStopReloader(lookup_ref_t *pThis); /* create a new lookup table object AND include it in our list of * lookup tables. */ 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->do_stop = 0; pThis->reload_on_hup = 1; /*DO reload on HUP (default)*/ 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; 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)); initialized++; /*1*/ CHKiConcCtrl(pthread_mutex_init(&pThis->reloader_mut, NULL)); initialized++; /*2*/ CHKiConcCtrl(pthread_cond_init(&pThis->run_reloader, NULL)); initialized++; /*3*/ CHKiConcCtrl(pthread_attr_init(&pThis->reloader_thd_attr)); initialized++; /*4*/ pThis->do_reload = pThis->do_stop = 0; CHKiConcCtrl(pthread_create(&pThis->reloader, &pThis->reloader_thd_attr, lookupTableReloader, pThis)); 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); /* Can not happen with current code, but might occur in the future when * an error-condition as added after step 5. If we leave it in, Coverity * scan complains. So we comment it out but do not remove the code. * Triggered by CID 185426 if (initialized > 4) lookupStopReloader(pThis); */ if (initialized > 3) pthread_attr_destroy(&pThis->reloader_thd_attr); if (initialized > 2) pthread_cond_destroy(&pThis->run_reloader); if (initialized > 1) pthread_mutex_destroy(&pThis->reloader_mut); if (initialized > 0) pthread_rwlock_destroy(&pThis->rwlock); } 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->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) { lookupStopReloader(pThis); pthread_mutex_destroy(&pThis->reloader_mut); pthread_cond_destroy(&pThis->run_reloader); pthread_attr_destroy(&pThis->reloader_thd_attr); 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); } 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); } 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); } 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; } return first_value - second_value; } 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; } return first_value - second_value; } /* 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; } return key - array_member_value; } 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)); } /* 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); } indexes[i].index = (uint32_t) json_object_get_int(jindex); 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); } pThis->table.sprsArr->entries[i].key = (uint32_t) json_object_get_int(jindex); 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; } 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 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"; } 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", &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 'value' field", table_type, name); 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)); } 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; 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() lookupDoReload(lookup_ref_t *pThis) { DEFiRet; iRet = lookupReloadOrStub(pThis, NULL); if ((iRet != RS_RET_OK) && (pThis->stub_value_for_reload_failure != NULL)) { iRet = lookupDoStub(pThis, pThis->stub_value_for_reload_failure); } freeStubValueForReloadFailure(pThis); RETiRet; } void * lookupTableReloader(void *self) { lookup_ref_t *pThis = (lookup_ref_t*) self; pthread_mutex_lock(&pThis->reloader_mut); while(1) { if (pThis->do_stop) { break; } else if (pThis->do_reload) { lookupDoReload(pThis); pThis->do_reload = 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; lookup_t *t; pthread_rwlock_rdlock(&pThis->rwlock); t = pThis->self; estr = t->lookup(t, key); pthread_rwlock_unlock(&pThis->rwlock); return estr; } /* 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); } 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; short i; #ifdef HAVE_PTHREAD_SETNAME_NP char *reloader_thd_name = NULL; int thd_name_len = 0; #endif 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); CHKiRet(lookupNew(&lu)); for(i = 0 ; i < modpblk.nParams ; ++i) { if(!pvals[i].bUsed) continue; if(!strcmp(modpblk.descr[i].name, "file")) { CHKmalloc(lu->filename = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if(!strcmp(modpblk.descr[i].name, "name")) { CHKmalloc(lu->name = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if(!strcmp(modpblk.descr[i].name, "reloadOnHUP")) { lu->reload_on_hup = (pvals[i].val.d.n != 0); } else { dbgprintf("lookup_table: program error, non-handled " "param '%s'\n", modpblk.descr[i].name); } } 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 :-( */ if(lu_name == NULL || lu_filename == NULL) { iRet = RS_RET_INTERNAL_ERROR; LogError(0, iRet, "internal error: lookup table name not set albeit being mandatory"); ABORT_FINALIZE(iRet); } #ifdef HAVE_PTHREAD_SETNAME_NP thd_name_len = ustrlen(lu_name) + strlen(reloader_prefix) + 1; CHKmalloc(reloader_thd_name = malloc(thd_name_len)); strcpy(reloader_thd_name, reloader_prefix); strcpy(reloader_thd_name + strlen(reloader_prefix), (char*) lu_name); reloader_thd_name[thd_name_len - 1] = '\0'; #if defined(__NetBSD__) pthread_setname_np(lu->reloader, "%s", reloader_thd_name); #elif defined(__APPLE__) pthread_setname_np(reloader_thd_name); // must check #else pthread_setname_np(lu->reloader, reloader_thd_name); #endif #endif 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: #ifdef HAVE_PTHREAD_SETNAME_NP free(reloader_thd_name); #endif cnfparamvalsDestruct(pvals, &modpblk); if (iRet != RS_RET_OK) { if (lu != NULL) { lookupDestruct(lu->self); lu->self = NULL; } } 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.2412.0/runtime/stringbuf.c0000664000175000017500000005150714723322534013004 /* 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-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. */ #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); /* does the string fit? */ if(pThis->iStrLen + iStrLen >= pThis->iBufSize) { CHKiRet(rsCStrExtendBuf(pThis, iStrLen)); /* 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; } /* 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), 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; 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) { rsCHECKVALIDOBJECT(pThis, OIDrsCStr); 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 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; /* 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 = (pThis->iStrLen >= len_sz) ? 0 : 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.2412.0/runtime/wtp.h0000664000175000017500000001066614650736301011621 /* 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) */ 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); /* 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); 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*)); PROTOTYPEpropSetMeth(wtp, toWrkShutdown, 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.2412.0/runtime/debug.c0000664000175000017500000003266214650736301012070 /* 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 __attribute__((unused))) { # if 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); # 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.2412.0/runtime/statsobj.h0000664000175000017500000001671214650736301012636 /* The statsobj object. * * Copyright 2010-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. */ #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 } 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 /* 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 (*AddCounter)(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr); rsRetVal (*AddManagedCounter)(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr, ctr_t **ref, int8_t linked); void (*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 13 /* 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) */ /* prototypes */ PROTOTYPEObj(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_INC(ctr, mut) \ if(GatherStats) \ ATOMIC_INC_uint64(&ctr, &mut); #define STATSCOUNTER_ADD(ctr, mut, delta) \ if(GatherStats) \ ATOMIC_ADD_uint64(&ctr, &mut, delta); #define STATSCOUNTER_DEC(ctr, mut) \ if(GatherStats) \ ATOMIC_DEC_uint64(&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(GatherStats && ((newmax) > (ctr))) \ ctr = newmax; #endif /* #ifndef INCLUDED_STATSOBJ_H */ rsyslog-8.2412.0/runtime/libossl.h0000664000175000017500000000516214704407366012457 /* 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.2412.0/runtime/unicode-helper.h0000664000175000017500000000335014650736301013702 /* 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 #define ustrncpy(psz1, psz2, len) strncpy((char*)(psz1), (char*)(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.2412.0/runtime/nsd_ptcp.c0000664000175000017500000007757114723322534012624 /* nsd_ptcp.c * * An implementation of the nsd interface for plain tcp sockets. * * Copyright 2007-2024 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 "nsdsel_ptcp.h" #include "nsdpoll_ptcp.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 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; } /* 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; } /* 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; } /* accept an incoming connection request * rgerhards, 2008-04-22 */ static rsRetVal AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew) { 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); do { iNewSock = accept(pThis->sock, (struct sockaddr*) &addr, &addrlen); } while(iNewSock < 0 && (errno == EINTR || errno == EAGAIN)); if(iNewSock < 0) { LogMsg(errno, RS_RET_ACCEPT_ERR, LOG_WARNING, "nds_ptcp: error accepting connection on socket %d", pThis->sock); ABORT_FINALIZE(RS_RET_ACCEPT_ERR); } /* 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. TODO: we need to implement a new ACL module to get rid * of this function. -- rgerhards, 2008-12-01 */ 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); } } if(listen(sock, iSessMax / 10 + 5) < 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.SetTlsKeyFile(pNewNsd, netstrms.GetDrvrTlsKeyFile(pNS))); CHKiRet(pNS->Drvr.SetTlsCertFile(pNewNsd, netstrms.GetDrvrTlsCertFile(pNS))); CHKiRet(pNS->Drvr.SetTlsVerifyDepth(pNewNsd, netstrms.GetDrvrTlsVerifyDepth(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) { 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; if(*pLenBuf == 0) { ABORT_FINALIZE(RS_RET_CLOSED); } else if (*pLenBuf < 0) { 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, "imptcp 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, "imptcp 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, "imptcp cannot set keepalive intvl - ignored"); } dbgprintf("KEEPALIVE enabled for socket %d\n", pThis->sock); 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 hints; 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; if(getaddrinfo((char*)host, (char*)port, &hints, &res) != 0) { LogError(errno, RS_RET_IO_ERROR, "cannot resolve hostname '%s'", host); 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((pThis->sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) { LogError(errno, RS_RET_IO_ERROR, "cannot bind socket for %s:%s", host, port); ABORT_FINALIZE(RS_RET_IO_ERROR); } if(device) { # if defined(SO_BINDTODEVICE) if(setsockopt(pThis->sock, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) < 0) # endif { dbgprintf("setsockopt(SO_BINDTODEVICE) failed\n"); ABORT_FINALIZE(RS_RET_IO_ERROR); } } struct timeval start, end; long seconds, useconds; gettimeofday(&start, NULL); if(connect(pThis->sock, res->ai_addr, res->ai_addrlen) != 0) { gettimeofday(&end, NULL); seconds = end.tv_sec - start.tv_sec; useconds = end.tv_usec - start.tv_usec; LogError(errno, RS_RET_IO_ERROR, "cannot connect to %s:%s (took %ld.%ld 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; } /* 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->CheckConnection = CheckConnection; pIf->EnableKeepAlive = EnableKeepAlive; pIf->SetKeepAliveIntvl = SetKeepAliveIntvl; pIf->SetKeepAliveProbes = SetKeepAliveProbes; pIf->SetKeepAliveTime = SetKeepAliveTime; pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage; pIf->SetPrioritizeSAN = SetPrioritizeSAN; pIf->SetTlsVerifyDepth = SetTlsVerifyDepth; pIf->SetTlsCAFile = SetTlsCAFile; pIf->SetTlsCRLFile = SetTlsCRLFile; pIf->SetTlsKeyFile = SetTlsKeyFile; pIf->SetTlsCertFile = SetTlsCertFile; 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 # ifdef HAVE_EPOLL_CREATE /* module only available if epoll() is supported! */ nsdpoll_ptcpClassExit(); # endif nsdsel_ptcpClassExit(); 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 */ CHKiRet(nsdsel_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ # ifdef HAVE_EPOLL_CREATE /* module only available if epoll() is supported! */ CHKiRet(nsdpoll_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ # endif ENDmodInit /* vi:set ai: */ rsyslog-8.2412.0/runtime/datetime.c0000664000175000017500000012310114650736301012563 /* 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 ramge 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) /* TODO: check this: under HP UX, the tz information is actually valid * data. So we need to obtain and process it there. */ 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; } /** * 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 = tenPowers[(ts->secfracPrecision - 1) % 6]; secfrac = 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 = tenPowers[(ts->secfracPrecision - 1) % 6]; secfrac = 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 sring. * 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 termnator). 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 Mai 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 Oktober 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; } /** * 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 sprintf(pBuf, "%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 sprintf(pBuf, "%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->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.2412.0/runtime/queue.h0000664000175000017500000002706014717607330012132 /* Definition of the queue support module. * * Copyright 2008-2019 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 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" /* 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_t; /* list member definition for linked list types of queues: */ typedef struct qLinkedList_S { struct qLinkedList_S *pNext; smsg_t *pMsg; } qLinkedList_t; /* the queue object */ struct queue_s { BEGINobjInstance; queueType_t qType; int nLogDeq; /* number of elements currently logically dequeued */ int bShutdownImmediate; /* should all workers cease processing messages? */ 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; 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? */ 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); /* 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? */ 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 */ } disk; } 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(ctrFull, mutCtrFull) STATSCOUNTER_DEF(ctrFDscrd, mutCtrFDscrd) STATSCOUNTER_DEF(ctrNFDscrd, mutCtrNFDscrd) int ctrMaxqsize; /* NOT guarded by a mutex */ 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); #define qqueueGetID(pThis) ((unsigned long) pThis) #ifdef ENABLE_IMDIAG extern unsigned int iOverallQueueSize; #endif #endif /* #ifndef QUEUE_H_INCLUDED */ rsyslog-8.2412.0/runtime/janitor.c0000664000175000017500000000547414650736301012451 /* 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; /* TODO: move to runConf? */ 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.2412.0/runtime/nsdsel_ossl.h0000664000175000017500000000276514650736301013340 /* An implementation of the nsd select interface for OpenSSL. * * Copyright (C) 2018-2018 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_NSDSEL_OSSL_H #define INCLUDED_NSDSEL_OSSL_H #include "nsd.h" typedef nsdsel_if_t nsdsel_ossl_if_t; /* we just *implement* this interface */ /* the nsdsel_ossl object */ struct nsdsel_ossl_s { BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */ nsdsel_t *pTcp; /* our aggregated ptcp sel handler (which does almost everything) */ int iBufferRcvReady; /* number of descriptiors where no RD select is needed because we have data in buf */ }; /* interface is defined in nsd.h, we just implement it! */ #define nsdsel_osslCURR_IF_VERSION nsdCURR_IF_VERSION /* prototypes */ PROTOTYPEObj(nsdsel_ossl); #endif /* #ifndef INCLUDED_NSDSEL_OSSL_H */ rsyslog-8.2412.0/runtime/datetime.h0000664000175000017500000000750414650736301012600 /* 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); 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.2412.0/runtime/janitor.h0000664000175000017500000000226214650736301012446 /* 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.2412.0/runtime/nspoll.h0000664000175000017500000000472114723310736012312 /* Definitions for the nspoll io activity waiter * * Copyright 2009 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_NSPOLL_H #define INCLUDED_NSPOLL_H #include "netstrms.h" /* some operations to be portable when we do not have epoll() available */ #define NSDPOLL_ADD 1 #define NSDPOLL_DEL 2 /* and some mode specifiers for waiting on input/output */ #define NSDPOLL_IN 1 /* EPOLLIN */ #define NSDPOLL_OUT 2 /* EPOLLOUT */ /* next is 4, 8, 16, ... - must be bit values, as they are ored! */ /* the nspoll object */ struct nspoll_s { BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */ nsd_t *pDrvrData; /**< the driver's data elements */ uchar *pBaseDrvrName; /**< nsd base driver name to use, or NULL if system default */ uchar *pDrvrName; /**< full base driver name (set when driver is loaded) */ nsdpoll_if_t Drvr; /**< our stream driver */ }; /* interface */ BEGINinterface(nspoll) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(nspoll_t **ppThis); rsRetVal (*ConstructFinalize)(nspoll_t *pThis); rsRetVal (*Destruct)(nspoll_t **ppThis); rsRetVal (*Wait)(nspoll_t *pNsdpoll, int timeout, int *numEntries, nsd_epworkset_t workset[]); rsRetVal (*Ctl)(nspoll_t *pNsdpoll, netstrm_t *pStrm, int id, void *pUsr, int mode, int op); rsRetVal (*IsEPollSupported)(void); /* static method */ /* v3 - 2013-09-17 by rgerhards */ rsRetVal (*SetDrvrName)(nspoll_t *pThis, uchar *name); ENDinterface(nspoll) #define nspollCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */ /* interface change in v2 is that wait supports multiple return objects */ /* prototypes */ PROTOTYPEObj(nspoll); /* the name of our library binary */ #define LM_NSPOLL_FILENAME LM_NETSTRMS_FILENAME #endif /* #ifndef INCLUDED_NSPOLL_H */ rsyslog-8.2412.0/runtime/srutils.c0000664000175000017500000005753214650736301012512 /**\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-2018 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 "rsyslog.h" #include "srUtils.h" #include "obj.h" #include "errmsg.h" #include "glbl.h" #include "rsconf.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; } /* execute a program with a single argument * returns child pid if everything ok, 0 on failure. if * it fails, errno is set. if it fails after the fork(), the caller * can not be notfied for obvious reasons. if bwait is set to 1, * the code waits until the child terminates - that potentially takes * a lot of time. * implemented 2007-07-20 rgerhards */ int execProg(uchar *program, int bWait, uchar *arg) { int pid; int sig; struct sigaction sigAct; dbgprintf("exec program '%s' with param '%s'\n", program, arg); 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); execlp((char*)program, (char*) program, (char*)arg, NULL); /* 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' with param '%s'\n", program, arg); 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); snprintf(buf, buflen, "%s", pszErr); #else # ifdef STRERROR_R_CHAR_P char *p = strerror_r(errnum, buf, buflen); if (p != buf) { strncpy(buf, p, buflen); buf[buflen - 1] = '\0'; } # 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; uchar buf[80]; assert(name != NULL); assert(codetab != NULL); DBGPRINTF("symbolic name: %s", name); if(isdigit((int) *name)) { DBGPRINTF("\n"); return (atoi((char*) name)); } strncpy((char*) buf, (char*) name, 79); 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 = malloc((*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.2412.0/runtime/perctile_ringbuf.c0000664000175000017500000002125714650736301014323 /* * 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.2412.0/runtime/operatingstate.h0000664000175000017500000000212014650736301014022 /* 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.2412.0/runtime/obj-types.h0000664000175000017500000003740414717407614012730 /* 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-2019 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" /* 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])(); 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);\ 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 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); \ 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);\ 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);\ 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);\ 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 - when we use interfaces, we just have few * functions that actually need to be non-static. */ #define PROTOTYPEObj(obj) \ PROTOTYPEObjClassInit(obj); \ PROTOTYPEObjClassExit(obj); \ PROTOTYPEObjQueryInterface(obj) /* ------------------------------ end object loader system ------------------------------ */ #include "modules.h" #endif /* #ifndef OBJ_TYPES_H_INCLUDED */ rsyslog-8.2412.0/runtime/tcpsrv.h0000664000175000017500000002574414723310736012334 /* Definitions for tcpsrv class. * * Copyright 2008-2022 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 #include "obj.h" #include "prop.h" #include "net.h" #include "tcps_sess.h" #include "statsobj.h" /* support for framing anomalies */ typedef enum ETCPsyslogFramingAnomaly { frame_normal = 0, frame_NetScreen = 1, frame_CiscoIOS = 2 } eTCPsyslogFramingAnomaly; /* config parameters for TCP listeners */ 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 */ 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 */ }; /* 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) tcpLstnPortList_t *pNext; /**< next port or NULL */ }; #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 */ 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 */ // TODO: REMOVE ME!!!! 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 bUsingEPoll; /**< are we in epoll mode (means we do not need to keep track of sessions!) */ 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 */ tcpLstnPortList_t **ppLstnPort; /**< pointer to relevant listen port description */ 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*/ 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 */ unsigned int ratelimitInterval; unsigned int ratelimitBurst; tcps_sess_t **pSessions;/**< array of all of our sessions */ 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*); 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*); rsRetVal (*OnSessConstructFinalize)(void*); rsRetVal (*pOnSessDestruct)(void*); rsRetVal (*OnMsgReceive)(tcps_sess_t *, uchar *pszMsg, int iLenMsg); /* submit message callback */ }; /** * The following structure is a set of descriptors that need to be processed. * This set will be the result of the epoll or select call and be used * in the actual request processing stage. It serves as a basis * to run multiple request by concurrent threads. -- rgerhards, 2011-01-24 */ 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); 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 (*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*)); 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*)); 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 (accidently 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); /* 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); ENDinterface(tcpsrv) #define tcpsrvCURR_IF_VERSION 26 /* 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 */ PROTOTYPEObj(tcpsrv); /* the name of our library binary */ #define LM_TCPSRV_FILENAME "lmtcpsrv" #endif /* #ifndef INCLUDED_TCPSRV_H */ rsyslog-8.2412.0/runtime/stream.c0000664000175000017500000023142314650736301012271 /* 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); 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. */ /* do the physical open() call on a file. */ static rsRetVal doPhysOpen(strm_t *pThis) { int iFlags = 0; struct stat statOpen; 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; } if(pThis->bAsyncWrite)d_pthread_mutex_lock(&pThis->mut); pThis->fd = open((char*)pThis->pszCurrFName, iFlags | O_LARGEFILE, pThis->tOpenMode); if(pThis->bAsyncWrite) d_pthread_mutex_unlock(&pThis->mut); 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) { LogError(errno_save, errcode, "file '%s': open error", pThis->pszCurrFName); 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: 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->iMaxFiles != 0); assert(pThis->fd != -1); 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; } 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; zprevMsgSegment, 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->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; 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); 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. */ } *bytesDel += statBuf.st_size; DBGPRINTF("strmMultiFileSeek: detected new filenum, was %u, new %u, " "deleting '%s' (%lld bytes)\n", pThis->iCurrFNum, FNum, pThis->pszCurrFName, (long long) statBuf.st_size); 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), 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, 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, 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->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; } /* 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->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->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->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.2412.0/runtime/ratelimit.h0000664000175000017500000000436614650736301013001 /* header for ratelimit.c * * Copyright 2012-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. */ #ifndef INCLUDED_RATELIMIT_H #define INCLUDED_RATELIMIT_H struct ratelimit_s { char *name; /**< rate limiter name, e.g. for user messages */ /* support for Linux kernel-type ratelimiting */ unsigned int interval; unsigned int burst; intTiny severity; /**< ratelimit only equal or lower severity levels (eq or higher values) */ 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 */ pthread_mutex_t mut; /**< mutex if thread-safe operation desired */ }; /* prototypes */ rsRetVal ratelimitNew(ratelimit_t **ppThis, const char *modname, const char *dynname); 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, intTiny severity); rsRetVal ratelimitMsgCount(ratelimit_t *ratelimit, time_t tt, const char* const appname); rsRetVal ratelimitMsg(ratelimit_t *ratelimit, smsg_t *pMsg, smsg_t **ppRep); rsRetVal 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); #endif /* #ifndef INCLUDED_RATELIMIT_H */ rsyslog-8.2412.0/runtime/gss-misc.c0000664000175000017500000001731314650736301012523 /* 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 "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 int read_all(int fd, char *buf, unsigned int nbyte) { int ret; char *ptr; struct timeval tv; #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; ptr += ret, nbyte -= ret) { FD_ZERO(pRfds); FD_SET(fd, pRfds); tv.tv_sec = 1; tv.tv_usec = 0; if ((ret = select(FD_SETSIZE, pRfds, NULL, NULL, &tv)) <= 0 || !FD_ISSET(fd, pRfds)) { freeFdSet(pRfds); return ret; } 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); } } freeFdSet(pRfds); return (ptr - buf); } static int write_all(int fd, char *buf, unsigned int nbyte) { int ret; char *ptr; for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) { ret = send(fd, ptr, nbyte, 0); if (ret < 0) { if (errno == EINTR) continue; return (ret); } else if (ret == 0) { return (ptr - buf); } } return (ptr - buf); } static int recv_token(int s, gss_buffer_t tok) { int ret; unsigned char lenbuf[4] = "xxx"; // initialized to make clang static analyzer happy unsigned int len; ret = read_all(s, (char *) lenbuf, 4); 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; } len = ((lenbuf[0] << 24) | (lenbuf[1] << 16) | (lenbuf[2] << 8) | lenbuf[3]); tok->length = ntohl(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); if (ret < 0) { LogError(0, NO_ERRCODE, "GSS-API error reading token data"); free(tok->value); return -1; } else if (ret != (int) 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]; unsigned int len; if (tok->length > 0xffffffffUL) abort(); /* TODO: we need to reconsider this, abort() is not really a solution - degrade, but keep running */ len = htonl(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.2412.0/runtime/libcry_common.c0000664000175000017500000001034014660643541013627 /* 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 "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((*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. */ // TODO: highly unoptimized version, should be used in buffered // mode 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; *keylen = atoi(rcvBuf); if((*key = malloc(*keylen)) == NULL) { r = -1; goto done; } if((r = readProgKey(fd, *key, *keylen)) != 0) goto done; done: return r; } rsyslog-8.2412.0/runtime/nsdsel_ptcp.c0000664000175000017500000001456014650736301013315 /* nsdsel_ptcp.c * * An implementation of the nsd select() interface for plain tcp sockets. * * Copyright 2008-2018 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 "errmsg.h" #include "nsd_ptcp.h" #include "nsdsel_ptcp.h" #include "unlimited_select.h" #define FDSET_INCREMENT 1024 /* increment for struct pollfds array allocation */ /* static data */ DEFobjStaticHelpers DEFobjCurrIf(glbl) /* Standard-Constructor */ BEGINobjConstruct(nsdsel_ptcp) /* be sure to specify the object type also in END macro! */ pThis->currfds = 0; pThis->maxfds = FDSET_INCREMENT; CHKmalloc(pThis->fds = calloc(FDSET_INCREMENT, sizeof(struct pollfd))); finalize_it: ENDobjConstruct(nsdsel_ptcp) /* destructor for the nsdsel_ptcp object */ BEGINobjDestruct(nsdsel_ptcp) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(nsdsel_ptcp) free(pThis->fds); ENDobjDestruct(nsdsel_ptcp) /* Add a socket to the select set */ static rsRetVal ATTR_NONNULL() Add(nsdsel_t *const pNsdsel, nsd_t *const pNsd, const nsdsel_waitOp_t waitOp) { DEFiRet; nsdsel_ptcp_t *const pThis = (nsdsel_ptcp_t*) pNsdsel; const nsd_ptcp_t *const pSock = (nsd_ptcp_t*) pNsd; ISOBJ_TYPE_assert(pSock, nsd_ptcp); ISOBJ_TYPE_assert(pThis, nsdsel_ptcp); if(pThis->currfds == pThis->maxfds) { struct pollfd *newfds; CHKmalloc(newfds = realloc(pThis->fds, sizeof(struct pollfd) * (pThis->maxfds + FDSET_INCREMENT))); pThis->maxfds += FDSET_INCREMENT; pThis->fds = newfds; } switch(waitOp) { case NSDSEL_RD: pThis->fds[pThis->currfds].events = POLLIN; break; case NSDSEL_WR: pThis->fds[pThis->currfds].events = POLLOUT; break; case NSDSEL_RDWR: pThis->fds[pThis->currfds].events = POLLIN | POLLOUT; break; } pThis->fds[pThis->currfds].fd = pSock->sock; ++pThis->currfds; finalize_it: RETiRet; } /* perform the select() piNumReady returns how many descriptors are ready for IO * TODO: add timeout! */ static rsRetVal ATTR_NONNULL() Select(nsdsel_t *const pNsdsel, int *const piNumReady) { DEFiRet; nsdsel_ptcp_t *pThis = (nsdsel_ptcp_t*) pNsdsel; ISOBJ_TYPE_assert(pThis, nsdsel_ptcp); assert(piNumReady != NULL); /* Output debug first*/ if(Debug) { dbgprintf("-------- calling poll, active fds (%d): ", pThis->currfds); for(uint32_t i = 0; i <= pThis->currfds; ++i) dbgprintf("%d ", pThis->fds[i].fd); dbgprintf("\n"); } assert(pThis->currfds >= 1); /* now do the select */ *piNumReady = poll(pThis->fds, pThis->currfds, -1); if(*piNumReady < 0) { if(errno == EINTR) { DBGPRINTF("nsdsel_ptcp 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() IsReady(nsdsel_t *const pNsdsel, nsd_t *const pNsd, const nsdsel_waitOp_t waitOp, int *const pbIsReady) { DEFiRet; const nsdsel_ptcp_t *const pThis = (nsdsel_ptcp_t*) pNsdsel; const nsd_ptcp_t *const pSock = (nsd_ptcp_t*) pNsd; ISOBJ_TYPE_assert(pThis, nsdsel_ptcp); ISOBJ_TYPE_assert(pSock, nsd_ptcp); const int sock = pSock->sock; // TODO: consider doing a binary search uint32_t idx; for(idx = 0 ; idx < pThis->currfds ; ++idx) { if(pThis->fds[idx].fd == sock) break; } if(idx >= pThis->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->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; } finalize_it: RETiRet; } /* ------------------------------ end support for the select() interface ------------------------------ */ /* queryInterface function */ BEGINobjQueryInterface(nsdsel_ptcp) CODESTARTobjQueryInterface(nsdsel_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(*)(nsdsel_t**)) nsdsel_ptcpConstruct; pIf->Destruct = (rsRetVal(*)(nsdsel_t**)) nsdsel_ptcpDestruct; pIf->Add = Add; pIf->Select = Select; pIf->IsReady = IsReady; finalize_it: ENDobjQueryInterface(nsdsel_ptcp) /* exit our class */ BEGINObjClassExit(nsdsel_ptcp, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(nsdsel_ptcp) /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); ENDObjClassExit(nsdsel_ptcp) /* Initialize the nsdsel_ptcp class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINObjClassInit(nsdsel_ptcp, 1, OBJ_IS_CORE_MODULE) /* class, version */ CHKiRet(objUse(glbl, CORE_COMPONENT)); ENDObjClassInit(nsdsel_ptcp) rsyslog-8.2412.0/runtime/sigprov.h0000664000175000017500000000276214650736301012476 /* 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.2412.0/runtime/module-template.h0000664000175000017500000011075614650736301014106 /* 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-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 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;\ } /* 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;\ } /* the following definition is the standard block for queryEtryPt for all types * of modules. It should be included in any module, and typically is so by calling * the module-type specific macros. */ #define CODEqueryEtryPt_STD_MOD_QUERIES \ if(!strcmp((char*) name, "modExit")) {\ *pEtryPoint = modExit;\ } else if(!strcmp((char*) name, "modGetID")) {\ *pEtryPoint = modGetID;\ } else if(!strcmp((char*) name, "getType")) {\ *pEtryPoint = modGetType;\ } else if(!strcmp((char*) name, "getKeepType")) {\ *pEtryPoint = modGetKeepType;\ } /* the following definition is the standard block for queryEtryPt for output * modules WHICH DO NOT SUPPORT TRANSACTIONS. */ #define CODEqueryEtryPt_STD_OMOD_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES \ else if(!strcmp((char*) name, "doAction")) {\ *pEtryPoint = doAction;\ } else if(!strcmp((char*) name, "dbgPrintInstInfo")) {\ *pEtryPoint = dbgPrintInstInfo;\ } else if(!strcmp((char*) name, "freeInstance")) {\ *pEtryPoint = freeInstance;\ } else if(!strcmp((char*) name, "parseSelectorAct")) {\ *pEtryPoint = parseSelectorAct;\ } else if(!strcmp((char*) name, "isCompatibleWithFeature")) {\ *pEtryPoint = isCompatibleWithFeature;\ } else if(!strcmp((char*) name, "tryResume")) {\ *pEtryPoint = tryResume;\ } /* the following definition is the standard block for queryEtryPt for output * modules using the transaction interface. */ #define CODEqueryEtryPt_STD_OMODTX_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES \ else if(!strcmp((char*) name, "beginTransaction")) {\ *pEtryPoint = beginTransaction;\ } else if(!strcmp((char*) name, "commitTransaction")) {\ *pEtryPoint = commitTransaction;\ } else if(!strcmp((char*) name, "dbgPrintInstInfo")) {\ *pEtryPoint = dbgPrintInstInfo;\ } else if(!strcmp((char*) name, "freeInstance")) {\ *pEtryPoint = freeInstance;\ } else if(!strcmp((char*) name, "parseSelectorAct")) {\ *pEtryPoint = parseSelectorAct;\ } else if(!strcmp((char*) name, "isCompatibleWithFeature")) {\ *pEtryPoint = isCompatibleWithFeature;\ } else if(!strcmp((char*) name, "tryResume")) {\ *pEtryPoint = tryResume;\ } /* standard queries for output module interface in rsyslog v8+ */ #define CODEqueryEtryPt_STD_OMOD8_QUERIES \ else if(!strcmp((char*) name, "createWrkrInstance")) {\ *pEtryPoint = createWrkrInstance;\ } else if(!strcmp((char*) name, "freeWrkrInstance")) {\ *pEtryPoint = freeWrkrInstance;\ } /* the following definition is queryEtryPt block that must be added * if an output module supports the transactional interface. * rgerhards, 2009-04-27 */ #define CODEqueryEtryPt_TXIF_OMOD_QUERIES \ else if(!strcmp((char*) name, "beginTransaction")) {\ *pEtryPoint = beginTransaction;\ } else if(!strcmp((char*) name, "endTransaction")) {\ *pEtryPoint = endTransaction;\ } /* the following definition is a queryEtryPt block that must be added * if a non-output module supports "isCompatibleWithFeature". * rgerhards, 2009-07-20 */ #define CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES \ else if(!strcmp((char*) name, "isCompatibleWithFeature")) {\ *pEtryPoint = isCompatibleWithFeature;\ } /* the following definition is the standard block for queryEtryPt for INPUT * modules. This can be used if no specific handling (e.g. to cover version * differences) is needed. */ #define CODEqueryEtryPt_STD_IMOD_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES \ else if(!strcmp((char*) name, "runInput")) {\ *pEtryPoint = runInput;\ } else if(!strcmp((char*) name, "willRun")) {\ *pEtryPoint = willRun;\ } else if(!strcmp((char*) name, "afterRun")) {\ *pEtryPoint = afterRun;\ } /* the following block is to be added for modules that support the v2 * config system. The config name is also provided. */ #define CODEqueryEtryPt_STD_CONF2_QUERIES \ else if(!strcmp((char*) name, "beginCnfLoad")) {\ *pEtryPoint = beginCnfLoad;\ } else if(!strcmp((char*) name, "endCnfLoad")) {\ *pEtryPoint = endCnfLoad;\ } else if(!strcmp((char*) name, "checkCnf")) {\ *pEtryPoint = checkCnf;\ } else if(!strcmp((char*) name, "activateCnf")) {\ *pEtryPoint = activateCnf;\ } else if(!strcmp((char*) name, "freeCnf")) {\ *pEtryPoint = freeCnf;\ } \ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES /* the following block is to be added for modules that support v2 * module global parameters [module(...)] */ #define CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES \ else if(!strcmp((char*) name, "setModCnf")) {\ *pEtryPoint = setModCnf;\ } \ /* the following block is to be added for output modules that support the v2 * config system. The config name is also provided. */ #define CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES \ else if(!strcmp((char*) name, "newActInst")) {\ *pEtryPoint = newActInst;\ } \ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES /* the following block is to be added for input modules that support the v2 * config system. The config name is also provided. */ #define CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES \ else if(!strcmp((char*) name, "newInpInst")) {\ *pEtryPoint = newInpInst;\ } \ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES /* the following block is to be added for modules that require * pre priv drop activation support. */ #define CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES \ else if(!strcmp((char*) name, "activateCnfPrePrivDrop")) {\ *pEtryPoint = activateCnfPrePrivDrop;\ } /* the following block is to be added for modules that support * their config name. This is required for the rsyslog v6 config * system, especially for outout modules which do not require * the new set of begin/end config settings. */ #define CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES \ else if(!strcmp((char*) name, "getModCnfName")) {\ *pEtryPoint = modGetCnfName;\ } /* the following definition is the standard block for queryEtryPt for LIBRARY * modules. This can be used if no specific handling (e.g. to cover version * differences) is needed. */ #define CODEqueryEtryPt_STD_LIB_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES /* the following definition is the standard block for queryEtryPt for PARSER * modules. This can be used if no specific handling (e.g. to cover version * differences) is needed. */ #define CODEqueryEtryPt_STD_PMOD_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES \ else if(!strcmp((char*) name, "parse")) {\ *pEtryPoint = parse;\ } else if(!strcmp((char*) name, "GetParserName")) {\ *pEtryPoint = GetParserName;\ } /* the following definition is the standard block for queryEtryPt for PARSER * modules obeying the v2+ config interface. */ #define CODEqueryEtryPt_STD_PMOD2_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES \ else if(!strcmp((char*) name, "parse2")) {\ *pEtryPoint = parse2;\ } else if(!strcmp((char*) name, "GetParserName")) {\ *pEtryPoint = GetParserName;\ } else if(!strcmp((char*) name, "newParserInst")) {\ *pEtryPoint = newParserInst;\ } else if(!strcmp((char*) name, "freeParserInst")) {\ *pEtryPoint = freeParserInst;\ } \ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES /* the following definition is the standard block for queryEtryPt for rscript function * modules. This can be used if no specific handling (e.g. to cover version * differences) is needed. */ #define CODEqueryEtryPt_STD_FMOD_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES \ else if(!strcmp((char*) name, "getFunctArray")) {\ *pEtryPoint = getFunctArray;\ } /* the following definition is the standard block for queryEtryPt for Strgen * modules. This can be used if no specific handling (e.g. to cover version * differences) is needed. */ #define CODEqueryEtryPt_STD_SMOD_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES \ else if(!strcmp((char*) name, "strgen")) {\ *pEtryPoint = strgen;\ } else if(!strcmp((char*) name, "GetName")) {\ *pEtryPoint = GetStrgenName;\ } /* 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); #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;\ } /* 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 ressources * 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 \ else if(!strcmp((char*) name, "doHUP")) {\ *pEtryPoint = doHUP;\ } #define BEGINdoHUP \ static rsRetVal doHUP(instanceData __attribute__((unused)) *pData)\ {\ DEFiRet; #define CODESTARTdoHUP #define ENDdoHUP \ RETiRet;\ } /* doHUPWrkr() * This is like doHUP(), but on an action worker level. * rgerhards, 2015-03-25 */ #define CODEqueryEtryPt_doHUPWrkr \ else 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 */ /* vim:set ai: */ rsyslog-8.2412.0/runtime/srUtils.h0000664000175000017500000000764314650736301012455 /*! \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 *arg); 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.2412.0/runtime/libossl.c0000664000175000017500000004301214704407366012446 /* 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 ((*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) { /* TODO: provide specific EOF case? */ 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: // TODO: remove once this code is sufficiently well-proven DBGPRINTF("osslfileGetBytesLeftInBlock returns %lld, iRet %d\n", (long long) *left, iRet); 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.2412.0/runtime/obj.h0000664000175000017500000001247414650736301011560 /* 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-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 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)(), rsRetVal (*objConstructFinalize)(), rsRetVal (*objDeserialize)()); 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.2412.0/runtime/libgcry.h0000664000175000017500000000521514704407366012442 /* 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.2412.0/runtime/rsyslog.c0000664000175000017500000002620614650736301012501 /* 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 "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 intial 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 */ 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.2412.0/runtime/parser.c0000664000175000017500000005372414650736301012300 /* 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) { /* 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; 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; } /* 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; 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 (!glbl.GetParserSpaceLFOnReceive(runConf)) { break; } } } else if(pszMsg[iSrc] > 127 && glbl.GetParserEscape8BitCharactersOnReceive(runConf)) { bNeedSanitize = 1; break; } } if(!bNeedSanitize) { if(bUpdatedLen == RSTRUE) MsgSetRawMsgSize(pMsg, lenMsg); FINALIZE; } /* 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))) { /* 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; } /* 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. */ static rsRetVal ParsePRI(smsg_t *pMsg) { syslog_pri_t pri; uchar *msg; int lenMsg; DEFiRet; /* pull PRI */ lenMsg = pMsg->iLenRawMsg; msg = pMsg->pszRawMsg; pri = DEFUPRI; if(pMsg->msgFlags & NO_PRI_IN_RAW) { /* In this case, simply do so as if the pri would be right at top */ MsgSetAfterPRIOffs(pMsg, 0); } else { if(*msg == '<') { pri = 0; while(--lenMsg > 0 && isdigit((int) *++msg) && pri <= LOG_MAXPRI) { pri = 10 * pri + (*msg - '0'); } if(*msg == '>') { ++msg; } else { pri = LOG_PRI_INVLD; } if(pri > LOG_MAXPRI) pri = LOG_PRI_INVLD; } msgSetPRI(pMsg, pri); MsgSetAfterPRIOffs(pMsg, (pri == LOG_PRI_INVLD) ? 0 : msg - pMsg->pszRawMsg); } 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(ParsePRI(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.2412.0/runtime/unlimited_select.h0000664000175000017500000000242514650736301014332 /* 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.2412.0/runtime/lmcry_gcry.h0000664000175000017500000000244214650736301013152 /* 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 */ PROTOTYPEObj(lmcry_gcry); #endif /* #ifndef INCLUDED_LMCRY_GCRY_H */ rsyslog-8.2412.0/runtime/nsd_gtls.c0000664000175000017500000022133714656663250012626 /* nsd_gtls.c * * An implementation of the nsd interface for GnuTLS. * * Copyright (C) 2007-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 #if GNUTLS_VERSION_NUMBER <= 0x020b00 # include #endif #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 "nsdsel_gtls.h" #include "nsd_gtls.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) /* 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 gnutls_dh_params_t dh_params; /**< server DH parameters for anon mode */ /* 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 ------------------------------ */ /* 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; inOurCerts; ++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! */ } ++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(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 gtlsRecordRecv(nsd_gtls_t *pThis) { 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!*/ if (gnutls_record_get_direction(pThis->sess) == gtlsDir_READ) { pThis->rtryCall = gtlsRtry_recv; dbgprintf("GnuTLS receive requires a retry, this most probably is OK and no error condition\n"); ABORT_FINALIZE(RS_RET_RETRY); } else { uchar *pErr = gtlsStrerror(lenRcvd); LogError(0, RS_RET_GNUTLS_ERR, "GnuTLS receive error %zd has wrong read direction(wants write) " "- this could be caused by a broken connection. GnuTLS reports: %s\n", lenRcvd, pErr); free(pErr); ABORT_FINALIZE(RS_RET_GNUTLS_ERR); } } 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; } /* 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) { LogMsg(0, RS_RET_CERT_MISSING, LOG_WARNING, "warning: certificate file is not set"); } if(keyFile == NULL) { LogMsg(0, RS_RET_CERTKEY_MISSING, LOG_WARNING, "warning: key file is not set"); } /* 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) { LogMsg(0, RS_RET_CA_CERT_MISSING, LOG_WARNING, "Warning: CA certificate is not set"); } else { 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 { dbgprintf("GTLS CRL file: '%s'\n", crlfile); gnuRet = gnutls_certificate_set_x509_crl_file(pThis->xcred, (char*)crlfile, GNUTLS_X509_FMT_PEM); if(gnuRet == GNUTLS_E_FILE_ERROR) { 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); } 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 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); 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... */ int iAltName; 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; 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! */ } ++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; } /* 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 *fromHost = NULL; errno = 0; pThis->bReportAuthErr = 0; nsd_ptcp.GetRemoteHName((nsd_t*)pThis->pTcp, &fromHost); LogError(0, RS_RET_TLS_NO_CERT, "error: peer %s did not provide a certificate, " "not permitted to talk to it", fromHost); free(fromHost); } 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 *fromHost = NULL; nsd_ptcp.GetRemoteHName((nsd_t*)pThis->pTcp, &fromHost); LogError(0, RS_RET_TLS_NO_CERT, "peer %s did not provide a certificate, not permitted to talk to it", fromHost); free(fromHost); 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 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); /* 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; } 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 */ PROTOTYPEobjDestruct(nsd_gtls); 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); if(pThis->bOurCertIsInit) for(unsigned i=0; inOurCerts; ++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_t*) 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_t*) 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_t*) 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_t*) 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_t*) 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_t*) 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_t*) 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_t*) 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_t*) 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_t*) 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 SetTlsKeyFile(nsd_t *pNsd, const uchar *const pszFile) { DEFiRet; nsd_gtls_t *const pThis = (nsd_gtls_t*) 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_t*) 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; } /* 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_t*) pNsd; ISOBJ_TYPE_assert((pThis), nsd_gtls); assert(sock >= 0); nsd_ptcp.SetSock(pThis->pTcp, sock); RETiRet; } /* Keep Alive Options */ static rsRetVal SetKeepAliveIntvl(nsd_t *pNsd, int keepAliveIntvl) { DEFiRet; nsd_gtls_t *pThis = (nsd_gtls_t*) 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_t*) 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_t*) pNsd; ISOBJ_TYPE_assert((pThis), nsd_gtls); assert(keepAliveTime >= 0); nsd_ptcp.SetKeepAliveTime(pThis->pTcp, keepAliveTime); 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_t*) 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_t*) pThis->pDrvrData)); CHKiRet(gtlsAddOurCert((nsd_gtls_t*) 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_t*) pNsd; ISOBJ_TYPE_assert(pThis, nsd_gtls); dbgprintf("CheckConnection for %p\n", pNsd); return nsd_ptcp.CheckConnection(pThis->pTcp); } /* 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_t*) 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_t*) 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_t*) 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) { DEFiRet; int gnuRet; nsd_gtls_t *pNew = NULL; nsd_gtls_t *pThis = (nsd_gtls_t*) 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)); 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->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 in" " Priority String: \"%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); LogError(0, RS_RET_TLS_HANDSHAKE_ERR, "gnutls returned error on handshake: %s\n", pGnuErr); 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) { DEFiRet; ssize_t iBytesCopy; /* how many bytes are to be copied to the client buffer? */ nsd_gtls_t *pThis = (nsd_gtls_t*) 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)); FINALIZE; } /* --- in TLS mode now --- */ /* 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)); } 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_t*) 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; } /* in TLS mode now */ while(1) { /* loop broken inside */ iSent = gnutls_record_send(pThis->sess, pBuf, *pLenBuf); if(iSent >= 0) { *pLenBuf = iSent; break; } if(iSent != GNUTLS_E_INTERRUPTED && iSent != GNUTLS_E_AGAIN) { /* 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_t*) 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 = 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_t*) 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 in" " Priority String: \"%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); } /* assign the socket to GnuTls */ CHKiRet(nsd_ptcp.GetSock(pThis->pTcp, &sock)); 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 */ 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->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->SetGnutlsPriorityString = SetGnutlsPriorityString; pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage; pIf->SetPrioritizeSAN = SetPrioritizeSAN; pIf->SetTlsVerifyDepth = SetTlsVerifyDepth; pIf->SetTlsCAFile = SetTlsCAFile; pIf->SetTlsCRLFile = SetTlsCRLFile; pIf->SetTlsKeyFile = SetTlsKeyFile; pIf->SetTlsCertFile = SetTlsCertFile; 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(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)); /* now do global TLS init stuff */ CHKiRet(gtlsGlblInit()); ENDObjClassInit(nsd_gtls) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit nsdsel_gtlsClassExit(); 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 */ CHKiRet(nsdsel_gtlsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ pthread_mutex_init(&mutGtlsStrerror, NULL); ENDmodInit /* vi:set ai: */ rsyslog-8.2412.0/runtime/rsyslog.h0000664000175000017500000013466514704407366012525 /* This is the header file for the rsyslog runtime. It must be included * if someone intends to use the runtime. * * Begun 2005-09-15 RGerhards * * Copyright (C) 2005-2023 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_RSYSLOG_H #define INCLUDED_RSYSLOG_H #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wdeclaration-after-statement" #pragma GCC diagnostic ignored "-Wredundant-decls" // TODO: remove! #pragma GCC diagnostic ignored "-Wstrict-prototypes" // TODO: remove! #pragma GCC diagnostic ignored "-Wswitch-default" // TODO: remove! #if __GNUC__ >= 8 /* 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" #endif /* if __GNUC__ >= 8 */ #if defined(__clang__) #define ATTR_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined"))) #else #define ATTR_NO_SANITIZE_UNDEFINED #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(...) #endif /* ifdef __GNUC__ */ #if defined(_AIX) #include /* AIXPORT : start*/ #define SRC_FD 13 #define SRCMSG (sizeof(srcpacket)) #endif /* src end */ #include #include "typedefs.h" #if defined(__GNUC__) #define PRAGMA_INGORE_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\"") #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_INGORE_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_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 # * * ############################################################# */ #define CONST_LEN_TIMESTAMP_3164 15 /* number of chars (excluding \0!) in a RFC3164 timestamp */ #define CONST_LEN_TIMESTAMP_3339 32 /* number of chars (excluding \0!) in a RFC3339 timestamp */ #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. */ #define CONF_TAG_MAXSIZE 512 /* a value that is deemed far too large for any valid TAG */ #define CONF_HOSTNAME_MAXSIZE 512 /* a value that is deemed far too large for any valid HOSTNAME */ #define CONF_RAWMSG_BUFSIZE 101 #define CONF_TAG_BUFSIZE 32 #define CONF_PROGNAME_BUFSIZE 16 #define CONF_HOSTNAME_BUFSIZE 32 #define CONF_PROP_BUFSIZE 16 /* should be close to sizeof(ptr) or lighly above it */ #define CONF_IPARAMS_BUFSIZE 16 /* initial size of iparams array in wti (is automatically extended) */ #define CONF_MIN_SIZE_FOR_COMPRESS 60 /* config param: minimum message size to try compression. The smaller * the message, the less likely is any compression gain. We check for * gain before we submit the message. But to do so we still need to * do the (costly) compress() call. The following setting sets a size * for which no call to compress() is done at all. This may result in * a few more bytes being transmited but better overall performance. * Note: I have not yet checked the minimum UDP packet size. It might be * that we do not save anything by compressing very small messages, because * UDP might need to pad ;) * rgerhards, 2006-11-30 */ #define CONF_OMOD_NUMSTRINGS_MAXSIZE 5 /* cache for pointers to output module buffer pointers. All * rsyslog-provided plugins do NOT need more than five buffers. If * more are needed (future developments, third-parties), rsyslog * must be recompiled with a larger parameter. Hardcoding this * saves us some overhead, both in runtime in code complexity. As * it is doubtful if ever more than 3 parameters are needed, the * approach taken here is considered appropriate. * rgerhards, 2010-06-24 */ #define CONF_NUM_MULTISUB 1024 /* default number of messages per multisub structure */ /* ############################################################# * * # End Config Settings # * * ############################################################# */ /* make sure we uses consistent macros, no matter what the * platform gives us. */ #undef LOG_NFACILITIES /* may be system defined, override */ #define LOG_NFACILITIES 24+1 /* plus one for our special "invld" facility! */ #define LOG_MAXPRI 191 /* highest supported valid PRI value --> RFC3164, RFC5424 */ #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 /*#define CORE_FEATURE_whatever 2 ... and so on ... */ #ifndef _PATH_CONSOLE #define _PATH_CONSOLE "/dev/console" #endif /* The error codes below are orginally "borrowed" from * liblogging. As such, we reserve values up to -2999 * just in case we need to borrow something more ;) */ enum rsRetVal_ /** return value. All methods return this if not specified otherwise */ { /* 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, /**< insufficient data, e.g. end of string during parsing */ 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 */ /* 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 ABORT_FINALIZE(errCode) \ do { \ iRet = errCode; \ goto finalize_it; \ } while (0) /** Object ID. These are for internal checking. Each * object is assigned a specific ID. This is contained in * all Object structs (just like C++ RTTI). We can use * this field to see if we have been passed a correct ID. * Other than that, there is currently no other use for * the object id. */ 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 extern pthread_attr_t default_thread_attr; #ifdef HAVE_PTHREAD_SETSCHEDPARAM extern struct sched_param default_sched_param; extern int default_thr_sched_policy; #endif /* The following structure defines immutable parameters which need to * be passed as action parameters. * * Note that output plugins may request multiple templates. Let's say * an output requests n templates. Than the overall table must hold * n*nbrMsgs records, and each messages begins on a n-boundary. There * is a macro defined below to access the proper element. * * WARNING: THIS STRUCTURE IS PART OF THE ***OUTPUT MODULE INTERFACE*** * It is passed into the doCommit() function. Do NOT modify it until * absolutely necessary - all output plugins need to be changed! * * If a change is "just" for internal working, consider adding a * separate parameter outside of this structure. Of course, it is * best to avoid this as well ;-) * rgerhards, 2013-12-04 */ 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 #if !defined(O_CLOEXEC) && !defined(_AIX) /* of course, this limits the functionality... */ # define O_CLOEXEC 0 #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 */ extern uchar *glblModPath; /* module load path */ extern void (*glblErrLogger)(const int, const int, const uchar*); /* some runtime prototypes */ void processImInternal(void); rsRetVal rsrtInit(const char **ppErrObj, obj_if_t *pObjIF); rsRetVal rsrtExit(void); int rsrtIsInit(void); void rsrtSetErrLogger(void (*errLogger)(const int, const int, const uchar*)); void dfltErrLogger(const int, const int, const uchar *errMsg); rsRetVal queryLocalHostname(rsconf_t *const); /* this define below is (later) intended to be used to implement empty * structs. TODO: check if compilers supports this and, if not, define * a dummy variable. This requires review of where in code empty structs * are already defined. -- rgerhards, 2010-07-26 */ #ifdef OS_SOLARIS #define EMPTY_STRUCT int remove_me_when_first_real_member_is_added; #else #define EMPTY_STRUCT #endif /* TODO: remove this -- this is only for transition of the config system */ extern rsconf_t *ourConf; /* defined by syslogd.c, a hack for functions that do not yet receive a copy, so that we can incrementially compile and change... -- rgerhars, 2011-04-19 */ /* here we add some stuff from the compatibility layer. A separate include * would be cleaner, but would potentially require changes all over the * place. So doing it here is better. The respective replacement * functions should usually be found under ./compat -- rgerhards, 2015-05-20 */ #ifndef HAVE_STRNDUP char * strndup(const char *s, size_t n); #endif #endif /* multi-include protection */ rsyslog-8.2412.0/runtime/netstrms.c0000664000175000017500000003474414656663250012674 /* netstrms.c * * Work on this module begung 2008-04-23 by Rainer Gerhards. * * 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 "module-template.h" #include "obj.h" #include "nsd.h" #include "netstrm.h" #include "nssel.h" #include "nspoll.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. * WARNING: this code is mostly identical to similar code in * nssel.c - TODO: abstract it and move it to some common place. * rgerhards, 2008-04-18 */ 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; } ENDobjDestruct(netstrms) /* ConstructionFinalizer */ static rsRetVal netstrmsConstructFinalize(netstrms_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); iRet = loadDrvr(pThis); 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 */ 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; } /* 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->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->GetDrvrTlsVerifyDepth = GetDrvrTlsVerifyDepth; 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 nsselClassExit(); nspollClassExit(); 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(nsselClassInit(pModInfo)); CHKiRet(nspollClassInit(pModInfo)); CHKiRet(netstrmsClassInit(pModInfo)); ENDmodInit rsyslog-8.2412.0/runtime/perctile_stats.c0000664000175000017500000005334214650736301014025 /* * 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 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]; if (ctr->ref_ctr_percentile_stat) { statsobj.DestructCounter(b->statsobj, ctr->ref_ctr_percentile_stat); } } free(pstat->ctrs); } if (pstat->refCtrWindowCount) { statsobj.DestructCounter(b->statsobj, pstat->refCtrWindowCount); } if (pstat->refCtrWindowMin) { statsobj.DestructCounter(b->statsobj, pstat->refCtrWindowMin); } if (pstat->refCtrWindowMax) { statsobj.DestructCounter(b->statsobj, pstat->refCtrWindowMax); } if (pstat->refCtrWindowSum) { statsobj.DestructCounter(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) { 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); statsobj.Destruct(&bkt->statsobj); pthread_rwlock_unlock(&bkt->lock); pthread_rwlock_destroy(&bkt->lock); 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) { perctile_bucket_t *head = bkts->listBuckets; if (head) { pthread_rwlock_wrlock(&bkts->lock); perctile_bucket_t *pnode = head, *pnext = NULL; while (pnode) { pnext = pnode->next; perctileBucketDestruct(pnode); pnode = pnext; } pthread_rwlock_unlock(&bkts->lock); } statsobj.Destruct(&bkts->global_stats); // 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", stat_name, stat_name_len); 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' truncated - too long for buffer size: %d\n", stat_name, stat_name_len); 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, const uchar* name) { uchar *metric_name_buff, *metric_suffix; const uchar *suffix_litteral; int name_len; DEFiRet; name_len = ustrlen(name); CHKmalloc(metric_name_buff = malloc((name_len + PERCTILE_MAX_BUCKET_NS_METRIC_LENGTH + 1) * sizeof(uchar))); strcpy((char*)metric_name_buff, (char*)name); 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) { if (b->pOpsOverflowCtr != NULL) { statsobj.DestructCounter(bkts->global_stats, b->pOpsOverflowCtr); } if (b->pNewKeyAddCtr != NULL) { statsobj.DestructCounter(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 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); // add bucket to list of buckets 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"); } // create the statsobj for this bucket CHKiRet(perctileInitNewBucketStats(b)); CHKiRet(perctileAddBucketMetrics(bkts, b, name)); } 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); perctiles[j] = atoi(cstr); 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.2412.0/runtime/lookup.h0000664000175000017500000000603414650736301012312 /* 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 #define STRING_LOOKUP_TABLE 1 #define ARRAY_LOOKUP_TABLE 2 #define SPARSE_ARRAY_LOOKUP_TABLE 3 #define STUBBED_LOOKUP_TABLE 4 #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_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 do_reload; 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; } 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); 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.2412.0/runtime/ratelimit.c0000664000175000017500000002756014650736301012775 /* ratelimit.c * support for rate-limiting sources, including "last message * repeated n times" processing. * * Copyright 2012-2020 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 "ratelimit.h" #include "datetime.h" #include "parser.h" #include "unicode-helper.h" #include "msg.h" #include "rsconf.h" #include "dirty.h" /* definitions for objects we access */ DEFobjStaticHelpers DEFobjCurrIf(glbl) DEFobjCurrIf(datetime) DEFobjCurrIf(parser) /* static data */ /* 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, ratelimit->burst, ratelimit->interval); 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); } if(ratelimit->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(ratelimit->burst != 0); 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 + ratelimit->interval)) || (tt < ratelimit->begin) ) { ratelimit->begin = 0; ratelimit->done = 0; tellLostCnt(ratelimit); } /* do actual limit check */ if(ratelimit->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(ratelimit->interval) { 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; } /* 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 ratelimitMsg(ratelimit_t *__restrict__ const ratelimit, smsg_t *pMsg, smsg_t **ppRepMsg) { DEFiRet; rsRetVal localRet; int severity = 0; *ppRepMsg = NULL; if(runConf->globals.bReduceRepeatMsgs || ratelimit->severity > 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(ratelimit->interval && (severity >= ratelimit->severity)) { 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) { return ratelimit->interval || 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) */ rsRetVal ratelimitAddMsg(ratelimit_t *ratelimit, multi_submit_t *pMultiSub, smsg_t *pMsg) { rsRetVal localRet; smsg_t *repMsg; DEFiRet; localRet = ratelimitMsg(ratelimit, pMsg, &repMsg); if(pMultiSub == NULL) { if(repMsg != NULL) CHKiRet(submitMsg2(repMsg)); CHKiRet(localRet); CHKiRet(submitMsg2(pMsg)); } else { if(repMsg != NULL) { pMultiSub->ppMsgs[pMultiSub->nElem++] = repMsg; if(pMultiSub->nElem == pMultiSub->maxElem) CHKiRet(multiSubmitMsg2(pMultiSub)); } CHKiRet(localRet); if(pMsg->iLenRawMsg > glblGetMaxLine(runConf)) { /* oversize message needs special processing. We keep * at least the previous batch as batch... */ if(pMultiSub->nElem > 0) { CHKiRet(multiSubmitMsg2(pMultiSub)); } CHKiRet(submitMsg2(pMsg)); FINALIZE; } pMultiSub->ppMsgs[pMultiSub->nElem++] = pMsg; if(pMultiSub->nElem == pMultiSub->maxElem) CHKiRet(multiSubmitMsg2(pMultiSub)); } finalize_it: 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; 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); } DBGPRINTF("ratelimit:%s:new ratelimiter\n", pThis->name); *ppThis = pThis; finalize_it: RETiRet; } /* enable linux-like ratelimiting */ void ratelimitSetLinuxLike(ratelimit_t *ratelimit, unsigned int interval, unsigned int burst) { ratelimit->interval = interval; ratelimit->burst = burst; ratelimit->done = 0; ratelimit->missed = 0; ratelimit->begin = 0; } /* 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; pthread_mutex_init(&ratelimit->mut, NULL); } void ratelimitSetNoTimeCache(ratelimit_t *ratelimit) { ratelimit->bNoTimeCache = 1; pthread_mutex_init(&ratelimit->mut, NULL); } /* Severity level determines which messages are subject to * ratelimiting. Default (no value set) is all messages. */ void ratelimitSetSeverity(ratelimit_t *ratelimit, intTiny severity) { ratelimit->severity = 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->bThreadSafe) pthread_mutex_destroy(&ratelimit->mut); free(ratelimit->name); free(ratelimit); } void ratelimitModExit(void) { objRelease(datetime, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(parser, CORE_COMPONENT); } rsRetVal ratelimitModInit(void) { DEFiRet; CHKiRet(objGetObjInterface(&obj)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); finalize_it: RETiRet; } rsyslog-8.2412.0/runtime/statsobj.c0000664000175000017500000004627214650736301012635 /* 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. */ #include "config.h" #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 void addToObjList(statsobj_t *pThis) { pthread_mutex_lock(&mutStats); 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; } pthread_mutex_unlock(&mutStats); } static void removeFromObjList(statsobj_t *pThis) { pthread_mutex_lock(&mutStats); 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; pthread_mutex_unlock(&mutStats); } static void addCtrToList(statsobj_t *pThis, ctr_t *pCtr) { pthread_mutex_lock(&pThis->mutCtr); pCtr->prev = pThis->ctrLast; if(pThis->ctrLast != NULL) pThis->ctrLast->next = pCtr; pThis->ctrLast = pCtr; if(pThis->ctrRoot == NULL) pThis->ctrRoot = pCtr; pthread_mutex_unlock(&pThis->mutCtr); } /* ------------------------------ methods ------------------------------ */ /* Standard-Constructor */ BEGINobjConstruct(statsobj) /* be sure to specify the object type also in END macro! */ pthread_mutex_init(&pThis->mutCtr, NULL); pThis->ctrLast = NULL; pThis->ctrRoot = NULL; pThis->read_notifier = NULL; pThis->flags = 0; ENDobjConstruct(statsobj) /* ConstructionFinalizer */ static rsRetVal statsobjConstructFinalize(statsobj_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, statsobj); addToObjList(pThis); 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; } if (linked) { addCtrToList(pThis, ctr); } *entryRef = ctr; finalize_it: if (iRet != RS_RET_OK) { if (ctr != NULL) { free(ctr->name); free(ctr); } } RETiRet; } static void addPreCreatedCounter(statsobj_t *pThis, ctr_t *pCtr) { pCtr->next = NULL; pCtr->prev = NULL; 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 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: *(pCtr->val.pIntCtr) = 0; break; case ctrType_Int: *(pCtr->val.pInt) = 0; 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 *(pCtr->val.pIntCtr); case ctrType_Int: return *(pCtr->val.pInt); } 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]; strncpy((char*)esbuf, (char*)pCtr->name, sizeof(esbuf)-1); esbuf[sizeof(esbuf)-1] = '\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, *(pCtr->val.pIntCtr)); // TODO: OK????? break; case ctrType_Int: rsCStrAppendInt(pcstr, *(pCtr->val.pInt)); 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); } /* 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; DEFiRet; 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; } CHKiRet(cb(usrptr, (const char*)cstrGetSzStrNoNULL(cstr))); rsCStrDestruct(&cstr); if (o->read_notifier != NULL) { o->read_notifier(o, o->read_notifier_ctx); } } getSenderStats(cb, usrptr, fmt, bResetCtrs); finalize_it: if(cstr != NULL) { rsCStrDestruct(&cstr); } RETiRet; } /* Enable statistics gathering. currently there is no function to disable it * again, as this is right now not needed. */ static rsRetVal enableStats(void) { GatherStats = 1; 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) removeFromObjList(pThis); /* 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->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 */ pthread_mutex_init(&mutStats, NULL); 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.2412.0/runtime/stringbuf.h0000664000175000017500000001150014650736301012776 /* 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. */ 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; /** * Construct a rsCStr object. */ 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 must be called after all data is added to it * but before that data is used. * 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. */ 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 */ rsRetVal rsCStrAppendStrWithLen(cstr_t *pThis, const uchar* psz, size_t iStrLen); /** * 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. */ 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); uchar* cstrGetSzStrNoNULL(cstr_t *pThis); #define rsCStrGetSzStrNoNULL(x) cstrGetSzStrNoNULL(x) 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); rsRetVal rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz, int iType, void *cache); void rsCStrRegexDestruct(void *rc); /* new calling interface */ 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.2412.0/runtime/net_ossl.h0000664000175000017500000001421314656663250012635 /* Definitions for generic OpenSSL include stuff. * * Copyright 2023 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 */ #include #include #include #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) # include #endif #include #include #include /* 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. */ /* 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 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) 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 */ #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 /*-----------------------------------------------------------------------------*/ /* 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 */ PROTOTYPEObj(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.2412.0/runtime/libgcry.c0000664000175000017500000004617214704407366012444 /* 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) { /* TODO: provide specific EOF case? */ 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: // TODO: remove once this code is sufficiently well-proven DBGPRINTF("gcryfileGetBytesLeftInBlock returns %lld, iRet %d\n", (long long) *left, iRet); 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. */ #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(gcryfile 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(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; } /* TODO: handle multiple blocks * 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); // TODO: remove dbgprintf once things are sufficently stable -- rgerhards, 2013-05-16 dbgprintf("libgcry: decrypted, bytesToBlkEnd %lld, buffer is now '%50.50s'\n", (long long) pF->bytesToBlkEnd, buf); 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.2412.0/runtime/netstrm.h0000664000175000017500000001336114650736301012476 /* Definitions for the stream-based netstrmworking class. * * 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. */ #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); rsRetVal (*Rcv)(netstrm_t *pThis, uchar *pRcvBuf, ssize_t *pLenBuf, int *oserr); 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... TODO: should be * reconsidered when a new ACL system is build. -- rgerhards, 2008-12-01 */ /* 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 (*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); /* v15 -- Tls cert functions */ rsRetVal (*SetDrvrTlsCAFile)(netstrm_t *pThis, const uchar* file); rsRetVal (*SetDrvrTlsCRLFile)(netstrm_t *pThis, const uchar* file); rsRetVal (*SetDrvrTlsKeyFile)(netstrm_t *pThis, const uchar* file); rsRetVal (*SetDrvrTlsCertFile)(netstrm_t *pThis, const uchar* file); ENDinterface(netstrm) #define netstrmCURR_IF_VERSION 16 /* 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 * */ /* prototypes */ PROTOTYPEObj(netstrm); /* the name of our library binary */ #define LM_NETSTRM_FILENAME LM_NETSTRMS_FILENAME #endif /* #ifndef INCLUDED_NETSTRM_H */ rsyslog-8.2412.0/runtime/im-helper.h0000664000175000017500000000430414650736301012661 /* 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 /* 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; finalize_it: RETiRet; } #endif /* #ifndef IM_HELPER_H_INCLUDED */ rsyslog-8.2412.0/runtime/prop.h0000664000175000017500000000524114650736301011760 /* The prop object. * * This implements props within rsyslog. * * Copyright 2009-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_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; } /* prototypes */ PROTOTYPEObj(prop); #endif /* #ifndef INCLUDED_PROP_H */ rsyslog-8.2412.0/runtime/operatingstate.c0000664000175000017500000001130714650736301014024 /* 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.2412.0/runtime/timezones.c0000664000175000017500000001311514650736301013007 /* 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); } else if(!strcmp(timezonepblk.descr[i].name, "offset")) { offset = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL); } 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.2412.0/runtime/lib_ksi_queue.h0000664000175000017500000000320514650736301013616 #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.2412.0/runtime/glbl.h0000664000175000017500000001425614704407366011734 /* 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 #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(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 10 /* increment whenever you change the interface structure! */ /* version 2 had PreserveFQDN added - rgerhards, 2008-12-08 */ /* the remaining prototypes */ PROTOTYPEObj(glbl); 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; #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); #endif /* #ifndef GLBL_H_INCLUDED */ rsyslog-8.2412.0/runtime/lmsig_ksi-ls12.h0000664000175000017500000000264414650736301013544 /* 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 */ PROTOTYPEObj(lmsig_ksi_ls12); #endif /* #ifndef INCLUDED_LMSIG_LS12_KSI_H */ rsyslog-8.2412.0/runtime/hashtable.h0000664000175000017500000001660014650736301012734 /* 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); #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); #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); #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.2412.0/runtime/lmsig_ksi-ls12.c0000664000175000017500000002700214650736301013532 /* 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 "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) #define REPORT_PARAM_MISSING(param) \ do { \ pThis->ctx->disabled = true; \ LogError(0, RS_RET_ERR, "%s missing - signing disabled", param); \ /* TODO: ABORT_FINALIZE actually is useless because the return value is not checked by the caller*/ \ ABORT_FINALIZE(RS_RET_KSI_ERR); \ } while(0) /* 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")) { hash = (char*) es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(pblk.descr[i].name, "sig.aggregator.url")) { ag_uri = es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(pblk.descr[i].name, "sig.aggregator.user")) { ag_loginid = es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(pblk.descr[i].name, "sig.aggregator.key")) { ag_key = es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(pblk.descr[i].name, "sig.aggregator.hmacAlg")) { 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")) { 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")) { 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")) { 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) { DEFiRet; DBGPRINTF("lmsig_ksi-ls12: onRecordWrite (%d): %s\n", lenRec - 1, rec); sigblkAddRecordKSI(pF, rec, lenRec - 1); 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.2412.0/runtime/tcps_sess.h0000664000175000017500000000634714650736301013016 /* Definitions for tcps_sess class. This implements a session of the * plain TCP server. * * Copyright 2008-2022 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 "obj.h" #include "prop.h" /* a forward-definition, we are somewhat cyclic */ struct tcpsrv_s; /* 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 } inputState; /* our current state */ 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; void *pUsr; /* a user-pointer */ rsRetVal (*DoSubmitMessage)(tcps_sess_t*, uchar*, int); /* submit message callback */ int iMaxLine; /* fast lookup buffer for config property */ }; /* 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 (*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 3 /* 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 */ /* prototypes */ PROTOTYPEObj(tcps_sess); #endif /* #ifndef INCLUDED_TCPS_SESS_H */ rsyslog-8.2412.0/runtime/typedefs.h0000664000175000017500000002527514650736301012634 /* 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 struct nspoll_s nspoll_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_gsspi_s nsd_gsspi_t; typedef struct nsd_nss_s nsd_nss_t; typedef struct nsdsel_ptcp_s nsdsel_ptcp_t; typedef struct nsdsel_gtls_s nsdsel_gtls_t; typedef struct nsdsel_ossl_s nsdsel_ossl_t; typedef struct nsdpoll_ptcp_s nsdpoll_ptcp_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; 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_tables_s lookup_tables_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; typedef void nsdsel_t; typedef void nsdpoll_t; #else typedef obj_t *obj_t_ptr; typedef obj_t nsd_t; typedef obj_t nsdsel_t; typedef obj_t nsdpoll_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_REGEX = 4, /* matches a (BRE) regular expression? */ FIOP_EREREGEX = 5, /* matches a ERE regular expression? */ FIOP_ISEMPTY = 6 /* 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_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 */ 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 /* statment 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.2412.0/runtime/parser.h0000664000175000017500000000566314650736301012304 /* header for parser.c * * Copyright 2008-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. */ #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 */ PROTOTYPEObj(parser); rsRetVal parserConstructViaModAndName(modInfo_t *pMod, uchar *const pName, void *parserInst); #endif /* #ifndef INCLUDED_PARSER_H */ rsyslog-8.2412.0/runtime/cfsysline.c0000664000175000017500000006746314723322534013010 /* 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 */ } /* 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; } /* 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; rsRetVal (*pHdlr)() = NULL; assert(pThis != NULL); assert(ppConfLine != NULL); switch(pThis->eType) { case eCmdHdlrCustomHandler: pHdlr = doCustomHdlr; break; case eCmdHdlrUID: pHdlr = doGetUID; break; case eCmdHdlrGID: pHdlr = doGetGID; break; case eCmdHdlrBinary: pHdlr = doBinaryOptionLine; break; case eCmdHdlrFileCreateMode: pHdlr = doFileCreateMode; break; case eCmdHdlrInt: pHdlr = doGetInt; break; case eCmdHdlrSize: pHdlr = doGetSize; break; case eCmdHdlrGetChar: pHdlr = doGetChar; break; case eCmdHdlrFacility: pHdlr = doFacility; break; case eCmdHdlrSeverity: pHdlr = doSeverity; break; case eCmdHdlrGetWord: pHdlr = doGetWord; break; case eCmdHdlrGoneAway: pHdlr = doGoneAway; break; /* some non-legacy handler (used in v6+ solely) */ case eCmdHdlrInvalid: case eCmdHdlrNonNegInt: case eCmdHdlrPositiveInt: 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; } /* we got a pointer to the handler, so let's call it */ assert(pHdlr != NULL); CHKiRet(pHdlr(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); 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, 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"); } /* our init function. TODO: remove once converted to a class */ rsRetVal cfsyslineInit(void) { DEFiRet; CHKiRet(objGetObjInterface(&obj)); CHKiRet(llInit(&llCmdList, cslcDestruct, cslcKeyDestruct, strcasecmp)); finalize_it: RETiRet; } rsyslog-8.2412.0/runtime/ruleset.h0000664000175000017500000001001114650736301012452 /* The ruleset object. * * This implements rulesets within rsyslog. * * Copyright 2009-2021 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 */ PROTOTYPEObj(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.2412.0/runtime/nsd_gtls.h0000664000175000017500000001134114650736301012613 /* An implementation of the nsd interface for GnuTLS. * * Copyright 2008-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. */ #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 */ int DrvrVerifyDepth; /* Verify Depth for certificate chains */ 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 */ PROTOTYPEObj(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); /* 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.2412.0/runtime/nsd_ossl.h0000664000175000017500000000675414650736301012636 /* An implementation of the nsd interface for OpenSSL. * * Copyright 2018-2023 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 */ 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 */ PROTOTYPEObj(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); 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.2412.0/runtime/Makefile.in0000664000175000017500000043002414723322621012672 # 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_OPENSSL_TRUE@am__append_15 = lmnsd_ossl.la # # GnuTLS netstream driver # @ENABLE_GNUTLS_TRUE@am__append_16 = lmnsd_gtls.la # # support library for libgcrypt # @ENABLE_LIBGCRYPT_TRUE@am__append_17 = libgcry.la @ENABLE_LIBGCRYPT_TRUE@am__append_18 = lmcry_gcry.la @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@am__append_19 = libossl.la @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@am__append_20 = lmcry_ossl.la # # support library for zstd # @ENABLE_LIBZSTD_TRUE@am__append_21 = lmzstdw.la # # gssapi support # @ENABLE_GSSAPI_TRUE@am__append_22 = lmgssutil.la @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_23 = $(LIBLOGGING_STDLOG_CFLAGS) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_24 = $(LIBLOGGING_STDLOG_LIBS) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_25 = $(LIBLOGGING_STDLOG_CFLAGS) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_26 = $(LIBLOGGING_STDLOG_LIBS) # # support library for Guardtime KSI-LS12 # @ENABLE_KSI_LS12_TRUE@am__append_27 = 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_2) am__dirstamp = $(am__leading_dot)dirstamp 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-ruleset.lo \ librsyslog_la-prop.lo librsyslog_la-ratelimit.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 @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_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 nssel.c nssel.h nspoll.c nspoll.h @ENABLE_INET_TRUE@am_lmnetstrms_la_OBJECTS = \ @ENABLE_INET_TRUE@ lmnetstrms_la-netstrms.lo \ @ENABLE_INET_TRUE@ lmnetstrms_la-netstrm.lo \ @ENABLE_INET_TRUE@ lmnetstrms_la-nssel.lo \ @ENABLE_INET_TRUE@ lmnetstrms_la-nspoll.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 nsdsel_gtls.c \ nsdsel_gtls.h @ENABLE_GNUTLS_TRUE@am_lmnsd_gtls_la_OBJECTS = \ @ENABLE_GNUTLS_TRUE@ lmnsd_gtls_la-nsd_gtls.lo \ @ENABLE_GNUTLS_TRUE@ lmnsd_gtls_la-nsdsel_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_OPENSSL_TRUE@lmnsd_ossl_la_DEPENDENCIES = \ @ENABLE_OPENSSL_TRUE@ $(am__DEPENDENCIES_1) am__lmnsd_ossl_la_SOURCES_DIST = net_ossl.c net_ossl.h nsd_ossl.c \ nsd_ossl.h nsdsel_ossl.c nsdsel_ossl.h @ENABLE_OPENSSL_TRUE@am_lmnsd_ossl_la_OBJECTS = \ @ENABLE_OPENSSL_TRUE@ lmnsd_ossl_la-net_ossl.lo \ @ENABLE_OPENSSL_TRUE@ lmnsd_ossl_la-nsd_ossl.lo \ @ENABLE_OPENSSL_TRUE@ lmnsd_ossl_la-nsdsel_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_OPENSSL_TRUE@am_lmnsd_ossl_la_rpath = -rpath $(pkglibdir) lmnsd_ptcp_la_DEPENDENCIES = am__lmnsd_ptcp_la_SOURCES_DIST = nsd_ptcp.c nsd_ptcp.h nsdsel_ptcp.c \ nsdsel_ptcp.h nsdpoll_ptcp.c nsdpoll_ptcp.h @ENABLE_INET_TRUE@am_lmnsd_ptcp_la_OBJECTS = \ @ENABLE_INET_TRUE@ lmnsd_ptcp_la-nsd_ptcp.lo \ @ENABLE_INET_TRUE@ lmnsd_ptcp_la-nsdsel_ptcp.lo \ @ENABLE_INET_TRUE@ lmnsd_ptcp_la-nsdpoll_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)/librsyslog_la-action.Plo \ ../$(DEPDIR)/librsyslog_la-outchannel.Plo \ ../$(DEPDIR)/librsyslog_la-parse.Plo \ ../$(DEPDIR)/librsyslog_la-template.Plo \ ../$(DEPDIR)/librsyslog_la-threads.Plo \ ./$(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-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-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-ratelimit.Plo \ ./$(DEPDIR)/librsyslog_la-rsconf.Plo \ ./$(DEPDIR)/librsyslog_la-rsyslog.Plo \ ./$(DEPDIR)/librsyslog_la-ruleset.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-timezones.Plo \ ./$(DEPDIR)/librsyslog_la-var.Plo \ ./$(DEPDIR)/librsyslog_la-wti.Plo \ ./$(DEPDIR)/librsyslog_la-wtp.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)/lmnetstrms_la-netstrm.Plo \ ./$(DEPDIR)/lmnetstrms_la-netstrms.Plo \ ./$(DEPDIR)/lmnetstrms_la-nspoll.Plo \ ./$(DEPDIR)/lmnetstrms_la-nssel.Plo \ ./$(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo \ ./$(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Plo \ ./$(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo \ ./$(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo \ ./$(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Plo \ ./$(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo \ ./$(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Plo \ ./$(DEPDIR)/lmnsd_ptcp_la-nsdsel_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_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_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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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_17) $(am__append_19) # # 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_18) $(am__append_20) $(am__append_21) \ $(am__append_22) lmtcpsrv.la lmtcpclt.la $(am__append_27) #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 \ 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 \ 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 \ ruleset.c \ ruleset.h \ prop.c \ prop.h \ ratelimit.c \ ratelimit.h \ lookup.c \ lookup.h \ cfsysline.c \ cfsysline.h \ \ ../action.h \ ../action.c \ ../threads.c \ ../threads.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@ $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \ @WITH_MODDIRS_FALSE@ $(LIBUUID_CFLAGS) $(LIBFASTJSON_CFLAGS) \ @WITH_MODDIRS_FALSE@ ${LIBESTR_CFLAGS} $(am__append_1) \ @WITH_MODDIRS_FALSE@ -I\$(top_srcdir)/tools # the files with ../ we need to work on - so that they either become part of the # runtime or will no longer be needed. -- rgerhards, 2008-06-13 # #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} $(am__append_1) \ @WITH_MODDIRS_TRUE@ -I\$(top_srcdir)/tools librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS) $(LIBUUID_LIBS) \ $(LIBFASTJSON_LIBS) ${LIBESTR_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 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@ nssel.c nssel.h \ @ENABLE_INET_TRUE@ nspoll.c nspoll.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@ nsdsel_ptcp.c nsdsel_ptcp.h \ @ENABLE_INET_TRUE@ nsdpoll_ptcp.c nsdpoll_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_OPENSSL_TRUE@lmnsd_ossl_la_SOURCES = net_ossl.c net_ossl.h nsd_ossl.c nsd_ossl.h nsdsel_ossl.c nsdsel_ossl.h @ENABLE_OPENSSL_TRUE@lmnsd_ossl_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(OPENSSL_CFLAGS) @ENABLE_OPENSSL_TRUE@lmnsd_ossl_la_LDFLAGS = -module -avoid-version @ENABLE_OPENSSL_TRUE@lmnsd_ossl_la_LIBADD = $(OPENSSL_LIBS) @ENABLE_GNUTLS_TRUE@lmnsd_gtls_la_SOURCES = nsd_gtls.c nsd_gtls.h nsdsel_gtls.c nsdsel_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_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 @ENABLE_GSSAPI_TRUE@lmgssutil_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_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_23) lmtcpsrv_la_LDFLAGS = -module -avoid-version $(am__append_24) lmtcpsrv_la_LIBADD = # # TCP (stream) client support # lmtcpclt_la_SOURCES = \ tcpclt.c \ tcpclt.h lmtcpclt_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \ $(am__append_25) lmtcpclt_la_LDFLAGS = -module -avoid-version $(am__append_26) 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) ../$(am__dirstamp): @$(MKDIR_P) .. @: > ../$(am__dirstamp) ../$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) ../$(DEPDIR) @: > ../$(DEPDIR)/$(am__dirstamp) ../librsyslog_la-action.lo: ../$(am__dirstamp) \ ../$(DEPDIR)/$(am__dirstamp) ../librsyslog_la-threads.lo: ../$(am__dirstamp) \ ../$(DEPDIR)/$(am__dirstamp) ../librsyslog_la-parse.lo: ../$(am__dirstamp) \ ../$(DEPDIR)/$(am__dirstamp) ../librsyslog_la-outchannel.lo: ../$(am__dirstamp) \ ../$(DEPDIR)/$(am__dirstamp) ../librsyslog_la-template.lo: ../$(am__dirstamp) \ ../$(DEPDIR)/$(am__dirstamp) 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_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) -rm -f ../*.$(OBJEXT) -rm -f ../*.lo distclean-compile: -rm -f *.tab.c @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-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-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)/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-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-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-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-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-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-timezones.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)/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)/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)/lmnetstrms_la-nspoll.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnetstrms_la-nssel.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_gtls_la-nsdsel_gtls.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-nsd_ossl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_ossl_la-nsdsel_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)/lmnsd_ptcp_la-nsdpoll_ptcp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_ptcp_la-nsdsel_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-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-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-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 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 lmnetstrms_la-nssel.lo: nssel.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-nssel.lo -MD -MP -MF $(DEPDIR)/lmnetstrms_la-nssel.Tpo -c -o lmnetstrms_la-nssel.lo `test -f 'nssel.c' || echo '$(srcdir)/'`nssel.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnetstrms_la-nssel.Tpo $(DEPDIR)/lmnetstrms_la-nssel.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nssel.c' object='lmnetstrms_la-nssel.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-nssel.lo `test -f 'nssel.c' || echo '$(srcdir)/'`nssel.c lmnetstrms_la-nspoll.lo: nspoll.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-nspoll.lo -MD -MP -MF $(DEPDIR)/lmnetstrms_la-nspoll.Tpo -c -o lmnetstrms_la-nspoll.lo `test -f 'nspoll.c' || echo '$(srcdir)/'`nspoll.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnetstrms_la-nspoll.Tpo $(DEPDIR)/lmnetstrms_la-nspoll.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nspoll.c' object='lmnetstrms_la-nspoll.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-nspoll.lo `test -f 'nspoll.c' || echo '$(srcdir)/'`nspoll.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_gtls_la-nsdsel_gtls.lo: nsdsel_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-nsdsel_gtls.lo -MD -MP -MF $(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Tpo -c -o lmnsd_gtls_la-nsdsel_gtls.lo `test -f 'nsdsel_gtls.c' || echo '$(srcdir)/'`nsdsel_gtls.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Tpo $(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsdsel_gtls.c' object='lmnsd_gtls_la-nsdsel_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-nsdsel_gtls.lo `test -f 'nsdsel_gtls.c' || echo '$(srcdir)/'`nsdsel_gtls.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-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_ossl_la-nsdsel_ossl.lo: nsdsel_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-nsdsel_ossl.lo -MD -MP -MF $(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Tpo -c -o lmnsd_ossl_la-nsdsel_ossl.lo `test -f 'nsdsel_ossl.c' || echo '$(srcdir)/'`nsdsel_ossl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Tpo $(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsdsel_ossl.c' object='lmnsd_ossl_la-nsdsel_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-nsdsel_ossl.lo `test -f 'nsdsel_ossl.c' || echo '$(srcdir)/'`nsdsel_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 lmnsd_ptcp_la-nsdsel_ptcp.lo: nsdsel_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-nsdsel_ptcp.lo -MD -MP -MF $(DEPDIR)/lmnsd_ptcp_la-nsdsel_ptcp.Tpo -c -o lmnsd_ptcp_la-nsdsel_ptcp.lo `test -f 'nsdsel_ptcp.c' || echo '$(srcdir)/'`nsdsel_ptcp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ptcp_la-nsdsel_ptcp.Tpo $(DEPDIR)/lmnsd_ptcp_la-nsdsel_ptcp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsdsel_ptcp.c' object='lmnsd_ptcp_la-nsdsel_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-nsdsel_ptcp.lo `test -f 'nsdsel_ptcp.c' || echo '$(srcdir)/'`nsdsel_ptcp.c lmnsd_ptcp_la-nsdpoll_ptcp.lo: nsdpoll_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-nsdpoll_ptcp.lo -MD -MP -MF $(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Tpo -c -o lmnsd_ptcp_la-nsdpoll_ptcp.lo `test -f 'nsdpoll_ptcp.c' || echo '$(srcdir)/'`nsdpoll_ptcp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Tpo $(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsdpoll_ptcp.c' object='lmnsd_ptcp_la-nsdpoll_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-nsdpoll_ptcp.lo `test -f 'nsdpoll_ptcp.c' || echo '$(srcdir)/'`nsdpoll_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 -rm -rf ../.libs ../_libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(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) -rm -f ../$(DEPDIR)/$(am__dirstamp) -rm -f ../$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ clean-noinstLTLIBRARIES clean-pkglibLTLIBRARIES \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -f ../$(DEPDIR)/librsyslog_la-action.Plo -rm -f ../$(DEPDIR)/librsyslog_la-outchannel.Plo -rm -f ../$(DEPDIR)/librsyslog_la-parse.Plo -rm -f ../$(DEPDIR)/librsyslog_la-template.Plo -rm -f ../$(DEPDIR)/librsyslog_la-threads.Plo -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-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-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-ratelimit.Plo -rm -f ./$(DEPDIR)/librsyslog_la-rsconf.Plo -rm -f ./$(DEPDIR)/librsyslog_la-rsyslog.Plo -rm -f ./$(DEPDIR)/librsyslog_la-ruleset.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-timezones.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)/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)/lmnetstrms_la-netstrm.Plo -rm -f ./$(DEPDIR)/lmnetstrms_la-netstrms.Plo -rm -f ./$(DEPDIR)/lmnetstrms_la-nspoll.Plo -rm -f ./$(DEPDIR)/lmnetstrms_la-nssel.Plo -rm -f ./$(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo -rm -f ./$(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Plo -rm -f ./$(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo -rm -f ./$(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo -rm -f ./$(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Plo -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Plo -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsdsel_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 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)/librsyslog_la-action.Plo -rm -f ../$(DEPDIR)/librsyslog_la-outchannel.Plo -rm -f ../$(DEPDIR)/librsyslog_la-parse.Plo -rm -f ../$(DEPDIR)/librsyslog_la-template.Plo -rm -f ../$(DEPDIR)/librsyslog_la-threads.Plo -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-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-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-ratelimit.Plo -rm -f ./$(DEPDIR)/librsyslog_la-rsconf.Plo -rm -f ./$(DEPDIR)/librsyslog_la-rsyslog.Plo -rm -f ./$(DEPDIR)/librsyslog_la-ruleset.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-timezones.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)/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)/lmnetstrms_la-netstrm.Plo -rm -f ./$(DEPDIR)/lmnetstrms_la-netstrms.Plo -rm -f ./$(DEPDIR)/lmnetstrms_la-nspoll.Plo -rm -f ./$(DEPDIR)/lmnetstrms_la-nssel.Plo -rm -f ./$(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo -rm -f ./$(DEPDIR)/lmnsd_gtls_la-nsdsel_gtls.Plo -rm -f ./$(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo -rm -f ./$(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo -rm -f ./$(DEPDIR)/lmnsd_ossl_la-nsdsel_ossl.Plo -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsdpoll_ptcp.Plo -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsdsel_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-generic clean-libtool clean-noinstLIBRARIES \ clean-noinstLTLIBRARIES clean-pkglibLTLIBRARIES \ clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-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.2412.0/runtime/lib_ksi_queue.c0000664000175000017500000001237414723322534013620 #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.2412.0/runtime/hashtable_itr.c0000664000175000017500000001240014650736301013577 /* 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.2412.0/runtime/libcry_common.h0000664000175000017500000000250014704407366013635 /* 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.2412.0/runtime/regexp.c0000664000175000017500000002454014650736301012270 /* 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 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 */ pthread_mutex_destroy(&mut_regexp); if (regex_to_uncomp) hashtable_destroy(regex_to_uncomp, 1); if (perthread_regexs) hashtable_destroy(perthread_regexs, 1); } ENDObjClassExit(regexp) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit 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.2412.0/runtime/dynstats.h0000664000175000017500000000507614650736301012657 /* * 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 "hashtable.h" typedef struct hashtable htable; 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 { 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; 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; }; struct dynstats_buckets_s { struct dynstats_bucket_s *list; statsobj_t *global_stats; pthread_rwlock_t lock; uint8_t initialized; }; 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(void); void dynstats_resetExpired(void); rsRetVal dynstatsClassInit(void); #endif /* #ifndef INCLUDED_DYNSTATS_H */ rsyslog-8.2412.0/runtime/queue.c0000664000175000017500000037360014650736301012126 /* 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 aquainted 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-2019 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 #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"? */ /* 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 qDestructDisk(qqueue_t *pThis); rsRetVal qqueueSetSpoolDir(qqueue_t *pThis, uchar *pszSpoolDir, int lenSpoolDir); /* 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.workerthreads", eCmdHdlrInt, 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 } }; 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); } } /*********************************************************************** * 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; 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 */ for( pPrev = pQueue->toDeleteLst ; pPrev != NULL && deqID > pPrev->deqID ; pPrev = pPrev->pNext) { /*JUST SEARCH*/; } if(pPrev == NULL) { pNew->pNext = pQueue->toDeleteLst; pQueue->toDeleteLst = pNew; } else { pNew->pNext = pPrev->pNext; pPrev->pNext = pNew; } 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; 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) { return (int) PREFER_FETCH_32BIT(pThis->iQueueSize); } /* 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) { return pThis->iQueueSize - pThis->nLogDeq; } /* 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 ressources and does * this much quicker than when we clean up ourselvs. -- 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); /* disk queues have always 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; } /* Start disk-assisted queue mode. * rgerhards, 2008-01-15 */ static rsRetVal StartDA(qqueue_t *pThis) { DEFiRet; uchar pszDAQName[128]; ISOBJ_TYPE_assert(pThis, qqueue); /* create message queue */ CHKiRet(qqueueConstruct(&pThis->pqDA, QUEUETYPE_DISK, 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; 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; if(pThis->useCryprov) { /* 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) { if(pThis->pqDA != NULL) { qqueueDestruct(&pThis->pqDA); } LogError(0, iRet, "%s: error creating disk queue - giving up.", obj.GetName((obj_t*)pThis)); pThis->bIsDA = 0; } 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. Ressources 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(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 -------------------- */ /* 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 * themselfs can lead to segfault. So we prefer to was some ressources 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)); 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.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)); CHKiRet(strm.SeekCurrOffs(pThis->tVars.disk.pReadDel)); CHKiRet(strm.SeekCurrOffs(pThis->tVars.disk.pReadDeq)); /* 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); /* and now check if there is some persistent information that needs to be read in */ iRet = qqueueTryLoadPersistedInfo(pThis); 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, 10000000)); CHKiRet(strm.SettOperationsMode(pThis->tVars.disk.pWrite, STREAMMODE_WRITE)); CHKiRet(strm.SetsType(pThis->tVars.disk.pWrite, STREAMTYPE_FILE_CIRCULAR)); 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, 10000000)); CHKiRet(strm.SettOperationsMode(pThis->tVars.disk.pReadDeq, STREAMMODE_READ)); CHKiRet(strm.SetsType(pThis->tVars.disk.pReadDeq, STREAMTYPE_FILE_CIRCULAR)); 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, 10000000)); CHKiRet(strm.SettOperationsMode(pThis->tVars.disk.pReadDel, STREAMMODE_READ)); CHKiRet(strm.SetsType(pThis->tVars.disk.pReadDel, STREAMTYPE_FILE_CIRCULAR)); 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) { int64 currOffs; strm.GetCurrOffset(pThis->tVars.disk.pWrite, &currOffs); if(currOffs == 0) { /* if no data is present, we can (and must!) delete this * file. Else we can leave garbagge after termination. */ 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); 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 qDeqDisk(qqueue_t *pThis, smsg_t **ppMsg) { DEFiRet; iRet = objDeserializeWithMethods(ppMsg, (uchar*) "msg", 3, pThis->tVars.disk.pReadDeq, NULL, NULL, msgConstructForDeserializer, NULL, MsgDeserialize); 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; } /* -------------------- 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(); pWti->pbShutdownImmediate = &pThis->bShutdownImmediate; 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->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; } /* generic code to dequeue a queue entry */ static rsRetVal qqueueDeq(qqueue_t *pThis, smsg_t **ppMsg) { DEFiRet; assert(pThis != NULL); /* we do NOT abort if we encounter an error, because otherwise the queue * will not be decremented, what will most probably result in an endless loop. * If we decrement, however, we may lose a message. But that is better than * losing the whole process because it loops... -- rgerhards, 2008-01-03 */ iRet = pThis->qDeq(pThis, ppMsg); ATOMIC_INC(&pThis->nLogDeq, &pThis->mutLogDeq); DBGOPRINT((obj_t*) pThis, "entry deleted, size now log %d, phys %d entries\n", getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis)); 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; pThis->bShutdownImmediate = 1; /* now DA queue */ if(pThis->bIsDA) { pThis->pqDA->bEnqOnly = 1; pThis->pqDA->bShutdownImmediate = 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; 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); } /* ... 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); } /* 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 */ } 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); int physQueueSize; physQueueSize = getPhysicalQueueSize(pThis); pthread_mutex_unlock(pThis->mut); if(physQueueSize > 0) { CHKiRet(tryShutdownWorkersWithinActionTimeout(pThis)); } CHKiRet(cancelWorkers(pThis)); /* ... finally ... all worker threads have terminated :-) * Well, more precisely, they *are in termination*. Some cancel cleanup handlers * may still be running. Note that the main queue's DA worker may still be running. */ 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->iNumWorkerThreads = iWorkerThreads; 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->pszFilePrefix = NULL; pThis->qType = qType; INIT_ATOMIC_HELPER_MUT(pThis->mutQueueSize); INIT_ATOMIC_HELPER_MUT(pThis->mutLogDeq); 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 */ } /* 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 */ } /* 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; } /* 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 anaylzer 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) { pThis->tVars.disk.sizeOnDisk -= bytesDel; 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; } /* remove messages from the physical queue store that are fully processed. This is * controlled via the to-delete list. */ static rsRetVal DeleteBatchFromQStore(qqueue_t *pThis, batch_t *pBatch) { toDeleteLst_t *pTdl; qDeqID deqIDDel; 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) { /* to-delete list empty */ DoDeleteBatchFromQStore(pThis, pBatch->nElem); } else if(pBatch->deqID == pThis->deqIDDel) { deqIDDel = pThis->deqIDDel; pTdl = tdlPeek(pThis); while(pTdl != NULL && deqIDDel == pTdl->deqID) { DoDeleteBatchFromQStore(pThis, pTdl->nElemDeq); tdlPop(pThis); ++deqIDDel; pTdl = tdlPeek(pThis); } /* old entries deleted, now delete current ones... */ DoDeleteBatchFromQStore(pThis, pBatch->nElem); } else { /* can not 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->nElem)); } 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); 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; struct timespec timeout; smsg_t *pMsg; rsRetVal localRet; DEFiRet; nDeleted = pWti->batch.nElemDeq; DeleteProcessedBatch(pThis, &pWti->batch); nDequeued = nDiscarded = 0; if(pThis->qType == QUEUETYPE_DISK) { pThis->tVars.disk.deqFileNumIn = strmGetCurrFileNum(pThis->tVars.disk.pReadDeq); } /* 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; } 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); *pSkippedMsgs = iQueueSize; # ifdef ENABLE_IMDIAG iOverallQueueSize -= iQueueSize; # endif pThis->iQueueSize -= iQueueSize; iQueueSize = 0; break; } localRet = qqueueDeq(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); } CHKiRet(localRet); /* 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(!pThis->bShutdownImmediate && 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) { 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) { 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) { 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); pWti->pbShutdownImmediate = &pThis->bShutdownImmediate; 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 && !pThis->bShutdownImmediate ; 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); } } 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! * If we are a child, we have done our duty when the queue is empty. In that case, * we can terminate. Version for the regular worker thread. */ 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; } else if(pThis->pqParent != NULL) { iRet = RS_RET_TERMINATE_WHEN_IDLE; } 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); } /* set type-specific handlers and other very type-specific things * (we can not totally hide it...) */ 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_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; } /* 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)); CHKiRet(wtpSetpUsr (pThis->pWtpReg, pThis)); CHKiRet(wtpConstructFinalize (pThis->pWtpReg)); /* set up DA system if we have a disk-assisted queue */ if(pThis->bIsDA) 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->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)); 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_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; #ifdef _AIX lentmpQIFName = strlen( pThis->pszQIFNam) + strlen(".tmp") + 1; tmpQIFName = malloc(sizeof(char)*lentmpQIFName); if(tmpQIFName == NULL) tmpQIFName = (char*)pThis->pszQIFNam; snprintf(tmpQIFName, lentmpQIFName, "%s.tmp", pThis->pszQIFNam); #else lentmpQIFName = asprintf((char **)&tmpQIFName, "%s.tmp", pThis->pszQIFNam); if(tmpQIFName == NULL) tmpQIFName = (char*)pThis->pszQIFNam; #endif 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.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; } /* check if we need to persist the current queue info. If an * error occurs, this should be ignored by caller (but we still * abide to our regular call interface)... * rgerhards, 2008-01-13 * nUpdates is the number of updates since the last call to this function. * It may be > 1 due to batches. -- rgerhards, 2009-05-12 */ static rsRetVal qqueueChkPersist(qqueue_t *const pThis, const int nUpdates) { DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); assert(nUpdates >= 0); if(nUpdates == 0) 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"); pThis->bShutdownImmediate = 0; /* would termiante 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); 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 */ if(pThis->qType != QUEUETYPE_DIRECT && pThis->pWtpReg != NULL) { wtpDestruct(&pThis->pWtpReg); } /* Now check if we actually have a DA queue and, if so, destruct it. * Note that the wtp must be destructed first, it may be in cancel cleanup handler * *right now* and actually *need* to access the queue object to persist some final * data (re-queueing case). So we need to destruct the wtp first, which will make * sure all workers have terminated. 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); /* 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); /* 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)) { 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, pThis->tVars.disk.sizeOnDisk, 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); 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(); pWti->pbShutdownImmediate = &pThis->bShutdownImmediate; 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 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); } } RETiRet; } void qqueueCorrectParams(qqueue_t *pThis) { int goodval; /* a "good value" to use for comparisons (different objects) */ 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 < 2 || pThis->iHighWtrMrk > pThis->iMaxQueueSize) { pThis->iHighWtrMrk = (pThis->iMaxQueueSize / 100) * 90; if(pThis->iHighWtrMrk == 0) { /* guard against very low max queue sizes! */ pThis->iHighWtrMrk = pThis->iMaxQueueSize; } } if( pThis->iLowWtrMrk < 2 || pThis->iLowWtrMrk > pThis->iMaxQueueSize || pThis->iLowWtrMrk > pThis->iHighWtrMrk ) { pThis->iLowWtrMrk = (pThis->iMaxQueueSize / 100) * 70; if(pThis->iLowWtrMrk == 0) { pThis->iLowWtrMrk = 1; } } 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")) { 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")) { pThis->cryprovName = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(pblk.descr[i].name, "queue.spooldirectory")) { free(pThis->pszSpoolDir); pThis->pszSpoolDir = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL); pThis->lenSpoolDir = es_strlen(pvals[i].val.d.estr); if(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.workerthreads")) { pThis->iNumWorkerThreads = 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 { DBGPRINTF("queue: program error, non-handled " "param '%s'\n", pblk.descr[i].name); } } 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; } } 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) { 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) { 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) && USTR_EQUALS(pszFilePrefix) && USTR_EQUALS(cryprovName) ); } /* some simple object access methods */ 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, iNumWorkerThreads, 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) /* 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.2412.0/runtime/nsdpoll_ptcp.c0000664000175000017500000002324214723310736013476 /* nsdpoll_ptcp.c * * An implementation of the nsd epoll() interface for plain tcp sockets. * * Copyright 2009-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" #ifdef HAVE_EPOLL_CREATE /* this module requires epoll! */ #include #include #include #include #ifdef HAVE_SYS_EPOLL_H # include #endif #include "rsyslog.h" #include "module-template.h" #include "obj.h" #include "errmsg.h" #include "srUtils.h" #include "nspoll.h" #include "nsd_ptcp.h" #include "nsdpoll_ptcp.h" /* static data */ DEFobjStaticHelpers DEFobjCurrIf(glbl) /* -START------------------------- helpers for event list ------------------------------------ */ /* add new entry to list. We assume that the fd is not already present and DO NOT check this! * Returns newly created entry in pEvtLst. * Note that we currently need to use level-triggered mode, because the upper layers do not work * in parallel. As such, in edge-triggered mode we may not get notified, because new data comes * in after we have read everything that was present. To use ET mode, we need to change the upper * peers so that they immediately start a new wait before processing the data read. That obviously * requires more elaborate redesign and we postpone this until the current more simplictic mode has * been proven OK in practice. * rgerhards, 2009-11-18 */ static rsRetVal addEvent(nsdpoll_ptcp_t *pThis, int id, void *pUsr, int mode, nsd_ptcp_t *pSock, nsdpoll_epollevt_lst_t **pEvtLst) { nsdpoll_epollevt_lst_t *pNew; DEFiRet; CHKmalloc(pNew = (nsdpoll_epollevt_lst_t*) calloc(1, sizeof(nsdpoll_epollevt_lst_t))); pNew->id = id; pNew->pUsr = pUsr; pNew->pSock = pSock; pNew->event.events = 0; /* TODO: at some time we should be able to use EPOLLET */ if(mode & NSDPOLL_IN) pNew->event.events |= EPOLLIN; if(mode & NSDPOLL_OUT) pNew->event.events |= EPOLLOUT; pNew->event.data.ptr = pNew; pthread_mutex_lock(&pThis->mutEvtLst); pNew->pNext = pThis->pRoot; pThis->pRoot = pNew; pthread_mutex_unlock(&pThis->mutEvtLst); *pEvtLst = pNew; finalize_it: RETiRet; } /* find and unlink the entry identified by id/pUsr from the list. * rgerhards, 2009-11-23 */ static rsRetVal unlinkEvent(nsdpoll_ptcp_t *pThis, int id, void *pUsr, nsdpoll_epollevt_lst_t **ppEvtLst) { nsdpoll_epollevt_lst_t *pEvtLst; nsdpoll_epollevt_lst_t *pPrev = NULL; DEFiRet; pthread_mutex_lock(&pThis->mutEvtLst); pEvtLst = pThis->pRoot; while(pEvtLst != NULL && !(pEvtLst->id == id && pEvtLst->pUsr == pUsr)) { pPrev = pEvtLst; pEvtLst = pEvtLst->pNext; } if(pEvtLst == NULL) ABORT_FINALIZE(RS_RET_NOT_FOUND); *ppEvtLst = pEvtLst; /* unlink */ if(pPrev == NULL) pThis->pRoot = pEvtLst->pNext; else pPrev->pNext = pEvtLst->pNext; finalize_it: pthread_mutex_unlock(&pThis->mutEvtLst); RETiRet; } /* destruct the provided element. It must already be unlinked from the list. * rgerhards, 2009-11-23 */ static rsRetVal delEvent(nsdpoll_epollevt_lst_t **ppEvtLst) { DEFiRet; free(*ppEvtLst); *ppEvtLst = NULL; RETiRet; } /* -END--------------------------- helpers for event list ------------------------------------ */ /* Standard-Constructor */ BEGINobjConstruct(nsdpoll_ptcp) /* be sure to specify the object type also in END macro! */ #if defined(EPOLL_CLOEXEC) && defined(HAVE_EPOLL_CREATE1) DBGPRINTF("nsdpoll_ptcp uses epoll_create1()\n"); pThis->efd = epoll_create1(EPOLL_CLOEXEC); if(pThis->efd < 0 && errno == ENOSYS) #endif { DBGPRINTF("nsdpoll_ptcp uses epoll_create()\n"); pThis->efd = epoll_create(100); /* size is ignored in newer kernels, but 100 is not bad... */ } if(pThis->efd < 0) { DBGPRINTF("epoll_create1() could not create fd\n"); ABORT_FINALIZE(RS_RET_IO_ERROR); } pthread_mutex_init(&pThis->mutEvtLst, NULL); finalize_it: ENDobjConstruct(nsdpoll_ptcp) /* destructor for the nsdpoll_ptcp object */ BEGINobjDestruct(nsdpoll_ptcp) /* be sure to specify the object type also in END and CODESTART macros! */ nsdpoll_epollevt_lst_t *node; nsdpoll_epollevt_lst_t *nextnode; CODESTARTobjDestruct(nsdpoll_ptcp) /* we check if the epoll list still holds entries. This may happen, but * is a bit unusual. */ if(pThis->pRoot != NULL) { for(node = pThis->pRoot ; node != NULL ; node = nextnode) { nextnode = node->pNext; dbgprintf("nsdpoll_ptcp destruct, need to destruct node %p\n", node); delEvent(&node); } } pthread_mutex_destroy(&pThis->mutEvtLst); ENDobjDestruct(nsdpoll_ptcp) /* Modify socket set */ static rsRetVal Ctl(nsdpoll_t *pNsdpoll, nsd_t *pNsd, int id, void *pUsr, int mode, int op) { nsdpoll_ptcp_t *pThis = (nsdpoll_ptcp_t*) pNsdpoll; nsd_ptcp_t *pSock = (nsd_ptcp_t*) pNsd; nsdpoll_epollevt_lst_t *pEventLst; int errSave; char errStr[512]; DEFiRet; if(op == NSDPOLL_ADD) { dbgprintf("adding nsdpoll entry %d/%p, sock %d\n", id, pUsr, pSock->sock); CHKiRet(addEvent(pThis, id, pUsr, mode, pSock, &pEventLst)); if(epoll_ctl(pThis->efd, EPOLL_CTL_ADD, pSock->sock, &pEventLst->event) < 0) { errSave = errno; rs_strerror_r(errSave, errStr, sizeof(errStr)); LogError(errSave, RS_RET_ERR_EPOLL_CTL, "epoll_ctl failed on fd %d, id %d/%p, op %d with %s\n", pSock->sock, id, pUsr, mode, errStr); } } else if(op == NSDPOLL_DEL) { dbgprintf("removing nsdpoll entry %d/%p, sock %d\n", id, pUsr, pSock->sock); CHKiRet(unlinkEvent(pThis, id, pUsr, &pEventLst)); if(epoll_ctl(pThis->efd, EPOLL_CTL_DEL, pSock->sock, &pEventLst->event) < 0) { errSave = errno; rs_strerror_r(errSave, errStr, sizeof(errStr)); LogError(errSave, RS_RET_ERR_EPOLL_CTL, "epoll_ctl failed on fd %d, id %d/%p, op %d with %s\n", pSock->sock, id, pUsr, mode, errStr); ABORT_FINALIZE(RS_RET_ERR_EPOLL_CTL); } CHKiRet(delEvent(&pEventLst)); } else { dbgprintf("program error: invalid NSDPOLL_mode %d - ignoring request\n", op); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: 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 Wait(nsdpoll_t *pNsdpoll, int timeout, int *numEntries, nsd_epworkset_t workset[]) { nsdpoll_ptcp_t *pThis = (nsdpoll_ptcp_t*) pNsdpoll; nsdpoll_epollevt_lst_t *pOurEvt; struct epoll_event event[128]; int nfds; int i; DEFiRet; assert(workset != NULL); if(*numEntries > 128) *numEntries = 128; DBGPRINTF("doing epoll_wait for max %d events\n", *numEntries); nfds = epoll_wait(pThis->efd, event, *numEntries, timeout); if(nfds == -1) { if(errno == EINTR) { ABORT_FINALIZE(RS_RET_EINTR); } else { DBGPRINTF("epoll() 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 returned %d entries\n", nfds); for(i = 0 ; i < nfds ; ++i) { pOurEvt = (nsdpoll_epollevt_lst_t*) event[i].data.ptr; workset[i].id = pOurEvt->id; workset[i].pUsr = pOurEvt->pUsr; } *numEntries = nfds; finalize_it: RETiRet; } /* ------------------------------ end support for the epoll() interface ------------------------------ */ /* queryInterface function */ BEGINobjQueryInterface(nsdpoll_ptcp) CODESTARTobjQueryInterface(nsdpoll_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(*)(nsdpoll_t**)) nsdpoll_ptcpConstruct; pIf->Destruct = (rsRetVal(*)(nsdpoll_t**)) nsdpoll_ptcpDestruct; pIf->Ctl = Ctl; pIf->Wait = Wait; finalize_it: ENDobjQueryInterface(nsdpoll_ptcp) /* exit our class */ BEGINObjClassExit(nsdpoll_ptcp, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(nsdpoll_ptcp) /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); ENDObjClassExit(nsdpoll_ptcp) /* Initialize the nsdpoll_ptcp class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINObjClassInit(nsdpoll_ptcp, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); /* set our own handlers */ ENDObjClassInit(nsdpoll_ptcp) #else #ifdef __xlc__ /* Xlc require some code, even unused, in source file*/ static void dummy(void) {} #endif #endif /* #ifdef HAVE_EPOLL_CREATE this module requires epoll! */ /* vi:set ai: */ rsyslog-8.2412.0/runtime/netstrm.c0000664000175000017500000003440514721360463012474 /* 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(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) { nsd_t *pNewNsd = NULL; DEFiRet; NULL_CHECK(pThis); assert(ppNew != NULL); /* accept the new connection */ CHKiRet(pThis->Drvr.AcceptConnReq(pThis->pDrvrData, &pNewNsd)); /* 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); CHKiRet(pNS->Drvr.LstnInit(pNS, pUsr, fAddLstn, iSessMax, cnf_params)); finalize_it: 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) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.Rcv(pThis->pDrvrData, pBuf, pLenBuf, oserr); 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 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; } 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; } /* 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; } /* 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->SetGnutlsPriorityString = SetGnutlsPriorityString; pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage; pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN; pIf->SetDrvrTlsVerifyDepth = SetDrvrTlsVerifyDepth; pIf->SetDrvrTlsCAFile = SetDrvrTlsCAFile; pIf->SetDrvrTlsCRLFile = SetDrvrTlsCRLFile; pIf->SetDrvrTlsKeyFile = SetDrvrTlsKeyFile; pIf->SetDrvrTlsCertFile = SetDrvrTlsCertFile; 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); 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 */ /* set our own handlers */ ENDObjClassInit(netstrm) rsyslog-8.2412.0/runtime/nsd.h0000664000175000017500000001442214723310736011566 /* 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-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_NSD_H #define INCLUDED_NSD_H #include /** * The following structure is a set of descriptors that need to be processed. * This set will be the result of the epoll call and be used * in the actual request processing stage. -- rgerhards, 2011-01-24 */ struct nsd_epworkset_s { int id; void *pUsr; }; 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); 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); 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... TODO: should be * reconsidered when a new ACL system is build. -- rgerhards, 2008-12-01 */ /* 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 (*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 *); ENDinterface(nsd) #define nsdCURR_IF_VERSION 16 /* 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 for the select call */ BEGINinterface(nsdsel) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(nsdsel_t **ppThis); rsRetVal (*Destruct)(nsdsel_t **ppThis); rsRetVal (*Add)(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp); rsRetVal (*Select)(nsdsel_t *pNsdsel, int *piNumReady); rsRetVal (*IsReady)(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady); ENDinterface(nsdsel) #define nsdselCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ /* interface for the epoll call */ BEGINinterface(nsdpoll) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(nsdpoll_t **ppThis); rsRetVal (*Destruct)(nsdpoll_t **ppThis); rsRetVal (*Ctl)(nsdpoll_t *pNsdpoll, nsd_t *pNsd, int id, void *pUsr, int mode, int op); rsRetVal (*Wait)(nsdpoll_t *pNsdpoll, int timeout, int *numReady, nsd_epworkset_t workset[]); ENDinterface(nsdpoll) #define nsdpollCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ #endif /* #ifndef INCLUDED_NSD_H */ rsyslog-8.2412.0/runtime/zlibw.h0000664000175000017500000000354714650736301012136 /* 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.2412.0/runtime/msg.c0000664000175000017500000046757214650736301011604 /* 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-2023 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 #define SYSLOG_NAMES #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 "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 */ /* inlines */ extern void msgSetPRI(smsg_t *const __restrict__ pMsg, syslog_pri_t pri); /* 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; /* 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); struct json_object *jsonDeepCopy(struct json_object *src); 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: */ static inline void MsgLock(smsg_t *pThis) { #if DEV_DEBUG == 1 dbgprintf("MsgLock(0x%lx)\n", (unsigned long) pThis); #endif pthread_mutex_lock(&pThis->mut); } static inline 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; } /* 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. */ static void 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); } } /* 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; prop_t *localName; 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) { /* we pass down the props, so no need for AddRef */ MsgSetRcvFromWithoutAddRef(pMsg, localName); MsgSetRcvFromIPWithoutAddRef(pMsg, ip); } } 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); 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); } } static 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; } /* 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, "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")) { *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_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); /* intialize 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->rcvFrom.pRcvFrom = NULL; pM->pRuleset = NULL; pM->json = NULL; pM->localvars = NULL; 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); } 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); 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); 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. We do not need to lock the * message object here, because a fully-created msg object is never * allowed to be manipulated. For this, MsgDup() must be used, so MsgDup() * can never run into a situation where the message object is being * modified while its content is copied - it's forbidden by definition. * rgerhards, 2007-07-10 */ 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->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); if(pOld->json != NULL) pNew->json = jsonDeepCopy(pOld->json); if(pOld->localvars != NULL) pNew->localvars = jsonDeepCopy(pOld->localvars); /* 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 /* 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); /* 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*) json_object_get_string(pThis->json); MsgUnlock(pThis); CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("json"), PROPTYPE_PSZ, (void*) psz)); } if(pThis->localvars != NULL) { MsgLock(pThis); psz = (uchar*) json_object_get_string(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) { if(pVar->val.pStr != NULL) rsCStrDestruct(&pVar->val.pStr); } } /* 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); } 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; } 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); } 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); 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(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(json_object_get_string(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); 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 { /* now we can try to emulate */ lenTAG = 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... */ 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; } /* 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; } /* 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) { strncpy(pThis->dfltTZ, tz, 7); pThis->dfltTZ[7] = '\0'; /* ensure 0-Term in case of overflow! */ } /* 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 msgSetFromSockinfo(smsg_t *pThis, struct sockaddr_storage *sa){ DEFiRet; assert(pThis->rcvFrom.pRcvFrom == NULL); CHKmalloc(pThis->rcvFrom.pfrominet = malloc(sizeof(struct sockaddr_storage))); memcpy(pThis->rcvFrom.pfrominet, sa, sizeof(struct sockaddr_storage)); finalize_it: RETiRet; } /* 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; } /* 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) { int lenNew; uchar *bufNew; DEFiRet; ISOBJ_TYPE_assert(pThis, msg); assert(pszMSG != NULL); lenNew = pThis->iLenRawMsg + lenMSG - pThis->iLenMSG; if(lenMSG > pThis->iLenMSG && lenNew >= CONF_RAWMSG_BUFSIZE) { /* we have lost our "bet" and need to alloc a new buffer ;) */ CHKmalloc(bufNew = malloc(lenNew + 1)); memcpy(bufNew, pThis->pszRawMsg, pThis->offMSG); if(pThis->pszRawMsg != pThis->szRawMsg) free(pThis->pszRawMsg); pThis->pszRawMsg = bufNew; } if(lenMSG > 0) memcpy(pThis->pszRawMsg + pThis->offMSG, pszMSG, lenMSG); pThis->pszRawMsg[lenNew] = '\0'; /* this also works with truncation! */ pThis->iLenRawMsg = lenNew; 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'. * 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! */ /* correct other information */ 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; } return(pBuf); } #undef tmpBUFSIZE /* clean up */ /* 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; CHKiRet(getJSONRootAndMutex(pMsg, pProp->id, &jroot, &mut)); pthread_mutex_lock(mut); 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(json_object_get_string(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; CHKiRet(getJSONRootAndMutex(pMsg, pProp->id, &jroot, &mut)); pthread_mutex_lock(mut); 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(json_object_get_string(*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); 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; uchar *dst_w; uchar *newbuf; DEFiRet; assert(len_none_escaped_head <= buflen); /* first copy over unescaped head string */ if(len_none_escaped_head+10 > sizeof(wrkbuf)) { dst_size = 2 * len_none_escaped_head; 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) { 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 != 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); *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; } /* we hope we have only few escapes... */ 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); *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**"));} 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 = 10; regmatch_t pmatch[10]; #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: pRes = getRcvFrom(pMsg); break; case PROP_FROMHOST_IP: pRes = getRcvFromIP(pMsg); 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: if(pMsg->json == NULL) { pRes = (uchar*) "{}"; bufLen = 2; *pbMustBeFreed = 0; } else { const char *jstr; MsgLock(pMsg); 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); MsgUnlock(pMsg); if(jstr == NULL) { RET_OUT_OF_MEMORY; } pRes = (uchar*)strdup(jstr); 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! */ pBufStart = pBuf = malloc(iLen + 1); if(pBuf == NULL) { if(*pbMustBeFreed == 1) free(pRes); RET_OUT_OF_MEMORY; } /* now copy */ memcpy(pBuf, pFld, iLen); bufLen = iLen; pBuf[iLen] = '\0'; /* terminate it */ if(*pbMustBeFreed == 1) free(pRes); pRes = pBufStart; *pbMustBeFreed = 1; } 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; uchar *pB; iLenBuf = pmatch[pTpe->data.field.iSubMatchToUse].rm_eo - pmatch[pTpe->data.field.iSubMatchToUse].rm_so; pB = malloc(iLenBuf + 1); if (pB == NULL) { if (*pbMustBeFreed == 1) free(pRes); RET_OUT_OF_MEMORY; } /* Lets copy the matched substring to the buffer */ memcpy(pB, pRes + iOffs + pmatch[pTpe->data.field.iSubMatchToUse].rm_so, iLenBuf); bufLen = iLenBuf; pB[iLenBuf] = '\0';/* terminate string, did not happen before */ if (*pbMustBeFreed == 1) free(pRes); pRes = pB; *pbMustBeFreed = 1; } } 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) { /* 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)) { snprintf((char*)szCCEsc, sizeof(szCCEsc), "#%3.3d", *pSrc); 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: json_object_get_string() manages the memory of the returned * string. So we MUST NOT free it! */ dbgprintf("DDDD: msgSetPropViaJSON key: '%s'\n", name); if(!strcmp(name, "rawmsg")) { psz = json_object_get_string(json); MsgSetRawMsg(pMsg, psz, strlen(psz)); } else if(!strcmp(name, "msg")) { psz = json_object_get_string(json); MsgReplaceMSG(pMsg, (const uchar*)psz, strlen(psz)); } else if(!strcmp(name, "syslogtag")) { psz = json_object_get_string(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 = json_object_get_string(json); MsgSetPROCID(pMsg, psz); } else if(!strcmp(name, "msgid")) { psz = json_object_get_string(json); MsgSetMSGID(pMsg, psz); } else if(!strcmp(name, "structured-data")) { psz = json_object_get_string(json); MsgSetStructuredData(pMsg, psz); } else if(!strcmp(name, "hostname") || !strcmp(name, "source")) { psz = json_object_get_string(json); MsgSetHOSTNAME(pMsg, (const uchar*)psz, strlen(psz)); } else if(!strcmp(name, "fromhost")) { psz = json_object_get_string(json); MsgSetRcvFromStr(pMsg, (const uchar*) psz, strlen(psz), &propFromHost); prop.Destruct(&propFromHost); } else if(!strcmp(name, "fromhost-ip")) { psz = json_object_get_string(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]; int key_len = strlen(key); char *array_idx_start = strstr(key, "["); 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 && (array_idx_end - key + 1) == key_len) { errno = 0; int idx = (int) strtol(array_idx_start + 1, &array_idx_num_end_discovered, 10); if (errno == 0 && array_idx_num_end_discovered == array_idx_end) { memcpy(namebuf, key, array_idx_start - key); namebuf[array_idx_start - key] = '\0'; json_bool found_obj = json_object_object_get_ex(root, namebuf, &arr); if (found_obj && json_object_is_type(arr, json_type_array)) { int len = json_object_array_length(arr); if (len > idx) { *value = json_object_array_get_idx(arr, 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 < sizeof(namebuf)-1 ; ++i, ++p) 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) { /* TODO: check & handle duplicate names */ 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; goto finalize_it; } 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); 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) { CHKiRet(jsonMerge(*jroot, 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(json_object_get_string(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 */ 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.2412.0/runtime/errmsg.c0000664000175000017500000002100614650736301012267 /* 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 "rsyslog.h" #include "obj.h" #include "msg.h" #include "errmsg.h" #include "operatingstate.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. */ static int fdOversizeMsgLog = -1; static pthread_mutex_t oversizeMsgLogMut = PTHREAD_MUTEX_INITIALIZER; /* ------------------------------ methods ------------------------------ */ /* Resets the error message flag. Must be done before processing config * files. */ void resetErrMsgsFlag(void) { bHadErrMsgs = 0; } int hadErrMsgs(void) { return bHadErrMsgs; } /* 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 */ 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) bHadErrMsgs = 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) { strncpy(buf, "error message lost due to problem with vsnprintf", sizeof(buf)); } 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) { strncpy(buf, "error message lost due to problem with vsnprintf", sizeof(buf)); } 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); json = json_object_new_object(); if(json == NULL) { FINALIZE; } getRawMsg(pMsg, &buf, &dummy); jval = json_object_new_string((char*)buf); json_object_object_add(json, "rawmsg", jval); getInputName(pMsg, &buf, &dummy); 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.2412.0/runtime/hashtable.c0000664000175000017500000002273314650736301012733 /* 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); 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; } /*****************************************************************************/ int hashtable_insert(struct hashtable *h, 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 = hash(h,k); idx = indexFor(h->tablelength,e->h); e->k = k; e->v = v; e->next = h->table[idx]; h->table[idx] = e; return -1; } /*****************************************************************************/ void * /* returns value associated with key */ hashtable_search(struct hashtable *h, void *k) { struct entry *e; unsigned int hashvalue, idx; hashvalue = hash(h,k); 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_remove(struct hashtable *h, 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 hashvalue, idx; hashvalue = hash(h,k); idx = indexFor(h->tablelength,hash(h,k)); 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; } /*****************************************************************************/ /* 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.2412.0/runtime/lmcry_ossl.h0000664000175000017500000000240014660643541013164 /* 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.2412.0/runtime/conf.c0000664000175000017500000004165514650736301011731 /* 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 abstration 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-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. */ #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 */ /* TODO: check NULL ptr */ 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 ) pmask[i] &= ~(1<> 3] = TABLE_ALLPRI; else pmask[i >> 3] = TABLE_NOPRI; } else if ( singlpri ) { if ( ignorepri ) pmask[i >> 3] &= ~(1<> 3] |= (1<> 3] = TABLE_NOPRI; else pmask[i >> 3] = TABLE_ALLPRI; } else { if ( ignorepri ) for (i2= 0; i2 <= pri; ++i2) pmask[i >> 3] &= ~(1<> 3] |= (1<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.2412.0/install-sh0000755000175000017500000003577614723322620011162 #!/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.2412.0/NEWS0000664000175000017500000000007614650736301007644 This file has been superseded by ChangeLog. Please see there. rsyslog-8.2412.0/COPYING0000664000175000017500000010451214330725737010206 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.2412.0/contrib/0000775000175000017500000000000014723322657010670 5rsyslog-8.2412.0/contrib/imhttp/0000775000175000017500000000000014723322657012175 5rsyslog-8.2412.0/contrib/imhttp/Makefile.am0000664000175000017500000000033214650736301014141 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) rsyslog-8.2412.0/contrib/imhttp/imhttp.c0000664000175000017500000011214414650736301013563 /* imhttp.c * This is an input module for receiving http input. * * 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 "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 INIT_SCRATCH_BUF_SIZE 4096 /* General purpose buffer size. */ #define IMHTTP_MAX_BUF_LEN (8192) struct option { const char *name; const char *val; }; struct auth_s { char workbuf[IMHTTP_MAX_BUF_LEN]; char* pworkbuf; size_t workbuf_len; char* pszUser; char* pszPasswd; }; struct data_parse_s { sbool content_compressed; sbool bzInitDone; /* did we do an init of zstrm already? */ z_stream zstrm; /* zip stream to use for tcp compression */ // 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; }; 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 */ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */ ratelimit_t *ratelimiter; unsigned int ratelimitInterval; unsigned int ratelimitBurst; 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 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]; 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 }, { "documentroot", eCmdHdlrString, 0 }, { "liboptions", eCmdHdlrArray, 0 }, }; static struct cnfparamblk modpblk = { CNFPARAMBLK_VERSION, sizeof(modpdescr)/sizeof(struct cnfparamdescr), modpdescr }; static struct cnfparamdescr inppdescr[] = { { "endpoint", eCmdHdlrString, 0}, { "basicauthfile", 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 }, { "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; /* FORWARD DECLARATIONS */ static rsRetVal processData(const instanceConf_t *const inst, struct conn_wrkr_s *connWrkr, const char* buf, size_t len); 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->ratelimiter = NULL; inst->pszInputName = NULL; inst->pInputName = NULL; inst->ratelimitBurst = 10000; /* arbitrary high limit */ inst->ratelimitInterval = 0; /* off */ 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 *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(*name = strdup(param)); CHKmalloc(*paramval = strdup(val)); finalize_it: 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; } #if 0 static int log_message(__attribute__((unused)) const struct mg_connection *conn, const char *message) { puts(message); return 1; } #endif /* * 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(__attribute__((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; 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); return NULL; } return data; } static void exit_thread(__attribute__((unused)) const struct mg_context *ctx, __attribute__((unused)) int thread_type, void *thread_pointer) { if (thread_type == 1) { struct conn_wrkr_s *data = (struct conn_wrkr_s *) thread_pointer; if (data->propRemoteAddr) { prop.Destruct(&data->propRemoteAddr); } if (data->scratchBufSize) { free(data->pScratchBuf); } free(data->pReadBuf); free(data->pMsg); free(data); } } 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); CHKmalloc(json = json_object_new_object()); for (int i = 0 ; i < count ; i++ ) { 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 */ strncpy(connWrkr->pScratchBuf, ri->http_headers[i].name, connWrkr->scratchBufSize - 1); /* make header lowercase */ char* pname = connWrkr->pScratchBuf; while (pname && *pname != '\0') { *pname = tolower(*pname); pname++; } json_object_object_add(json, (const char *const)connWrkr->pScratchBuf, jval); } CHKiRet(msgAddJSON(pMsg, (uchar*)"!metadata!httpheaders", json, 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) { strncpy(connWrkr->pScratchBuf, ri->query_string, connWrkr->scratchBufSize - 1); 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); CHKmalloc(jval); json_object_object_add(json, (const char *)key, jval); } } CHKiRet(msgAddJSON(pMsg, (uchar*)"!metadata!queryparams", json, 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; 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)); } ratelimitAddMsg(inst->ratelimiter, &connWrkr->multiSub, pMsg); STATSCOUNTER_INC(statsCounter.ctrSubmitted, statsCounter.mutCtrSubmitted); finalize_it: connWrkr->iMsg = 0; if (iRet != RS_RET_OK) { 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 %lu octets - max msg size is %lu\n", connWrkr->parseState.iOctetsRemain, s_iMaxLine); LogError(0, NO_ERRCODE, "received oversize message from peer: " "(hostname) (ip) %s: size is %lu bytes, max msg " "size is %lu, 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) { 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) { if (ch == '\n') { doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg); connWrkr->parseState.inputState = eAtStrtFram; } else { connWrkr->pMsg[connWrkr->iMsg++] = ch; } } else { doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg); connWrkr->parseState.inputState = eAtStrtFram; } pbuf++; } else { assert (connWrkr->parseState.framingMode == TCP_FRAMING_OCTET_COUNTING); /* parsing payload */ size_t remainingBytes = pbufLast - pbuf; // figure out how much is in block size_t count = min (connWrkr->parseState.iOctetsRemain, remainingBytes); if (connWrkr->iMsg + count >= s_iMaxLine) { count = s_iMaxLine - connWrkr->iMsg; } // just copy the bytes if (count) { memcpy(connWrkr->pMsg + connWrkr->iMsg, pbuf, count); pbuf += count; connWrkr->iMsg += count; connWrkr->parseState.iOctetsRemain -= count; } if (connWrkr->parseState.iOctetsRemain == 0) { doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg); connWrkr->parseState.inputState = eAtStrtFram; } } } else { // unexpected assert(0); break; } } 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; } doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg); } 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) { if (ch == '\n') { doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg); } else { connWrkr->pMsg[connWrkr->iMsg++] = ch; } } else { doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg); } pbuf++; } } 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 = len; /* run inflate() on buffer until everything has been uncompressed */ int outtotal = 0; do { int zRet = 0; int 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(processDataUncompressed(inst, connWrkr, (const char*)connWrkr->zipBuf, outavail)); } } 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; } /* Return 1 on success. Always initializes the auth structure. */ static int parse_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; } /* Parse authorization header */ const char* src = auth_header + 6; size_t len = apr_base64_decode_len((const char*)src); auth->pworkbuf = auth->workbuf; if (len > sizeof(auth->workbuf)) { auth->pworkbuf = calloc(0, len); auth->workbuf_len = len; } len = apr_base64_decode(auth->pworkbuf, src); if (len == 0) { return 0; } char *passwd = NULL, *saveptr = NULL; char *user = strtok_r(auth->pworkbuf, ":", &saveptr); if (user) { passwd = strtok_r(NULL, ":", &saveptr); } auth->pszUser = user; auth->pszPasswd = passwd; return 1; } static int read_auth_file(FILE* filep, struct auth_s *auth) { if (!filep) { 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(workbuf[l-1]) || iscntrl(workbuf[l-1])) { l--; workbuf[l] = 0; } else { break; } } if (l < 1) { continue; } if (workbuf[0] == '#') { continue; } user = workbuf; passwd = strchr(workbuf, ':'); if (!passwd) { continue; } *passwd = '\0'; passwd++; if (!strcasecmp(auth->pszUser, user)) { return (apr_password_validate(auth->pszPasswd, passwd) == APR_SUCCESS); } } return 0; } /* Authorize against the opened passwords file. Return 1 if authorized. */ static int authorize(struct mg_connection* conn, FILE* filep) { if (!conn || !filep) { return 0; } struct auth_s auth = { .workbuf_len=0, .pworkbuf=NULL, .pszUser=NULL, .pszPasswd=NULL}; if (!parse_auth_header(conn, &auth)) { return 0; } /* validate against htpasswd file */ return read_auth_file(filep, &auth); } /* Provides Basic Authorization handling that validates against a 'htpasswd' file. see also: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization */ static int basicAuthHandler(struct mg_connection *conn, void *cbdata) { const instanceConf_t* inst = (const instanceConf_t*) cbdata; char errStr[512]; FILE *fp = NULL; int ret = 1; if (!inst->pszBasicAuthFile) { mg_cry(conn, "warning: 'BasicAuthFile' not configured.\n"); ret = 0; goto finalize; } fp = fopen((const char *)inst->pszBasicAuthFile, "r"); if (fp == NULL) { if (strerror_r(errno, errStr, sizeof(errStr)) == 0) { mg_cry(conn, "error: 'BasicAuthFile' file '%s' could not be accessed: %s\n", inst->pszBasicAuthFile, errStr); } else { mg_cry(conn, "error: 'BasicAuthFile' file '%s' could not be accessed: %d\n", inst->pszBasicAuthFile, errno); } ret = 0; goto finalize; } ret = authorize(conn, fp); finalize: if (!ret) { mg_send_http_error(conn, 401, "WWW-Authenticate: Basic realm=\"User Visible Realm\"\n"); } if (fp ) { fclose(fp); } return ret; } /* 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; 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); connWrkr->multiSub.nElem = 0; memset(&connWrkr->parseState, 0, sizeof(connWrkr->parseState)); 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__); 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->content_length >= 0) { /* We know the content length in advance */ if (ri->content_length > (long long) connWrkr->readBufSize) { connWrkr->pReadBuf = realloc(connWrkr->pReadBuf, ri->content_length+1); if (!connWrkr->pReadBuf) { mg_cry(conn, "%s() - realloc failed!\n", __FUNCTION__); FINALIZE; } 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 */ } 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; } } } while (1) { int count = mg_read(conn, connWrkr->pReadBuf, connWrkr->readBufSize); if (count > 0) { processData(inst, connWrkr, (const char*)connWrkr->pReadBuf, count); } else { break; } } /* submit remainder */ doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg); multiSubmitFlush(&connWrkr->multiSub); 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; } static int runloop(void) { dbgprintf("imhttp started.\n"); /* Add handler for form data */ 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); mg_set_request_handler(s_httpserv->ctx, (char *)inst->pszEndpoint, postHandler, inst); if (inst->pszBasicAuthFile) { mg_set_auth_handler(s_httpserv->ctx, (char *)inst->pszEndpoint, basicAuthHandler, inst); } } } /* 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")) { inst->pszEndpoint = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "basicauthfile")) { inst->pszBasicAuthFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "ruleset")) { inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "name")) { inst->pszInputName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "ratelimit.burst")) { inst->ratelimitBurst = (unsigned int) pvals[i].val.d.n; } else if(!strcmp(inppblk.descr[i].name, "ratelimit.interval")) { inst->ratelimitInterval = (unsigned int) pvals[i].val.d.n; } 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->pszInputName) { CHKiRet(prop.Construct(&inst->pInputName)); CHKiRet(prop.SetString(inst->pInputName, inst->pszInputName, ustrlen(inst->pszInputName))); CHKiRet(prop.ConstructFinalize(inst->pInputName)); } CHKiRet(ratelimitNew(&inst->ratelimiter, "imphttp", NULL)); ratelimitSetLinuxLike(inst->ratelimiter, inst->ratelimitInterval, 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; ENDbeginCnfLoad BEGINsetModCnf struct cnfparamvals *pvals = 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); loadModConf->ports.name = strdup(CIVETWEB_OPTION_NAME_PORTS); loadModConf->ports.val = 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); loadModConf->docroot.name = strdup(CIVETWEB_OPTION_NAME_DOCUMENT_ROOT); loadModConf->docroot.val = es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(modpblk.descr[i].name, "liboptions")) { loadModConf->nOptions = pvals[i].val.d.ar->nmemb; CHKmalloc(loadModConf->options = malloc(sizeof(struct option) * pvals[i].val.d.ar->nmemb )); for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) { char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL); CHKiRet(processCivetwebOptions(cstr, &loadModConf->options[j].name, &loadModConf->options[j].val)); free(cstr); } } else { dbgprintf("imhttp: 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 */ 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, "imhttp: ruleset '%s' for %s not found - " "using default ruleset instead", inst->pszBindRuleset, inst->pszEndpoint); } BEGINcheckCnf instanceConf_t *inst; CODESTARTcheckCnf for(inst = pModConf->root ; inst != NULL ; inst = inst->next) { std_checkRuleset(pModConf, inst); } /* 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; } } 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; } count += (2 * runModConf->nOptions); 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); 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); } finalize_it: if (iRet != RS_RET_OK) { free(s_httpserv); s_httpserv = NULL; 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->pszBindRuleset); free(inst->pszInputName); 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); 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 if (s_httpserv) { mg_stop(s_httpserv->ctx); mg_exit_library(); free(s_httpserv->civetweb_options); free(s_httpserv); } 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.2412.0/contrib/imhttp/Makefile.in0000664000175000017500000006253014723322620014156 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/imhttp_la-imhttp.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/README0000664000175000017500000000110314650736301011455 This 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.2412.0/contrib/ffaup/0000775000175000017500000000000014723322656011770 5rsyslog-8.2412.0/contrib/ffaup/Makefile.am0000664000175000017500000000031414650736301013735 # # 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.2412.0/contrib/ffaup/ffaup.c0000664000175000017500000003005514650736301013153 /* 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; } 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.2412.0/contrib/ffaup/Makefile.in0000664000175000017500000006251114723322620013751 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/ffaup_la-ffaup.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/mmcount/0000775000175000017500000000000014723322656012351 5rsyslog-8.2412.0/contrib/mmcount/Makefile.am0000664000175000017500000000031114650736301014313 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 = rsyslog-8.2412.0/contrib/mmcount/mmcount.c0000664000175000017500000002016114650736301014112 /* 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")) { pData->pszAppName = es_str2cstr(pvals[i].val.d.estr, NULL); continue; } if(!strcmp(actpblk.descr[i].name, "key")) { pData->pszKey = es_str2cstr(pvals[i].val.d.estr, NULL); continue; } if(!strcmp(actpblk.descr[i].name, "value")) { 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.2412.0/contrib/mmcount/Makefile.in0000664000175000017500000006257714723322620014346 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/mmcount_la-mmcount.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/mmsequence/0000775000175000017500000000000014723322656013031 5rsyslog-8.2412.0/contrib/mmsequence/mmsequence.c0000664000175000017500000002314514650736301015257 /* 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 { 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")) { pData->pszKey = es_str2cstr(pvals[i].val.d.estr, NULL); continue; } if(!strcmp(actpblk.descr[i].name, "var")) { 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 if (RS_RET_OK != msgAddJSON(pMsg, (uchar *)pData->pszVar + 1, json, 0, 0)) { LogError(0, RS_RET_OBJ_CREATION_FAILED, "mmsequence: unable to pass out the value"); json_object_put(json); } 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.2412.0/contrib/mmsequence/Makefile.am0000664000175000017500000000033314650736301014777 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 = rsyslog-8.2412.0/contrib/mmsequence/Makefile.in0000664000175000017500000006305514723322620015016 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/mmsequence_la-mmsequence.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/imtuxedoulog/0000775000175000017500000000000014723322657013415 5rsyslog-8.2412.0/contrib/imtuxedoulog/Makefile.am0000664000175000017500000000043314650736301015363 pkglib_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.2412.0/contrib/imtuxedoulog/imtuxedoulog.c0000664000175000017500000006160214650736301016225 /* 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; 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 = atoi(rawMsg+7); /* 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'; strtData = strtData + 2; /* Case 4 */ if (memcmp(strtData, "gtrid", 5) == 0) { strtData = memchr(strtData, ':', msgLen-(strtData - rawMsg)); if (strtData != NULL) strtData += 2; } text = strtData; /* ecid point to message text or the word ECID */ if (strtData != NULL && memcmp(strtData, "ECID", 4) == 0) { text = memchr(strtData+6, '>', msgLen-(strtData-rawMsg)); /* case 3 : we have the word ECID */ if (text != NULL) { *(--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")) { inst->pszUlogBaseName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "tag")) { 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")) { 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.2412.0/contrib/imtuxedoulog/README.md0000664000175000017500000000410114650736301014602 # 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.2412.0/contrib/imtuxedoulog/Makefile.in0000664000175000017500000006334614723322620015404 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/omczmq/0000775000175000017500000000000014723322655012174 5rsyslog-8.2412.0/contrib/omczmq/README0000664000175000017500000000557314650736301013002 CZMQ 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.2412.0/contrib/omczmq/Makefile.am0000664000175000017500000000033714650736301014147 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 = rsyslog-8.2412.0/contrib/omczmq/omczmq.c0000664000175000017500000004324714650736301013574 /* omczmq.c * Copyright (C) 2016 Brian Knox * Copyright (C) 2014 Rainer Gerhards * * Author: Brian Knox * * 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 "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 }; 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: #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; } 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; } 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 */ #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); } } #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; iauthenticator = (int)pvals[i].val.d.n; } else if(!strcmp(modpblk.descr[i].name, "authtype")) { 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")) { 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")) { 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")) { 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")) { 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")) { pData->sendTimeout = atoi(es_str2cstr(pvals[i].val.d.estr, NULL)); DBGPRINTF("omczmq: sendTimeout set to %d\n", pData->sendTimeout); } else if(!strcmp(actpblk.descr[i].name, "sendhwm")) { pData->sendTimeout = atoi(es_str2cstr(pvals[i].val.d.estr, NULL)); 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")) { pData->heartbeatIvl = atoi(es_str2cstr(pvals[i].val.d.estr, NULL)); DBGPRINTF("omczmq: heartbeatbeatIvl set to %d\n", pData->heartbeatIvl); } else if(!strcmp(actpblk.descr[i].name, "heartbeattimeout")) { pData->heartbeatTimeout = atoi(es_str2cstr(pvals[i].val.d.estr, NULL)); DBGPRINTF("omczmq: heartbeatTimeout set to %d\n", pData->heartbeatTimeout); } else if(!strcmp(actpblk.descr[i].name, "heartbeatttl")) { pData->heartbeatTimeout = atoi(es_str2cstr(pvals[i].val.d.estr, NULL)); DBGPRINTF("omczmq: heartbeatTTL set to %d\n", pData->heartbeatTTL); } #endif else if(!strcmp(actpblk.descr[i].name, "socktype")){ char *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"); } #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 = 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.2412.0/contrib/omczmq/Makefile.in0000664000175000017500000006262214723322620014161 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/omczmq_la-omczmq.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/omrabbitmq/0000775000175000017500000000000014723322655013023 5rsyslog-8.2412.0/contrib/omrabbitmq/omrabbitmq.c0000664000175000017500000013044514650736301015247 /* 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 "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 #include "amqp.h" #include "amqp_framing.h" #include "amqp_tcp_socket.h" #include "amqp_ssl_socket.h" #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) { if (!self->pData->initOpenSSL) { // prevent OpenSSL double initialization amqp_set_initialize_ssl_library(0); } 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); #if ((AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR > 8)) || (AMQP_VERSION_MAJOR > 0) 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); #if ((AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR > 8)) || (AMQP_VERSION_MAJOR > 0) 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); #if ((AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR > 8)) || (AMQP_VERSION_MAJOR > 0) 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; } /* 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; #if ((AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR > 8)) || (AMQP_VERSION_MAJOR > 0) 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; ibytes = 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; ipData->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=%ld s", pData->recover_policy.return_check_interval); dbgprintf("\t\tquick oscillation limit=%ld s", 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=%ld s", 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")) { host = (char*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(actpblk.descr[i].name, "recover_policy")) { 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")) { vhost = (char*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(actpblk.descr[i].name, "user")) { user = (char*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(actpblk.descr[i].name, "password")) { 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")) { 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")) { pData->exchange = cstring_bytes(es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "routing_key")) { pData->routing_key = cstring_bytes(es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "routing_key_template")) { 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 = (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")) { pData->body_template = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(actpblk.descr[i].name, "content_type")) { pData->content_type = es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(actpblk.descr[i].name, "exchange_type")) { 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.2412.0/contrib/omrabbitmq/Makefile.am0000664000175000017500000000037414650736301014777 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 = rsyslog-8.2412.0/contrib/omrabbitmq/Makefile.in0000664000175000017500000006317314723322620015012 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/omrabbitmq_la-omrabbitmq.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/improg/0000775000175000017500000000000014723322657012165 5rsyslog-8.2412.0/contrib/improg/Makefile.am0000664000175000017500000000050714650736301014135 pkglib_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.2412.0/contrib/improg/improg.c0000664000175000017500000004677714650736301013565 /* 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") 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; extern char **environ; /* POSIX environment ptr, by std not in a header... (see man 7 environ) */ 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); } #include "im-helper.h" /* must be included AFTER the type definitions! */ /* 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_OK : 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")) { 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")) { 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; 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 (FD_ISSET(pInst->fdPipeFromChild, &temp)) { DBGPRINTF("read child %s\n",pInst->pszBinary); readChild(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.2412.0/contrib/improg/Makefile.in0000664000175000017500000006277414723322620014160 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/improg_la-improg.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/pmaixforwardedfrom/0000775000175000017500000000000014723322654014565 5rsyslog-8.2412.0/contrib/pmaixforwardedfrom/pmaixforwardedfrom.c0000664000175000017500000001312614650736301020551 /* 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.2412.0/contrib/pmaixforwardedfrom/Makefile.am0000664000175000017500000000044214650736301016536 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 = rsyslog-8.2412.0/contrib/pmaixforwardedfrom/Makefile.in0000664000175000017500000006402714723322620016554 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/mmrfc5424addhmac/0000775000175000017500000000000014723322656013614 5rsyslog-8.2412.0/contrib/mmrfc5424addhmac/Makefile.am0000664000175000017500000000044114650736301015562 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 = rsyslog-8.2412.0/contrib/mmrfc5424addhmac/mmrfc5424addhmac.c0000664000175000017500000002147614650736301016632 /* 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")) { 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")) { 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")) { 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) { int i, j; i = *rootIdx; j = 0; if(sdbuf[i] != '[') { ++i; goto done; } ++i; while(i < sdlen && sdbuf[i] != '=' && sdbuf[i] != ' ' && sdbuf[i] != ']' && sdbuf[i] != '"') { sdid[j++] = sdbuf[i++]; } done: 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); 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); MsgAddToStructuredData(pMsg, newsd, lenNewsd); RETiRet; } BEGINdoAction instanceData *pData = pWrkrData->pData; smsg_t *pMsg; CODESTARTdoAction pMsg = (smsg_t*) ppString[0]; 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.2412.0/contrib/mmrfc5424addhmac/Makefile.in0000664000175000017500000006374114723322620015603 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/mmdarwin/0000775000175000017500000000000014723322656012505 5rsyslog-8.2412.0/contrib/mmdarwin/Makefile.am0000664000175000017500000000033014650736301014450 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 = rsyslog-8.2412.0/contrib/mmdarwin/mmdarwin.c0000664000175000017500000006436614650736301014421 /* 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 #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; strncpy(pWrkrData->addr.sun_path, (char *)pWrkrData->pData->pSockName, sizeof(pWrkrData->addr.sun_path) - 1); 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")) { 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")) { 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 = 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 = 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 *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) { 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.2412.0/contrib/mmdarwin/protocol.h0000664000175000017500000000452014650736301014433 /* 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.2412.0/contrib/mmdarwin/Makefile.in0000664000175000017500000006270414723322620014472 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/mmdarwin_la-mmdarwin.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/imbatchreport/0000775000175000017500000000000014723322657013533 5rsyslog-8.2412.0/contrib/imbatchreport/Makefile.am0000664000175000017500000000035514650736301015504 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 = rsyslog-8.2412.0/contrib/imbatchreport/imbatchreport.c0000664000175000017500000007125014650736301016461 /* 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); strcpy((char*)pInst->pszNewFName + matches[0].rm_so, (toolargeOrFailure) ? pInst->ff_reject : pInst->ff_rename); 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) { strcpy(dirn + matches[0].rm_so, inst->ff_rename); 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); } } strcpy(dirn + matches[0].rm_so, inst->ff_reject); 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")) { inst->pszFollow_glob = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "tag")) { inst->pszTag = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); inst->lenTag = ustrlen(inst->pszTag); } else if(!strcmp(inppblk.descr[i].name, "programkey")) { 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")) { 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")) { 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); } 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); } 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.2412.0/contrib/imbatchreport/Makefile.in0000664000175000017500000006334014723322620015514 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/imbatchreport_la-imbatchreport.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/omamqp1/0000775000175000017500000000000014723322657012243 5rsyslog-8.2412.0/contrib/omamqp1/Makefile.am0000664000175000017500000000037114650736301014212 pkglib_LTLIBRARIES = omamqp1.la omamqp1_la_SOURCES = omamqp1.c omamqp1_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(PROTON_CFLAGS) omamqp1_la_LDFLAGS = -module -avoid-version omamqp1_la_LIBADD = $(PROTON_LIBS) $(PTHREADS_LIBS) EXTRA_DIST = rsyslog-8.2412.0/contrib/omamqp1/README.md0000664000175000017500000002552214650736301013442 # 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.2412.0/contrib/omamqp1/omamqp1.c0000664000175000017500000006467714650736301013720 /* * 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 * */ #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 _shutdown_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 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 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 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 = 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")) { cs->templateName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(actpblk.descr[i].name, "target")) { cs->target = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(actpblk.descr[i].name, "username")) { cs->username = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(actpblk.descr[i].name, "password")) { 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; pState->buffer_size *= 2; free(pState->encode_buffer); pState->encode_buffer = (char *)malloc(pState->buffer_size); CHKmalloc(pState->encode_buffer); 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; } 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; } } // Send a command to the protocol thread and // wait for the command to complete 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; } // check if a command needs processing 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; } pthread_mutex_unlock(&ipc->lock); } /* runs the protocol engine, allowing it to handle TCP socket I/O and timer * events in the background. */ 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) { 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; } 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; } 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.2412.0/contrib/omamqp1/Makefile.in0000664000175000017500000006277514723322620014237 # 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) am__DEPENDENCIES_1 = omamqp1_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 omamqp1_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(PROTON_CFLAGS) omamqp1_la_LDFLAGS = -module -avoid-version omamqp1_la_LIBADD = $(PROTON_LIBS) $(PTHREADS_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/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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/omamqp1_la-omamqp1.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/mmkubernetes/0000775000175000017500000000000014723322657013371 5rsyslog-8.2412.0/contrib/mmkubernetes/Makefile.am0000664000175000017500000000053214650736301015337 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 rsyslog-8.2412.0/contrib/mmkubernetes/mmkubernetes.c0000664000175000017500000023030614650736301016154 /* 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 "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_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 */ /* 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; 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 *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 */ }; /* action (instance) configuration data */ typedef struct _instanceData { uchar *kubernetesUrl; /* scheme, host, port, and optional path prefix for Kubernetes API lookups */ 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 */ } instanceData; typedef struct wrkrInstanceData { instanceData *pData; CURL *curlCtx; struct curl_slist *curlHdr; 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", eCmdHdlrString, 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 } #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", eCmdHdlrString, 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 } #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 int init_annotationmatch(annotation_match_t *match, struct cnfarray *ar) { DEFiRet; match->nmemb = ar->nmemb; CHKmalloc(match->patterns = calloc(sizeof(uchar*), match->nmemb)); CHKmalloc(match->regexps = calloc(sizeof(regex_t), match->nmemb)); 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(sizeof(regex_t), dest->nmemb)); 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; for(i = 0 ; i < modpblk.nParams ; ++i) { if(!pvals[i].bUsed) { continue; } else if(!strcmp(modpblk.descr[i].name, "kubernetesurl")) { free(loadModConf->kubernetesUrl); loadModConf->kubernetesUrl = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(modpblk.descr[i].name, "srcmetadatapath")) { free(loadModConf->srcMetadataPath); 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); 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); 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); 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")) { 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); loadModConf->token = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(modpblk.descr[i].name, "tokenfile")) { free(loadModConf->tokenFile); 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); 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); 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); 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 { 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); } } /* 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 free(pData->kubernetesUrl); 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 BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance CURL *ctx; struct curl_slist *hdr = NULL; char *tokenHdr = NULL; FILE *fp = NULL; char *token = NULL; 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)); hdr = curl_slist_append(hdr, "Content-Type: text/json; charset=utf-8"); if (pWrkrData->pData->token) { if ((-1 == asprintf(&tokenHdr, "Authorization: Bearer %s", pWrkrData->pData->token)) || (!tokenHdr)) { 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))); if (0 < (bytesread = fread(token, sizeof(char), statbuf.st_size, fp))) { token[bytesread] = '\0'; if ((-1 == asprintf(&tokenHdr, "Authorization: Bearer %s", token)) || (!tokenHdr)) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } } free(token); token = NULL; } if (fp) { fclose(fp); fp = NULL; } } if (tokenHdr) { hdr = curl_slist_append(hdr, tokenHdr); free(tokenHdr); } pWrkrData->curlHdr = hdr; ctx = curl_easy_init(); curl_easy_setopt(ctx, CURLOPT_HTTPHEADER, hdr); 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, 0); if(pWrkrData->pData->skipVerifyHost) curl_easy_setopt(ctx, CURLOPT_SSL_VERIFYHOST, 0); #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 pWrkrData->curlCtx = ctx; finalize_it: free(token); free(statsName); if ((iRet != RS_RET_OK) && pWrkrData->stats) { statsobj.Destruct(&(pWrkrData->stats)); } if (fp) { fclose(fp); } 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->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; /* 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 (!hashtable_insert(ht, (void *)(bDupKey ? strdup(key) : key), cache_entry)) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (isnsmd) { STATSCOUNTER_INC(pWrkrData->namespaceCacheNumEntries, pWrkrData->mutNamespaceCacheNumEntries); } else { STATSCOUNTER_INC(pWrkrData->podCacheNumEntries, pWrkrData->mutPodCacheNumEntries); } cache_entry = NULL; } finalize_it: 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; for(i = 0 ; i < actpblk.nParams ; ++i) { if(!pvals[i].bUsed) { continue; } else if(!strcmp(actpblk.descr[i].name, "kubernetesurl")) { free(pData->kubernetesUrl); pData->kubernetesUrl = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "srcmetadatapath")) { msgPropDescrDestruct(pData->srcMetadataDescr); free(pData->srcMetadataDescr); CHKmalloc(pData->srcMetadataDescr = malloc(sizeof(msgPropDescr_t))); 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); 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); 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")) { 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")) { 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); pData->token = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "tokenfile")) { free(pData->tokenFile); 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); 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); 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); 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 { 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->kubernetesUrl == NULL) { if(loadModConf->kubernetesUrl == NULL) { CHKmalloc(pData->kubernetesUrl = (uchar *) strdup(DFLT_KUBERNETES_URL)); } else { CHKmalloc(pData->kubernetesUrl = (uchar *) strdup((char *) loadModConf->kubernetesUrl)); } } 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)) 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; free(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); 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; 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); 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); } 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; } /* 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; 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) { char *url = NULL; struct json_object *jReply = NULL, *jo2 = NULL, *jNsMeta = NULL, *jPodData = NULL; /* check cache for namespace metadata */ jNsMeta = cache_entry_get_nsmd(pWrkrData, (const char *)ns, now); if(jNsMeta == NULL) { /* query kubernetes for namespace info */ /* todo: move url definitions elsewhere */ if ((-1 == asprintf(&url, "%s/api/v1/namespaces/%s", (char *) pWrkrData->pData->kubernetesUrl, ns)) || (!url)) { pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } iRet = queryKB(pWrkrData, url, now, &jReply); free(url); 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(&url, "%s/api/v1/namespaces/%s/pods/%s", (char *) pWrkrData->pData->kubernetesUrl, ns, podName)) || (!url)) { pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } iRet = queryKB(pWrkrData, url, now, &jReply); free(url); 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); 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.2412.0/contrib/mmkubernetes/k8s_container_name.rulebase0000664000175000017500000000050714650736301020600 version=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.2412.0/contrib/mmkubernetes/k8s_filename.rulebase0000664000175000017500000000017214650736301017374 version=2 rule=:/var/log/containers/%pod_name:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log rsyslog-8.2412.0/contrib/mmkubernetes/Makefile.in0000664000175000017500000006353414723322620015357 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/mmkubernetes_la-mmkubernetes.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/gnutls/0000775000175000017500000000000014723322653012200 5rsyslog-8.2412.0/contrib/gnutls/cert.pem0000664000175000017500000000165014330725737013566 -----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.2412.0/contrib/gnutls/ca.pem0000664000175000017500000000156714330725737013223 -----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.2412.0/contrib/gnutls/key.pem0000664000175000017500000000156714330725737013430 -----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.2412.0/contrib/imdocker/0000775000175000017500000000000014723322655012463 5rsyslog-8.2412.0/contrib/imdocker/Makefile.am0000664000175000017500000000036614650736301014440 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) rsyslog-8.2412.0/contrib/imdocker/imdocker.c0000664000175000017500000015217414650736301014352 /* 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, 2019 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 "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") extern int Debug; #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_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_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; 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); /* 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 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 + 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; } 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); 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) { 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))); pThis->id = strdup((char*)id); strncpy((char*) pThis->short_id, id, sizeof(pThis->short_id)-1); CHKiRet(dockerContLogsReqNew(&pThis->logsReq, submitMsg)); /* make a copy */ if (container_info) { CHKiRet(dockerContainerInfoNew(&pThis->container_info)); if (container_info->image_id) { 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 */ pThis->container_info->name = (uchar*)dupDockerContainerName(pname); } if (container_info->json_str_labels) { 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) { 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) { char url[256]; 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; } snprintf(url, sizeof(url), "%s/%s/containers/%s/logs?%s", pApiAddr, runModConf->apiVersionStr, containerId, container_log_options); DBGPRINTF("%s() - url: %s\n", __FUNCTION__, url); return dockerContLogsInstSetUrl(pThis, curlm, url); } /* 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)); 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->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; if (!pContLogsReqInst) { return RS_RET_ERR; } uchar *keyName = (uchar*)strdup((char*)pContLogsReqInst->id); if (keyName) { 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 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->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; 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")) { loadModConf->listContainersOptions = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(modpblk.descr[i].name, "getcontainerlogoptions")) { loadModConf->getContainerLogOptions = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); /* also intialize the non-tail version */ size_t offset = 0; char buf[256]; size_t buf_size = sizeof(buf); strncpy(buf, (char*)loadModConf->getContainerLogOptions, buf_size-1); size_t option_str_len = strlen((char*)loadModConf->getContainerLogOptions); uchar *option_str = calloc(1, option_str_len); CHKmalloc(option_str); 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; } int len = strlen(token); if (offset + len + 1 >= option_str_len) { break; } int bytes = snprintf((char*)option_str + offset, (option_str_len - offset), "%s&", token); if (bytes <= 0) { break; } offset += bytes; token = strtok(NULL, "&"); } loadModConf->getContainerLogOptionsWithoutTail = option_str; } else if(!strcmp(modpblk.descr[i].name, "dockerapiunixsockaddr")) { loadModConf->dockerApiUnixSockAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(modpblk.descr[i].name, "dockerapiaddr")) { loadModConf->dockerApiAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(modpblk.descr[i].name, "apiversionstr")) { 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); ENDsetModCnf BEGINendCnfLoad CODESTARTendCnfLoad ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf if (!loadModConf->dockerApiUnixSockAddr) { loadModConf->dockerApiUnixSockAddr = (uchar*) strdup(DFLT_dockerAPIUnixSockAddr); } if (!loadModConf->apiVersionStr) { loadModConf->apiVersionStr = (uchar*) strdup(DFLT_apiVersionStr); } if (!loadModConf->listContainersOptions) { loadModConf->listContainersOptions = (uchar*) strdup(DFLT_listContainersOptions); } if (!loadModConf->getContainerLogOptions) { loadModConf->getContainerLogOptions = (uchar*) strdup(DFLT_getContainerLogOptions); } if (!loadModConf->getContainerLogOptionsWithoutTail) { 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[4] = { (const uchar*) DOCKER_CONTAINER_ID_PARSE_NAME, (const uchar*) DOCKER_CONTAINER_NAMES_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_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[4] = { id, name, image_id, json_str_labels }; return msgAddMultiMetadata(pMsg, names, values, 4); } 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(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) 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 = size*nmemb; uchar *pbuf=NULL; imdocker_buf_t *mem = (imdocker_buf_t*)buffer; 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; enqMsg(pInst, message, len, (const uchar*)pszTag, facility, severity, NULL); size_t size = mem->len - pInst->prevSegEnd; memmove(mem->data, mem->data+pInst->prevSegEnd, size); mem->data[len] = '\0'; mem->len = size; pBufData->bytes_remaining = 0; RETiRet; } static rsRetVal SubmitMsgWithStartRegex(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar* pszTag) { 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) { SubmitMultiLineMsg(pInst, pBufData, pszTag, pInst->prevSegEnd); pInst->prevSegEnd = 0; FINALIZE; } else { /* just continue parsing using same buffer */ pInst->prevSegEnd = mem->len; } finalize_it: return RS_RET_OK; } static rsRetVal SubmitMsg2(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar* pszTag) { 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) { SubmitMsgWithStartRegex(pInst, pBufData, pszTag); } else { SubmitMsg(pInst, pBufData, pszTag); } return RS_RET_OK; } static rsRetVal SubmitMsg(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar* pszTag) { 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; 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; return RS_RET_OK; } /** 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 = size*nmemb; const uchar* pdata = data; size_t write_size = 0; #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); } 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__); 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; 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); /* 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_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_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) { 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) { if (pInstances->last_container_created < containerInfo.created) { pInstances->last_container_created = containerInfo.created; if (pInstances->last_container_id) { free(pInstances->last_container_id); } pInstances->last_container_id = (uchar*)strdup(containerId); DBGPRINTF("last_container_id updated: ('%s', %u)\n", pInstances->last_container_id, (unsigned)pInstances->last_container_created); } CHKiRet(dockerContLogsInstSetUrlById(isInit, pInst, pInstances->curlm, containerId)); CHKiRet(dockerContLogReqsAdd(pInstances, pInst)); } } } } } finalize_it: if (mut_locked) { pthread_mutex_unlock(&pInstances->mut); } if (json_obj) { json_object_put(json_obj); } RETiRet; } static rsRetVal getContainerIds(sbool isInit, docker_cont_log_instances_t *pInstances, const char* url) { DEFiRet; imdocker_req_t *req=NULL; 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); } 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[256]; const uchar* pApiAddr = (uchar*)"http:"; if (runModConf->dockerApiAddr) { pApiAddr = runModConf->dockerApiAddr; } /* * TODO: consider if we really need 'isInit' parameter. I suspect we don't need it * and i'm almost certain Travis CI will complain its not used. */ if (pInstances->last_container_id) { snprintf(url, sizeof(url), "%s/%s/containers/json?%s&filters={\"since\":[\"%s\"]}", pApiAddr, runModConf->apiVersionStr, runModConf->listContainersOptions, pInstances->last_container_id); } else { snprintf(url, sizeof(url), "%s/%s/containers/json?%s", pApiAddr, runModConf->apiVersionStr, runModConf->listContainersOptions); } DBGPRINTF("listcontainers url: %s\n", url); CHKiRet(getContainerIds(isInit, pInstances, (const char*)url)); if (Debug) { dockerContLogReqsPrint(pInstances); } finalize_it: 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) { srSleep(runModConf->iPollInterval, 10); 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; int get_containers_thread_initialized = 0; time_t now; CODESTARTrunInput datetime.GetTime(&now); CHKiRet(ratelimitNew(&ratelimiter, "imdocker", NULL)); curl_global_init(CURL_GLOBAL_ALL); 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_kill(thrd_id, SIGTTIN); pthread_join(thrd_id, NULL); pthread_attr_destroy(&thrd_attr); } if (pInstances) { dockerContLogReqsDestruct(pInstances); } if (ratelimiter) { ratelimitDestruct(ratelimiter); } 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.2412.0/contrib/imdocker/Makefile.in0000664000175000017500000006301514723322620014445 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/imdocker_la-imdocker.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/imkmsg/0000775000175000017500000000000014723322654012154 5rsyslog-8.2412.0/contrib/imkmsg/Makefile.am0000664000175000017500000000035114650736301014124 pkglib_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.2412.0/contrib/imkmsg/kmsg.c0000664000175000017500000002067114650736301013204 /* 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-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. */ #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 intial 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) { long 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'); } buf++; /* get messages sequence number and add it to json */ for (; isdigit(*buf); buf++) { sequnum = (sequnum * 10) + (*buf - '0'); } 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++; /* skip everything till the first ; */ } buf++; /* skip ; */ /* get message */ offs = 0; for (; *buf != '\n' && *buf != '\0'; buf++, offs++) { 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++, offs++) { name[offs] = *buf; } name[offs] = '\0'; buf++; /* skip = or ' ' */; offs = 0; for (; *buf != '\n' && *buf != '\0'; buf++, offs++) { 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 && (errno == EAGAIN || errno == EWOULDBLOCK)) { 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.2412.0/contrib/imkmsg/imkmsg.h0000664000175000017500000000511314650736301013531 /* 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); int klogFacilIntMsg(); /* 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.2412.0/contrib/imkmsg/imkmsg.c0000664000175000017500000002514014650736301013526 /* 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(!pThrd->bShallStop) { /* 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 { const char *const cstr = es_str2cstr(pvals[i].val.d.estr, NULL); LogError(0, RS_RET_PARAM_ERROR, "imkmsg: unknown " "parse mode '%s'", cstr); free((void*)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 { const char *const 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((void*)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.2412.0/contrib/imkmsg/Makefile.in0000664000175000017500000006502014723322620014135 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 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 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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/omtcl/0000775000175000017500000000000014723322657012006 5rsyslog-8.2412.0/contrib/omtcl/Makefile.am0000664000175000017500000000027414650736301013757 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 = rsyslog-8.2412.0/contrib/omtcl/omtcl.c0000664000175000017500000001003314650736301013177 /* 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.2412.0/contrib/omtcl/Makefile.in0000664000175000017500000006246714723322620014000 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/omtcl_la-omtcl.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/imhiredis/0000775000175000017500000000000014723322657012645 5rsyslog-8.2412.0/contrib/imhiredis/README0000664000175000017500000000423514650736301013443 Redis 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.2412.0/contrib/imhiredis/Makefile.am0000664000175000017500000000036414650736301014616 pkglib_LTLIBRARIES = imhiredis.la imhiredis_la_SOURCES = imhiredis.c imhiredis_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(HIREDIS_CFLAGS) imhiredis_la_LDFLAGS = -module -avoid-version imhiredis_la_LIBADD = $(HIREDIS_LIBS) EXTRA_DIST = rsyslog-8.2412.0/contrib/imhiredis/COPYING0000664000175000017500000010437014650736301013617 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.2412.0/contrib/imhiredis/imhiredis.c0000664000175000017500000021077414723322534014713 /* 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 #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_MAXLEN 44 // "18446744073709551615-18446744073709551615" #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; 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; 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 }, }; static struct cnfparamblk inppblk = { CNFPARAMBLK_VERSION, sizeof(inppdescr)/sizeof(struct cnfparamdescr), inppdescr }; struct timeval glblRedisConnectTimeout = { 3, 0 }; /* 3 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, uchar *password, redisNode **result); rsRetVal redisAuthenticate(instanceConf_t *inst); 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); /* 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_MAXLEN)); inst->streamAutoclaimIdleTime = 0; inst->streamConsumerACK = 1; inst->pszBindRuleset = NULL; inst->pBindRuleset = NULL; inst->fieldList.nmemb = 0; /* Redis objects */ inst->conn = NULL; inst->aconn = NULL; /* 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); } 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")) { inst->redisNodesList->server = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "socketPath")) { inst->redisNodesList->socketPath = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "ruleset")) { 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")) { inst->password = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "stream.consumerGroup")) { inst->streamConsumerGroup = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "stream.consumerName")) { 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")) { // inst->streamReadFrom is already allocated, only copy contents memcpy(inst->streamReadFrom, es_getBufAddr(pvals[i].val.d.estr), es_strlen(pvals[i].val.d.estr)); inst->streamReadFrom[es_strlen(pvals[i].val.d.estr)] = '\0'; } 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")) { 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")) { inst->key = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } 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) inst->evtBase = event_base_new(); } 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; } 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(); 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); 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); // original object is put: no need for it anymore json_object_put(json); } 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; } } else { if(RS_RET_OK != msgAddJSON(pMsg, (uchar*)"!", json, 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 && RS_RET_OK != msgAddJSON(pMsg, (uchar*)".", metadata, 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 * password can be NULL, meaning no authentication will be done * 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, uchar *password, redisNode **result) { DEFiRet; redisContext *context; redisReply *reply = NULL, *replica; unsigned int i; assert(node != NULL); CHKiRet(redisConnectSync(&context, node)); if(password != NULL && password[0] != '\0') { CHKiRet(redisAuthentSynchronous(context, 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->password, &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->password, &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); } } 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; } /* * connection function for synchronous (queue) mode * node should not be NULL */ rsRetVal redisConnectSync(redisContext **conn, redisNode *node) { DEFiRet; assert(node != NULL); if (node->usesSocket) *conn = redisConnectUnixWithTimeout((const char *)node->socketPath, glblRedisConnectTimeout); else *conn = redisConnectWithTimeout((const char *)node->server, node->port, glblRedisConnectTimeout); 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; assert(node != NULL); if (node->usesSocket) *aconn = redisAsyncConnectUnix((const char*)node->socketPath); else *aconn = redisAsyncConnect((const char *)node->server, node->port); 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); } 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); } 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; ibatchsize; ++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; ibatchsize; 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 memcpy(inst->streamReadFrom, msgObj->element[0]->str, msgObj->element[0]->len); inst->streamReadFrom[msgObj->element[0]->len] = '\0'; 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" memcpy(*autoclaimIndex, reply->element[0]->str, reply->element[0]->len); (*autoclaimIndex)[reply->element[0]->len] = '\0'; 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_MAXLEN)); // 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"); memcpy(autoclaimIndex, "0-0", 4); } else { memcpy(autoclaimIndex, inst->streamReadFrom, STREAM_INDEX_STR_MAXLEN); } 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.2412.0/contrib/imhiredis/Makefile.in0000664000175000017500000006312114723322620014623 # 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_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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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) imhiredis_la_LDFLAGS = -module -avoid-version imhiredis_la_LIBADD = $(HIREDIS_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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/imhiredis_la-imhiredis.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/omhttp/0000775000175000017500000000000014723322655012201 5rsyslog-8.2412.0/contrib/omhttp/Makefile.am0000664000175000017500000000034614650736301014154 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 = rsyslog-8.2412.0/contrib/omhttp/omhttp.c0000664000175000017500000023760314650736301013607 /* omhttp.c * This is an http output module based on omelasticsearch * * NOTE: read comments in module-template.h for more specifics! * * 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 #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) statsobj_t *httpStats; 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(ctrHttpRequestCount, mutCtrHttpRequestCount); // Number of attempted HTTP requests 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 static prop_t *pInputName = NULL; static int omhttpInstancesCnt = 0; #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 VALID_BATCH_FORMATS "newline jsonarray kafkarest lokirest" typedef enum batchFormat_e { FMT_NEWLINE, FMT_JSONARRAY, FMT_KAFKAREST, FMT_LOKIREST } batchFormat_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 *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; sbool bFreeBatchFormatName; sbool dynRestPath; size_t maxBatchBytes; size_t maxBatchSize; 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; unsigned int ratelimitInterval; unsigned int ratelimitBurst; /* for retries */ ratelimit_t *ratelimiter; uchar *retryRulesetName; ruleset_t *retryRuleset; struct instanceConf_s *next; uchar *statsName; statsobj_t *stats; STATSCOUNTER_DEF(ctrHttpRequestsCount, mutCtrHttpRequestsCount); // Number of attempted HTTP requests STATSCOUNTER_DEF(httpRequestsBytes, mutHttpRequestsBytes); STATSCOUNTER_DEF(httpRequestsTimeMs, mutHttpRequestsTimeMs); 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 } 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 */ typedef struct wrkrInstanceData { PTR_ASSERT_DEF instanceData *pData; int serverIndex; int replyLen; char *reply; long httpStatusCode; /* http status code of response */ 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 */ uchar *restURL; /* last used URL for error reporting */ 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 */ uchar *restPath; /* Helper for restpath in batch mode */ 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; } 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 }, { "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 }, { "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 }, { "name", eCmdHdlrGetWord, 0 }, { "httpignorablecodes", eCmdHdlrArray, 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 curlCheckConnSetup(wrkrInstanceData_t *const pWrkrData); /* 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); pData->caCertFile = NULL; pData->myCertFile = NULL; pData->myPrivKeyFile = NULL; pData->ratelimiter = NULL; pData->retryRulesetName = NULL; pData->retryRuleset = NULL; ENDcreateInstance BEGINcreateWrkrInstance uchar **batchData; CODESTARTcreateWrkrInstance PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); pWrkrData->curlHeader = NULL; pWrkrData->curlPostHandle = NULL; pWrkrData->curlCheckConnHandle = NULL; pWrkrData->serverIndex = 0; pWrkrData->httpStatusCode = 0; pWrkrData->restURL = NULL; 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->batch.restPath = NULL; } } initCompressCtx(pWrkrData); iRet = curlSetup(pWrkrData); 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->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); if (pData->bFreeBatchFormatName) free(pData->batchFormatName); if (pData->stats) { statsobj.Destruct(&pData->stats); } free(pData->statsName); ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance curlCleanup(pWrkrData); free(pWrkrData->restURL); pWrkrData->restURL = NULL; free(pWrkrData->batch.data); pWrkrData->batch.data = NULL; if (pWrkrData->batch.restPath != NULL) { free(pWrkrData->batch.restPath); pWrkrData->batch.restPath = NULL; } if (pWrkrData->bzInitDone) deflateEnd(&pWrkrData->zstrm); freeCompressCtx(pWrkrData); 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("\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("\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); 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("\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='%u'\n", pData->ratelimitInterval); dbgprintf("\tratelimit.burst='%u'\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); ENDdbgPrintInstInfo /* http POST result string ... useful for debugging */ static size_t curlResult(void *ptr, size_t size, size_t nmemb, void *userdata) { char *p = (char *)ptr; wrkrInstanceData_t *pWrkrData = (wrkrInstanceData_t*) userdata; char *buf; size_t newlen; PTR_ASSERT_CHK(pWrkrData, WRKR_DATA_TYPE_ES); newlen = pWrkrData->replyLen + size*nmemb; if((buf = realloc(pWrkrData->reply, newlen + 1)) == NULL) { LogError(errno, RS_RET_ERR, "omhttp: realloc failed in curlResult"); return 0; /* abort due to failure */ } memcpy(buf+pWrkrData->replyLen, p, size*nmemb); pWrkrData->replyLen = newlen; pWrkrData->reply = buf; return size*nmemb; } /* 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; } /* 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) { CURL *curl; CURLcode res; es_str_t *urlBuf = NULL; char* healthUrl; char* serverUrl; char* checkPath; int i; int r; DEFiRet; if (pWrkrData->pData->checkPath == NULL) { DBGPRINTF("omhttp: checkConn no health check uri configured skipping it\n"); FINALIZE; } pWrkrData->reply = NULL; pWrkrData->replyLen = 0; curl = pWrkrData->curlCheckConnHandle; urlBuf = es_newStr(256); if (urlBuf == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: unable to allocate buffer for health check uri."); ABORT_FINALIZE(RS_RET_SUSPENDED); } for(i = 0; i < pWrkrData->pData->numServers; ++i) { serverUrl = (char*) pWrkrData->pData->serverBaseUrls[pWrkrData->serverIndex]; checkPath = (char*) pWrkrData->pData->checkPath; es_emptyStr(urlBuf); r = es_addBuf(&urlBuf, serverUrl, strlen(serverUrl)); if(r == 0 && checkPath != NULL) r = es_addBuf(&urlBuf, checkPath, strlen(checkPath)); if(r == 0) healthUrl = es_str2cstr(urlBuf, NULL); if(r != 0 || healthUrl == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: unable to allocate buffer for health check uri."); ABORT_FINALIZE(RS_RET_SUSPENDED); } curlCheckConnSetup(pWrkrData); curl_easy_setopt(curl, CURLOPT_URL, healthUrl); res = curl_easy_perform(curl); free(healthUrl); if (res == CURLE_OK) { DBGPRINTF("omhttp: checkConn %s completed with success " "on attempt %d\n", serverUrl, i); ABORT_FINALIZE(RS_RET_OK); } DBGPRINTF("omhttp: checkConn %s failed on attempt %d: %s\n", serverUrl, i, curl_easy_strerror(res)); incrementServerIndex(pWrkrData); } LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING, "omhttp: checkConn failed after %d attempts.", i); ABORT_FINALIZE(RS_RET_SUSPENDED); finalize_it: if(urlBuf != NULL) es_deleteStr(urlBuf); free(pWrkrData->reply); pWrkrData->reply = NULL; /* don't leave dangling pointer */ RETiRet; } BEGINtryResume CODESTARTtryResume DBGPRINTF("omhttp: tryResume called\n"); iRet = checkConn(pWrkrData); ENDtryResume /* get the current index and type for this message */ static void ATTR_NONNULL(1) getRestPath(const instanceData *const pData, uchar **const tpls, uchar **const restPath) { *restPath = pData->restPath; if(tpls == NULL) { goto done; } int iNumTpls = 1; if(pData->dynRestPath) { *restPath = tpls[iNumTpls]; ++iNumTpls; } done: assert(restPath != NULL); return; } static rsRetVal ATTR_NONNULL(1) setPostURL(wrkrInstanceData_t *const pWrkrData, uchar **const tpls) { uchar *restPath; char* baseUrl; es_str_t *url; int r; DEFiRet; instanceData *const pData = pWrkrData->pData; 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 new estr for POST url."); ABORT_FINALIZE(RS_RET_ERR); } if (pWrkrData->batch.restPath != NULL) { /* get from batch if set! */ restPath = pWrkrData->batch.restPath; } else { getRestPath(pData, tpls, &restPath); } r = 0; if (restPath != NULL) r = es_addBuf(&url, (char*)restPath, ustrlen(restPath)); if(r != 0) { LogError(0, RS_RET_ERR, "omhttp: failure in creating restURL, " "error code: %d", r); ABORT_FINALIZE(RS_RET_ERR); } if(pWrkrData->restURL != NULL) free(pWrkrData->restURL); pWrkrData->restURL = (uchar*)es_str2cstr(url, NULL); curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_URL, pWrkrData->restURL); DBGPRINTF("omhttp: using REST URL: '%s'\n", pWrkrData->restURL); 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; if ((req = fjson_object_new_object()) == NULL) ABORT_FINALIZE(RS_RET_ERR); fjson_object_object_add(req, "url", fjson_object_new_string((char *)pWrkrData->restURL)); 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 { fjson_object_object_add(res, "message", fjson_object_new_string_len(pWrkrData->reply, pWrkrData->replyLen)); } 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); *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) { json_object_object_add(json, "body", json_object_new_string(pWrkrData->reply)); } json_object_object_add(json, "batch_index", json_object_new_int(batch_index)); CHKiRet(msgAddJSON(pMsg, (uchar*)"!omhttp!response", json, 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; 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)); CHKiRet(MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_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(ctrMessagesRetry, mutCtrMessagesRetry); } finalize_it: RETiRet; } static rsRetVal checkResult(wrkrInstanceData_t *pWrkrData, uchar *reqmsg) { instanceData *pData; long statusCode; size_t numMessages; DEFiRet; CURLcode resCurl = 0; pData = pWrkrData->pData; statusCode = pWrkrData->httpStatusCode; if (pData->batchMode) { numMessages = pWrkrData->batch.nmemb; } else { numMessages = 1; } // 500+ errors return RS_RET_SUSPENDED if NOT batchMode and should be retried // status 0 is the default and the request failed for some reason, retry this too // 400-499 are malformed input and should not be retried just logged instead if (statusCode == 0) { // request failed, suspend or retry STATSCOUNTER_ADD(ctrMessagesFail, mutCtrMessagesFail, numMessages); STATSCOUNTER_INC(pData->ctrHttpRequestsStatus0xx, pData->mutCtrHttpRequestsStatus0xx); iRet = RS_RET_SUSPENDED; } else if (statusCode >= 500) { // server error, suspend or retry STATSCOUNTER_INC(ctrHttpStatusFail, mutCtrHttpStatusFail); STATSCOUNTER_ADD(ctrMessagesFail, mutCtrMessagesFail, numMessages); iRet = RS_RET_SUSPENDED; } else if (statusCode >= 300) { // redirection or client error, NO suspend nor retry STATSCOUNTER_INC(ctrHttpStatusFail, mutCtrHttpStatusFail); STATSCOUNTER_ADD(ctrMessagesFail, mutCtrMessagesFail, numMessages); iRet = RS_RET_SUSPENDED; if (statusCode >= 300 && statusCode < 400) { STATSCOUNTER_INC(pData->ctrHttpRequestsStatus3xx, pData->mutCtrHttpRequestsStatus3xx); } else if (statusCode >= 400 && statusCode < 500) { STATSCOUNTER_INC(pData->ctrHttpRequestsStatus4xx, pData->mutCtrHttpRequestsStatus4xx); } else if (statusCode >= 500 && statusCode < 600) { STATSCOUNTER_INC(pData->ctrHttpRequestsStatus5xx, pData->mutCtrHttpRequestsStatus5xx); } } else { // success, normal state // includes 2XX (success like 200-OK) // includes 1XX (informational like 100-Continue) STATSCOUNTER_INC(ctrHttpStatusSuccess, mutCtrHttpStatusSuccess); STATSCOUNTER_ADD(ctrMessagesSuccess, mutCtrMessagesSuccess, numMessages); // increment instance counts if enabled if (statusCode >= 0 && statusCode < 100) { STATSCOUNTER_INC(pData->ctrHttpRequestsStatus0xx, pData->mutCtrHttpRequestsStatus0xx); } else if (statusCode >= 100 && statusCode < 200) { STATSCOUNTER_INC(pData->ctrHttpRequestsStatus1xx, pData->mutCtrHttpRequestsStatus1xx); } else if (statusCode >= 200 && statusCode < 300) { STATSCOUNTER_INC(pData->ctrHttpRequestsStatus2xx, pData->mutCtrHttpRequestsStatus2xx); } iRet = RS_RET_OK; } // get curl stats for instance { long req = 0; double total = 0; /* record total bytes */ resCurl = curl_easy_getinfo(pWrkrData->curlPostHandle, CURLINFO_REQUEST_SIZE, &req); if (!resCurl) { STATSCOUNTER_ADD(pWrkrData->pData->httpRequestsBytes, pWrkrData->pData->mutHttpRequestsBytes, (uint64_t)req); } resCurl = curl_easy_getinfo(pWrkrData->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(pWrkrData->pData->httpRequestsTimeMs, pWrkrData->pData->mutHttpRequestsTimeMs, (uint64_t)total_time_ms); } } /* when retriable codes are configured, always check status codes */ if (pData->nhttpRetryCodes) { 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) { /* just force retry */ iRet = RS_RET_SUSPENDED; } else { iRet = RS_RET_OK; } } // 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; break; } } } if (iRet != RS_RET_OK) { LogMsg(0, iRet, LOG_ERR, "omhttp: checkResult error http status code: %ld reply: %s", statusCode, pWrkrData->reply != NULL ? pWrkrData->reply : "NULL"); writeDataError(pWrkrData, pWrkrData->pData, reqmsg); if (iRet == RS_RET_DATAFAIL) ABORT_FINALIZE(iRet); if (pData->batchMode && pData->maxBatchSize > 1) { // Write each message back to retry ruleset if configured if (pData->retryFailures && pData->retryRuleset != NULL) { // Retry stats counted inside this function call iRet = queueBatchOnRetryRuleset(pWrkrData, pData); if (iRet != RS_RET_OK) { LogMsg(0, iRet, LOG_ERR, "omhttp: checkResult error while queueing to retry ruleset" "some messages may be lost"); } } iRet = RS_RET_OK; // We've done all we can tell rsyslog to carry on } } 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, unsigned len) { int zRet; unsigned outavail; uchar zipBuf[32*1024]; DEFiRet; 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; } CHKiRet(resetCompressCtx(pWrkrData, len)); /* now doing the compression */ pWrkrData->zstrm.next_in = (Bytef*) message; pWrkrData->zstrm.avail_in = 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. */ static rsRetVal ATTR_NONNULL() buildCurlHeaders(wrkrInstanceData_t *pWrkrData, sbool contentEncodeGzip) { struct curl_slist *slist = NULL; DEFiRet; if (pWrkrData->pData->httpcontenttype != NULL) { // If content type specified use it, otherwise use a sane default slist = curl_slist_append(slist, (char *)pWrkrData->pData->headerContentTypeBuf); } else { if (pWrkrData->pData->batchMode) { // If in batch mode, use the approprate content type header for the format, // defaulting to text/plain with newline switch (pWrkrData->pData->batchFormat) { case FMT_JSONARRAY: slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_JSON); break; case FMT_KAFKAREST: slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_KAFKA); break; case FMT_NEWLINE: slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_TEXT); break; case FMT_LOKIREST: slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_JSON); break; default: slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_TEXT); } } else { // Otherwise non batch, presume most users are sending JSON slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_JSON); } } CHKmalloc(slist); // Configured headers.. if (pWrkrData->pData->headerBuf != NULL) { slist = curl_slist_append(slist, (char *)pWrkrData->pData->headerBuf); CHKmalloc(slist); } for (int k = 0 ; k < pWrkrData->pData->nHttpHeaders; k++) { slist = curl_slist_append(slist, (char *)pWrkrData->pData->httpHeaders[k]); CHKmalloc(slist); } // When sending more than 1Kb, libcurl automatically sends an Except: 100-Continue header // and will wait 1s for a response, could make this configurable but for now disable slist = curl_slist_append(slist, HTTP_HEADER_EXPECT_EMPTY); CHKmalloc(slist); if (contentEncodeGzip) { slist = curl_slist_append(slist, HTTP_HEADER_ENCODING_GZIP); CHKmalloc(slist); } if (pWrkrData->curlHeader != NULL) curl_slist_free_all(pWrkrData->curlHeader); pWrkrData->curlHeader = slist; finalize_it: if (iRet != RS_RET_OK) { curl_slist_free_all(slist); LogError(0, iRet, "omhttp: error allocating curl header slist, using previous one"); } RETiRet; } static rsRetVal ATTR_NONNULL(1, 2) curlPost(wrkrInstanceData_t *pWrkrData, uchar *message, int msglen, uchar **tpls, const int nmsgs __attribute__((unused))) { CURLcode curlCode; CURL *const curl = pWrkrData->curlPostHandle; char errbuf[CURL_ERROR_SIZE] = ""; char *postData; int postLen; sbool compressed; DEFiRet; PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); if(pWrkrData->pData->numServers > 1) { /* needs to be called to support ES HA feature */ CHKiRet(checkConn(pWrkrData)); } CHKiRet(setPostURL(pWrkrData, tpls)); pWrkrData->reply = NULL; pWrkrData->replyLen = 0; pWrkrData->httpStatusCode = 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 %d to %d bytes\n", msglen, postLen); } } buildCurlHeaders(pWrkrData, compressed); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postLen); curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_HTTPHEADER, pWrkrData->curlHeader); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf); curlCode = curl_easy_perform(curl); DBGPRINTF("omhttp: curlPost curl returned %lld\n", (long long) curlCode); STATSCOUNTER_INC(ctrHttpRequestCount, mutCtrHttpRequestCount); STATSCOUNTER_INC(pWrkrData->pData->ctrHttpRequestsCount, pWrkrData->pData->mutCtrHttpRequestsCount); if (curlCode != CURLE_OK) { STATSCOUNTER_INC(ctrHttpRequestFail, mutCtrHttpRequestFail); LogError(0, RS_RET_SUSPENDED, "omhttp: suspending ourselves due to server failure %lld: %s", (long long) curlCode, errbuf); // 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(ctrHttpRequestSuccess, 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 = '%d'\n", pWrkrData->replyLen); } else { DBGPRINTF("omhttp: curlPost pWrkrData replyLen = '%d'\n", pWrkrData->replyLen); if(pWrkrData->replyLen > 0) { pWrkrData->reply[pWrkrData->replyLen] = '\0'; /* Append 0 Byte if replyLen is above 0 - byte has been reserved in malloc */ } //TODO: replyLen++? because 0 Byte is appended DBGPRINTF("omhttp: curlPost pWrkrData reply: '%s'\n", pWrkrData->reply); } CHKiRet(checkResult(pWrkrData, message)); finalize_it: incrementServerIndex(pWrkrData); if (pWrkrData->reply != NULL) { free(pWrkrData->reply); pWrkrData->reply = NULL; /* don't leave dangling pointer */ } 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 // numMessages == 0 handled implicitly in multiplication extraBytes = (numMessages * 10) + 14; 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]]} // ]} // message (11) * numMessages + header ( 16 ) extraBytes = (numMessages * 2) + 14; break; default: // newlines between each message extraBytes = numMessages > 0 ? numMessages - 1 : 0; } return sizeBytes + extraBytes + 1; // plus a null } static void ATTR_NONNULL() initializeBatch(wrkrInstanceData_t *pWrkrData) { pWrkrData->batch.sizeBytes = 0; pWrkrData->batch.nmemb = 0; if (pWrkrData->batch.restPath != NULL) { free(pWrkrData->batch.restPath); pWrkrData->batch.restPath = NULL; } } /* 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; } BEGINbeginTransaction CODESTARTbeginTransaction if(!pWrkrData->pData->batchMode) { FINALIZE; } initializeBatch(pWrkrData); finalize_it: ENDbeginTransaction BEGINdoAction size_t nBytes; sbool submit; CODESTARTdoAction instanceData *const pData = pWrkrData->pData; uchar *restPath = NULL; STATSCOUNTER_INC(ctrMessagesSubmitted, mutCtrMessagesSubmitted); if (pWrkrData->pData->batchMode) { if(pData->dynRestPath) { /* Get copy of restpath in batch mode if dynRestPath enabled */ getRestPath(pData, ppString, &restPath); if (pWrkrData->batch.restPath == NULL) { pWrkrData->batch.restPath = (uchar*)strdup((char*)restPath); } else if (strcmp((char*)pWrkrData->batch.restPath, (char*)restPath) != 0) { /* Check if the restPath changed - if yes submit the current batch first*/ CHKiRet(submitBatch(pWrkrData, NULL)); initializeBatch(pWrkrData); } } /* If the maxbatchsize is 1, then build and immediately post a batch with 1 element. * This mode will play nicely with rsyslog's action.resumeRetryCount logic. */ if (pWrkrData->pData->maxBatchSize == 1) { initializeBatch(pWrkrData); CHKiRet(buildBatch(pWrkrData, ppString[0])); CHKiRet(submitBatch(pWrkrData, ppString)); FINALIZE; } /* We should submit if any of these conditions are true * 1. Total batch size > pWrkrData->pData->maxBatchSize * 2. Total bytes > pWrkrData->pData->maxBatchBytes */ nBytes = ustrlen((char *)ppString[0]) - 1 ; submit = 0; if (pWrkrData->batch.nmemb >= pWrkrData->pData->maxBatchSize) { submit = 1; DBGPRINTF("omhttp: maxbatchsize limit reached submitting batch of %zd elements.\n", pWrkrData->batch.nmemb); } else if (computeBatchSize(pWrkrData) + nBytes > pWrkrData->pData->maxBatchBytes) { submit = 1; DBGPRINTF("omhttp: maxbytes limit reached submitting partial batch of %zd elements.\n", pWrkrData->batch.nmemb); } if (submit) { CHKiRet(submitBatch(pWrkrData, ppString)); initializeBatch(pWrkrData); } CHKiRet(buildBatch(pWrkrData, ppString[0])); /* If there is only one item in the batch, all previous items have been * submitted or this is the first item for this transaction. Return previous * committed so that all items leading up to the current (exclusive) * are not replayed should a failure occur anywhere else in the transaction. */ iRet = pWrkrData->batch.nmemb == 1 ? RS_RET_PREVIOUS_COMMITTED : RS_RET_DEFER_COMMIT; } else { CHKiRet(curlPost(pWrkrData, ppString[0], strlen((char*)ppString[0]), ppString, 1)); } finalize_it: ENDdoAction BEGINendTransaction CODESTARTendTransaction /* End Transaction only if batch data is not empty */ if (pWrkrData->batch.nmemb > 0) { CHKiRet(submitBatch(pWrkrData, NULL)); } else { dbgprintf("omhttp: endTransaction, pWrkrData->batch.nmemb = 0, " "nothing to send. \n"); } finalize_it: ENDendTransaction /* 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, CURL *const handle) { PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); curl_easy_setopt(handle, CURLOPT_HTTPHEADER, pWrkrData->curlHeader); curl_easy_setopt(handle, CURLOPT_NOSIGNAL, TRUE); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curlResult); curl_easy_setopt(handle, CURLOPT_WRITEDATA, pWrkrData); if (pWrkrData->pData->proxyHost != NULL) { curl_easy_setopt(handle, CURLOPT_PROXY, pWrkrData->pData->proxyHost); } if (pWrkrData->pData->proxyPort != 0) { curl_easy_setopt(handle, CURLOPT_PROXYPORT, pWrkrData->pData->proxyPort); } if (pWrkrData->pData->restPathTimeout) { curl_easy_setopt(handle, CURLOPT_TIMEOUT_MS, pWrkrData->pData->restPathTimeout); } if(pWrkrData->pData->allowUnsignedCerts) curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, FALSE); if(pWrkrData->pData->skipVerifyHost) curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, FALSE); if(pWrkrData->pData->authBuf != NULL) { curl_easy_setopt(handle, CURLOPT_USERPWD, pWrkrData->pData->authBuf); curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); } if(pWrkrData->pData->caCertFile) curl_easy_setopt(handle, CURLOPT_CAINFO, pWrkrData->pData->caCertFile); if(pWrkrData->pData->myCertFile) curl_easy_setopt(handle, CURLOPT_SSLCERT, pWrkrData->pData->myCertFile); if(pWrkrData->pData->myPrivKeyFile) curl_easy_setopt(handle, CURLOPT_SSLKEY, pWrkrData->pData->myPrivKeyFile); /* uncomment for in-dept debuggung: curl_easy_setopt(handle, CURLOPT_VERBOSE, TRUE); */ } static void ATTR_NONNULL() curlCheckConnSetup(wrkrInstanceData_t *const pWrkrData) { PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); curlSetupCommon(pWrkrData, pWrkrData->curlCheckConnHandle); curl_easy_setopt(pWrkrData->curlCheckConnHandle, CURLOPT_TIMEOUT_MS, pWrkrData->pData->healthCheckTimeout); } static void ATTR_NONNULL(1) curlPostSetup(wrkrInstanceData_t *const pWrkrData) { PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); curlSetupCommon(pWrkrData, pWrkrData->curlPostHandle); curl_easy_setopt(pWrkrData->curlPostHandle, CURLOPT_POST, 1); CURLcode cRet; /* Enable TCP keep-alive for this transfer */ cRet = curl_easy_setopt(pWrkrData->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(pWrkrData->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(pWrkrData->curlPostHandle, CURLOPT_TCP_KEEPINTVL, 60L); if (cRet != CURLE_OK) DBGPRINTF("omhttp: curlPostSetup unknown option CURLOPT_TCP_KEEPINTVL\n"); } static rsRetVal ATTR_NONNULL() curlSetup(wrkrInstanceData_t *const pWrkrData) { struct curl_slist *slist = NULL; DEFiRet; if (pWrkrData->pData->httpcontenttype != NULL) { slist = curl_slist_append(slist, (char *)pWrkrData->pData->headerContentTypeBuf); } else { slist = curl_slist_append(slist, HTTP_HEADER_CONTENT_JSON); } if (pWrkrData->pData->headerBuf != NULL) { slist = curl_slist_append(slist, (char *)pWrkrData->pData->headerBuf); CHKmalloc(slist); } for (int k = 0 ; k < pWrkrData->pData->nHttpHeaders; k++) { slist = curl_slist_append(slist, (char *)pWrkrData->pData->httpHeaders[k]); CHKmalloc(slist); } // When sending more than 1Kb, libcurl automatically sends an Except: 100-Continue header // and will wait 1s for a response, could make this configurable but for now disable slist = curl_slist_append(slist, HTTP_HEADER_EXPECT_EMPTY); pWrkrData->curlHeader = slist; CHKmalloc(pWrkrData->curlPostHandle = curl_easy_init()); curlPostSetup(pWrkrData); CHKmalloc(pWrkrData->curlCheckConnHandle = curl_easy_init()); curlCheckConnSetup(pWrkrData); finalize_it: if(iRet != RS_RET_OK && pWrkrData->curlPostHandle != NULL) { curl_easy_cleanup(pWrkrData->curlPostHandle); pWrkrData->curlPostHandle = NULL; } RETiRet; } static void ATTR_NONNULL() curlCleanup(wrkrInstanceData_t *const pWrkrData) { if (pWrkrData->curlHeader != NULL) { curl_slist_free_all(pWrkrData->curlHeader); pWrkrData->curlHeader = NULL; } if (pWrkrData->curlCheckConnHandle != NULL) { curl_easy_cleanup(pWrkrData->curlCheckConnHandle); pWrkrData->curlCheckConnHandle = NULL; } if (pWrkrData->curlPostHandle != NULL) { curl_easy_cleanup(pWrkrData->curlPostHandle); pWrkrData->curlPostHandle = NULL; } } static void ATTR_NONNULL() setInstParamDefaults(instanceData *const pData) { pData->serverBaseUrls = NULL; pData->defaultPort = 443; pData->healthCheckTimeout = 3500; pData->uid = NULL; pData->restPathTimeout = 0; 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->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 = 10485760; //i.e. 10 MB Is the default max message size for AWS API Gateway pData->maxBatchSize = 100; // 100 messages 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 = 20000; pData->ratelimitInterval = 600; pData->ratelimiter = NULL; pData->retryRulesetName = NULL; pData->retryRuleset = NULL; pData->nIgnorableCodes = 0; pData->ignorableCodes = NULL; // 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; } BEGINnewActInst struct cnfparamvals *pvals; char* serverParam = NULL; struct cnfarray* servers = 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")) { 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, "restpathtimeout")) { pData->restPathTimeout = (long) pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "uid")) { pData->uid = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "httpcontenttype")) { pData->httpcontenttype = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "httpheaderkey")) { pData->httpheaderkey = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "httpheadervalue")) { pData->httpheadervalue = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "httpheaders")) { pData->nHttpHeaders = pvals[i].val.d.ar->nmemb; CHKmalloc(pData->httpHeaders = malloc(sizeof(uchar *) * pvals[i].val.d.ar->nmemb )); for(int j = 0 ; j < pvals[i].val.d.ar->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")) { pData->pwd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "restpath")) { pData->restPath = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "checkpath")) { 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")) { 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")) { 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, "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")) { pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "tls.cacert")) { 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")) { 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")) { 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")) { pData->nhttpRetryCodes = pvals[i].val.d.ar->nmemb; // note: use zero as sentinel value CHKmalloc(pData->httpRetryCodes = calloc(pvals[i].val.d.ar->nmemb, sizeof(unsigned int) )); int count = 0; for(int j = 0 ; j < pvals[i].val.d.ar->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")) { 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 = (unsigned int) pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "ratelimit.interval")) { pData->ratelimitInterval = (unsigned int) pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "name")) { pData->statsName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "httpignorablecodes")) { pData->nIgnorableCodes = pvals[i].val.d.ar->nmemb; // note: use zero as sentinel value CHKmalloc(pData->ignorableCodes = calloc(pvals[i].val.d.ar->nmemb, sizeof(unsigned int))); int count = 0; for(int j = 0 ; j < pvals[i].val.d.ar->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 { LogError(0, RS_RET_INTERNAL_ERROR, "omhttp: program error, " "non-handled param '%s'", actpblk.descr[i].name); } } 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); } if (pData->proxyHost == NULL) { if (getenv("http_proxy") != NULL) { pData->proxyHost = ustrdup(getenv("http_proxy")); } else if (getenv("HTTP_PROXY") != NULL) { pData->proxyHost = ustrdup(getenv("HTTP_PROXY")); } } if (pData->uid != NULL) CHKiRet(computeAuthHeader((char*) pData->uid, (char*) pData->pwd, &pData->authBuf)); 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)); 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 (servers != NULL) { pData->numServers = servers->nmemb; pData->serverBaseUrls = malloc(servers->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); } 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'; } 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); } CHKiRet(computeBaseUrl("localhost", pData->defaultPort, pData->useHttps, pData->serverBaseUrls)); } if (pData->retryFailures) { CHKiRet(ratelimitNew(&pData->ratelimiter, "omhttp", NULL)); ratelimitSetLinuxLike(pData->ratelimiter, pData->ratelimitInterval, pData->ratelimitBurst); ratelimitSetNoTimeCache(pData->ratelimiter); } if(!pData->statsName) { uchar pszAName[64]; snprintf((char*) pszAName, sizeof(pszAName), "omhttp-%d", omhttpInstancesCnt); pData->statsName = ustrdup(pszAName); } // instantiate the stats object and add the counters CHKiRet(statsobj.Construct(&pData->stats)); CHKiRet(statsobj.SetName(pData->stats, (uchar *)pData->statsName)); CHKiRet(statsobj.SetOrigin(pData->stats, (uchar *)"omhttp")); STATSCOUNTER_INIT(pData->ctrHttpRequestsCount, pData->mutCtrHttpRequestsCount); CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"requests.count", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrHttpRequestsCount)); STATSCOUNTER_INIT(pData->ctrHttpRequestsStatus0xx, pData->mutCtrHttpRequestsStatus0xx); CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"requests.status.0xx", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrHttpRequestsStatus0xx)); STATSCOUNTER_INIT(pData->ctrHttpRequestsStatus1xx, pData->mutCtrHttpRequestsStatus1xx); CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"requests.status.1xx", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrHttpRequestsStatus1xx)); STATSCOUNTER_INIT(pData->ctrHttpRequestsStatus2xx, pData->mutCtrHttpRequestsStatus2xx); CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"requests.status.2xx", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrHttpRequestsStatus2xx)); STATSCOUNTER_INIT(pData->ctrHttpRequestsStatus3xx, pData->mutCtrHttpRequestsStatus3xx); CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"requests.status.3xx", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrHttpRequestsStatus3xx)); STATSCOUNTER_INIT(pData->ctrHttpRequestsStatus4xx, pData->mutCtrHttpRequestsStatus4xx); CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"requests.status.4xx", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrHttpRequestsStatus4xx)); STATSCOUNTER_INIT(pData->ctrHttpRequestsStatus5xx, pData->mutCtrHttpRequestsStatus5xx); CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"requests.status.5xx", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->ctrHttpRequestsStatus5xx)); STATSCOUNTER_INIT(pData->httpRequestsBytes, pData->mutHttpRequestsBytes); CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"requests.bytes", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->httpRequestsBytes)); STATSCOUNTER_INIT(pData->httpRequestsTimeMs, pData->mutHttpRequestsTimeMs); CHKiRet(statsobj.AddCounter(pData->stats, (uchar *)"requests.time_ms", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pData->httpRequestsTimeMs)); CHKiRet(statsobj.ConstructFinalize(pData->stats)); /* 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); 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); statsobj.Destruct(&httpStats); ENDmodExit NO_LEGACY_CONF_parseSelectorAct BEGINqueryEtryPt CODESTARTqueryEtryPt CODEqueryEtryPt_STD_OMOD_QUERIES CODEqueryEtryPt_STD_OMOD8_QUERIES CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES CODEqueryEtryPt_doHUP CODEqueryEtryPt_doHUPWrkr /* Load the worker HUP handling code */ CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */ CODEqueryEtryPt_STD_CONF2_QUERIES ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit *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)); CHKiRet(statsobj.Construct(&httpStats)); CHKiRet(statsobj.SetName(httpStats, (uchar *)"omhttp")); CHKiRet(statsobj.SetOrigin(httpStats, (uchar*)"omhttp")); STATSCOUNTER_INIT(ctrMessagesSubmitted, mutCtrMessagesSubmitted); CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"messages.submitted", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrMessagesSubmitted)); STATSCOUNTER_INIT(ctrMessagesSuccess, mutCtrMessagesSuccess); CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"messages.success", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrMessagesSuccess)); STATSCOUNTER_INIT(ctrMessagesFail, mutCtrMessagesFail); CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"messages.fail", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrMessagesFail)); STATSCOUNTER_INIT(ctrMessagesRetry, mutCtrMessagesRetry); CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"messages.retry", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrMessagesRetry)); STATSCOUNTER_INIT(ctrHttpRequestCount, mutCtrHttpRequestCount); CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"request.count", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrHttpRequestCount)); STATSCOUNTER_INIT(ctrHttpRequestSuccess, mutCtrHttpRequestSuccess); CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"request.success", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrHttpRequestSuccess)); STATSCOUNTER_INIT(ctrHttpRequestFail, mutCtrHttpRequestFail); CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"request.fail", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrHttpRequestFail)); STATSCOUNTER_INIT(ctrHttpStatusSuccess, mutCtrHttpStatusSuccess); CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"request.status.success", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrHttpStatusSuccess)); STATSCOUNTER_INIT(ctrHttpStatusFail, mutCtrHttpStatusFail); CHKiRet(statsobj.AddCounter(httpStats, (uchar *)"request.status.fail", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrHttpStatusFail)); CHKiRet(statsobj.ConstructFinalize(httpStats)); 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); } CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("omhttp"), sizeof("omhttp") - 1)); CHKiRet(prop.ConstructFinalize(pInputName)); ENDmodInit /* vi:set ai: */ rsyslog-8.2412.0/contrib/omhttp/Makefile.in0000664000175000017500000006265114723322620014170 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/omhttp_la-omhttp.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/pmcisconames/0000775000175000017500000000000014723322654013346 5rsyslog-8.2412.0/contrib/pmcisconames/Makefile.am0000664000175000017500000000036614650736301015324 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 = rsyslog-8.2412.0/contrib/pmcisconames/Makefile.in0000664000175000017500000006326314723322620015336 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/pmcisconames_la-pmcisconames.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/pmcisconames/pmcisconames.c0000664000175000017500000001340314650736301016111 /* 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.2412.0/contrib/impcap/0000775000175000017500000000000014723322657012141 5rsyslog-8.2412.0/contrib/impcap/tcp_parser.c0000664000175000017500000000752314650736301014370 /* 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 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.2412.0/contrib/impcap/ipv6_parser.c0000664000175000017500000002153114650736301014461 /* 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 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"); /* 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 */ uint8_t hByteLength = hbh_header->hLength * 8 + 8; DBGPRINTF("hByteLength: %d\n", hByteLength); *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"); /* 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 */ uint8_t hByteLength = dest_header->hLength * 8 + 8; DBGPRINTF("hByteLength: %d\n", hByteLength); *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"); /* 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 */ uint8_t hByteLength = route_header->hLength * 8 + 8; *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"); /* 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_DOPTS: nextHeader = dest_header_parse(&packet, &pktSize); break; default: hasNext = 0; break; } } while (hasNext); json_object_object_add(jparent, "IP_proto", json_object_new_int(nextHeader)); RETURN_DATA_AFTER(0) } rsyslog-8.2412.0/contrib/impcap/smb_parser.c0000664000175000017500000001074014650736301014356 /* 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 > 0) { /* 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.2412.0/contrib/impcap/ftp_parser.c0000664000175000017500000001014514650736301014365 /* 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(pktSize * sizeof(uchar)); memcpy(packet2, packet, pktSize); // strtok changes original packet uchar *frst_part_ftp; frst_part_ftp = (uchar *)strtok((char *)packet2, " "); // Get first part of packet ftp strtok(NULL, "\r\n"); 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.2412.0/contrib/impcap/http_parser.c0000664000175000017500000001055514650736301014560 /* 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(pktSize + 1); 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.2412.0/contrib/impcap/Makefile.am0000664000175000017500000000123614650736301014111 pkglib_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.2412.0/contrib/impcap/ipx_parser.c0000664000175000017500000000711114650736301014373 /* 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.2412.0/contrib/impcap/dns_parser.c0000664000175000017500000002517214650736301014366 /* 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 *"; } 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; const uchar *end_packet = packet + pktSize; DBGPRINTF("dns_parse\n"); DBGPRINTF("packet size %d\n", 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.2412.0/contrib/impcap/arp_parser.c0000664000175000017500000001360014650736301014355 /* 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; /* * 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 (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 (ntohs(rarp_header->hwType) == 1) { /* ethernet addresses */ char *hwAddrSrc = ether_ntoa((struct ether_addr *)rarp_header->pAddr); char *hwAddrDst = ether_ntoa((struct ether_addr *)(rarp_header->pAddr + rarp_header->hwAddrLen + rarp_header->pAddrLen)); 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.2412.0/contrib/impcap/llc_parser.c0000664000175000017500000000711714650736301014353 /* 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 */ 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 */ 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.2412.0/contrib/impcap/udp_parser.c0000664000175000017500000000554514650736301014374 /* 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.2412.0/contrib/impcap/ipv4_parser.c0000664000175000017500000000633314650736301014462 /* 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 */ 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.2412.0/contrib/impcap/parsers.h0000664000175000017500000001206214650736301013704 /* 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(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.2412.0/contrib/impcap/icmp_parser.c0000664000175000017500000000473514650736301014534 /* 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.2412.0/contrib/impcap/Makefile.in0000664000175000017500000012464714723322620014132 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 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 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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/impcap/impcap.c0000664000175000017500000005447414650736301013506 /* 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 "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 ; iinterface = (char *)es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(inppblk.descr[i].name, "file")) { 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")) { inst-> filter = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(inppblk.descr[i].name, "tag")) { inst->tag = (uchar *) es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(inppblk.descr[i].name, "ruleset")) { 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 ; isnap_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")) { loadModConf->metadataContainer = (char *)es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(modpblk.descr[i].name, "data_container")) { 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); } 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; uint16_t i; retBuf = malloc((2 * length + 1) * sizeof(char)); 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)); data_ret_t * dataLeft = eth_parse(packet, pkthdr->caplen, jown); 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 = ATOMIC_FETCH_32BIT(&bTerminateInputs, &mutTerminateInputs); DBGPRINTF("impcap: awoken via SIGTTIN; bTerminateInputs: %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.2412.0/contrib/impcap/eth_parser.c0000664000175000017500000001340414650736301014355 /* 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) { 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); /* 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); /* 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.2412.0/contrib/pmpanngfw/0000775000175000017500000000000014723322654012662 5rsyslog-8.2412.0/contrib/pmpanngfw/Makefile.am0000664000175000017500000000034414650736301014634 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 = rsyslog-8.2412.0/contrib/pmpanngfw/pmpanngfw.c0000664000175000017500000001754314650736301014752 /* 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 */ log_type = *((uint64 *)p2parse); 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.2412.0/contrib/pmpanngfw/README.md0000664000175000017500000001072514650736301014063 # 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.2412.0/contrib/pmpanngfw/Makefile.in0000664000175000017500000006301714723322620014647 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/pmpanngfw_la-pmpanngfw.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/imczmq/0000775000175000017500000000000014723322655012166 5rsyslog-8.2412.0/contrib/imczmq/README0000664000175000017500000000206514650736301012765 CZMQ 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.2412.0/contrib/imczmq/Makefile.am0000664000175000017500000000033714650736301014141 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 = rsyslog-8.2412.0/contrib/imczmq/imczmq.c0000664000175000017500000003562514650736301013561 /* imczmq.c * Copyright (C) 2016 Brian Knox * Copyright (C) 2014 Rainer Gerhards * * Author: Brian Knox * * 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 "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; 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 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; } 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: #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; } if(iconf->topics) { // A zero-length topic means subscribe to everything if(!*iconf->topics && iconf->sockType == ZMQ_SUB) { DBGPRINTF("imczmq: subscribing to all topics\n"); zsock_set_subscribe(pData->sock, ""); } char topic[256]; while(*iconf->topics) { char *delimiter = strchr(iconf->topics, ','); if(!delimiter) { delimiter = iconf->topics + strlen(iconf->topics); } memcpy (topic, iconf->topics, delimiter - iconf->topics); topic[delimiter-iconf->topics] = 0; DBGPRINTF("imczmq: subscribing to %s\n", topic); if(iconf->sockType == ZMQ_SUB) { zsock_set_subscribe (pData->sock, topic); } #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; } iconf->topics = 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; } 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")) { runModConf->authType = es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(modpblk.descr[i].name, "servercertpath")) { runModConf->serverCertPath = es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(modpblk.descr[i].name, "clientcertpath")) { 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); 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")) { inst->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "endpoints")) { inst->sockEndpoints = es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "topics")) { inst->topics = es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(inppblk.descr[i].name, "socktype")){ char *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; } #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 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.2412.0/contrib/imczmq/Makefile.in0000664000175000017500000006262214723322620014153 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/imczmq_la-imczmq.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/omhttpfs/0000775000175000017500000000000014723322656012533 5rsyslog-8.2412.0/contrib/omhttpfs/Makefile.am0000664000175000017500000000042514650736301014503 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 = rsyslog-8.2412.0/contrib/omhttpfs/README.md0000664000175000017500000000302014650736301013720 OmHTTPFS === 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.2412.0/contrib/omhttpfs/omhttpfs.c0000664000175000017500000005217614723322534014471 /* 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 "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 = size * nmemb; char *newreply = NULL; wrkrInstanceData_t *mem = (wrkrInstanceData_t *)userp; newreply = realloc(mem->reply, mem->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[mem->replyLen]), contents, realsize); mem->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); strncpy(jre->class, str, sizeof(jre->class)); jre->class[sizeof(jre->class)-1] = '\0'; json_object_object_get_ex(json, "exception", &jobj); str = json_object_get_string(jobj); strncpy(jre->exception, str, sizeof(jre->exception)); jre->exception[sizeof(jre->exception)-1] = '\0'; json_object_object_get_ex(json, "message", &jobj); str = json_object_get_string(jobj); strncpy(jre->message, str, sizeof(jre->message)); jre->message[sizeof(jre->message)-1] = '\0'; 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, 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_FALSE; } } /** * 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, 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_FALSE; } } /** * 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) { /* TODO: log error */ DBGPRINTF("omhttpfs: Append fail HTTP %ld: %s\n", response_code, pWrkrData->file); return RS_RET_FALSE; } 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_FALSE; } 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")) { 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")) { 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")) { 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")) { 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.2412.0/contrib/omhttpfs/Makefile.in0000664000175000017500000006311414723322620014514 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/omhttpfs_la-omhttpfs.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/fmhash/0000775000175000017500000000000014723322655012134 5rsyslog-8.2412.0/contrib/fmhash/fmhash.c0000664000175000017500000002552414650736301013472 /* * 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; }; /* * 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; } /*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.2412.0/contrib/fmhash/Makefile.am0000664000175000017500000000033314650736301014103 # # 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.2412.0/contrib/fmhash/Makefile.in0000664000175000017500000006261414723322620014122 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/fmhash_la-fmhash.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/pmsnare/0000775000175000017500000000000014723322654012332 5rsyslog-8.2412.0/contrib/pmsnare/Makefile.am0000664000175000017500000000033014650736301014277 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 = rsyslog-8.2412.0/contrib/pmsnare/pmsnare.c0000664000175000017500000003415614650736301014071 /* 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 }; struct instanceConf_s { int bEscapeCCOnRcv; int bEscapeTab; int bParserEscapeCCCStyle; uchar cCCEscapeChar; int tabLength; char tabRepresentation[5]; struct instanceConf_s *next; }; /* 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")) { inst->cCCEscapeChar = (uchar) *es_str2cstr(pvals[i].val.d.estr, NULL); } 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 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) { strncpy(inst->tabRepresentation, "\\t", 5); } else { strncpy(inst->tabRepresentation, "#011", 5); inst->tabRepresentation[0] = inst->cCCEscapeChar; } } else { strncpy(inst->tabRepresentation, "\t", 5); } 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 instanceConf_t *inst, *del; CODESTARTfreeCnf for(inst = modInstances->root ; inst != NULL ; ) { del = inst; inst = inst->next; free(del); } free(modInstances); ENDfreeCnf BEGINparse2 uchar *p2parse; int lenMsg; 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. */ if(strncasecmp((char*)(p2parse + pInst->tabLength), "MSWinEventLog", 13) == 0) { dbgprintf("Found a non-syslog Windows Snare message.\n"); snaremessage = p2parse - pMsg->pszRawMsg + pInst->tabLength + 13; } else if(strncasecmp((char*) (p2parse + pInst->tabLength), "LinuxKAudit", 11) == 0) { 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(lenMsg > 13 && strncasecmp((char*) p2parse, "MSWinEventLog", 13) == 0) { dbgprintf("Found a syslog Windows Snare message.\n"); snaremessage = p2parse - pMsg->pszRawMsg + 13; } else if(lenMsg > 11 && strncasecmp((char*) p2parse, "LinuxKAudit", 11) == 0) { 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. */ *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.2412.0/contrib/pmsnare/Makefile.in0000664000175000017500000006261614723322620014323 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/pmsnare_la-pmsnare.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/mmgrok/0000775000175000017500000000000014723322656012163 5rsyslog-8.2412.0/contrib/mmgrok/README0000664000175000017500000000244214650736301012760 Grok 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.2412.0/contrib/mmgrok/Makefile.am0000664000175000017500000000037014650736301014132 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 = rsyslog-8.2412.0/contrib/mmgrok/mmgrok.c0000664000175000017500000002335514650736301013546 /* 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; char *type; }result_t; /* config variables */ typedef struct _instanceData { char *pszPatternDir; char *pszMatch; char *pszSource; char *pszTarget;/* as a json root for store parse json data */ smsg_t *pmsg; /* store origin messages*/ }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); ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance ENDfreeWrkrInstance static inline void setInstParamDefaults(instanceData *pData) { pData->pszPatternDir= NULL; pData->pszMatch = NULL; pData->pszSource = NULL; pData->pszTarget = NULL; pData->pmsg = 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")) { pData->pszPatternDir= es_str2cstr(pvals[i].val.d.estr, NULL); continue; } else if(!strcmp(actpblk.descr[i].name, "match")) { pData->pszMatch = es_str2cstr(pvals[i].val.d.estr, NULL); continue; } else if(!strcmp(actpblk.descr[i].name, "source")) { pData->pszSource= es_str2cstr(pvals[i].val.d.estr, NULL); continue; } else if(!strcmp(actpblk.descr[i].name,"target")) { 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("!")); } 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) { 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(pData->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) { GList *re_list = NULL; char *pname; const char *pdata; int pname_len,pdata_len; char *key; char *type; 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; type = strchr(key,':'); int type_len; if(type != NULL) { key_len = (type - key); type = type+1; type_len = pname_len - key_len -1; type[type_len] = '\0'; } else { type = (char*)"null"; } /* store parse result into list */ result->key = key; result->key_len = key_len; result->value = pdata; result->value_len = pdata_len; result->type = type; /* the value of merger the same key*/ re_list = g_list_append(re_list,result); } } smsg_to_json(re_list,pData); g_list_free(re_list); grok_match_walk_end(&gm); RETiRet; } /* motify message for per line */ static rsRetVal MotifyLine(char *line,grok_t *grok,instanceData *pData) { 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); } parse_result_store(gm,pData); finalize_it: RETiRet; } /* motify rsyslog messages */ static rsRetVal MotifyMessage(instanceData *pData) { char *saveptr = NULL; DEFiRet; grok_t *grok = CreateGrok(); char *msg = strdup(pData->pszSource); char *line = NULL; line = strtok_r(msg, "\n", &saveptr); while(line!=NULL) { MotifyLine(line,grok,pData); line = strtok_r(NULL, "\n", &saveptr); } free(msg);msg=NULL; RETiRet; } BEGINdoAction_NoStrings smsg_t **ppMsg = (smsg_t **) pMsgData; smsg_t *pMsg = ppMsg[0]; uchar *buf; instanceData *pData; CODESTARTdoAction pData = pWrkrData->pData; buf = getMSG(pMsg); pData->pmsg = pMsg; while(*buf && isspace(*buf)) { ++buf; } if(*buf == '\0' ) { DBGPRINTF("mmgrok: not msg for mmgrok!"); ABORT_FINALIZE(RS_RET_NO_CEE_MSG); } pData->pszSource = (char *)buf; CHKiRet(MotifyMessage(pData)); finalize_it: 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.2412.0/contrib/mmgrok/Makefile.in0000664000175000017500000006270314723322620014147 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/mmgrok_la-mmgrok.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/fmunflatten/0000775000175000017500000000000014723322656013212 5rsyslog-8.2412.0/contrib/fmunflatten/Makefile.am0000664000175000017500000000035714650736301015166 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) rsyslog-8.2412.0/contrib/fmunflatten/fmunflatten.c0000664000175000017500000001511314650736301015615 /* * 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.2412.0/contrib/fmunflatten/Makefile.in0000664000175000017500000006317314723322620015200 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/fmunflatten_la-fmunflatten.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/omfile-hardened/0000775000175000017500000000000014723322654013710 5rsyslog-8.2412.0/contrib/omfile-hardened/Makefile.am0000664000175000017500000000041014650736301015654 pkglib_LTLIBRARIES = omfile-hardened.la omfile_hardened_la_SOURCES = omfile-hardened.c omfile_hardened_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools omfile_hardened_la_LDFLAGS = -module -avoid-version omfile_hardened_la_LIBADD = EXTRA_DIST = rsyslog-8.2412.0/contrib/omfile-hardened/omfile-hardened.c0000664000175000017500000015734314650736301017031 /* 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-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 "rsyslog.h" #include "glbl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_ATOMIC_BUILTINS # include #endif #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.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); /* internal structures */ DEF_OMOD_STATIC_DATA DEFobjCurrIf(glbl) DEFobjCurrIf(strm) DEFobjCurrIf(statsobj) /* for our current LRU mechanism, we need a monotonically increasing counters. We use * it much like a "Lamport logical clock": we do not need the actual time, we just need * to know the sequence in which files were accessed. So we use a simple counter to * create that sequence. We use an unsigned 64 bit value which is extremely unlike to * wrap within the lifetime of a process. If we process 1,000,000 file writes per * second, the process could still exist over 500,000 years before a wrap to 0 happens. * That should be sufficient (and even than, there would no really bad effect ;)). * The variable below is the global counter/clock. */ #if HAVE_ATOMIC_BUILTINS64 static uint64 clockFileAccess = 0; #else static unsigned clockFileAccess = 0; #endif /* and the "tick" function */ #ifndef HAVE_ATOMIC_BUILTINS static pthread_mutex_t mutClock; #endif static uint64 getClockFileAccess(void) { #if HAVE_ATOMIC_BUILTINS64 return ATOMIC_INC_AND_FETCH_uint64(&clockFileAccess, &mutClock); #else return ATOMIC_INC_AND_FETCH_unsigned(&clockFileAccess, &mutClock); #endif } /* The following structure is a dynafile name cache entry. */ 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 */ 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 */ 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 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) */ uint iCurrCacheSize; /* currently cache size (1-based) */ uint 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 */ int iZipLevel; /* zip mode to use for this selector */ uint 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; 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; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; typedef struct configSettings_s { uint 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? */ EMPTY_STRUCT } configSettings_t; static configSettings_t cs; uchar *pszFileDfltTplName; /* name of the default template to use */ 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; }; 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 }, { "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 }, { "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 */ { "sig.provider", eCmdHdlrGetWord, 0 }, { "cry.provider", eCmdHdlrGetWord, 0 }, { "closetimeout", eCmdHdlrPositiveInt, 0 }, { "template", eCmdHdlrGetWord, 0 } }; static struct cnfparamblk actpblk = { CNFPARAMBLK_VERSION, sizeof(actpdescr)/sizeof(struct cnfparamdescr), actpdescr }; /* 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(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("\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 /* 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); 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; } /* set the dynaFile cache size. Does some limit checking. * rgerhards, 2007-07-31 */ static rsRetVal setDynaFileCacheSize(void __attribute__((unused)) *pVal, int iNewVal) { DEFiRet; if(iNewVal < 1) { errno = 0; parser_errmsg( "DynaFileCacheSize must be greater 0 (%d given), changed to 1.", iNewVal); iRet = RS_RET_VAL_OUT_OF_RANGE; iNewVal = 1; } else if(iNewVal > 1000) { errno = 0; parser_errmsg( "DynaFileCacheSize maximum is 1,000 (%d given), changed to 1,000.", iNewVal); iRet = RS_RET_VAL_OUT_OF_RANGE; iNewVal = 1000; } cs.iDynaFileCacheSize = iNewVal; DBGPRINTF("DynaFileCacheSize changed to %d.\n", iNewVal); RETiRet; } /* Helper to cfline(). Parses a output channel name up until the first * comma and then looks for the template specifier. Tries * to find that template. Maps the output channel to the * proper filed structure settings. Everything is stored in the * filed struct. Over time, the dependency on filed might be * removed. * rgerhards 2005-06-21 */ 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; /* WARNING: It is dangerous "just" to pass the pointer. As we * never rebuild the output channel description, this is acceptable here. */ pData->pszSizeLimitCmd = pOch->cmdOnSizeLimit; iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, getDfltTpl()); finalize_it: RETiRet; } /* This function deletes an entry from the dynamic file name * cache. A pointer to the cache must be passed in as well * as the index of the to-be-deleted entry. This index may * point to an unallocated entry, in whcih case the * function immediately returns. Parameter bFreeEntry is 1 * if the entry should be free()ed and 0 if not. */ 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) { 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; } /* This function frees all dynamic file name cache entries and closes the * relevant files. Part of Shutdown and HUP processing. * rgerhards, 2008-10-23 */ static void dynaFileFreeCacheEntries(instanceData *__restrict__ const pData) { register uint i; assert(pData != NULL); for(i = 0 ; i < pData->iCurrCacheSize ; ++i) { dynaFileDelCacheEntry(pData, i, 1); } pData->iCurrElt = -1; /* invalidate current element */ } /* This function frees the dynamic file name cache. */ static void dynaFileFreeCache(instanceData *__restrict__ const pData) { assert(pData != NULL); dynaFileFreeCacheEntries(pData); if(pData->dynCache != NULL) free(pData->dynCache); } /* close current file */ static rsRetVal closeFile(instanceData *__restrict__ const pData) { DEFiRet; if(pData->useSigprov) { pData->sigprov.OnFileClose(pData->sigprovFileData); pData->sigprovFileData = NULL; } strm.Destruct(&pData->pStrm); RETiRet; } /* This prepares the signature provider to process a file */ static rsRetVal sigprovPrepare(instanceData *__restrict__ const pData, uchar *__restrict__ const fn) { DEFiRet; pData->sigprov.OnFileOpen(pData->sigprovData, fn, &pData->sigprovFileData); RETiRet; } /* This is now shared code for all types of files. It simply prepares * file access, which, among others, means the the file 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 prepareFile(instanceData *__restrict__ const pData, const uchar *__restrict__ const newFileName) { 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) */ fd = open((char*) newFileName, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY|O_CLOEXEC, 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 { ABORT_FINALIZE(RS_RET_ERR); } } /* 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.SetbSync(pData->pStrm, pData->bSyncFile)); CHKiRet(strm.SetsType(pData->pStrm, STREAMTYPE_FILE_SINGLE)); CHKiRet(strm.SetiSizeLimit(pData->pStrm, pData->iSizeLimit)); 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; } // /* verify enough we have space left for writes */ static rsRetVal fsCheck(instanceData *__restrict__ const pData, const uchar *__restrict__ const fileName) { DEFiRet; struct statvfs stat; char *pathcopy; const char *path; pathcopy = strdup((char*)fileName); path = dirname(pathcopy); if (statvfs(path, &stat) != 0) { iRet = RS_RET_FILE_NO_STAT; LogError(0, iRet, "could not stat %s", path); FINALIZE; } /* check if we have space available for all buffers to be flushed and for * a maximum length message, perhaps current msg size would be enough */ if (stat.f_bsize * stat.f_bavail < pData->iIOBufSize * pData->iDynaFileCacheSize + (uint)(glbl.GetMaxLine(runModConf->pConf))) { iRet = RS_RET_FS_ERR; LogError(0, iRet, "too few available blocks in %s", path); FINALIZE; } /* there must be enough inodes left, one is left for administrative purposes * check is not done if file system reports 0 total inodes, such as btrfs */ if (stat.f_favail < 2 && stat.f_files > 0) { iRet = RS_RET_FS_ERR; LogError(0, iRet, "too few available inodes in %s", path); FINALIZE; } /* file system must not be read only */ if (stat.f_flag == ST_RDONLY) { iRet = RS_RET_FS_ERR; LogError(0, iRet, "file-system is read-only in %s", path); FINALIZE; } iRet = RS_RET_OK; finalize_it: if (pathcopy != NULL) free(pathcopy); RETiRet; } // /* This function handles dynamic file names. It checks if the * requested file name is already open and, if not, does everything * needed to switch to the it. * Function returns 0 if all went well and non-zero otherwise. * On successful return pData->fd must point to the correct file to * be written. * This is a helper to writeFile(). rgerhards, 2007-07-03 */ static rsRetVal prepareDynFile(instanceData *__restrict__ const pData, const uchar *__restrict__ const newFileName) { uint64 ctOldest; /* "timestamp" of oldest element */ int iOldest; uint i; int iFirstFree; rsRetVal localRet; dynaFileCacheEntry **pCache; DEFiRet; assert(pData != NULL); assert(newFileName != NULL); pCache = pData->dynCache; /* first check, if we still have the current file */ if( (pData->iCurrElt != -1) && !ustrcmp(newFileName, pCache[pData->iCurrElt]->pName)) { CHKiRet(fsCheck(pData, newFileName)); /* 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; } /* ok, no luck. 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 */ 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)) { CHKiRet(fsCheck(pData, newFileName)); /* 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++; STATSCOUNTER_SETMAX_NOMUT(pData->ctrMax, (unsigned) pData->iCurrCacheSize); } /* 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 ;) */ } else { /* 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); /* ignore exact error, we check fd below */ /* check if we had an error */ if(localRet != RS_RET_OK) { /* 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]", newFileName, localRet); ABORT_FINALIZE(localRet); } localRet = fsCheck(pData, newFileName); if(localRet != RS_RET_OK) { parser_errmsg("Invalid file-system condition for dynamic file '%s' [state %d]", newFileName, localRet); ABORT_FINALIZE(localRet); } if((pCache[iFirstFree]->pName = ustrdup(newFileName)) == NULL) { closeFile(pData); /* need to free failed entry! */ 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; 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; } /* do the actual write process. This function is to be called once we are ready for writing. * It will do buffered writes and persist data only when the buffer is full. Note that we must * be careful to detect when the file handle changed. * rgerhards, 2009-06-03 */ static rsRetVal doWrite(instanceData *__restrict__ const pData, uchar *__restrict__ const pszBuf, const int lenBuf) { DEFiRet; assert(pData != NULL); assert(pszBuf != NULL); DBGPRINTF("omfile: write to stream, pData->pStrm %p, lenBuf %d, strt data %.128s\n", pData->pStrm, lenBuf, pszBuf); if(pData->pStrm != NULL){ CHKiRet(strm.Write(pData->pStrm, pszBuf, lenBuf)); if(pData->useSigprov) { CHKiRet(pData->sigprov.OnRecordWrite(pData->sigprovFileData, pszBuf, lenBuf)); } } finalize_it: RETiRet; } /* rgerhards 2004-11-11: write to a file output. */ 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); CHKiRet(prepareDynFile(pData, actParam(pParam, pData->iNumTpls, iMsg, 1).param)); } else { /* "regular", non-dynafile */ if(pData->pStrm == NULL) { CHKiRet(prepareFile(pData, pData->fname)); if(pData->pStrm == NULL) { parser_errmsg( "Could not open output file '%s'", pData->fname); } CHKiRet(fsCheck(pData, 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; 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")) { 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, "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 { dbgprintf("omfile: program error, non-handled " "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); } } finalize_it: if(pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf /* This function checks dynafile cache for janitor action */ static void janitorChkDynaFiles(instanceData *__restrict__ const pData) { uint 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 >= 0) { if((uint)(pData->iCurrElt) == i) pData->iCurrElt = -1; /* no longer available! */ } } else { pCache[i]->nInactive += runModConf->pConf->globals.janitorInterval; } } } /* callback for the janitor. This cleans out files (if so configured) */ 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; pthread_mutex_init(&pData->mutWrite, NULL); ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance ENDcreateWrkrInstance BEGINfreeInstance CODESTARTfreeInstance free(pData->tplName); free(pData->fname); 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 BEGINtryResume CODESTARTtryResume ENDtryResume BEGINbeginTransaction CODESTARTbeginTransaction /* we have nothing to do to begin a transaction */ ENDbeginTransaction BEGINcommitTransaction instanceData *__restrict__ const pData = pWrkrData->pData; unsigned i; CODESTARTcommitTransaction pthread_mutex_lock(&pData->mutWrite); for(i = 0 ; i < nParams ; ++i) { CHKiRet(writeFile(pData, pParams, i)); } /* 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) { CHKiRet(strm.Flush(pData->pStrm)); } finalize_it: if (iRet != RS_RET_OK) { if (runModConf->bDynafileDoNotSuspend == 0 || !(pData->bDynamicName)) { LogError(0, iRet, "suspending action"); iRet = RS_RET_SUSPENDED; } else { LogError(0, iRet, "discarding message"); } } pthread_mutex_unlock(&pData->mutWrite); ENDcommitTransaction static void setInstParamDefaults(instanceData *__restrict__ const pData) { pData->fname = NULL; pData->tplName = NULL; 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->sigprovName = NULL; pData->cryprovName = NULL; pData->useSigprov = 0; pData->useCryprov = 0; pData->iCloseTimeout = -1; } 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; } 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; } 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 = (uint) pvals[i].val.d.n; } 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 = (uint) 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, "file")) { 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"); } 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, "template")) { pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "sig.provider")) { pData->sigprovName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "cry.provider")) { 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 { dbgprintf("omfile: program error, non-handled " "param '%s'\n", actpblk.descr[i].name); } } if(pData->fname == NULL) { parser_errmsg("omfile: either the \"file\" or " "\"dynafile\" parameter must be given"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } 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_NO_RQD_TPL_OPTS)); 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)); 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_NO_RQD_TPL_OPTS)); /* 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 = (uint) 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 /* Reset config variables for this module to default values. * rgerhards, 2007-07-17 */ 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(glbl, CORE_COMPONENT); 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_doHUP ENDqueryEtryPt BEGINmodInit(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)); CHKiRet(objUse(glbl, CORE_COMPONENT)); ENDmodInit rsyslog-8.2412.0/contrib/omfile-hardened/Makefile.in0000664000175000017500000006354514723322620015703 # 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/omfile-hardened 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) omfile_hardened_la_DEPENDENCIES = am_omfile_hardened_la_OBJECTS = omfile_hardened_la-omfile-hardened.lo omfile_hardened_la_OBJECTS = $(am_omfile_hardened_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 = omfile_hardened_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(omfile_hardened_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)/omfile_hardened_la-omfile-hardened.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 = $(omfile_hardened_la_SOURCES) DIST_SOURCES = $(omfile_hardened_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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 = omfile-hardened.la omfile_hardened_la_SOURCES = omfile-hardened.c omfile_hardened_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools omfile_hardened_la_LDFLAGS = -module -avoid-version omfile_hardened_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/omfile-hardened/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/omfile-hardened/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}; \ } omfile-hardened.la: $(omfile_hardened_la_OBJECTS) $(omfile_hardened_la_DEPENDENCIES) $(EXTRA_omfile_hardened_la_DEPENDENCIES) $(AM_V_CCLD)$(omfile_hardened_la_LINK) -rpath $(pkglibdir) $(omfile_hardened_la_OBJECTS) $(omfile_hardened_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omfile_hardened_la-omfile-hardened.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 $@ $< omfile_hardened_la-omfile-hardened.lo: omfile-hardened.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omfile_hardened_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omfile_hardened_la-omfile-hardened.lo -MD -MP -MF $(DEPDIR)/omfile_hardened_la-omfile-hardened.Tpo -c -o omfile_hardened_la-omfile-hardened.lo `test -f 'omfile-hardened.c' || echo '$(srcdir)/'`omfile-hardened.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omfile_hardened_la-omfile-hardened.Tpo $(DEPDIR)/omfile_hardened_la-omfile-hardened.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfile-hardened.c' object='omfile_hardened_la-omfile-hardened.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) $(omfile_hardened_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omfile_hardened_la-omfile-hardened.lo `test -f 'omfile-hardened.c' || echo '$(srcdir)/'`omfile-hardened.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(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 distclean: distclean-am -rm -f ./$(DEPDIR)/omfile_hardened_la-omfile-hardened.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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)/omfile_hardened_la-omfile-hardened.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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/pmdb2diag/0000775000175000017500000000000014723322657012521 5rsyslog-8.2412.0/contrib/pmdb2diag/Makefile.am0000664000175000017500000000034414650736301014470 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 = rsyslog-8.2412.0/contrib/pmdb2diag/pmdb2diag.c0000664000175000017500000002103214650736301014426 /* 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) /* 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; int lprog, lpid, lvl_len; char buffer[128]; CODESTARTparse2 assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); DBGPRINTF("Message will now be parsed by \"db2diag\" parser.\n"); if(pMsg->iLenRawMsg - (int)pMsg->offAfterPRI < pInst->levelpos+4) 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 = (char*)(pMsg->pszRawMsg + pMsg->offAfterPRI + 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(pMsg->iLenRawMsg - (int)pMsg->offAfterPRI < pInst->levelpos+lvl_len) ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); DBGPRINTF("db2parse Level %d\n", pMsg->iSeverity); end = (char*)pMsg->pszRawMsg + pMsg->iLenRawMsg ; timepos = (char*)pMsg->pszRawMsg + pMsg->offAfterPRI + 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 = strchr((char*)pMsg->pszRawMsg + pInst->levelpos + lvl_len, ':'); if (!pid || pid>=end) ABORT_FINALIZE(0); pid += 2; lpid = strchr(pid, ' ') - pid; DBGPRINTF("db2parse pid %.*s\n", lpid, pid); /* set the pid */ snprintf(buffer, 128, "%.*s", lpid, pid); MsgSetPROCID(pMsg, buffer); prog = pid + pInst->pidstarttoprogstartshift; /* this offset between start of pid to start of prog */ if (prog>=end) ABORT_FINALIZE(0); eprog = strchr(prog, ' '); /* let find the end of the program */ if (eprog && eprog>=end) ABORT_FINALIZE(0); backslash = strchr(prog, '\\'); /* perhaps program contain an backslash */ if (!backslash || backslash>=end) backslash = end; /* Determine the final length of prog */ lprog = (eprog && eprogtimeformat); ENDfreeParserInst 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")) { 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) { inst->timeformat = strdup("%Y-%m-%d-%H.%M.%S."); inst->sepSec = '.'; }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.2412.0/contrib/pmdb2diag/Makefile.in0000664000175000017500000006300214723322620014475 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/pmdb2diag_la-pmdb2diag.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/omhiredis/0000775000175000017500000000000014723322655012651 5rsyslog-8.2412.0/contrib/omhiredis/README0000664000175000017500000000334314650736301013450 Redis 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.2412.0/contrib/omhiredis/omhiredis.c0000664000175000017500000006066614650736301014732 /* 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 * */ #include "config.h" #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 "unicode-helper.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 */ 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 */ } instanceData; typedef struct wrkrInstanceData { instanceData *pData; /* instanc data */ redisContext *conn; /* redis connection */ int count; /* count of command sent for current batch */ } wrkrInstanceData_t; static struct cnfparamdescr actpdescr[] = { { "server", eCmdHdlrGetWord, 0 }, { "serverport", eCmdHdlrInt, 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 }, }; static struct cnfparamblk actpblk = { CNFPARAMBLK_VERSION, sizeof(actpdescr)/sizeof(struct cnfparamdescr), actpdescr }; BEGINcreateInstance CODESTARTcreateInstance ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance pWrkrData->conn = NULL; /* Connect later */ 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; } } /* Free our instance data. */ BEGINfreeInstance CODESTARTfreeInstance if (pData->server != NULL) { free(pData->server); } free(pData->key); free(pData->modeDescription); free(pData->serverpassword); free(pData->tplName); free(pData->streamKeyAck); free(pData->streamGroupAck); free(pData->streamIndexAck); free(pData->streamOutField); 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; redisReply *reply = NULL; DEFiRet; server = (pWrkrData->pData->server == NULL) ? (char *)"127.0.0.1" : (char*) pWrkrData->pData->server; DBGPRINTF("omhiredis: trying connect to '%s' at port %d\n", server, pWrkrData->pData->port); struct timeval timeout = { 1, 500000 }; /* 1.5 seconds */ pWrkrData->conn = redisConnectWithTimeout(server, pWrkrData->pData->port, timeout); if (pWrkrData->conn->err) { if(!bSilent) LogError(0, RS_RET_SUSPENDED, "can not initialize redis handle"); ABORT_FINALIZE(RS_RET_SUSPENDED); } 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: error while authenticating: %s", reply->str); ABORT_FINALIZE(RS_RET_ERR); } } finalize_it: if (iRet != RS_RET_OK && pWrkrData-> conn != NULL) { redisFree(pWrkrData->conn); pWrkrData->conn = NULL; } 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) { DBGPRINTF("omhiredis: could not get reply from ROLE command\n"); ABORT_FINALIZE(RS_RET_SUSPENDED); } else if (reply->type == REDIS_REPLY_ERROR) { LogMsg(0, RS_RET_REDIS_ERROR, LOG_WARNING, "omhiredis: got an error while querying role -> " "%s\n", 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: did not get a proper reply from ROLE command"); ABORT_FINALIZE(RS_RET_SUSPENDED); } else { if (strncmp(reply->element[0]->str, "master", 6)) { LogMsg(0, RS_RET_OK, LOG_WARNING, "omhiredis: current connected node is not a master"); 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", 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", 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", 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, "Error while processing replies: %s", pWrkrData->conn->errstr); closeHiredis(pWrkrData); ABORT_FINALIZE(RS_RET_SUSPENDED); } else { if (reply->type == REDIS_REPLY_ERROR) { LogError(0, RS_RET_REDIS_ERROR, "Received error from redis -> %s", 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->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; } /* 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")) { 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, "serverpassword")) { pData->serverpassword = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "template")) { 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")) { pData->streamOutField = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "stream.keyAck")) { 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")) { 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")) { 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")) { 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")) { 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); } else { dbgprintf("omhiredis: program error, non-handled " "param '%s'\n", actpblk.descr[i].name); } } dbgprintf("omhiredis: checking config sanity\n"); if (!pData->modeDescription) { dbgprintf("omhiredis: no mode specified, setting it to 'template'\n"); pData->mode = OMHIREDIS_MODE_TEMPLATE; } if (pData->mode == OMHIREDIS_MODE_STREAM && !pData->streamOutField) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: no stream.outField set, "\ "using 'msg' as default"); pData->streamOutField = ustrdup("msg"); } if (pData->tplName == NULL) { if(pData->mode == OMHIREDIS_MODE_TEMPLATE) { LogError(0, RS_RET_CONF_PARSE_ERROR, "omhiredis: selected mode requires a template"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } else { CHKmalloc(pData->tplName = ustrdup("RSYSLOG_ForwardFormat")); LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: no template set, "\ "using RSYSLOG_ForwardFormat as default"); } } if (pData->mode != OMHIREDIS_MODE_TEMPLATE && pData->key == NULL) { LogError(0, RS_RET_CONF_PARSE_ERROR, "omhiredis: mode %s requires a key", pData->modeDescription); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (pData->expiration && pData->mode != OMHIREDIS_MODE_SET) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: expiration set but mode is not "\ "'set', expiration will be ignored"); } if (pData->mode != OMHIREDIS_MODE_STREAM) { if (pData->streamOutField) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.outField set "\ "but mode is not 'stream', field will be ignored"); } if (pData->streamAck) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.ack set "\ "but mode is not 'stream', XACK will be ignored"); } if (pData->streamDel) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.del set "\ "but mode is not 'stream', XDEL will be ignored"); } if (pData->streamCapacityLimit) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.capacityLimit set "\ "but mode is not 'stream', stream trimming will be ignored"); } if (pData->streamKeyAck) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.keyAck set "\ "but mode is not 'stream', parameter will be ignored"); } if (pData->streamDynaKeyAck) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.dynaKeyAck set "\ "but mode is not 'stream', parameter will be ignored"); } if (pData->streamGroupAck) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.groupAck set "\ "but mode is not 'stream', parameter will be ignored"); } if (pData->streamDynaGroupAck) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.dynaGroupAck set "\ "but mode is not 'stream', parameter will be ignored"); } if (pData->streamIndexAck) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.indexAck set "\ "but mode is not 'stream', parameter will be ignored"); } if (pData->streamDynaIndexAck) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: stream.dynaIndexAck set "\ "but mode is not 'stream', parameter will be ignored"); } } else { if(pData->streamAck) { if(!pData->streamKeyAck || !pData->streamGroupAck || !pData->streamIndexAck) { LogError(0, RS_RET_CONF_PARSE_ERROR, "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) { LogError(0, RS_RET_CONF_PARSE_ERROR, "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) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: 'stream.dynaKeyAck' set "\ "but 'stream.keyAck' is empty, disabling"); pData->streamDynaKeyAck = 0; } if (pData->streamDynaGroupAck && pData->streamGroupAck == NULL) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: 'stream.dynaGroupAck' set "\ "but 'stream.groupAck' is empty, disabling"); pData->streamDynaGroupAck = 0; } if (pData->streamDynaIndexAck && pData->streamIndexAck == NULL) { LogError(0, RS_RET_CONF_PARSE_WARNING, "omhiredis: 'stream.dynaGroupAck' 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_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); ENDmodInit rsyslog-8.2412.0/contrib/omhiredis/Makefile.am0000664000175000017500000000036514650736301014625 pkglib_LTLIBRARIES = omhiredis.la omhiredis_la_SOURCES = omhiredis.c omhiredis_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(HIREDIS_CFLAGS) omhiredis_la_LDFLAGS = -module -avoid-version omhiredis_la_LIBADD = $(HIREDIS_LIBS) EXTRA_DIST = rsyslog-8.2412.0/contrib/omhiredis/COPYING0000664000175000017500000010437014650736301013625 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.2412.0/contrib/omhiredis/Makefile.in0000664000175000017500000006312114723322620014631 # 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_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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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) omhiredis_la_LDFLAGS = -module -avoid-version omhiredis_la_LIBADD = $(HIREDIS_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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/omhiredis_la-omhiredis.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/contrib/mmtaghostname/0000775000175000017500000000000014723322657013534 5rsyslog-8.2412.0/contrib/mmtaghostname/mmtaghostname.c0000664000175000017500000001312414650736301016457 /* 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")) { 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.2412.0/contrib/mmtaghostname/Makefile.am0000664000175000017500000000035514650736301015505 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 = rsyslog-8.2412.0/contrib/mmtaghostname/Makefile.in0000664000175000017500000006333614723322620015522 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 distclean: distclean-am -rm -f ./$(DEPDIR)/mmtaghostname_la-mmtaghostname.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-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-generic clean-libtool clean-pkglibLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-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.2412.0/config.h.in0000664000175000017500000004676714723322617011213 /* 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 /* 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 /* 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 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 /* 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 RELP is present */ #undef ENABLE_RELP /* 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 `strerror_r', and to 0 if you don't. */ #undef HAVE_DECL_STRERROR_R /* 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 /* 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 /* 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 to 1 if you have the header file. */ #undef HAVE_LINUX_CLOSE_RANGE_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 /* 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 /* Define to 1 if you have the `mongoc_client_set_ssl_opts' function. */ #undef HAVE_MONGOC_CLIENT_SET_SSL_OPTS /* 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 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 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 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 `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 /* 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_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 `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 /* 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 /* 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.2412.0/README.md0000664000175000017500000001562314650736301010430 Rsyslog - what is it? ===================== [![Help Contribute to Open Source](https://www.codetriage.com/rsyslog/rsyslog/badges/users.svg)](https://www.codetriage.com/rsyslog/rsyslog) Rsyslog is a **r**ocket-fast **sys**tem for **log** processing. It offers high-performance, great security features and a modular design. While it started as a regular syslogd, rsyslog has evolved into a kind of swiss army knife of logging, being able to accept inputs from a wide variety of sources, transform them, and output to the results to diverse destinations. Rsyslog can deliver over one million messages per second to local destinations when limited processing is applied (based on v7, December 2013). Even with remote destinations and more elaborate processing the performance is usually considered "stunning". Mailing List ============ http://lists.adiscon.net/mailman/listinfo/rsyslog Installing rsyslog ================== Most distributions carry rsyslog in their repository. So you usually just need to use the package manager to install it. Note that on non-systemd systems (most notably Ubuntu), rsyslog usually is already installed. Project-Provided Packages ---------------------------- Unfortunately, distributions often do not catch up with the pace of rsyslog development and as such only offer old versions. To solve that problem, we have created packages for current versions ourselves. They are available for: * RPM-based systems: https://www.rsyslog.com/rhelcentos-rpms/ * Ubuntu: https://www.rsyslog.com/ubuntu-repository/ * Debian: https://www.rsyslog.com/debian-repository/ Building from Source -------------------- Follow the instructions at: https://www.rsyslog.com/doc/v8-stable/installation/build_from_repo.html ### Build Environment In general, you need * pkg-config * libestr * liblogging (stdlog component, for testbench) It is best to build these from source. #### CentOS 6 / RHEL For json-c, we need: ``` export PKG_CONFIG_PATH=/lib64/pkgconfig/ ``` ``` sudo yum install git valgrind autoconf automake flex bison python-docutils python-sphinx json-c-devel libuuid-devel libgcrypt-devel zlib-devel openssl-devel libcurl-devel gnutls-devel mysql-devel postgresql-devel libdbi-dbd-mysql libdbi-devel net-snmp-devel ``` #### Ubuntu Add Adiscon repository: ``` apt-get update && apt-get install -y software-properties-common add-apt-repository -y ppa:adiscon/v8-stable ``` *Note:* if you are a developer who wants to work with git master branch, adding the Adiscon repository is probably not a good idea. It then is better to also compile the supporting libraries from source, because newer versions of rsyslog may need newer versions of the libraries than there are in the repositories. Libraries in question are at least: libestr, liblognorm, libfastjson. Needed packages to build with omhiredis support: ``` apt-get update && apt-get install -y build-essential pkg-config libestr-dev libfastjson-dev zlib1g-dev uuid-dev libgcrypt20-dev libhiredis-dev uuid-dev libgcrypt11-dev liblogging-stdlog-dev flex bison ``` Aditional packages for other modules: ``` libdbi-dev libmysqlclient-dev postgresql-client libpq-dev libnet-dev librdkafka-dev libgrok-dev libgrok1 libgrok-dev libpcre3-dev libtokyocabinet-dev libglib2.0-dev libmongo-client-dev ``` For KSI, from the Adiscon PPA: ``` sudo apt-get install libksi0 libksi-devel ``` #### Debian ``` sudo apt install build-essential pkg-config libestr-dev libfastjson-dev zlib1g-dev uuid-dev libgcrypt20-dev libcurl4-gnutls-dev zlib1g-dev liblogging-stdlog-dev flex bison ``` *Note:* For certain libraries version requirements might be higher, in that case adding debian backports repositories might help. For example installing with apt libfastjson-dev -t stretch-backports. Aditional packages for other modules: ``` libdbi-dev libmysqlclient-dev postgresql-client libpq-dev libnet-dev librdkafka-dev libgrok-dev libgrok1 libgrok-dev libpcre3-dev libtokyocabinet-dev libglib2.0-dev libmongo-client-dev ``` #### openSUSE 13 ``` sudo zypper install gcc make autoconf automake libtool libcurl-devel flex bison valgrind python-docutils libjson-devel uuid-devel libgcrypt-devel libgnutls-devel libmysqlclient-devel libdbi-devel libnet-devel postgresql-devel net-snmp-devellibuuid-devel libdbi-drivers-dbd-mysql ``` For the testbench VMs: ``` sudo zypper install gvim mutt ``` #### SUSE LINUX Enterprise Server 11 Available packages: ``` zypper install gcc make autoconf libtool flex bison ``` Missing packages: ``` libcurl-devel valgrind python-docutils uuid-devel libgcrypt-devel libgnutls-devel libmysqlclient-devel libdbi-devel postgresql-devel net-snmp-devel libdbi-drivers-dbd-mysql json-c zlib-dev libdbi ``` Reporting Bugs ============== Talk to the mailing list if you think something is a bug. Often, it's just a matter of doing some config trickery. File bugs at: https://github.com/rsyslog/rsyslog/issues How to Contribute ================= Contributions to rsyslog are very welcome. Fork and send us your Pull Requests. For more information about contributing, see the [CONTRIBUTING](CONTRIBUTING.md) file. Note that it is easy to add output plugins using languages like Python or Perl. So if you need to connect to a system which is not yet supported, you can easily do so via an external plugin. For more information see the [README](plugins/external/README.md) file in the external plugin directory. Documentation ============= The main rsyslog documentation is available in HTML format. To read it, point your web browser to ./doc/manual.html. Alternatively, you can view the documentation for *the most recent rsyslog version* online at: https://www.rsyslog.com/doc/ Project Philosophy ================== We are an open source project in all aspects and very open to outside feedback and contribution. We base our work on standards and try to solve all real-world needs (of course, we occasionally fail tackling actually all needs ;)). While the project is primarily sponsored by Adiscon, technical development is independent from company goals and most decisions are solely based on mailing list discussion results. There is an active community around rsyslog. There is no such thing like being an official member of the rsyslog team. The closest to that is being subscribed to the mailing list: http://lists.adiscon.net/mailman/listinfo/rsyslog This method of open discussions is modelled after the IETF process, which is probably the best-known and most successive collaborative standards body. Project Funding =============== Rsyslog's main sponsor Adiscon tries to fund rsyslog by selling custom development and support contracts. Adiscon does NOT license rsyslog under a commercial license (this is simply impossible for anyone due to rsyslog's license structure). Any third party is obviously also free to offer custom development, support and rsyslog consulting. We gladly merge results of such third-party work into the main repository (assuming it matches the few essential things written down in our contribution policy). rsyslog-8.2412.0/parse.h0000664000175000017500000000722314650736301010431 /* 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.2412.0/compat/0000775000175000017500000000000014723322653010507 5rsyslog-8.2412.0/compat/asprintf.c0000664000175000017500000000244314650736301012422 /* 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" #ifndef HAVE_ASPRINTF #include #include #include int asprintf(char **strp, const char *fmt, ...) { va_list ap; int len; va_start(ap, fmt); len = vsnprintf(NULL, 0, fmt, ap); va_end(ap); *strp = malloc(len+1); if (!*strp) { return -1; } va_start(ap, fmt); vsnprintf(*strp, len+1, fmt, ap); va_end(ap); (*strp)[len] = 0; return len; } #else /* XLC needs at least one method in source file even static to compile */ #ifdef __xlc__ static void dummy() {} #endif #endif /* #ifndef HAVE_ASPRINTF */ rsyslog-8.2412.0/compat/getifaddrs.c0000775000175000017500000003203414650736301012712 #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 */ (void) strncpy(ifrl.ifr_name, ifrp->ifr_name, sizeof (ifrl.ifr_name)); (void) strncpy(ifrl6.ifr_name, ifrp->ifr_name, sizeof (ifrl.ifr_name)); 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 */ (void) strncpy(lifrl.lifr_name, lifrp->lifr_name, sizeof (lifrl.lifr_name)); 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.2412.0/compat/Makefile.am0000664000175000017500000000040514650736301012460 noinst_LTLIBRARIES = compat.la compat_la_SOURCES = getifaddrs.c ifaddrs.h strndup.c asprintf.c 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.2412.0/compat/solaris_elf_fix.c0000664000175000017500000000206314650736301013742 /* 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.2412.0/compat/Makefile.in0000664000175000017500000006564714723322620012510 # 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__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@ 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@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ 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@ 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@ 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@ 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@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ 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@ 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@ 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@ 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@ 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 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 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 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 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-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-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.2412.0/compat/ifaddrs.h0000775000175000017500000000577114650736301012227 #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.2412.0/compat/strndup.c0000664000175000017500000000241514650736301012272 /* 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() {} #endif #endif /* #ifndef HAVE_STRNDUP */ rsyslog-8.2412.0/aclocal.m40000664000175000017500000064660314723322617011023 # 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}"])]) # 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.2412.0/CONTRIBUTING.md0000664000175000017500000002024714650736301011400 # How to Contribute Rsyslog is a real open source project and open to contributions. By contributing, you help improve the state of logging as well as improve your own professional profile. Contributing is easy, and there are options for everyone - you do not need to be a developer. These are many ways to contribute to the project: * become a rsyslog ambassador and let other people know about rsyslog and how to utilize it for best results. Help rsyslog getting backlinks, be present on Internet news sites or at meetings you attend. * help others by offering support on * the rsyslog's github home at https://github.com/rsyslog/rsyslog * the rsyslog mailing list at http://lists.adiscon.net/mailman/listinfo/rsyslog * help with the documentation; you can either contribute * to the [rsyslog doc directory](https://github.com/rsyslog/rsyslog-doc), which is shown on http://rsyslog.com/doc * to the rsyslog project web site -- just ask us for account creation * become a bug-hunter and help with testing rsyslog development releases * help driving the rsyslog infrastructure with its web sites and the like * help creating packages * or, obviously, help with rsyslog code development This list is not conclusive. There for sure are many more ways to contribute and if you find one, just let us know. We are very open to new suggestions and like to try out new things. ## When to submit Pull Requests? It is OK to submit PRs that are not yet fully ready for merging. You want to do this in order to get early CI system coverage for your patch. However, all patches should be reasonably complete and "work" in a sense. If you submit such PRs, please flag them as "work in progress" by adding "WiP:" in front of the title. We will NOT merge these PRs before you tell us they are now ready for merging. If you just want/need to do a temporary experiment, you may open a PR, flag it as "EXPERIMENT - DO NOT MERGE", let the CI tests run, check results and close the PR thereafter. This prevents unnecessary cluttering of the open PR list. We will take the liberty to close such PRs if they are left open for an extended period of time. Please note, though, that the rsyslog repo is fully set up to use Travis CI. Travis covers about 95% of all essential testing. So we highly recommend that you use Travis to do initial checks on your work and create the PR only after this looks good. That saves both you and us some time. ## Requirements for patches In order to ensure good code quality, after applying the path the code must - no legacy configuration statements ($someSetting) must be added, all configuration must be in v6+ style (RainerScript) - compile cleanly without WARNING messages under both gcc and clang - pass clang static analyzer without any report - pass all CI tests - new functionality must have associated * testbench tests * doc additions in the rsyslog-doc sister project - be [sufficiently squashed](https://rainer.gerhards.net/2019/03/squash-your-pull-requests.html) ### Testbench Coverage If you fix a bug that is not detected by the current testbench, it is appreciated if you also add testbench test to make sure the problem does not re-occur in the future. In contrast to new feature PRs, this is not a hard requirement, but it helps to speed up merging. If there is no testbench test added, the core rsyslog developers will try to add one based on the patch. That means merging needs to wait until we have time to do this. ### Compiler Diagnostics Note that both warning messages and static analyzer warnings may be false positives. We have decided to accept that fate and work around it (e.g. by re-arranging the code, etc). Otherwise, we cannot use these useful features. As a last resort, compiler warnings can be turned off via #pragma diagnostic directives. This should really only be done if there is no other known way around it. If so, it should be applied to a single function, only and not to full source file. Be sure to re-enable the warning after the function in question. We have done this in some few cases ourselves, and if someone can fix the root cause, we would appreciate help. But, again, this is a last resort which should normally not be used. Please read [on the importance of static analysis and why we request you to work around false positives](https://rainer.gerhards.net/2018/06/why-static-code-analysis.html). ### Continuous Integration Testing All patches are run though our continuous integration system, which ensures no regressions are inside the code as well as rsyslog project policies are followed (as far as we can check in an automated way). For pull requests submitted via github, these two conditions are verified automatically. See the PR for potential failures. For patches submitted otherwise, they will be verified semi-manually. Also, patches are requested to not break the testbench. Unfortunately, the current testbench has some racy tests, which are still useful enough so that we do not want to disable them until the root cause has been found. If your PR runs into something that you think is not related to your code, just sit back and relax. The rsyslog core developer team reviews PRs regularly and restarts tests which we know to look racy. If the problem persists, we will contact you. All PRs will be tested on a variety of systems, with the help of both Travis CI and buildbot. The core goal of this multi-platform testing is to find issues that surface only on some systems (e.g. 32bit related issues, etc). We continuously strive to update the CI system coverage. If you can provide a buildbot slave for a not-yet-supported test platform, please let us know. We will gladly add it. Note that test coverage differs between platforms. For example, not all databases etc. are tested on each platform. Also note that due to resource constraints some very lengthy tests are only execute on some (maybe only a single) platform. Note that we always try to merge with the most recent master branch and try a build from that version (if automatic merging is possible). If this test fails but no other, chances are good that there is an inter-PR issue. If this happens, it is suggested to rebase to git master branch and update the PR. ## Note to developers Please address pull requests against the master branch. ## Testbench coding Tips - look for similar tests and use them as copy template. Be sure to update comments as well. - see ./tests/diag.sh -- this is the base testing framework and it contains many functions you can use inside your tests - keep test cases simple and focussed on one topic. Otherwise it is hard to address test failures when they happen in the future. ------------------------------------------------------------------------------------- LEGAL GDPR NOTICE: According to the European data protection laws (GDPR), we would like to make you aware that contributing to rsyslog via git will permanently store the name and email address you provide as well as the actual commit and the time and date you made it inside git's version history. This is inevitable, because it is a main feature git. If you are concerned about your privacy, we strongly recommend to use --author "anonymous " together with your commit. Also please do NOT sign your commit in this case, as that potentially could lead back to you. Please note that if you use your real identity, the GDPR grants you the right to have this information removed later. However, we have valid reasons why we cannot remove that information later on. The reasons are: * this would break git history and make future merges unworkable * the rsyslog projects has legitimate interest to keep a permanent record of the contributor identity, once given, for - copyright verification - being able to provide proof should a malicious commit be made Please also note that your commit is public and as such will potentially be processed by many third-parties. Git's distributed nature makes it impossible to track where exactly your commit, and thus your personal data, will be stored and be processed. If you would not like to accept this risk, please do either commit anonymously or refrain from contributing to the rsyslog project. ------------------------------------------------------------------------------------- rsyslog-8.2412.0/tests/0000775000175000017500000000000014723322661010365 5rsyslog-8.2412.0/tests/mmanon_recognize_ipv6.sh0000775000175000017500000000375014650736301015146 #!/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.2412.0/tests/mmnormalize_processing_test4.sh0000775000175000017500000000326114650736301016556 #!/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" 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=`echo $srcdir/testsuites/mmnormalize_processing_tests.rulebase` useRawMsg="on") if ($!v_file == "") then { set $!v_file=$!v_tag; } action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_file_record") action(type="omfile" File=`echo $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.2412.0/tests/imuxsock_hostname.sh0000775000175000017500000000164014650736301014404 #!/bin/bash # test set hostname . ${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 NUMMESSAGES=1 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' global(localHostName="rsyslog-testbench-hostname") module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off") input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket") template(name="outfmt" type="string" string="%hostname:%\n") local1.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup # the message itself is irrelevant. The only important thing is # there is one ./syslog_caller -m1 -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket" shutdown_when_empty wait_shutdown export EXPECTED="rsyslog-testbench-hostname" cmp_exact exit_test rsyslog-8.2412.0/tests/sndrcv_dtls_certvalid_missing.sh0000775000175000017500000000370214650736301016760 #!/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=1 # export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" generate_conf export PORT_RCVR="$(get_free_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="'$PORT_RCVR'" 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 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") $imdiagInjectDelayMode full # 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.2412.0/tests/rscript_compare_numstr-str.sh0000775000175000017500000000015314650736301016254 #!/bin/bash export LOWER_VAL='"1"' export HIGHER_VAL='"abc"' source ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2412.0/tests/sndrcv_omsnmpv1_udp_invalidoid.sh0000775000175000017500000000236614650736301017063 #!/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 export PORT_SNMP="$(get_free_port)" # 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.2412.0/tests/imuxsock_logger_root.sh0000775000175000017500000000163614650736301015115 #!/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=`echo $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.2412.0/tests/clickhouse-load.sh0000775000175000017500000000172314650736301013714 #!/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.2412.0/tests/rscript_compare_num-str.sh0000775000175000017500000000014714650736301015526 #!/bin/bash export LOWER_VAL='1' export HIGHER_VAL='"b"' source ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2412.0/tests/es-bulk-errfile-popul-erronly-interleaved.sh0000775000175000017500000000272114720125021020747 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz 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" searchType="test-type" 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 if [ $? -ne 0 ] then echo "error: Format for error file different! " $? exit 1 fi exit_test rsyslog-8.2412.0/tests/compresssp-stringtpl.sh0000775000175000017500000000172314650736301015070 #!/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" 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.2412.0/tests/omprog-feedback-mt.sh0000775000175000017500000000351314650736301014310 #!/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 NUMMESSAGES=10000 # number of logs to send 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 --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES shutdown_when_empty wait_shutdown exit_test rsyslog-8.2412.0/tests/rscript_compare_num-num-vg.sh0000775000175000017500000000017714650736301016132 #!/bin/bash export USE_VALGRIND="YES" export LOWER_VAL='1' export HIGHER_VAL='2' source ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2412.0/tests/imuxsock_logger_syssock.sh0000775000175000017500000000133714650736301015626 #!/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.2412.0/tests/omhttp-batch-kafkarest-retry.sh0000775000175000017500000000320314650736301016347 #!/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.2412.0/tests/imuxsock_logger_err.sh0000775000175000017500000000213314650736301014713 #!/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=`echo $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.2412.0/tests/omamqp1-basic-vg.sh0000775000175000017500000000011314650736301013702 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:=.}/omamqp1-basic.sh rsyslog-8.2412.0/tests/sndrcv_kafka.sh0000775000175000017500000000623114650736301013301 #!/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 KEEP_KAFKA_RUNNING="YES" export TESTMESSAGES=100000 export TESTMESSAGESFULL=100000 # Generate random topic name export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1) # 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") $imdiagInjectDelayMode full 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.2412.0/tests/execonlywhenprevsuspended-queue.sh0000775000175000017500000000176514650736301017316 #!/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.2412.0/tests/rscript_previous_action_suspended.sh0000775000175000017500000000123314650736301017673 #!/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" 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=`echo $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.2412.0/tests/omprog-feedback-timeout.sh0000775000175000017500000000242014650736301015352 #!/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 reportFailures="on" ) } ' startup injectmsg 0 10 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.2412.0/tests/fieldtest-udp.sh0000775000175000017500000000162414650736301013417 #!/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:F,32:2%\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: 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.2412.0/tests/README0000664000175000017500000000571114650736301011170 This directory contains the rsyslog testbench. It is slowly evolving. New tests are always welcome. So far, most tests check out the functionality of a single module. More complex tests are welcome. For a simple sample, see rtinit.c, which does a simple init/deinit check of the runtime system. Test Naming =========== Test that use valgrind shall end in "-vg.sh". Test that use valgrind's helgrind thread debugger shall end in "-vgthread.sh". Setting up Test Environments ============================ Setting up MariaDB/MySQL ------------------------ to create the necessary user: 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 -------- To configure system properties like hostname and firewall, use the graphical "yast2" administration tool. Note the ssh-access by default is disable in the firewall! Before running tests ==================== make check - this will compile all of the C code used in the tests, as well as do any other preparations, and will start running all of the tests. Ctrl-C to stop running all of the tests. Running all tests ================= make check Running named tests =================== make testname.log For example, to run the imfile-basic.sh test, use make imfile-basic.log Test output is in imfile-basic.log To re-run the test, first remove imfile-basic.log then make again Or an alternative option is to run make check TESTS='imfile-basic.sh' * Using gdb to debug rsyslog during a test run Edit your test like this: . $srcdir/diag.sh startup if [ -n "${USE_GDB:-}" ] ; then echo attach gdb here sleep 54321 || : fi Run your test in the background: USE_GDB=1 make mytest.sh.log & Tail mytest.sh.log until you see 'attach gdb here'. The log should also tell you what is the rsyslogd pid. gdb ../tools/rsyslogd $rsyslogd_pid Set breakpoints, whatever, then 'continue' In another window, do ps -ef|grep 54321, then kill that pid Core Dump Analysis ================== The testbench contains some limited (yet useful) support for automatically analyzing core dumps. In order for this to work, obviously core files need to be generated. This often doesn't work as intended. If you hit this problem, check 1. ulimit -c unlimited (or a reasonable limit) Note that root may need to increase a system-wide limit, which is usually recorded in /etc/security/limits.conf You need: * soft core unlimited 2. cat /proc/sys/kernel/core_pattern" On systemd systems (and some others), the pattern is changed to save core files so that systemd can import them -- with the result that the testbench doesn't see them any longer. We require classic format, which can be set via $ sudo bash -c "echo \"core\" > /proc/sys/kernel/core_pattern" Note that you probably want to do neither of these changes to a production system. rsyslog-8.2412.0/tests/override_gethostname_nonfqdn.c0000664000175000017500000000035414650736301016412 #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.2412.0/tests/imfile-error-not-repeated.sh0000775000175000017500000000255014650736301015626 #!/bin/bash # add 2017-04-28 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' 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 ./msleep 3000 echo 'testmessage1 testmessage2 testmessage3' > $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.2412.0/tests/rscript_num2ipv4.sh0000775000175000017500000000270014650736301014074 #!/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" 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.2412.0/tests/diskqueue-full.sh0000775000175000017500000000150114650736301013577 #!/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.2412.0/tests/randomgen.c0000664000175000017500000000651014650736301012424 /* 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() { 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.2412.0/tests/dynfile_invld_async.sh0000775000175000017500000000367314650736301014677 #!/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" 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.2412.0/tests/operatingstate-empty.sh0000775000175000017500000000135714650736301015036 #!/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.2412.0/tests/imfile-freshStartTail1.sh0000775000175000017500000000146014650736301015127 #!/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.2412.0/tests/mmanon_zero_50_ipv6.sh0000775000175000017500000000240714650736301014442 #!/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.2412.0/tests/omfwd-lb-2target-retry.sh0000775000175000017500000000443014704407366015072 #!/bin/bash # 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 start_minitcpsrvr $RSYSLOG_OUT_LOG 1 # 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'", "'$TCPFLOOD_PORT'"] 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" echo WARNING: The next part of this test is flacky, because there is an echo inevitable race on the port number for minitcpsrvr. If another echo parallel test has aquired it in the interim, this test here will echo invalidly fail. ./minitcpsrv -t127.0.0.1 -p $TCPFLOOD_PORT -f "$RSYSLOG2_OUT_LOG" \ -P "$RSYSLOG_DYNNAME.minitcpsrvr_port2" & # Note: we use the port file just to make sure minitcpsrvr has initialized! wait_file_exists "$RSYSLOG_DYNNAME.minitcpsrvr_port2" BGPROCESS=$! echo "### background minitcpsrv process id is $BGPROCESS port $TCPFLOOD_PORT ###" echo "waiting a bit to ensure rsyslog retries the currently suspended pool member" sleep 3 injectmsg $NUMMESSAGES $NUMMESSAGES shutdown_when_empty wait_shutdown if [ "$(wc -l < $RSYSLOG2_OUT_LOG)" != "$(( NUMMESSAGES / 2 ))" ]; then echo "ERROR: RSYSLOG2_OUT_LOG has invalid number of messages $(( NUMMESSAGES / 2 ))" 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.2412.0/tests/rscript_compare_str-num-vg.sh0000775000175000017500000000020114650736301016127 #!/bin/bash export USE_VALGRIND="YES" export LOWER_VAL='"-"' export HIGHER_VAL='1' source ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2412.0/tests/action-tx-errfile.sh0000775000175000017500000000230314650736301014175 #!/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 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 ' $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" 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="$(cat ${srcdir}/testsuites/action-tx-errfile.result)" cmp_exact ${RSYSLOG2_OUT_LOG} mysql_get_data seq_check 0 $((NUMMESSAGES - 2)) -i2 exit_test rsyslog-8.2412.0/tests/hostname-with-slash-pmrfc3164.sh0000775000175000017500000000156714650736301016176 #!/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" 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.2412.0/tests/clickhouse-wrong-template-option.sh0000775000175000017500000000217414650736301017251 #!/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.2412.0/tests/clickhouse-limited-batch.sh0000775000175000017500000000173514650736301015506 #!/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.2412.0/tests/discard-allmark.sh0000775000175000017500000000146614650736301013704 #!/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" 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.2412.0/tests/cfg1.cfgtest0000664000175000017500000000035214650736301012505 rsyslogd: 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.2412.0/tests/killrsyslog.sh0000775000175000017500000000063314650736301013223 #!/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.2412.0/tests/manytcp.sh0000775000175000017500000000201514672761741012326 #!/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" 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" 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 # 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.2412.0/tests/imptcp-msg-truncation-on-number.sh0000775000175000017500000000250714650736301017013 #!/bin/bash # addd 2017-03-01 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init 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") 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.2412.0/tests/cfg4.cfgtest0000664000175000017500000000005514522461111012500 rsyslogd: End of config validation run. Bye. rsyslog-8.2412.0/tests/imdtls-basic-timeout.sh0000775000175000017500000000331214656663250014711 #!/bin/bash # added 2023-10-05 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=2000 export SENDESSAGES=500 generate_conf export PORT_RCVR="$(get_free_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="'$PORT_RCVR'" 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 # 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.2412.0/tests/glbl-internalmsg_severity-info-shown.sh0000775000175000017500000000111414650736301020120 #!/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.2412.0/tests/mmanon_zero_8_ipv4.sh0000775000175000017500000000152314650736301014361 #!/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.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.2412.0/tests/omhttp-batch-lokirest-retry-vg.sh0000775000175000017500000000013214650736301016640 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:=.}/omhttp-batch-kafkarest-retry.sh rsyslog-8.2412.0/tests/imhiredis-redis-start-after.sh0000775000175000017500000000217714650736301016165 #!/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.2412.0/tests/es-basic-errfile-empty.sh0000775000175000017500000000161514720125021015103 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz 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.2412.0/tests/imfile-endmsg.regex-with-example.sh0000775000175000017500000001102714650736301017077 #!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # This test tests imfile endmsg.regex. . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify export IMFILECHECKTIMEOUT="60" export IMFILELASTINPUTLINES="6" mkdir $RSYSLOG_DYNNAME.statefiles generate_conf add_conf ' module(load="../plugins/imfile/.libs/imfile") module(load="../plugins/mmnormalize/.libs/mmnormalize") input(type="imfile" statefile.directory="'${RSYSLOG_DYNNAME}'.statefiles" 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 echo '{"time":"date", "stream":"stdout", "log":"msgnum:1\n"}' >> $RSYSLOG_DYNNAME.json.input echo 'date stdout F msgnum:2' >> $RSYSLOG_DYNNAME.crio.input echo '{"time":"date", "stream":"stdout", "log":"msgnum:2\n"}' >> $RSYSLOG_DYNNAME.json.input # sleep a little to give rsyslog a chance to begin processing if [ -n "${USE_GDB:-}" ] ; then sleep 54321 || : else sleep 1 fi 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 # give it time to finish if [ -n "${USE_GDB:-}" ] ; then sleep 54321 || : else sleep 1 fi echo 'date stdout F msgnum:6' >> $RSYSLOG_DYNNAME.crio.input echo '{"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 content_check_with_count "$RSYSLOG_DYNNAME" $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 # give it time to write the output file sleep 1 ## 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.2412.0/tests/imfile-endregex-timeout-polling.sh0000775000175000017500000000312014650736301017031 #!/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! echo '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.2412.0/tests/imfile-persist-state-1.sh0000775000175000017500000000147214650736301015057 #!/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.2412.0/tests/improg_prog_confirm.sh0000775000175000017500000000132214650736301014702 #!/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 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.2412.0/tests/omfwd-errfile-maxsize-filled.sh0000775000175000017500000000113114650736301016314 #!/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.2412.0/tests/sndrcv_gzip.sh0000775000175000017500000000240214650736301013171 #!/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" 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.2412.0/tests/imfile-wildcards-dirs.sh0000775000175000017500000000335714650736301015031 #!/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 touch $RSYSLOG_DYNNAME.input.dir$i/file.logfile ./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.dir$i/file.logfile done ls -d $RSYSLOG_DYNNAME.input.* # Content check with timeout content_check_with_count "HEADER msgnum:00000000:" $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.2412.0/tests/now-utc-casecmp.sh0000775000175000017500000000211014650736301013642 #!/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" 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.2412.0/tests/complex1.sh0000775000175000017500000000771114650736301012401 #!/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 export RSYSLOG_PORT2="$(get_free_port)" export RSYSLOG_PORT3="$(get_free_port)" generate_conf echo ports: $TCPFLOOD_PORT $RSYSLOG_PORT2 $RSYSLOG_PORT3 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 '$TCPFLOOD_PORT' $InputTCPServerBindRuleset R13514 $InputTCPServerRun '$TCPFLOOD_PORT' ## 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 '$RSYSLOG_PORT2' $InputTCPServerBindRuleset R_PORT2 $InputTCPServerRun '$RSYSLOG_PORT2' ## 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 '$RSYSLOG_PORT3' $InputTCPServerBindRuleset R_PORT3 $InputTCPServerRun '$RSYSLOG_PORT3' ' 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 # 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.2412.0/tests/uxsockrcvr.c0000664000175000017500000001002514650736301012657 /* 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) * -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 #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 sock; int addNL = 0; /* called to clean up on exit */ void cleanup(void) { unlink(sockName); close(sock); } void doTerm(int __attribute__((unused)) signum) { exit(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" "if -o ist not specified, stdout is used\n"); exit(1); } int main(int argc, char *argv[]) { int opt; int rlen; int timeout = DFLT_TIMEOUT; FILE *fp = stdout; unsigned char data[128*1024]; struct sockaddr_un addr; /* address of server */ struct sockaddr from; socklen_t fromlen; struct pollfd fds[1]; if(argc < 2) { fprintf(stderr, "error: too few arguments!\n"); usage(); } while((opt = getopt(argc, argv, "s:o:lt:")) != EOF) { switch((char)opt) { case 'l': addNL = 1; break; case 's': sockName = optarg; break; case 'o': if((fp = fopen(optarg, "w")) == NULL) { perror(optarg); exit(1); } break; case 't': timeout = atoi(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); } /* Create a UNIX datagram socket for server */ if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { perror("server: socket"); exit(1); } atexit(cleanup); /* Set up address structure for server socket */ memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, sockName); if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0) { close(sock); perror("server: bind"); exit(1); } fds[0].fd = sock; fds[0].events = POLLIN; /* 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) { fromlen = sizeof(from); rlen = poll(fds, 1, timeout); if(rlen == -1) { perror("uxsockrcvr : poll\n"); exit(1); } else if(rlen == 0) { fprintf(stderr, "Socket timed out - nothing to receive\n"); exit(1); } else { rlen = recvfrom(sock, 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); } } } return 0; } rsyslog-8.2412.0/tests/rscript_compare_str-num.sh0000775000175000017500000000014714650736301015526 #!/bin/bash export LOWER_VAL='"-"' export HIGHER_VAL='1' source ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2412.0/tests/rscript_is_time.sh0000775000175000017500000000735414650736301014053 #!/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" 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.2412.0/tests/rscript_unflatten_non_object.sh0000775000175000017500000000167714650736301016624 #!/bin/bash # added 2021-03-09 by Julien Thomas, released under ASL 2.0 source "${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" 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=`echo $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.2412.0/tests/imfile-endregex-timeout-with-shutdown-polling.sh0000775000175000017500000000324414650736301021662 #!/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.2412.0/tests/template-pos-from-to-oversize.sh0000775000175000017500000000265114650736301016506 #!/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" 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" 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.2412.0/tests/imfile-fileNotFoundError-parameter.sh0000775000175000017500000000131314650736301017470 #!/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.2412.0/tests/imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh0000775000175000017500000000346214650736301020203 #!/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" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" name="i1" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" name="i2" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port3" name="i3" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" 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.2412.0/tests/sndrcv_tls_anon_rebind.sh0000775000175000017500000000410614704407366015371 #!/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 export NUMMESSAGES=25000 #25000 # uncomment for debugging support: # start up the instances #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf export PORT_RCVR="$(get_free_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'" 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'.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 PORT_RCVR=$TCPFLOOD_PORT # save this, will be rewritten with next config #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.2412.0/tests/omruleset-queue.sh0000775000175000017500000000272614650736301014013 #!/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.2412.0/tests/rscript_privdropgroup.sh0000775000175000017500000000120014650736301015324 #!/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.2412.0/tests/rscript_exists-yes.sh0000775000175000017500000000075414650736301014534 #!/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.2412.0/tests/rscript-config_enable-off-vg.sh0000775000175000017500000000100614650736301016261 #!/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.2412.0/tests/mmdb-container-empty.sh0000775000175000017500000000154214650736301014700 #!/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.2412.0/tests/rs-cnum.sh0000775000175000017500000000133414650736301012230 #!/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" 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.2412.0/tests/execonlywhenprevsuspended.sh0000775000175000017500000000163314650736301016166 #!/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.2412.0/tests/gzipwr_flushInterval.sh0000775000175000017500000000165414650736301015101 #!/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" 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.2412.0/tests/json_object_looping.sh0000775000175000017500000000561114650736301014674 #!/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 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.2412.0/tests/rscript_http_request.sh0000775000175000017500000000272014650736301015141 #!/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" 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.2412.0/tests/omfile-module-params.sh0000775000175000017500000000101714650736301014661 #!/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.2412.0/tests/omhttp-batch-fail-with-400.sh0000775000175000017500000000206414650736301015422 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Starting actual testbench . ${srcdir:=.}/diag.sh init omhttp_start_server 0 --fail-with-400-after 1000 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%\"}") # 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" # Auth usehttps="off" ) & stop } if $msg contains "msgnum:" then call ruleset_omhttp ' startup injectmsg 0 10000 shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint omhttp_stop_server seq_check 0 999 exit_test rsyslog-8.2412.0/tests/imbatchreport_errmsg_rename_params.sh0000775000175000017500000000067414650736301017766 #!/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.2412.0/tests/rscript_unflatten_conflict1-vg.sh0000775000175000017500000000013114650736301016760 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/rscript_unflatten_conflict1.sh rsyslog-8.2412.0/tests/rscript_ruleset_call_indirect-invld.sh0000775000175000017500000000140414650736301020061 #!/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.2412.0/tests/cee_diskqueue.sh0000775000175000017500000000131414650736301013455 #!/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 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="disk" queue.filename="rsyslog-act1") ' startup injectmsg shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2412.0/tests/chkseq.c0000664000175000017500000001462714650736301011740 /* 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 messagt 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 int main(int argc, char *argv[]) { FILE *fp; int val; 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; int edLen; /* length of extra data */ static char edBuf[500*1024]; /* buffer for extra data (pretty large to be on the save side...) */ static char ioBuf[sizeof(edBuf)+1024]; char *file = NULL; 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 file -sstart -eend -d -E\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) { if(fgets(ioBuf, sizeof(ioBuf), fp) == NULL) { scanfOK = 0; } else { scanfOK = sscanf(ioBuf, "%d,%d,%s\n", &val, &edLen, edBuf) == 3 ? 1 : 0; } if(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) { 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; } 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) { if(fgets(ioBuf, sizeof(ioBuf), fp) == NULL) { scanfOK = 0; } else { scanfOK = sscanf(ioBuf, "%d,%d,%s\n", &val, &edLen, edBuf) == 3 ? 1 : 0; } if(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(val != i) { reachedEOF = 0; 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.2412.0/tests/imdocker-basic.sh0000775000175000017500000000202514650736301013516 #!/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 export COOKIE=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 10 | head -n 1) 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.2412.0/tests/mmjsonparse_simple.sh0000775000175000017500000000137514650736301014560 #!/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=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m $NUMMESSAGES -j "@cee: " shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2412.0/tests/kafka-selftest.sh0000775000175000017500000000275014650736301013553 #!/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 kafkacat export KEEP_KAFKA_RUNNING="YES" export TESTMESSAGES=100000 export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1) # 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 kafkacat\n' injectmsg_kafkacat # experimental: wait until kafkacat receives everything timeoutend=10 timecounter=0 printf 'receiving messages via kafkacat\n' while [ $timecounter -lt $timeoutend ]; do (( timecounter++ )) kafkacat -b localhost: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 [ "x$timecounter" == "x$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.2412.0/tests/pmnormalize-invld-rulebase-vg.sh0000775000175000017500000000022614650736301016524 #!/bin/bash # added 2019-04-10 by Rainer Gerhards, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:-.}/pmnormalize-invld-rulebase.sh rsyslog-8.2412.0/tests/omfwd-errfile-maxsize.sh0000775000175000017500000000074214650736301015066 #!/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.2412.0/tests/mmanon_zero_33_ipv4.sh0000775000175000017500000000214014650736301014433 #!/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.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.2412.0/tests/rscript_unflatten_conflict3.sh0000775000175000017500000000237414650736301016363 #!/bin/bash # added 2021-03-09 by Julien Thomas, released under ASL 2.0 source "${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" 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.2412.0/tests/imhttp-getrequest-file.sh0000775000175000017500000000101614650736301015251 #!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf IMHTTP_PORT="$(get_free_port)" add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../contrib/imhttp/.libs/imhttp" ports="'$IMHTTP_PORT'" documentroot="'$srcdir'/testsuites/docroot") ' startup 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.2412.0/tests/abort-uncleancfg-badcfg-check.sh0000775000175000017500000000073014650736301016334 #!/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.2412.0/tests/pmnormalize-rule_invld-data.sh0000775000175000017500000000201114650736301016242 #!/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" 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.2412.0/tests/msg-deadlock-headerless-noappname.sh0000775000175000017500000000115314650736301017266 #!/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" 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.2412.0/tests/privdropgroupid.sh0000775000175000017500000000115514650736301014104 #!/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.2412.0/tests/empty-hostname.sh0000775000175000017500000000227714650736301013625 #!/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" 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.2412.0/tests/imtcp_spframingfix.sh0000775000175000017500000000152614650736301014540 #!/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" 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.2412.0/tests/fac_mail.sh0000775000175000017500000000115314650736301012376 #!/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" 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.2412.0/tests/clickhouse-stop.sh0000775000175000017500000000132514650736301013760 #!/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.2412.0/tests/rscript_unflatten_object-vg.sh0000775000175000017500000000012614650736301016350 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/rscript_unflatten_object.sh rsyslog-8.2412.0/tests/omfwd-lb-1target-retry-1_byte_buf.sh0000775000175000017500000000017114704407366017104 #!/bin/bash export OMFWD_IOBUF_SIZE=10 # triggers edge cases source ${srcdir:-.}/omfwd-lb-1target-retry-test_skeleton.sh rsyslog-8.2412.0/tests/omazureeventhubs-interrupt.sh0000775000175000017500000001261214650736301016305 #!/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 # --- 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="" # --- source 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" # 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") $imdiagInjectDelayMode full # 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 100 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.2412.0/tests/timegenerated-dateordinal.sh0000775000175000017500000000722714650736301015754 #!/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" 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.2412.0/tests/omhttp-basic-ignorecodes-vg.sh0000775000175000017500000000012614650736301016145 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:=.}/omhttp-basic-ignorecodes.sh rsyslog-8.2412.0/tests/imrelp-manyconn.sh0000775000175000017500000000121114650736301013746 #!/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.2412.0/tests/lookup_table_no_hup_reload.sh0000775000175000017500000000176514650736301016232 #!/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.2412.0/tests/rscript_number_comparison_LE-vg.sh0000775000175000017500000000013214650736301017121 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/rscript_number_comparison_LE.sh rsyslog-8.2412.0/tests/json-onempty-at-end.sh0000775000175000017500000000120514650736301014451 #!/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.2412.0/tests/imdocker-basic-vg.sh0000775000175000017500000000011414650736301014125 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/imdocker-basic.sh rsyslog-8.2412.0/tests/sndrcv_kafka_multi_topics.sh0000775000175000017500000001132514650736301016074 #!/bin/bash # added 2018-08-13 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export TESTMESSAGES=50000 export TESTMESSAGESFULL=100000 # Generate random topic name export RANDTOPIC1=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1) export RANDTOPIC2=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1) # 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") $imdiagInjectDelayMode full 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" 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.2412.0/tests/imdocker-new-logs-from-start-vg.sh0000775000175000017500000000013214650736301016673 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/imdocker-new-logs-from-start.sh rsyslog-8.2412.0/tests/imtuxedoulog_errmsg_no_params.sh0000775000175000017500000000057314650736301017013 #!/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.2412.0/tests/omhttp-retry-timeout-vg.sh0000775000175000017500000000012214650736301015412 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:=.}/omhttp-retry-timeout.sh rsyslog-8.2412.0/tests/msgdup.sh0000775000175000017500000000240614650736301012144 #!/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.2412.0/tests/incltest_dir.sh0000775000175000017500000000103514650736301013325 #!/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.2412.0/tests/es-maxbytes-bulk.sh0000775000175000017500000000136414720125021014030 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz 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.2412.0/tests/omrabbitmq_data_1server-vg.sh0000775000175000017500000000022114650736301016045 #!/bin/bash # add 2019-09-03 by Philippe Duveau, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:-.}/omrabbitmq_data_1server.sh rsyslog-8.2412.0/tests/test_id_usage_output.sh0000775000175000017500000000042314650736301015101 #!/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.2412.0/tests/imuxsock_ccmiddle_syssock.sh0000775000175000017500000000165714650736301016120 #!/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=`echo $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.2412.0/tests/clickhouse-dflt-tpl.sh0000775000175000017500000000156014650736301014522 #!/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","172.20.245.8","tag"," msgnum:00000000:"' exit_test rsyslog-8.2412.0/tests/pmnormalize-neither_rule_rulebase-vg.sh0000775000175000017500000000023514650736301020157 #!/bin/bash # added 2019-04-10 by Rainer Gerhards, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:-.}/pmnormalize-neither_rule_rulebase.sh rsyslog-8.2412.0/tests/omhttp-batch-kafkarest-retry-vg.sh0000775000175000017500000000013214650736301016757 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:=.}/omhttp-batch-kafkarest-retry.sh rsyslog-8.2412.0/tests/omprog-single-instance-vg.sh0000775000175000017500000000021314650736301015635 #!/bin/bash # addd 2019-04-15 by RGerhards, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:=.}/omprog-single-instance.sh rsyslog-8.2412.0/tests/sndrcv_ossl_cert_chain.sh0000775000175000017500000000461414650736301015366 #!/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 export PORT_RCVR="$(get_free_port)" ### This is important, as it must be exactly the same ### as the ones configured in used certificates export HOSTNAME="fedora" add_conf ' global( DefaultNetstreamDriver="ossl" DefaultNetstreamDriverCAFile="'$srcdir/testsuites/certchain/ca-cert.pem'" DefaultNetstreamDriverCertFile="'$srcdir/testsuites/certchain/server-cert.pem'" DefaultNetstreamDriverKeyFile="'$srcdir/testsuites/certchain/server-key.pem'" NetstreamDriverCAExtraFiles="'$srcdir/testsuites/certchain/ca-root-cert.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" PermittedPeer="'$HOSTNAME'" StreamDriver.AuthMode="x509/name" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="'$PORT_RCVR'" ) $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" generate_conf 2 export TCPFLOOD_PORT="$(get_free_port)" add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/certchain/ca-root-cert.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/certchain/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/certchain/client-key.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" ) # set up the action action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="x509/name" StreamDriverPermittedPeers="'$HOSTNAME'" ) ' 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.2412.0/tests/omfwd-lb-2target-impstats.sh0000775000175000017500000000346614704407366015601 #!/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.2412.0/tests/imfile-logrotate-multiple.sh0000775000175000017500000000375414650736301015750 #!/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" { 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.2412.0/tests/mmkubernetes-basic-vg.sh0000775000175000017500000002404114650736301015036 #!/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 #export RSYSLOG_DEBUG="debug" USE_VALGRIND=true . ${srcdir:=.}/diag.sh init check_command_available timeout pwd=$( pwd ) k8s_srv_port=$( get_free_port ) generate_conf 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") ' testsrv=mmk8s-test-server echo starting kubernetes \"emulator\" timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py $k8s_srv_port ${RSYSLOG_DYNNAME}${testsrv}.pid ${RSYSLOG_DYNNAME}${testsrv}.started > ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log 2>&1 & BGPROCESS=$! wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started echo background mmkubernetes_test_server.py process id is $BGPROCESS 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.2412.0/tests/rscript_re_match_i.sh0000775000175000017500000000123014650736301014477 #!/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" 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.2412.0/tests/discard-rptdmsg-vg.sh0000775000175000017500000000022014650736301014336 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:-.}/discard-rptdmsg.sh rsyslog-8.2412.0/tests/rscript_http_request-vg.sh0000775000175000017500000000016214650736301015551 #!/bin/bash export USE_VALGRIND="YES" export TB_TEST_MAX_RUNTIME=1500 source ${srcdir:-.}/rscript_http_request.sh rsyslog-8.2412.0/tests/inputname-imtcp.sh0000775000175000017500000000216214650736301013756 #!/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" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1" name="l1") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2" ruleset="ruleset1" name="l2") input(type="imtcp" 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.2412.0/tests/es-basic-ha-vg.sh0000775000175000017500000000130014720125021013310 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100 export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz 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.2412.0/tests/imbatchreport_errmsg_delete_params.sh0000775000175000017500000000066714650736301017763 #!/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.2412.0/tests/template-const-jsonf.sh0000775000175000017500000000070614650736301014722 #!/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.2412.0/tests/clickhouse-bulk.sh0000775000175000017500000000304414650736301013730 #!/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.2412.0/tests/glbl-oversizeMsg-split.sh0000775000175000017500000000366214650736301015236 #!/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.2412.0/tests/pmlastmsg-udp.sh0000775000175000017500000000333714650736301013446 #!/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.2412.0/tests/tcp_forwarding_retries.sh0000775000175000017500000000233214650736301015410 #!/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.2412.0/tests/imfile-readmode2-with-persists.sh0000775000175000017500000000474314650736301016603 #!/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.2412.0/tests/sndrcv_tls_ossl_anon_ipv4.sh0000775000175000017500000000412314656663250016051 #!/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 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.2412.0/tests/rscript_wrap2.sh0000775000175000017500000000154714650736301013453 #!/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" 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.2412.0/tests/imtcp-NUL.sh0000775000175000017500000000127114650736301012414 #!/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" 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.2412.0/tests/template-pure-json.sh0000775000175000017500000000103214650736301014372 #!/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.jsonf="on") { property(outname="message" name="msg" format="jsonf") constant(outname="@version" value="1" format="jsonf") } local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown export EXPECTED='{"message":" msgnum:00000000:", "@version": "1"}' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2412.0/tests/rscript_parse_time.sh0000775000175000017500000001066214650736301014546 #!/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" 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.2412.0/tests/queue-persist.sh0000775000175000017500000000115114650736301013454 #!/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.2412.0/tests/smtradfile-vg.sh0000775000175000017500000000017714650736301013414 #!/bin/bash # addd 2019-04-15 by RGerhards, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:=.}/smtradfile.sh rsyslog-8.2412.0/tests/dynfile_invld_sync.sh0000775000175000017500000000367414650736301014537 #!/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" 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 off $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.2412.0/tests/array_lookup_table-vg.sh0000775000175000017500000000027014650736301015132 #!/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" source ${srcdir:-.}/array_lookup_table.sh rsyslog-8.2412.0/tests/zstd.sh0000775000175000017500000000306514650736301011633 #!/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.2412.0/tests/execonlywhenprevsuspended_multiwrkr.sh0000775000175000017500000000170714650736301020310 #!/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.2412.0/tests/dynstats_prevent_premature_eviction-vg.sh0000775000175000017500000000531714650736301020663 #!/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.2412.0/tests/now_family_utc.sh0000775000175000017500000000160514650736301013664 #!/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" 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.2412.0/tests/sndrcv_relp_tls_prio.sh0000775000175000017500000000242714650736301015104 #!/bin/bash # added 2013-12-10 by Rgerhards # 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 export PORT_RCVR="$(get_free_port)" add_conf ' module(load="../plugins/imrelp/.libs/imrelp") # then SENDER sends to this port (not tcpflood!) input(type="imrelp" port="'$PORT_RCVR'" 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 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.2412.0/tests/omprog-feedback-vg.sh0000775000175000017500000000144014650736301014301 #!/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.2412.0/tests/omfwd_impstats-udp.sh0000775000175000017500000000172414650736301014475 #!/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.2412.0/tests/rscript_unflatten_conflict3-vg.sh0000775000175000017500000000013114650736301016762 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/rscript_unflatten_conflict3.sh rsyslog-8.2412.0/tests/imfile-symlink-multi.sh0000775000175000017500000000474514650736301014736 #!/bin/bash # This test points multiple symlinks (all watched by rsyslog via wildcard) # to single file and checks that message is reported once for each symlink # with correct corresponding metadata. # This is part of the rsyslog testbench, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify export IMFILEINPUTFILES="10" 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 # Wait little for correct timing ./msleep 50 done 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.2412.0/tests/imrelp-sessionbreak-vg.sh0000775000175000017500000000331114650736301015231 #!/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.2412.0/tests/rfc5424parser-sp_at_msg_start.sh0000775000175000017500000000156114650736301016343 #!/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.2412.0/tests/imdtls-error-cert.sh0000775000175000017500000000151414650736301014222 #!/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 export PORT_RCVR="$(get_free_port)" 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="'$PORT_RCVR'") 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.2412.0/tests/allowed-sender-tcp-ok.sh0000775000175000017500000000134014650736301014741 #!/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.2412.0/tests/imfile-logrotate.sh0000775000175000017500000000346414650736301014115 #!/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" { 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.2412.0/tests/incltest.sh0000775000175000017500000000043014650736301012465 #!/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.2412.0/tests/queue-minbatch-queuefull.sh0000775000175000017500000000123314650736301015556 #!/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.2412.0/tests/mmrm1stspace-basic.sh0000775000175000017500000000200114650736301014327 #!/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" 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.2412.0/tests/rscript_unflatten_key_truncated.sh0000775000175000017500000000336614650736301017342 #!/bin/bash # added 2021-03-09 by Julien Thomas, released under ASL 2.0 source "${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" 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.2412.0/tests/imdtls-basic-tlscommands.sh0000775000175000017500000000241214650736301015537 #!/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 export PORT_RCVR="$(get_free_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="'$PORT_RCVR'") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup # 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.2412.0/tests/rscript_compare_numstr-numstr.sh0000775000175000017500000000015114650736301016772 #!/bin/bash export LOWER_VAL='"1"' export HIGHER_VAL='"2"' source ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2412.0/tests/mysql-basic-cnf6.sh0000775000175000017500000000072314650736301013723 #!/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.2412.0/tests/mmanon_zero_12_ipv4.sh0000775000175000017500000000152414650736301014435 #!/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.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.2412.0/tests/queue-encryption-disk_keyfile.sh0000775000175000017500000000172414650736301016623 #!/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.2412.0/tests/privdropuser.sh0000775000175000017500000000111514650736301013405 #!/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.2412.0/tests/no-dynstats.sh0000775000175000017500000000160414650736301013127 #!/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.2412.0/tests/sndrcv_dtls_certvalid_ciphers.sh0000775000175000017500000000423414656663250016755 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${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 export PORT_RCVR="$(get_free_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="'$PORT_RCVR'") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup 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.2412.0/tests/glbl-invld-param.sh0000775000175000017500000000070614650736301013776 #!/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.2412.0/tests/minitcpsrv_usage_output.sh0000775000175000017500000000044114650736301015644 #!/bin/bash # add 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; exit_test rsyslog-8.2412.0/tests/mmanon_simple_mallformed_ipv4.sh0000775000175000017500000000262414650736301016651 #!/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" 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.2412.0/tests/action-tx-errfile-maxsize.sh0000775000175000017500000000203714650736301015657 #!/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.2412.0/tests/imtcp-tls-ossl-error-ca.sh0000775000175000017500000000146714650736301015255 #!/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" 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 could not be accessed" content_check "OpenSSL Error Stack:" exit_test rsyslog-8.2412.0/tests/rscript_lt.sh0000775000175000017500000000131314650736301013026 #!/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.2412.0/tests/sndrcv_tls_certless_clientonly.sh0000775000175000017500000000362214650736301017173 #!/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 export PORT_RCVR="$(get_free_port)" 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="'$PORT_RCVR'" ) $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup # sender export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 #export TCPFLOOD_PORT="$(get_free_port)" 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.2412.0/tests/rscript_parse_time_get-ts.py0000664000175000017500000001270014650736301016037 # 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.2412.0/tests/clickhouse-wrong-insert-syntax.sh0000775000175000017500000000233114650736301016753 #!/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.2412.0/tests/mmnormalize_parsesuccess.sh0000775000175000017500000000151014650736301015755 #!/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.2412.0/tests/mmnormalize_tokenized.sh0000775000175000017500000000366614650736301015264 #!/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.2412.0/tests/dynstats-json.sh0000775000175000017500000000356714650736301013476 #!/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.2412.0/tests/imrelp-tls-chainedcert.sh0000775000175000017500000000234714650736301015210 #!/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.2412.0/tests/rscript_trim-vg.sh0000775000175000017500000000566714650736301014014 #!/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" 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.2412.0/tests/config_output-o-option.sh0000775000175000017500000000127414650736301015276 #!/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.2412.0/tests/mmpstrucdata.sh0000775000175000017500000000127214650736301013351 #!/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" 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.2412.0/tests/omjournal-abort-template.sh0000775000175000017500000000120314650736301015563 #!/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.2412.0/tests/imrelp-basic.sh0000775000175000017500000000104614650736301013213 #!/bin/bash # addd 2016-05-13 by RGerhards, released under ASL 2.0 . ${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" 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 shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2412.0/tests/now-utc-ymd.sh0000775000175000017500000000161614650736301013032 #!/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" 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=`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 export EXPECTED="2016-01-01,2015-12-31" exit_test rsyslog-8.2412.0/tests/rscript_trim.sh0000775000175000017500000000564314650736301013374 #!/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" 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.2412.0/tests/imhiredis-redis-restart.sh0000775000175000017500000000275614650736301015420 #!/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.2412.0/tests/omprog-close-unresponsive.sh0000775000175000017500000000310414650736301016005 #!/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.2412.0/tests/omhttp-batch-jsonarray-compress-vg.sh0000775000175000017500000000013514650736301017505 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:=.}/omhttp-batch-jsonarray-compress.sh rsyslog-8.2412.0/tests/localvar-concurrency.sh0000775000175000017500000000225514650736301015002 #!/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" 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.2412.0/tests/omhttp-multiplehttpheaders.sh0000775000175000017500000000152414650736301016245 #!/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.2412.0/tests/NoExistFile.cfgtest0000664000175000017500000000030414650736301014053 rsyslogd: 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.2412.0/tests/omjournal-abort-no-template.sh0000775000175000017500000000107414650736301016203 #!/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.2412.0/tests/mmdarwin_errmsg_no_sock-vg.sh0000775000175000017500000000022114650736301016160 #!/bin/bash # add 2019-04-02 by Rainer Gerhards, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:=.}/mmdarwin_errmsg_no_sock.sh rsyslog-8.2412.0/tests/imfile-basic-vg.sh0000775000175000017500000000011214650736301013573 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/imfile-basic.sh rsyslog-8.2412.0/tests/ruleset-direct-queue.sh0000775000175000017500000000121014650736301014712 #!/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.2412.0/tests/imkafka_multi_group.sh0000775000175000017500000000630114650736301014674 #!/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 kafkacat 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 export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1) 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="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_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_kafkacat # 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.2412.0/tests/rscript_re_match-dbl_quotes.sh0000775000175000017500000000105314650736301016331 #!/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.2412.0/tests/imuxsock_logger_ruleset.sh0000775000175000017500000000144114650736301015607 #!/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=`echo $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.2412.0/tests/privdropabortonidfaillegacy.sh0000775000175000017500000000174614650736301016443 #!/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.2412.0/tests/rscript_number_comparison_LT.sh0000775000175000017500000000104214650736301016527 #!/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.2412.0/tests/improg_errmsg_no_params-vg.sh0000775000175000017500000000023014650736301016163 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:-.}/improg_errmsg_no_params.sh rsyslog-8.2412.0/tests/imhiredis-stream.sh0000775000175000017500000000246114650736301014114 #!/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.2412.0/tests/imtcp-multi-drvr-basic.sh0000775000175000017500000000246414650736301015147 #!/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" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" 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.2412.0/tests/omprog-if-error.sh0000775000175000017500000000227314650736301013675 #!/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.2412.0/tests/imuxsock_traillf_root.sh0000775000175000017500000000216614650736301015272 #!/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=`echo $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.2412.0/tests/imtcp-tls-ossl-x509name.sh0000775000175000017500000000231514656663250015112 #!/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" 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.2412.0/tests/asynwr_timeout.sh0000775000175000017500000000220214650736301013730 #!/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" 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.2412.0/tests/msgvar-concurrency.sh0000775000175000017500000000172314650736301014475 #!/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" 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.2412.0/tests/mmanon_ipv6_port.sh0000775000175000017500000000342314650736301014142 #!/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.2412.0/tests/omprog-transactions.sh0000775000175000017500000001001214650736301014646 #!/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.2412.0/tests/omhttp-batch-dynrestpath.sh0000775000175000017500000000203514650736301015600 #!/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.2412.0/tests/rscript_unflatten_conflict1.sh0000775000175000017500000000245414650736301016360 #!/bin/bash # added 2021-03-09 by Julien Thomas, released under ASL 2.0 source "${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" 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=`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": { "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.2412.0/tests/proprepltest-rfctag.sh0000775000175000017500000000211014650736301014644 #!/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" 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.2412.0/tests/rscript_random.sh0000775000175000017500000000142114650736301013667 #!/bin/bash # added 2015-06-22 by singh.janmejay # 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%\n") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $.random_no = random(10); 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 "^[0-9]$" exit_test rsyslog-8.2412.0/tests/improg_prog_simple-vg.sh0000775000175000017500000000022314650736301015147 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:-.}/improg_prog_simple.sh rsyslog-8.2412.0/tests/abort-uncleancfg-goodcfg-check.sh0000775000175000017500000000070714650736301016542 #!/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.2412.0/tests/perctile-simple-vg.sh0000775000175000017500000000011514650736301014350 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/perctile-simple.sh rsyslog-8.2412.0/tests/imfile-endregex-save-lf.sh0000775000175000017500000000313014650736301015237 #!/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.2412.0/tests/clickhouse-bulk-load.sh0000775000175000017500000000171614650736301014651 #!/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.2412.0/tests/pmnormalize-rule_and_rulebase-vg.sh0000775000175000017500000000023114650736301017257 #!/bin/bash # added 2019-04-10 by Rainer Gerhards, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:-.}/pmnormalize-rule_and_rulebase.sh rsyslog-8.2412.0/tests/fac_ftp.sh0000775000175000017500000000105714650736301012250 #!/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" 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.2412.0/tests/parsertest-snare_ccoff_udp2.sh0000775000175000017500000000537314650736301016247 #!/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.2412.0/tests/imhiredis-stream-from-beginning.sh0000775000175000017500000000250714650736301017014 #!/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.2412.0/tests/imptcp_multi_line.sh0000775000175000017500000000220214650736301014354 #!/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.2412.0/tests/omrabbitmq_params_missing2.sh0000775000175000017500000000060414650736301016156 #!/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.2412.0/tests/cfg2.testin0000664000175000017500000000003314522461111012341 $includeconfig cfg1.testin rsyslog-8.2412.0/tests/mmnormalize_rule_from_array.sh0000775000175000017500000000220014650736301016437 #!/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" 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=`echo $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.2412.0/tests/omprog-transactions-failed-messages.sh0000775000175000017500000001177614650736301017717 #!/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 # # TODO: Issue #2420: Deferred messages within a transaction are # not retried by rsyslog. # If that's the expected behavior, what's then the difference # between the RS_RET_OK and the RS_RET_DEFER_COMMIT return codes? # If that's not the expected behavior, the following lines must # be removed when the bug is solved. # # (START OF CODE THAT WILL POSSIBLY NEED TO BE REMOVED) messages_processed+=("${messages_to_commit[@]}") unset "messages_processed[${#messages_processed[@]}-1]" # (END OF CODE THAT WILL POSSIBLY NEED TO BE REMOVED) 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.2412.0/tests/operatingstate-unclean.sh0000775000175000017500000000161314650736301015320 #!/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.2412.0/tests/mmnormalize_rule_from_string.sh0000775000175000017500000000212314650736301016633 #!/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" 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.2412.0/tests/libdbi-basic-vg.sh0000775000175000017500000000036114650736301013561 #!/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" source ${srcdir:=.}/libdbi-basic.sh rsyslog-8.2412.0/tests/Makefile.am0000664000175000017500000025242314723322534012350 TEST_EXTENSIONS=.sh if ENABLE_TESTBENCH 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_* \ zookeeper.pid \ tmp.qi nocert CLEANFILES+= \ IN_AUTO_DEBUG # 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. pkglib_LTLIBRARIES = pkglib_LTLIBRARIES += liboverride_gethostname.la liboverride_gethostname_la_SOURCES = override_gethostname.c liboverride_gethostname_la_CFLAGS = liboverride_gethostname_la_LDFLAGS = -avoid-version -shared pkglib_LTLIBRARIES += liboverride_gethostname_nonfqdn.la liboverride_gethostname_nonfqdn_la_SOURCES = override_gethostname_nonfqdn.c liboverride_gethostname_nonfqdn_la_CFLAGS = liboverride_gethostname_nonfqdn_la_LDFLAGS = -avoid-version -shared pkglib_LTLIBRARIES += liboverride_getaddrinfo.la liboverride_getaddrinfo_la_SOURCES = override_getaddrinfo.c liboverride_getaddrinfo_la_CFLAGS = liboverride_getaddrinfo_la_LDFLAGS = -avoid-version -shared # TODO: reenable TESTRUNS = rt_init rscript 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_ELASTICSEARCH_TESTS_MINIMAL TESTS += \ es-duplicated-ruleset.sh # the following test need to be serialized: TESTS += \ es-basic-es6.0.sh \ es-basic-es7.14.sh \ es-basic.sh \ es-basic-bulk.sh es-basic-es7.14.log: es-basic-es6.0.log es-basic.log: es-basic-es7.14.log 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 TESTS += elasticsearch-stop.sh elasticsearch-stop.log: es-basic-bulk.log if HAVE_VALGRIND TESTS += \ es-duplicated-ruleset-vg.sh \ es-basic-vg.sh 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 += \ es-basic-vgthread.sh 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 += \ 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 \ es-searchType-empty.sh \ diskqueue-multithread-es.sh \ es-writeoperation.sh 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 es-searchType-empty.log: es-bulk-errfile-popul.log diskqueue-multithread-es.log: es-searchType-empty.log es-writeoperation.log: diskqueue-multithread-es.log elasticsearch-stop.log: es-writeoperation.log if ENABLE_IMPSTATS TESTS += \ es-basic-ha.sh \ es-bulk-retry.sh 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 += \ 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 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 += \ es-basic-bulk-vg.sh \ es-basic-ha-vg.sh 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 if ENABLE_DEFAULT_TESTS TESTS += \ 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 \ minitcpsrv_usage_output.sh \ test_id_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 \ 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-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 \ 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-tls-invalid-permitExpiredCerts.sh \ omfwd-keepalive.sh \ omusrmsg-errmsg-no-params.sh \ omusrmsg-noabort.sh \ omfile-module-params.sh \ omfile-read-only-errmsg.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 \ privdropgroup.sh \ privdropgroupid.sh \ privdropabortonidfail.sh \ privdropabortonidfaillegacy.sh \ json-nonstring.sh \ json-onempty-at-end.sh \ template-json.sh \ template-pure-json.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 \ 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-defaultTag.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-hostname-ok.sh \ allowed-sender-tcp-hostname-fail.sh \ imtcp-discard-truncated-msg.sh \ imtcp-basic.sh \ imtcp-basic-hup.sh \ imtcp-maxFrameSize.sh \ imtcp-msg-truncation-on-number.sh \ imtcp-msg-truncation-on-number2.sh \ imtcp-NUL.sh \ imtcp-NUL-rawmsg.sh \ imtcp_incomplete_frame_at_end.sh \ imtcp-multiport.sh \ imtcp-bigmessage-octetcounting.sh \ imtcp-bigmessage-octetstuffing.sh \ da-queue-persist.sh \ daqueue-persist.sh \ daqueue-invld-qi.sh \ daqueue-dirty-shutdown.sh \ diskq-rfc5424.sh \ diskqueue.sh \ diskqueue-fsync.sh \ diskqueue-full.sh \ diskqueue-fail.sh \ diskqueue-non-unique-prefix.sh \ rulesetmultiqueue.sh \ rulesetmultiqueue-v6.sh \ manytcp.sh \ rsf_getenv.sh \ msg-deadlock-headerless-noappname.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 \ imudp_thread_hang.sh \ sndrcv_udp_nonstdpt_v6.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 \ abort-uncleancfg-goodcfg.sh \ abort-uncleancfg-goodcfg-check.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_logger.sh \ imuxsock_logger_ratelimit.sh \ imuxsock_logger_ruleset.sh \ imuxsock_logger_ruleset_ratelimit.sh \ imuxsock_logger_err.sh \ imuxsock_logger_parserchain.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 \ 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_optimizer1.sh \ rscript_ruleset_call.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_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_format_time.sh \ rscript_parse_time.sh \ rscript_is_time.sh \ rscript_script_error.sh \ rscript_parse_json.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 \ config_output-o-option.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-hup-backgrounded.sh \ lookup_table_no_hup_reload.sh \ key_dereference_on_uninitialized_variable_space.sh \ array_lookup_table.sh \ sparse_array_lookup_table.sh \ lookup_table_bad_configs.sh \ lookup_table_rscript_reload.sh \ lookup_table_rscript_reload_without_stub.sh \ config_multiple_include.sh \ include-obj-text-from-file.sh \ include-obj-text-from-file-noexist.sh \ multiple_lookup_tables.sh \ parsertest-parse1.sh \ parsertest-parse1-udp.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 if ENABLE_LIBZSTD TESTS += \ zstd.sh if HAVE_VALGRIND TESTS += \ zstd-vg.sh endif # if HAVE_VALGRIND endif if ENABLE_LIBGCRYPT TESTS += \ queue-encryption-disk.sh \ queue-encryption-disk_keyfile.sh \ queue-encryption-disk_keyprog.sh \ queue-encryption-da.sh endif # ENABLE_LIBGCRYPT if HAVE_VALGRIND TESTS += \ omusrmsg-noabort-vg.sh \ omfile_hup-vg.sh \ gzipwr_hup-vg.sh \ tcpflood_wrong_option_output.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_parse_json-vg.sh \ rscript_backticks-vg.sh \ rscript_backticks_empty_envvar-vg.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 if ENABLE_LIBGCRYPT TESTS += \ queue-encryption-disk_keyfile-vg.sh endif # ENABLE_LIBGCRYPT endif # HAVE_VALGRIND endif # ENABLE_DEFAULT_TESTS if ENABLE_SNMP TESTS += \ omsnmp_errmsg_no_params.sh if ENABLE_SNMP_TESTS TESTS += \ sndrcv_omsnmpv1_udp.sh \ sndrcv_omsnmpv1_udp_dynsource.sh \ sndrcv_omsnmpv1_udp_invalidoid.sh endif # if ENABLE_SNMP_TESTS endif # if ENABLE_SNMP if ENABLE_MMUTF8FIX TESTS += \ mmutf8fix_no_error.sh endif # if ENABLE_MAIL if ENABLE_MAIL TESTS += \ ommail_errmsg_no_params.sh endif # if ENABLE_MAIL if ENABLE_MMANON TESTS += \ 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 endif # if ENABLE_MMANON if ENABLE_CLICKHOUSE_TESTS TESTS += \ 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-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 += \ clickhouse-basic-vg.sh \ clickhouse-load-vg.sh \ clickhouse-bulk-vg.sh \ clickhouse-bulk-load-vg.sh 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 TESTS += clickhouse-stop.sh endif # CLICKHOUSE_TESTS if ENABLE_LIBFAKETIME TESTS += \ 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 \ timegenerated-utc.sh \ timegenerated-utc-legacy.sh \ timereported-utc.sh \ timereported-utc-legacy.sh # now come faketime tests that utilize mmnormalize - aka "no endif here" if ENABLE_MMNORMALIZE TESTS += \ mmnormalize_processing_test1.sh \ mmnormalize_processing_test2.sh \ mmnormalize_processing_test3.sh \ mmnormalize_processing_test4.sh endif endif if ENABLE_PGSQL if ENABLE_PGSQL_TESTS TESTS += \ 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 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 += \ pgsql-basic-vg.sh \ pgsql-template-vg.sh \ pgsql-basic-cnf6-vg.sh \ pgsql-template-cnf6-vg.sh \ pgsql-actq-mt-withpause-vg.sh 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 += \ mysqld-start.sh \ mysql-basic.sh \ mysql-basic-cnf6.sh \ mysql-asyn.sh \ mysql-actq-mt.sh \ mysql-actq-mt-withpause.sh \ action-tx-single-processing.sh \ action-tx-errfile-maxsize.sh \ action-tx-errfile.sh mysql-basic.log: mysqld-start.log mysql-basic-cnf6.log: mysqld-start.log mysql-asyn.log: mysqld-start.log mysql-actq-mt.log: mysqld-start.log mysql-actq-mt-withpause.log: mysqld-start.log action-tx-single-processing.log: mysqld-start.log action-tx-errfile.log: mysqld-start.log mysqld-stop.log: mysql-basic.log \ mysql-basic-cnf6.log \ mysql-asyn.log \ mysql-actq-mt.log \ mysql-actq-mt-withpause.log \ action-tx-single-processing.log \ action-tx-errfile.log if HAVE_VALGRIND TESTS += \ mysql-basic-vg.sh \ mysql-asyn-vg.sh \ mysql-actq-mt-withpause-vg.sh mysql-basic-vg.log: mysqld-start.log mysql-asyn-vg.log: mysqld-start.log mysql-actq-mt-withpause-vg.log: mysqld-start.log mysqld-stop.log: mysql-basic-vg.log \ mysql-asyn-vg.log \ mysql-actq-mt-withpause-vg.log endif if ENABLE_OMLIBDBI # we piggy-back on MYSQL_TESTS as we need the same environment TESTS += \ libdbi-basic.sh \ libdbi-asyn.sh libdbi-basic.log: mysqld-start.log libdbi-asyn.log: mysqld-start.log mysqld-stop.log: libdbi-basic.log \ libdbi-asyn.log if HAVE_VALGRIND TESTS += \ libdbi-basic-vg.sh libdbi-basic-vg.log: mysqld-start.log mysqld-stop.log: libdbi-basic-vg.log endif endif TESTS += mysqld-stop.sh endif # MYSQL_TESTS if ENABLE_FMHTTP TESTS += \ rscript_http_request.sh if HAVE_VALGRIND TESTS += \ rscript_http_request-vg.sh endif # HAVE_VALGRIND endif # ENABLE_FMHTTP if ENABLE_ROOT_TESTS TESTS += \ sndrcv_udp.sh \ imuxsock_logger_root.sh \ imuxsock_traillf_root.sh \ imuxsock_ccmiddle_root.sh \ imklog_permitnonkernelfacility_root.sh if ENABLE_IP TESTS += tcp_forwarding_ns_tpl.sh endif if HAVE_VALGRIND TESTS += \ mmexternal-SegFault-empty-jroot-vg.sh endif endif if ENABLE_JOURNAL_TESTS if ENABLE_IMJOURNAL TESTS += \ imjournal-basic.sh \ imjournal-statefile.sh if HAVE_VALGRIND TESTS += \ imjournal-basic-vg.sh \ imjournal-statefile-vg.sh endif endif if ENABLE_OMJOURNAL TESTS += \ omjournal-abort-template.sh \ omjournal-abort-no-template.sh \ omjournal-basic-template.sh \ omjournal-basic-no-template.sh endif endif #if ENABLE_JOURNAL_TESTS if ENABLE_IMPROG TESTS += \ improg_errmsg_no_params.sh \ improg_prog_simple.sh \ improg_prog_confirm.sh \ improg_prog_confirm_killonclose.sh \ improg_prog_killonclose.sh \ improg_simple_multi.sh if HAVE_VALGRIND TESTS += \ improg_errmsg_no_params-vg.sh \ improg_prog_simple-vg.sh endif # ENABLE_IMPROG endif if ENABLE_MMDARWIN TESTS += \ mmdarwin_errmsg_no_params.sh \ mmdarwin_errmsg_no_sock.sh if HAVE_VALGRIND TESTS += \ mmdarwin_errmsg_no_sock-vg.sh endif # HAVE_VALGRIND endif # ENABLE_IMPROG if ENABLE_OMPROG TESTS += \ 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-single-instance.sh \ omprog-single-instance-outfile.sh \ omprog-transactions.sh \ omprog-if-error.sh \ omprog-transactions-failed-messages.sh \ omprog-transactions-failed-commits.sh if HAVE_VALGRIND TESTS += \ 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 endif endif if ENABLE_OMHTTP TESTS += \ omhttp-auth.sh \ omhttp-basic.sh \ omhttp-basic-ignorecodes.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-retry-metadata.sh \ omhttp-batch-lokirest-retry.sh \ omhttp-batch-lokirest.sh \ omhttp-batch-newline.sh \ omhttp-retry.sh \ omhttp-retry-timeout.sh \ omhttp-httpheaderkey.sh \ omhttp-multiplehttpheaders.sh \ omhttp-dynrestpath.sh \ omhttp-batch-dynrestpath.sh if HAVE_VALGRIND TESTS += \ 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-retry-metadata-vg.sh \ omhttp-batch-lokirest-retry-vg.sh \ omhttp-retry-vg.sh \ omhttp-retry-timeout-vg.sh \ omhttp-batch-lokirest-vg.sh endif endif if ENABLE_OMKAFKA if ENABLE_IMKAFKA if ENABLE_KAFKA_TESTS TESTS += \ kafka-selftest.sh \ omkafka.sh \ omkafkadynakey.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 \ sndrcv_kafka.sh \ sndrcv_kafka_multi_topics.sh # Tests below need to be stable first! # sndrcv_kafka_fail.sh \ # sndrcv_kafka_failresume.sh \ # needs properly to much mempory on arm devices! # sndrcv_kafka_multi.sh omkafka.log: kafka-selftest.log 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 sndrcv_kafka_multi_topics.log: imkafka_multi_group.log omkafkadynakey.log: sndrcv_kafka_multi_topics.log if HAVE_VALGRIND TESTS += \ omkafka-vg.sh \ imkafka-vg.sh omkafka-vg.log: sndrcv_kafka_multi_topics.log imkafka-vg.log: omkafka-vg.log endif endif endif endif if ENABLE_OMAZUREEVENTHUBS if ENABLE_OMAZUREEVENTHUBS_TESTS TESTS += \ omazureeventhubs-basic.sh \ omazureeventhubs-basic-url.sh \ omazureeventhubs-list.sh \ omazureeventhubs-stress.sh \ omazureeventhubs-interrupt.sh if HAVE_VALGRIND TESTS += \ omazureeventhubs-basic-vg.sh \ omazureeventhubs-interrupt-vg.sh endif endif endif if ENABLE_IMDOCKER if ENABLE_IMDOCKER_TESTS TESTS += \ imdocker-basic.sh \ imdocker-long-logline.sh \ imdocker-new-logs-from-start.sh \ imdocker-multi-line.sh if HAVE_VALGRIND TESTS += \ imdocker-basic-vg.sh \ imdocker-long-logline-vg.sh \ imdocker-new-logs-from-start-vg.sh \ imdocker-multi-line-vg.sh endif # HAVE_VALGRIND endif # ENABLE_IMDOCKER_TESTS endif # ENABLE_IMDOCKER if ENABLE_IMHTTP TESTS += \ imhttp-post-payload.sh \ imhttp-post-payload-basic-auth.sh \ imhttp-post-payload-query-params.sh \ imhttp-post-payload-large.sh \ imhttp-post-payload-multi.sh \ imhttp-post-payload-multi-lf.sh \ imhttp-post-payload-compress.sh \ imhttp-getrequest-file.sh if HAVE_VALGRIND TESTS += \ 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 endif # HAVE_VALGRIND endif # ENABLE_IMHTTP 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 += \ 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 if HAVE_VALGRIND TESTS += \ omrabbitmq_data_1server-vg.sh endif # HAVE_VALGRIND endif # ENABLE_OMRABBITMQ if ENABLE_REDIS_TESTS if ENABLE_IMHIREDIS TESTS += \ 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 if HAVE_VALGRIND TESTS += \ 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 endif # HAVE_VALGRIND endif # ENABLE_IMHIREDIS if ENABLE_OMHIREDIS TESTS += \ mmdb-reload.sh \ 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 if HAVE_VALGRIND TESTS += \ mmdb-reload-vg.sh \ 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 endif # HAVE_VALGRIND endif # ENABLE_OMHIREDIS endif # ENABLE_REDIS_TESTS if ENABLE_IMPSTATS TESTS += \ impstats-hup.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 \ dynstats-json.sh \ stats-cee.sh \ stats-json-es.sh \ dynstats_reset_without_pstats_reset.sh \ dynstats_prevent_premature_eviction.sh \ omfwd-lb-2target-impstats.sh \ omfwd_fast_imuxsock.sh \ omfwd_impstats-udp.sh \ omfwd_impstats-tcp.sh if HAVE_VALGRIND TESTS += \ 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 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 += \ manyptcp.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_addtlframedelim.sh \ imptcp_conndrop.sh \ imptcp_no_octet_counted.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 \ rscript_random.sh \ rscript_hash32.sh \ rscript_hash64.sh \ rscript_replace.sh \ omfile-sizelimitcmd-many.sh \ omfile-outchannel-many.sh if HAVE_VALGRIND TESTS += \ imptcp-octet-framing-too-long-vg.sh \ imptcp_conndrop-vg.sh if ENABLE_FMHASH TESTS += \ rscript_hash32-vg.sh \ rscript_hash64-vg.sh endif # ENABLE_FMHASH endif # HAVE_VALGRIND if ENABLE_FMUNFLATTEN TESTS += \ 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 if HAVE_VALGRIND TESTS += \ 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 endif # HAVE_VALGRIND endif # ENABLE_FMUNFLATTEN if ENABLE_FFAUP TESTS += \ 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 if HAVE_VALGRIND TESTS += \ 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 endif # HAVE_VALGRIND endif # ENABLE_FFAUP endif if ENABLE_MMPSTRUCDATA TESTS += \ mmpstrucdata.sh \ mmpstrucdata-escaping.sh \ mmpstrucdata-case.sh if HAVE_VALGRIND TESTS += \ mmpstrucdata-vg.sh \ mmpstrucdata-invalid-vg.sh endif endif if ENABLE_MMRM1STSPACE TESTS += \ mmrm1stspace-basic.sh endif if ENABLE_PMNULL TESTS += \ pmnull-basic.sh \ pmnull-withparams.sh endif if ENABLE_OMSTDOUT TESTS += \ omstdout-basic.sh endif if ENABLE_PMNORMALIZE TESTS += \ 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 if HAVE_VALGRIND TESTS += \ 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 endif endif if ENABLE_MMNORMALIZE TESTS += msgvar-concurrency-array.sh \ msgvar-concurrency-array-event.tags.sh \ mmnormalize_rule_from_string.sh \ mmnormalize_rule_from_array.sh \ mmnormalize_parsesuccess.sh if HAVE_VALGRIND TESTS += \ mmnormalize_parsesuccess-vg.sh endif if ENABLE_IMPTCP TESTS += \ mmnormalize_regex_defaulted.sh \ mmnormalize_regex_disabled.sh \ mmnormalize_variable.sh \ mmnormalize_tokenized.sh endif if LOGNORM_REGEX_SUPPORTED TESTS += \ mmnormalize_regex.sh endif endif # ENABLE_MMNORMALIZE if ENABLE_MMJSONPARSE TESTS += \ mmjsonparse-w-o-cookie.sh \ mmjsonparse-w-o-cookie-multi-spaces.sh if ENABLE_IMPSTATS TESTS += \ mmjsonparse-invalid-containerName.sh \ wtpShutdownAll-assertionFailure.sh endif if ENABLE_IMPTCP TESTS += \ mmjsonparse_simple.sh \ imptcp-oversize-message-display.sh \ imptcp-msg-truncation-on-number.sh \ imptcp-msg-truncation-on-number2.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 endif if HAVE_VALGRIND TESTS += \ mmjsonparse_extra_data-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 endif TESTS += \ stop_when_array_has_element.sh \ json_null_array.sh \ json_null.sh \ json_var_cmpr.sh \ json_var_case.sh endif if ENABLE_MMDBLOOKUP TESTS += \ mmdb.sh \ mmdb-space.sh \ mmdb-container.sh \ mmdb-container-empty.sh if HAVE_VALGRIND TESTS += \ mmdb-vg.sh \ mmdb-multilevel-vg.sh endif endif if ENABLE_GNUTLS_TESTS TESTS += \ imtcp-tls-basic.sh \ imtcp-tls-input-basic.sh \ imtcp-tls-input-2certs.sh \ imtcp-tls-basic-verifydepth.sh \ imtcp_conndrop_tls.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 \ 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.sh \ imtcp-tls-gtls-x509name-legacy.sh \ imtcp-drvr-in-input-basic.sh \ imtcp-multi-drvr-basic.sh \ imtcp-multi-drvr-basic-parallel.sh if HAVE_VALGRIND TESTS += \ imtcp-tls-basic-vg.sh \ imtcp_conndrop_tls-vg.sh \ manytcp-too-few-tls-vg.sh endif if ENABLE_OPENSSL TESTS += \ imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh endif endif if ENABLE_OPENSSL TESTS += \ imtcp-tls-ossl-basic.sh \ imtcp-tls-ossl-input-basic.sh \ imtcp-tls-ossl-input-2certs.sh \ imtcp-tls-ossl-basic-tlscommands.sh \ imtcp-tls-ossl-basic-verifydepth.sh \ imtcp-tls-ossl-invalid-verifydepth.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.sh \ sndrcv_tls_ossl_certvalid_action_level.sh \ sndrcv_tls_ossl_certvalid_expired.sh \ sndrcv_tls_ossl_certvalid_tlscommand.sh \ sndrcv_tls_ossl_certvalid_ciphers.sh \ sndrcv_tls_ossl_certvalid_revoked.sh \ imtcp-tls-ossl-x509valid.sh \ imtcp-tls-ossl-x509name.sh \ imtcp-tls-ossl-x509fingerprint.sh \ imtcp-tls-ossl-error-ca.sh \ imtcp-tls-ossl-error-cert.sh \ imtcp-tls-ossl-error-key.sh \ imtcp-tls-ossl-error-key2.sh # imtcp-tls-ossl-basic-stress.sh if HAVE_VALGRIND TESTS += \ imtcp-tls-ossl-basic-vg.sh \ imtcp-tls-ossl-basic-brokenhandshake-vg.sh endif endif if ENABLE_GNUTLS_TESTS if ENABLE_OPENSSL TESTS += \ 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 endif endif if ENABLE_OMUXSOCK TESTS += uxsock_simple.sh endif if ENABLE_RELP TESTS += sndrcv_relp.sh \ sndrcv_relp_rebind.sh \ omrelp_errmsg_no_connect.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 \ omrelp-invld-tlslib.sh \ sndrcv_relp_dflt_pt.sh \ glbl-oversizeMsg-log.sh \ glbl-oversizeMsg-truncate.sh \ glbl-oversizeMsg-split.sh if ENABLE_GNUTLS TESTS += \ 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-chainedcert.sh \ imrelp-tls-mixed-chainedcert.sh \ imrelp-tls-mixed-chainedcert2.sh if USE_RELPENGINESETTLSCFGCMD TESTS += \ imrelp-tls-cfgcmd.sh \ sndrcv_relp_tls-cfgcmd.sh endif # USE_RELPENGINESETTLSCFGCMD endif # ENABLE_GNUTLS if HAVE_VALGRIND TESTS += \ imrelp-basic-vg.sh \ imrelp-sessionbreak-vg.sh \ imrelp-manyconn-vg.sh \ sndrcv_relp-vg-rcvr.sh \ sndrcv_relp-vg-sender.sh endif # HAVE_VALGRIND endif if ENABLE_IMDTLS TESTS += \ imdtls-basic.sh \ imdtls-basic-tlscommands.sh \ imdtls-basic-timeout.sh \ imdtls-error-cert.sh \ imdtls-sessionbreak.sh if HAVE_VALGRIND TESTS += \ imdtls-basic-vg.sh \ imdtls-sessionbreak-vg.sh endif # HAVE_VALGRIND if ENABLE_OMDTLS TESTS += \ 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 if HAVE_VALGRIND TESTS += \ sndrcv_dtls_certvalid-vg.sh endif # HAVE_VALGRIND endif # ENABLE_OMDTLS endif # ENABLE_IMDTLS if ENABLE_OMUDPSPOOF TESTS += \ omudpspoof_errmsg_no_params.sh \ sndrcv_omudpspoof.sh \ sndrcv_omudpspoof-bigmsg.sh \ sndrcv_omudpspoof_nonstdpt.sh 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 += \ 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 endif if ENABLE_OMRULESET TESTS += \ omruleset.sh \ omruleset-queue.sh endif if ENABLE_PMDB2DIAG TESTS += \ pmdb2diag_parse.sh endif if ENABLE_PMSNARE TESTS += \ 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-modoverride.sh \ pmsnare-modoverride-udp.sh endif if ENABLE_PMLASTMSG TESTS += \ pmlastmsg.sh \ pmlastmsg-udp.sh 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 += \ imfile-basic-2GB-file.sh \ imfile-truncate-2GB-file.sh endif # ENABLE_IMFILE_TESTS endif if ENABLE_IMFILE_TESTS TESTS += \ imfile-basic.sh \ imfile-basic-legacy.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-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-old-state-file.sh \ imfile-rename-while-stopped.sh \ imfile-rename.sh \ imfile-symlink.sh \ imfile-symlink-multi.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-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 if ENABLE_MMNORMALIZE TESTS += \ imfile-endmsg.regex-with-example.sh endif if HAVE_VALGRIND TESTS += \ imfile-basic-vg.sh \ imfile-endregex-vg.sh \ imfile-endmsg.regex-vg.sh \ imfile-readmode0-vg.sh \ imfile-readmode2-vg.sh if ENABLE_HELGRIND TESTS += \ imfile-basic-vgthread.sh endif # ENABLE_HELGRIND if ENABLE_MMNORMALIZE TESTS += \ imfile-endmsg.regex-with-example-vg.sh endif # ENABLE_MMNORMALIZE endif # HAVE_VALGRIND endif # ENABLE_IMFILE_TESTS if ENABLE_IMBATCHREPORT TESTS += \ 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 if HAVE_VALGRIND TESTS += \ imbatchreport_errmsg_no_params-vg.sh endif # ENABLE_IMBATCHREPORT endif if ENABLE_OMTCL TESTS += \ omtcl.sh endif if ENABLE_MMTAGHOSTNAME TESTS += \ mmtaghostname_tag.sh \ mmtaghostname_server.sh endif if ENABLE_MMKUBERNETES if ENABLE_MMJSONPARSE if ENABLE_IMFILE if ENABLE_IMPSTATS TESTS += \ mmkubernetes-basic.sh \ mmkubernetes-cache-expire.sh if HAVE_VALGRIND TESTS += \ mmkubernetes-basic-vg.sh \ mmkubernetes-cache-expire-vg.sh endif endif endif endif endif if ENABLE_IMTUXEDOULOG TESTS += \ imtuxedoulog_errmsg_no_params.sh \ imtuxedoulog_data.sh if HAVE_VALGRIND TESTS += \ imtuxedoulog_errmsg_no_params-vg.sh endif # ENABLE_IMTUXEDOULOG endif if ENABLE_OMAMQP1 TESTS += \ omamqp1-basic.sh if HAVE_VALGRIND TESTS += \ omamqp1-basic-vg.sh endif endif # ENABLE_OMAMQP1 endif # if ENABLE_TESTBENCH TESTS_ENVIRONMENT = RSYSLOG_MODDIR='$(abs_top_builddir)'/runtime/.libs/ TESTS_ENVIRONMENT+= TOP_BUILDDIR='$(top_builddir)' TESTS_ENVIRONMENT+= TESTTOOL_DIR='$(abs_top_builddir)/tests' test_files = testbench.h runtime-dummy.c DISTCLEANFILES=rsyslog.pid distclean-local: rm -rf .dep_cache .dep_wrk EXTRA_DIST= \ set-envvars.in \ urlencode.py \ dnscache-TTL-0.sh \ dnscache-TTL-0-vg.sh \ loadbalance.sh \ smtradfile.sh \ smtradfile-vg.sh \ immark.sh \ immark-inputname.sh \ immark-ruleset.sh \ immark-ruleset-custom-msg.sh \ operatingstate-basic.sh \ operatingstate-empty.sh \ operatingstate-unclean.sh \ internal-errmsg-memleak-vg.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-oversizeMsg-log-vg.sh \ config_enabled-on.sh \ config_enabled-off.sh \ empty-app-name.sh \ empty-hostname.sh \ func-substring-invld-startpos.sh \ func-substring-invld-startpos-vg.sh \ func-substring-large-endpos.sh \ func-substring-large-neg-endpos.sh \ func-substring-relative-endpos.sh \ hostname-with-slash-pmrfc5424.sh \ hostname-with-slash-pmrfc3164.sh \ pmrfc3164-msgFirstSpace.sh \ pmrfc3164-AtSignsInHostname.sh \ pmrfc3164-AtSignsInHostname_off.sh \ pmrfc3164-tagEndingByColon.sh \ pmrfc3164-defaultTag.sh \ pmrfc3164-json.sh \ hostname-with-slash-dflt-invld.sh \ hostname-with-slash-dflt-slash-valid.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 \ imtuxedoulog_errmsg_no_params.sh \ imtuxedoulog_data.sh \ imtuxedoulog_errmsg_no_params-vg.sh \ pmdb2diag_parse.sh \ mmtaghostname_tag.sh \ mmtaghostname_server.sh \ 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 \ imbatchreport_errmsg_no_params-vg.sh \ mmexternal-SegFault.sh \ mmexternal-SegFault-empty-jroot-vg.sh \ testsuites/mmexternal-SegFault-mm-python.py \ mmexternal-InvldProg-vg.sh \ nested-call-shutdown.sh \ 1.rstest 2.rstest 3.rstest err1.rstest \ config_multiple_include.sh \ testsuites/include-std1-omfile-action.conf \ testsuites/include-std2-omfile-action.conf \ invalid_nested_include.sh \ validation-run.sh \ 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/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 \ cfg.sh \ cfg1.cfgtest \ cfg1.testin \ cfg2.cfgtest \ cfg2.testin \ cfg3.cfgtest \ cfg3.testin \ cfg4.cfgtest \ cfg4.testin \ DevNull.cfgtest \ err1.rstest \ NoExistFile.cfgtest \ tcp_forwarding_tpl.sh \ tcp_forwarding_ns_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 \ killrsyslog.sh \ parsertest-parse1.sh \ parsertest-parse1-udp.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 \ fieldtest.sh \ fieldtest-udp.sh \ proprepltest-nolimittag-udp.sh \ proprepltest-nolimittag.sh \ proprepltest-rfctag-udp.sh \ proprepltest-rfctag.sh \ timestamp-3164.sh \ timestamp-3339.sh \ timestamp-isoweek.sh \ timestamp-mysql.sh \ timestamp-pgsql.sh \ timestamp-subseconds.sh \ rsf_getenv.sh \ diskq-rfc5424.sh \ rfc5424parser-sp_at_msg_start.sh \ diskqueue-full.sh \ diskqueue-fail.sh \ diskqueue.sh \ diskqueue-non-unique-prefix.sh \ arrayqueue.sh \ include-obj-text-from-file.sh \ include-obj-text-from-file-noexist.sh \ include-obj-outside-control-flow-vg.sh \ include-obj-in-if-vg.sh \ include-obj-text-vg.sh \ config_output-o-option.sh \ rscript-config_enable-off-vg.sh \ rscript-config_enable-on.sh \ rscript_http_request.sh \ rscript_http_request-vg.sh \ rscript_bare_var_root.sh \ rscript_bare_var_root-empty.sh \ rscript_contains.sh \ rscript_ipv42num.sh \ rscript_field.sh \ rscript_field-vg.sh \ rscript_stop.sh \ rscript_stop2.sh \ stop.sh \ rscript_le.sh \ rscript_le_var.sh \ rscript_ge.sh \ rscript_ge_var.sh \ rscript_lt.sh \ rscript_lt_var.sh \ rscript_gt.sh \ rscript_gt_var.sh \ rscript_ne.sh \ rscript_ne_var.sh \ rscript_number_comparison_LE.sh \ rscript_number_comparison_LE-vg.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_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 \ rscript_compare-common.sh \ rscript_num2ipv4.sh \ rscript_int2Hex.sh \ rscript_trim.sh \ rscript_substring.sh \ rscript_format_time.sh \ rscript_parse_time.sh \ rscript_parse_time_get-ts.py \ rscript_is_time.sh \ rscript_script_error.sh \ rscript_parse_json.sh \ rscript_parse_json-vg.sh \ rscript_backticks-vg.sh \ rscript_backticks_empty_envvar-vg.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_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_exclamation.sh \ rscript_unflatten_object.sh \ 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_exclamation-vg.sh \ rscript_unflatten_object-vg.sh \ rscript_get_property.sh \ rscript_get_property-vg.sh \ rs-cnum.sh \ rs-int2hex.sh \ rs-substring.sh \ omsnmp_errmsg_no_params.sh \ sndrcv_omsnmpv1_udp.sh \ sndrcv_omsnmpv1_udp_dynsource.sh \ sndrcv_omsnmpv1_udp_invalidoid.sh \ snmptrapreceiver.py \ ommail_errmsg_no_params.sh \ mmdarwin_errmsg_no_params.sh \ mmdarwin_errmsg_no_sock.sh \ mmdarwin_errmsg_no_sock-vg.sh \ mmutf8fix_no_error.sh \ tcpflood_wrong_option_output.sh \ msleep_usage_output.sh \ mangle_qi_usage_output.sh \ minitcpsrv_usage_output.sh \ test_id_usage_output.sh \ 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 \ rscript_eq.sh \ rscript_eq_var.sh \ rscript_set_memleak-vg.sh \ rscript_set_unset_invalid_var.sh \ rscript_set_modify.sh \ stop-localvar.sh \ stop-msgvar.sh \ omfwd-lb-1target-retry-full_buf.sh \ omfwd-lb-1target-retry-1_byte_buf.sh \ omfwd-lb-1target-retry-test_skeleton.sh \ omfwd-lb-1target-retry-1_byte_buf-TargetFail.sh \ omfwd-lb-1target-retry-test_skeleton-TargetFail.sh \ omfwd-lb-susp.sh \ omfwd-lb-2target-basic.sh \ omfwd-lb-2target-impstats.sh \ omfwd-lb-2target-retry.sh \ omfwd-lb-2target-one_fail.sh \ omfwd-tls-invalid-permitExpiredCerts.sh \ omfwd-keepalive.sh \ omfwd_fast_imuxsock.sh \ omfile_hup-vg.sh \ zstd.sh \ zstd-vg.sh \ gzipwr_hup-vg.sh \ omusrmsg-errmsg-no-params.sh \ omusrmsg-noabort.sh \ omusrmsg-noabort-vg.sh \ omfile-module-params.sh \ omfile-read-only-errmsg.sh \ omfile-null-filename.sh \ omfile-whitespace-filename.sh \ omfile-read-only.sh \ omfile-outchannel.sh \ omfile-outchannel-many.sh \ omfile-sizelimitcmd-many.sh \ omfile_both_files_set.sh \ omfile_hup.sh \ 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_1server-vg.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 \ imhiredis-queue.sh \ imhiredis-queue-vg.sh \ imhiredis-queue-lpop.sh \ imhiredis-queue-lpop-vg.sh \ imhiredis-redis-restart.sh \ imhiredis-redis-restart-vg.sh \ imhiredis-redis-start-after.sh \ imhiredis-redis-start-after-vg.sh \ imhiredis-subscribe.sh \ imhiredis-subscribe-vg.sh \ imhiredis-stream.sh \ imhiredis-stream-vg.sh \ imhiredis-stream-from-beginning.sh \ imhiredis-stream-from-beginning-vg.sh \ imhiredis-stream-consumerGroup-ack.sh \ imhiredis-stream-consumerGroup-ack-vg.sh \ imhiredis-stream-consumerGroup-noack.sh \ imhiredis-stream-consumerGroup-noack-vg.sh \ imhiredis-stream-consumerGroup-reclaim.sh \ imhiredis-stream-consumerGroup-reclaim-vg.sh \ msgvar-concurrency.sh \ msgvar-concurrency-array.sh \ testsuites/msgvar-concurrency-array.rulebase \ msgvar-concurrency-array-event.tags.sh \ testsuites/msgvar-concurrency-array-event.tags.rulebase \ localvar-concurrency.sh \ exec_tpl-concurrency.sh \ prop-jsonmesg-vg.sh \ prop-all-json-concurrency.sh \ no-parser-errmsg.sh \ global_vars.sh \ no-parser-errmsg.sh \ no-parser-vg.sh \ prop-programname.sh \ prop-programname-with-slashes.sh \ rfc5424parser.sh \ rscript_privdropuser.sh \ rscript_privdropuserid.sh \ rscript_privdropgroup.sh \ rscript_privdropgroupid.sh \ privdrop_common.sh \ privdropuser.sh \ privdropuserid.sh \ privdropgroup.sh \ privdropgroupid.sh \ privdropabortonidfail.sh \ privdropabortonidfaillegacy.sh \ json-nonstring.sh \ json-onempty-at-end.sh \ template-json.sh \ template-pure-json.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 \ template-topos-neg.sh \ fac_authpriv.sh \ fac_local0.sh \ fac_local0-vg.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 \ compresssp.sh \ compresssp-stringtpl.sh \ now_family_utc.sh \ now-utc-ymd.sh \ now-utc-casecmp.sh \ now-utc.sh \ now-unixtimestamp.sh \ faketime_common.sh \ imjournal-basic.sh \ imjournal-statefile.sh \ imjournal-statefile-vg.sh \ imjournal-basic-vg.sh \ omjournal-abort-template.sh \ omjournal-abort-no-template.sh \ omjournal-basic-template.sh \ omjournal-basic-no-template.sh \ timegenerated-ymd.sh \ timegenerated-uxtimestamp.sh \ timegenerated-uxtimestamp-invld.sh \ timegenerated-dateordinal.sh \ timegenerated-dateordinal-invld.sh \ timegenerated-utc.sh \ timegenerated-utc-legacy.sh \ timereported-utc.sh \ timereported-utc-legacy.sh \ timereported-utc-vg.sh \ mmrm1stspace-basic.sh \ mmnormalize_parsesuccess.sh \ mmnormalize_parsesuccess-vg.sh \ mmnormalize_rule_from_string.sh \ mmnormalize_rule_from_array.sh \ pmnull-basic.sh \ pmnull-withparams.sh \ omstdout-basic.sh \ testsuites/mmnormalize_processing_tests.rulebase \ mmnormalize_processing_test1.sh \ mmnormalize_processing_test2.sh \ mmnormalize_processing_test3.sh \ mmnormalize_processing_test4.sh \ pmnormalize-basic.sh \ pmnormalize-rule.sh \ pmnormalize-rule_and_rulebase.sh \ pmnormalize-neither_rule_rulebase.sh \ pmnormalize-invld-rulebase.sh \ pmnormalize-rule_invld-data.sh \ testsuites/pmnormalize_basic.rulebase \ pmnormalize-basic-vg.sh \ pmnormalize-rule-vg.sh\ pmnormalize-rule_and_rulebase-vg.sh \ pmnormalize-neither_rule_rulebase-vg.sh \ pmnormalize-invld-rulebase-vg.sh \ pmnormalize-rule_invld-data-vg.sh \ rawmsg-after-pri.sh \ rs_optimizer_pri.sh \ rscript_prifilt.sh \ rscript_optimizer1.sh \ rscript_ruleset_call.sh \ rscript_ruleset_call_indirect-basic.sh \ rscript_ruleset_call_indirect-var.sh \ rscript_ruleset_call_indirect-invld.sh \ cee_simple.sh \ cee_diskqueue.sh \ mmjsonparse-w-o-cookie.sh \ mmjsonparse-w-o-cookie-multi-spaces.sh \ mmjsonparse_simple.sh \ mmjsonparse-invalid-containerName.sh \ wtpShutdownAll-assertionFailure.sh \ imptcp-octet-framing-too-long-vg.sh \ imptcp-oversize-message-display.sh \ imptcp-msg-truncation-on-number.sh \ imptcp-msg-truncation-on-number2.sh \ imptcp-maxFrameSize-parameter.sh \ mmjsonparse_cim.sh \ mmjsonparse_cim2.sh \ mmjsonparse_localvar.sh \ mmdb.sh \ mmdb-space.sh \ mmdb.rb \ test.mmdb \ with_space.mmdb \ mmdb-vg.sh \ mmdb-container.sh \ mmdb-container-empty.sh \ mmdb-multilevel-vg.sh \ incltest.sh \ incltest_dir.sh \ incltest_dir_empty_wildcard.sh \ incltest_dir_wildcard.sh \ testsuites/es.yml \ clickhouse-dflt-tpl.sh \ clickhouse-retry-error.sh \ clickhouse-start.sh \ clickhouse-stop.sh \ clickhouse-basic.sh \ clickhouse-load.sh \ clickhouse-bulk.sh \ clickhouse-bulk-load.sh \ clickhouse-limited-batch.sh \ clickhouse-select.sh \ clickhouse-wrong-quotation-marks.sh \ clickhouse-wrong-template-option.sh \ clickhouse-errorfile.sh \ clickhouse-wrong-insert-syntax.sh \ clickhouse-basic-vg.sh \ clickhouse-load-vg.sh \ clickhouse-bulk-vg.sh \ clickhouse-bulk-load-vg.sh \ es_response_get_msgnum.py \ elasticsearch-error-format-check.py \ es-duplicated-ruleset.sh \ es-duplicated-ruleset-vg.sh \ es-basic-es6.0.sh \ es-basic-es7.14.sh \ es-basic.sh \ es-basic-vgthread.sh \ es-basic-server.sh \ es-execOnlyWhenPreviousSuspended.sh \ es-basic-ha.sh \ es-basic-bulk.sh \ es-basic-errfile-empty.sh \ es-basic-errfile-popul.sh \ es-bulk-errfile-empty.sh \ es-bulk-errfile-popul.sh \ 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 \ es-searchType-empty.sh \ diskqueue-multithread-es.sh \ es-basic-vg.sh \ es-basic-bulk-vg.sh \ es-basic-ha-vg.sh \ es-maxbytes-bulk.sh \ es-bulk-retry.sh \ elasticsearch-stop.sh \ linkedlistqueue.sh \ da-mainmsg-q.sh \ diskqueue-fsync.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-hostname-ok.sh \ allowed-sender-tcp-hostname-fail.sh \ imtcp-octet-framing-too-long-vg.sh \ imtcp-discard-truncated-msg.sh \ imtcp-basic.sh \ imtcp-basic-hup.sh \ imtcp-maxFrameSize.sh \ imtcp-msg-truncation-on-number.sh \ imtcp-msg-truncation-on-number2.sh \ imtcp-NUL.sh \ imtcp-NUL-rawmsg.sh \ imtcp-tls-gtls-x509fingerprint-invld.sh \ imtcp-tls-gtls-x509fingerprint.sh \ imtcp-tls-gtls-x509name-invld.sh \ imtcp-tls-gtls-x509name.sh \ imtcp-tls-gtls-x509name-legacy.sh \ imtcp-drvr-in-input-basic.sh \ imtcp-multi-drvr-basic.sh \ imtcp-multi-drvr-basic-parallel.sh \ imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh \ imtcp-tls-basic.sh \ imtcp-tls-input-basic.sh \ imtcp-tls-input-2certs.sh \ imtcp-tls-basic-verifydepth.sh \ imtcp-tls-basic-vg.sh \ imtcp-tls-no-lstn-startup.sh \ imtcp_incomplete_frame_at_end.sh \ imtcp-multiport.sh \ imtcp-bigmessage-octetcounting.sh \ imtcp-bigmessage-octetstuffing.sh \ udp-msgreduc-orgmsg-vg.sh \ udp-msgreduc-vg.sh \ manytcp-too-few-tls-vg.sh \ imtcp-tls-ossl-basic.sh \ imtcp-tls-ossl-input-basic.sh \ imtcp-tls-ossl-input-2certs.sh \ imtcp-tls-ossl-basic-tlscommands.sh \ imtcp-tls-ossl-basic-verifydepth.sh \ imtcp-tls-ossl-invalid-verifydepth.sh \ imtcp-tls-ossl-basic-stress.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_certvalid.sh \ sndrcv_tls_ossl_certvalid_action_level.sh \ sndrcv_tls_ossl_certvalid_expired.sh \ sndrcv_tls_ossl_certvalid_tlscommand.sh \ sndrcv_tls_ossl_certvalid_ciphers.sh \ sndrcv_tls_ossl_certvalid_revoked.sh \ imtcp-tls-ossl-x509valid.sh \ imtcp-tls-ossl-x509name.sh \ imtcp-tls-ossl-x509fingerprint.sh \ imtcp-tls-ossl-basic-vg.sh \ imtcp-tls-ossl-basic-brokenhandshake-vg.sh \ imtcp-tls-ossl-error-ca.sh \ imtcp-tls-ossl-error-cert.sh \ imtcp-tls-ossl-error-key.sh \ imtcp-tls-ossl-error-key2.sh \ manytcp.sh \ manyptcp.sh \ imptcp-basic-hup.sh \ imptcp-NUL.sh \ imptcp-NUL-rawmsg.sh \ imptcp_framing_regex.sh \ testsuites/imptcp_framing_regex.testdata \ imptcp_framing_regex-oversize.sh \ testsuites/imptcp_framing_regex-oversize.testdata \ imptcp_large.sh \ imptcp-connection-msg-disabled.sh \ imptcp-connection-msg-received.sh \ imptcp-discard-truncated-msg.sh \ imptcp_addtlframedelim.sh \ imptcp_conndrop-vg.sh \ imptcp_conndrop.sh \ imptcp_multi_line.sh \ testsuites/imptcp_multi_line.testdata \ imptcp_no_octet_counted.sh \ imtcp_addtlframedelim_on_input.sh \ testsuites/no_octet_counted.testdata \ imtcp_no_octet_counted.sh \ testsuites/spframingfix.testdata \ imtcp_spframingfix.sh \ imtcp-connection-msg-recieved.sh \ imptcp_spframingfix.sh \ msg-deadlock-headerless-noappname.sh \ imtcp_conndrop.sh \ imtcp_conndrop_tls.sh \ imtcp_conndrop_tls-vg.sh \ imtcp_addtlframedelim.sh \ tcp-msgreduc-vg.sh \ inputname-imtcp.sh \ omod-if-array.sh \ omod-if-array-udp.sh \ discard.sh \ failover-no-rptd.sh \ failover-no-rptd-vg.sh \ failover-no-basic.sh \ failover-no-basic-vg.sh \ failover-rptd.sh \ failover-rptd-vg.sh \ failover-basic.sh \ failover-basic-vg.sh \ failover-async.sh \ failover-double.sh \ suspend-via-file.sh \ suspend-omfwd-via-file.sh \ externalstate-failed-rcvr.sh \ discard-rptdmsg.sh \ discard-rptdmsg-vg.sh \ discard-allmark.sh \ discard-allmark-vg.sh \ diag.sh \ rcvr_fail_restore.sh \ queue-encryption-disk.sh \ queue-encryption-disk_keyfile.sh \ queue-encryption-disk_keyfile-vg.sh \ queue-encryption-disk_keyprog.sh \ queue-encryption-da.sh \ da-queue-persist.sh \ daqueue-dirty-shutdown.sh \ daqueue-invld-qi.sh \ daqueue-persist.sh \ daqueue-persist-drvr.sh \ queue-persist.sh \ queue-persist-drvr.sh \ threadingmq.sh \ threadingmqaq.sh \ sndrcv_drvr.sh \ sndrcv_drvr_noexit.sh \ sndrcv_failover.sh \ sndrcv.sh \ omrelp_errmsg_no_connect.sh \ imrelp-basic.sh \ imrelp-basic-hup.sh \ imrelp-basic-vg.sh \ imrelp-basic-oldstyle.sh \ imrelp-manyconn.sh \ imrelp-manyconn-vg.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-sessionbreak-vg.sh \ omrelp-invld-tlslib.sh \ glbl-oversizeMsg-log.sh \ glbl-oversizeMsg-truncate.sh \ glbl-oversizeMsg-split.sh \ sndrcv_relp.sh \ sndrcv_relp_rebind.sh \ sndrcv_relp_tls_prio.sh \ sndrcv_relp_tls_chainedcert.sh \ sndrcv_relp_tls.sh \ sndrcv_relp_tls_certvalid.sh \ sndrcv_relp-vg-rcvr.sh \ sndrcv_relp-vg-sender.sh \ relp_tls_certificate_not_found.sh \ omrelp_wrong_authmode.sh \ imrelp-tls.sh \ imrelp-tls-cfgcmd.sh \ imrelp-tls-chainedcert.sh \ imrelp-tls-mixed-chainedcert.sh \ imrelp-tls-mixed-chainedcert2.sh \ sndrcv_relp_tls-cfgcmd.sh \ sndrcv_relp_dflt_pt.sh \ sndrcv_udp.sh \ imudp_thread_hang.sh \ sndrcv_udp_nonstdpt.sh \ sndrcv_udp_nonstdpt_v6.sh \ omudpspoof_errmsg_no_params.sh \ sndrcv_omudpspoof.sh \ sndrcv_omudpspoof-bigmsg.sh \ sndrcv_omudpspoof_nonstdpt.sh \ sndrcv_gzip.sh \ imdtls-basic.sh \ imdtls-basic-tlscommands.sh \ imdtls-basic-timeout.sh \ imdtls-error-cert.sh \ imdtls-sessionbreak.sh \ imdtls-basic-vg.sh \ imdtls-sessionbreak-vg.sh \ 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 \ sndrcv_dtls_certvalid-vg.sh \ action-tx-single-processing.sh \ omfwd-errfile-maxsize.sh \ omfwd-errfile-maxsize-filled.sh \ action-tx-errfile-maxsize.sh \ action-tx-errfile.sh \ testsuites/action-tx-errfile.result \ pipeaction.sh \ improg-simul.sh \ improg-multiline-test.py \ improg_errmsg_no_params.sh \ improg_errmsg_no_params-vg.sh \ improg_prog_simple.sh \ improg_prog_confirm.sh \ improg_prog_confirm_killonclose.sh \ improg_prog_killonclose.sh \ improg_prog_simple-vg.sh \ improg_simple_multi.sh \ imhttp-post-payload.sh \ imhttp-post-payload-vg.sh \ imhttp-post-payload-basic-auth.sh \ imhttp-post-payload-basic-auth-vg.sh \ imhttp-post-payload-query-params.sh \ imhttp-post-payload-query-params-vg.sh \ imhttp-post-payload-large.sh \ imhttp-post-payload-large-vg.sh \ testsuites/imhttp-large-data.txt \ imhttp-post-payload-multi.sh \ imhttp-post-payload-multi-vg.sh \ imhttp-getrequest-file.sh \ imhttp-getrequest-file-vg.sh \ imhttp-post-payload-multi-lf.sh \ imhttp-post-payload-multi-lf-vg.sh \ imhttp-post-payload-compress.sh \ imhttp-post-payload-compress-vg.sh \ testsuites/docroot/file.txt \ testsuites/htpasswd \ omhttp-auth.sh \ omhttp-basic.sh \ omhttp-basic-ignorecodes.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-batch-lokirest-vg.sh \ omhttp-batch-newline.sh \ omhttp-batch-retry-metadata.sh \ omhttp-retry-timeout.sh \ omhttp-basic-ignorecodes-vg.sh \ omhttp-batch-retry-metadata-vg.sh \ omhttp-retry-timeout-vg.sh \ omhttp-retry.sh \ omhttp-httpheaderkey.sh \ omhttp-multiplehttpheaders.sh \ omhttp-dynrestpath.sh \ omhttp-batch-dynrestpath.sh \ omhttp-auth-vg.sh \ omhttp-basic-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_server.py \ omhttp-validate-response.py \ omprog-defaults.sh \ omprog-defaults-vg.sh \ omprog-output-capture.sh \ omprog-output-capture-mt.sh \ omprog-output-capture-vg.sh \ omprog-feedback.sh \ omprog-feedback-mt.sh \ omprog-feedback-vg.sh \ omprog-feedback-timeout.sh \ omprog-close-unresponsive.sh \ omprog-close-unresponsive-vg.sh \ omprog-close-unresponsive-noterm.sh \ omprog-restart-terminated.sh \ omprog-restart-terminated-vg.sh \ omprog-restart-terminated-outfile.sh \ omprog-single-instance.sh \ omprog-single-instance-vg.sh \ omprog-single-instance-outfile.sh \ omprog-if-error.sh \ omprog-transactions.sh \ omprog-transactions-vg.sh \ omprog-transactions-failed-messages.sh \ omprog-transactions-failed-commits.sh \ testsuites/omprog-defaults-bin.sh \ testsuites/omprog-output-capture-bin.sh \ testsuites/omprog-output-capture-mt-bin.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-restart-terminated-bin.sh \ testsuites/omprog-single-instance-bin.sh \ testsuites/omprog-transactions-bin.sh \ pipe_noreader.sh \ uxsock_simple.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 \ abort-uncleancfg-goodcfg.sh \ abort-uncleancfg-goodcfg-check.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 \ complex1.sh \ random.sh \ testsuites/imfile-old-state-file_imfile-state_.-rsyslog.input \ imfile-readmode0-vg.sh \ imfile-readmode2.sh \ imfile-readmode2-polling.sh \ imfile-readmode2-vg.sh \ imfile-readmode2-with-persists-data-during-stop.sh \ imfile-readmode2-with-persists.sh \ imfile-endregex-save-lf.sh \ imfile-endregex-save-lf-persist.sh \ imfile-endregex.sh \ imfile-endregex-vg.sh \ imfile-basic.sh \ imfile-basic-legacy.sh \ imfile-basic-2GB-file.sh \ imfile-truncate-2GB-file.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-basic-vg.sh \ imfile-basic-vgthread.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-escapelf.replacement.sh \ imfile-escapelf.replacement-empty.sh \ imfile-endmsg.regex.sh \ imfile-endmsg.regex-vg.sh \ imfile-endmsg.regex-with-example.sh \ imfile-endmsg.regex-with-example-vg.sh \ imfile-endmsg.regex.crio.rulebase \ imfile-endmsg.regex.json.rulebase \ imfile-statefile-no-file_id.sh \ imfile-statefile-no-file_id-TO-file_id.sh \ imfile-statefile-directory.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-truncate.sh \ imfile-truncate-multiple.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-old-state-file.sh \ imfile-rename-while-stopped.sh \ imfile-rename.sh \ imfile-symlink.sh \ imfile-symlink-multi.sh \ imfile-symlink-ext-tmp-dir-tree.sh \ imfile-logrotate.sh \ imfile-logrotate-async.sh \ imfile-logrotate-copytruncate.sh \ imfile-logrotate-nocopytruncate.sh \ imfile-logrotate-multiple.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 \ dynfile_invld_async.sh \ dynfile_invld_sync.sh \ dynfile_invalid2.sh \ rulesetmultiqueue.sh \ rulesetmultiqueue-v6.sh \ omruleset.sh \ omruleset-queue.sh \ badqi.sh \ bad_qi/dbq.qi \ execonlyonce.sh \ execonlywhenprevsuspended.sh \ execonlywhenprevsuspended2.sh \ execonlywhenprevsuspended3.sh \ execonlywhenprevsuspended4.sh \ execonlywhenprevsuspended_multiwrkr.sh \ execonlywhenprevsuspended-queue.sh \ execonlywhenprevsuspended-nonsusp.sh \ execonlywhenprevsuspended-nonsusp-queue.sh \ tabescape_dflt.sh \ tabescape_dflt-udp.sh \ tabescape_off.sh \ tabescape_off-udp.sh \ tabescape_on.sh \ dircreate_dflt.sh \ dircreate_off.sh \ imuxsock_legacy.sh \ imuxsock_logger_parserchain.sh \ imuxsock_logger.sh \ imuxsock_logger_ratelimit.sh \ imuxsock_logger_ruleset.sh \ imuxsock_logger_ruleset_ratelimit.sh \ imuxsock_logger_err.sh \ imuxsock_logger_root.sh \ imuxsock_logger_syssock.sh \ imuxsock_traillf.sh \ imuxsock_traillf_root.sh \ imuxsock_traillf_syssock.sh \ imuxsock_ccmiddle.sh \ imuxsock_ccmiddle_root.sh \ imklog_permitnonkernelfacility_root.sh \ imuxsock_ccmiddle_syssock.sh \ imuxsock_hostname.sh \ testsuites/mysql-truncate.sql \ testsuites/mysql-select-msg.sql \ libdbi-basic.sh \ libdbi-asyn.sh \ mysqld-start.sh \ mysqld-stop.sh \ mysql-basic.sh \ mysql-basic-cnf6.sh \ mysql-basic-vg.sh \ mysql-asyn.sh \ mysql-asyn-vg.sh \ mysql-actq-mt.sh \ mysql-actq-mt-withpause.sh \ mysql-actq-mt-withpause-vg.sh \ kafka-selftest.sh \ omkafka.sh \ omkafkadynakey.sh \ omkafka-vg.sh \ imkafka-hang-on-no-kafka.sh \ imkafka-hang-other-action-on-no-kafka.sh \ imkafka-backgrounded.sh \ imkafka-config-err-ruleset.sh \ imkafka-config-err-param.sh \ imkafka.sh \ imkafka-vg.sh \ imkafka_multi_single.sh \ imkafka_multi_group.sh \ sndrcv_kafka.sh \ sndrcv_kafka_multi_topics.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 \ omazureeventhubs-basic.sh \ omazureeventhubs-basic-url.sh \ omazureeventhubs-list.sh \ omazureeventhubs-stress.sh \ omazureeventhubs-interrupt.sh \ omazureeventhubs-basic-vg.sh \ omazureeventhubs-interrupt-vg.sh \ mmpstrucdata.sh \ mmpstrucdata-escaping.sh \ mmpstrucdata-case.sh \ mmpstrucdata-vg.sh \ mmpstrucdata-invalid-vg.sh \ libdbi-basic-vg.sh \ dynstats_ctr_reset.sh \ dynstats_reset_without_pstats_reset.sh \ dynstats_nometric.sh \ dynstats_overflow.sh \ dynstats_overflow-vg.sh \ dynstats_reset.sh \ dynstats_reset-vg.sh \ impstats-hup.sh \ dynstats.sh \ dynstats-vg.sh \ dynstats_prevent_premature_eviction.sh \ dynstats_prevent_premature_eviction-vg.sh \ 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 \ no-dynstats-json.sh \ no-dynstats.sh \ omfwd_impstats-udp.sh \ omfwd_impstats-tcp.sh \ perctile-simple.sh \ perctile-simple-vg.sh \ stats-json.sh \ stats-json-vg.sh \ stats-cee.sh \ stats-cee-vg.sh \ stats-json-es.sh \ dynstats-json.sh \ dynstats-json-vg.sh \ mmnormalize_variable.sh \ mmnormalize_tokenized.sh \ testsuites/mmnormalize_variable.rulebase \ testsuites/date_time_msg \ testsuites/mmnormalize_tokenized.rulebase \ testsuites/tokenized_input \ rscript_random.sh \ rscript_hash32.sh \ rscript_hash32-vg.sh \ rscript_hash64.sh \ rscript_hash64-vg.sh \ rscript_replace.sh \ rscript_replace_complex.sh \ testsuites/complex_replace_input \ rscript_unaffected_reset.sh \ rscript_wrap2.sh \ rscript_wrap3.sh \ testsuites/wrap3_input\ json_array_subscripting.sh \ testsuites/json_array_input \ testsuites/json_object_input \ testsuites/json_nonarray_input \ json_array_looping.sh \ json_object_looping.sh \ json_object_looping-vg.sh \ json_array_looping-vg.sh \ json_object_suicide_in_loop-vg.sh \ json_nonarray_looping.sh \ json_null.sh \ json_null-vg.sh \ json_null_array.sh \ json_null_array-vg.sh \ mmjsonparse_extra_data-vg.sh \ mmnormalize_regex.sh \ testsuites/mmnormalize_regex.rulebase \ testsuites/regex_input \ mmnormalize_regex_disabled.sh \ mmnormalize_regex_defaulted.sh \ stop_when_array_has_element.sh \ testsuites/stop_when_array_has_elem_input \ key_dereference_on_uninitialized_variable_space.sh \ rscript_re_extract_i.sh \ rscript_re_extract.sh \ rscript_re_match_i.sh \ rscript_re_match.sh \ rscript_re_match-dbl_quotes.sh \ lookup_table.sh \ lookup_table-hup-backgrounded.sh \ lookup_table_no_hup_reload.sh \ lookup_table_no_hup_reload-vg.sh \ lookup_table_rscript_reload.sh \ lookup_table_rscript_reload_without_stub.sh \ lookup_table_rscript_reload-vg.sh \ lookup_table_rscript_reload_without_stub-vg.sh \ rscript_trim-vg.sh \ testsuites/xlate.lkp_tbl \ testsuites/xlate_more.lkp_tbl \ unused_lookup_table-vg.sh \ lookup_table-vg.sh \ array_lookup_table.sh \ array_lookup_table-vg.sh \ array_lookup_table_misuse-vg.sh \ multiple_lookup_tables.sh \ multiple_lookup_tables-vg.sh \ testsuites/xlate_array.lkp_tbl \ testsuites/xlate_array_more.lkp_tbl \ testsuites/xlate_array_misuse.lkp_tbl \ testsuites/xlate_array_more_misuse.lkp_tbl \ sparse_array_lookup_table.sh \ sparse_array_lookup_table-vg.sh \ testsuites/xlate_sparse_array.lkp_tbl \ testsuites/xlate_sparse_array_more.lkp_tbl \ lookup_table_bad_configs.sh \ lookup_table_bad_configs-vg.sh \ 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 \ json_var_cmpr.sh \ imptcp_maxsessions.sh \ imptcp_nonProcessingPoller.sh \ imptcp_veryLargeOctateCountedMessages.sh \ known_issues.supp \ libmaxmindb.supp \ travis/trusty.supp \ linux_localtime_r.supp \ CI/centos6-9.supp \ CI/centos7.supp \ CI/gcov.supp \ CI/ubuntu20.04.supp \ json_var_case.sh \ cfg.sh \ empty-prop-comparison.sh \ sndrcv_tls_anon_rebind.sh \ sndrcv_tls_anon_hostname.sh \ sndrcv_tls_anon_ipv4.sh \ sndrcv_tls_anon_ipv6.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 \ 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_ossl_serveranon_ossl_clientanon.sh \ sndrcv_tls_ossl_servercert_ossl_clientanon.sh \ 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 \ sndrcv_tls_client_missing_cert.sh \ sndrcv_ossl_cert_chain.sh \ omtcl.sh \ omtcl.tcl \ 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-modoverride.sh \ pmsnare-modoverride-udp.sh \ pmlastmsg.sh \ pmlastmsg-udp.sh \ pgsql-basic.sh \ testsuites/pgsql-basic.sql \ testsuites/pgsql-select-msg.sql \ testsuites/pgsql-select-syslogtag.sql \ 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 \ pgsql-basic-vg.sh \ pgsql-template-vg.sh \ pgsql-basic-cnf6-vg.sh \ pgsql-template-cnf6-vg.sh \ pgsql-actq-mt-withpause-vg.sh \ ../devtools/prep-mysql-db.sh \ ../devtools/prepare_clickhouse.sh \ mmkubernetes-basic.sh \ mmkubernetes-basic-vg.sh \ mmkubernetes_test_server.py \ mmkubernetes-basic.out.json \ mmkubernetes-cache-expire.sh \ mmkubernetes-cache-expire-vg.sh \ mmkubernetes-cache-expire.out.expected \ mmkubernetes.supp \ es-writeoperation.sh \ imdocker-basic.sh \ imdocker-basic-vg.sh \ imdocker-long-logline.sh \ imdocker-long-logline-vg.sh \ imdocker-new-logs-from-start.sh \ imdocker-new-logs-from-start-vg.sh \ imdocker-multi-line.sh \ imdocker-multi-line-vg.sh \ 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 \ omamqp1-common.sh \ omamqp1-basic.sh \ omamqp1-basic-vg.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_OPENSSL tcpflood_CFLAGS += $(OPENSSL_CFLAGS) tcpflood_CPPFLAGS += $(OPENSSL_CFLAGS) tcpflood_LDADD += $(OPENSSL_LIBS) 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.2412.0/tests/glbl_setenv_err.sh0000775000175000017500000000121214650736301014013 #!/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.2412.0/tests/omod-if-array-udp.sh0000775000175000017500000000154214650736301014101 #!/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="%PRI%%timestamp%%hostname%%programname%%syslogtag%\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\"" shutdown_when_empty wait_shutdown echo '167Mar 6 16:57:54172.20.245.8%PIX-7-710005%PIX-7-710005:' | 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.2412.0/tests/parsertest-parse_8bit_escape-udp.sh0000775000175000017500000000167414650736301017213 #!/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.2412.0/tests/mmkubernetes-basic.sh0000775000175000017500000002404214650736301014425 #!/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 #export RSYSLOG_DEBUG="debug" USE_VALGRIND=false . ${srcdir:=.}/diag.sh init check_command_available timeout pwd=$( pwd ) k8s_srv_port=$( get_free_port ) generate_conf 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") ' testsrv=mmk8s-test-server echo starting kubernetes \"emulator\" timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py $k8s_srv_port ${RSYSLOG_DYNNAME}${testsrv}.pid ${RSYSLOG_DYNNAME}${testsrv}.started > ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log 2>&1 & BGPROCESS=$! wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started echo background mmkubernetes_test_server.py process id is $BGPROCESS 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.2412.0/tests/imtcp_addtlframedelim_on_input.sh0000775000175000017500000000111314650736301017064 #!/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" 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.2412.0/tests/rscript_exists-not4.sh0000775000175000017500000000103514650736301014611 #!/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.2412.0/tests/es-execOnlyWhenPreviousSuspended.sh0000775000175000017500000000262314650736301017273 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100 #10000 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.2412.0/tests/imtcp_conndrop_tls.sh0000775000175000017500000000246114656663250014556 #!/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=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" 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.2412.0/tests/imrelp-oversizeMode-accept.sh0000775000175000017500000000245114650736301016043 #!/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.2412.0/tests/omfile-sizelimitcmd-many.sh0000775000175000017500000000315614650736301015560 #!/bin/bash # addd 2023-01-11 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 echo "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'") } ' startup injectmsg shutdown_when_empty wait_shutdown ls -l $RSYSLOG_DYNNAME.channel.* cat $RSYSLOG_DYNNAME.channel.* > $RSYSLOG_OUT_LOG seq_check exit_test rsyslog-8.2412.0/tests/omprog-close-unresponsive-vg.sh0000775000175000017500000000213414650736301016421 #!/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.2412.0/tests/have_relpSrvSetTlsConfigCmd.c0000664000175000017500000000026514650736301016024 #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.2412.0/tests/rscript_compare_str-numstr.sh0000775000175000017500000000015114650736301016252 #!/bin/bash export LOWER_VAL='"-"' export HIGHER_VAL='"2"' source ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2412.0/tests/rs-int2hex.sh0000775000175000017500000000142614650736301012651 #!/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" 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.2412.0/tests/rawmsg-after-pri.sh0000775000175000017500000000174014650736301014034 #!/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" 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.2412.0/tests/rscript_hash32.sh0000775000175000017500000000174314650736301013506 #!/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" 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 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.2412.0/tests/sndrcv.sh0000775000175000017500000000273114650736301012145 #!/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" 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.2412.0/tests/diskq-rfc5424.sh0000775000175000017500000000225314650736301013047 #!/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 generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" 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="disk" 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.2412.0/tests/udp-msgreduc-vg.sh0000775000175000017500000000222114650736301013651 #!/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.2412.0/tests/imdtls-basic-vg.sh0000775000175000017500000000053114650736301013627 #!/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" source ${srcdir:-.}/imdtls-basic.sh rsyslog-8.2412.0/tests/imhiredis-redis-start-after-vg.sh0000775000175000017500000000031414650736301016566 #!/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" source ${srcdir:=.}/imhiredis-redis-start-after.sh rsyslog-8.2412.0/tests/imptcp-discard-truncated-msg.sh0000775000175000017500000000321014650736301016315 #!/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.2412.0/tests/queue-encryption-disk.sh0000775000175000017500000000162414650736301015112 #!/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.2412.0/tests/have_relpEngineSetTLSLibByName.c0000664000175000017500000000027014650736301016324 #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.2412.0/tests/omhttp-batch-jsonarray.sh0000775000175000017500000000155514650736301015251 #!/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.2412.0/tests/queue-encryption-disk_keyprog.sh0000775000175000017500000000207514650736301016653 #!/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.2412.0/tests/rscript_unflatten_key_truncated-vg.sh0000775000175000017500000000013514650736301017743 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/rscript_unflatten_key_truncated.sh rsyslog-8.2412.0/tests/omhttp-retry-vg.sh0000775000175000017500000000011214650736301013725 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:=.}/omhttp-retry.sh rsyslog-8.2412.0/tests/imtcp_conndrop.sh0000775000175000017500000000164314650736301013665 #!/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" 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.2412.0/tests/rscript_unflatten_arg2_invalid-vg.sh0000775000175000017500000000013414650736301017442 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/rscript_unflatten_arg2_invalid.sh rsyslog-8.2412.0/tests/known_issues.supp0000664000175000017500000000237014650736301013746 { 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:pselect 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) } rsyslog-8.2412.0/tests/es-basic-vg.sh0000775000175000017500000000010614650736301012740 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:=.}/es-basic.sh rsyslog-8.2412.0/tests/omrabbitmq_error_server0.sh0000775000175000017500000000320514650736301015657 #!/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 172.20.245.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:172.20.245.8, fromhost:127.0.0.1, delivery-mode:transient, expiration:5000, timestamp:OK, app-id:tag, msg:<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq' cmp_exact $RSYSLOG_DYNNAME.amqp.log content_check "exchange declare failed PRECONDITION_FAILED" exit_test rsyslog-8.2412.0/tests/pipeaction.sh0000775000175000017500000000241214650736301012775 #!/bin/bash # Test for the pipe output action. # will create a fifo in the current directory, write to it and # then do the usual sequence checks. # 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 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 ' 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 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.2412.0/tests/sndrcv_tls_ossl_serveranon_ossl_clientanon.sh0000775000175000017500000000311014650736301021573 #!/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 export PORT_RCVR="$(get_free_port)" 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="'$PORT_RCVR'" ) $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" generate_conf 2 export TCPFLOOD_PORT="$(get_free_port)" 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.2412.0/tests/pgsql-basic-cnf6.sh0000775000175000017500000000123614650736301013704 #!/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.2412.0/tests/rs-substring.sh0000775000175000017500000000134714650736301013312 #!/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" 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.2412.0/tests/improg_simple_multi.sh0000775000175000017500000000115314650736301014723 #!/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 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.2412.0/tests/mysql-asyn-vg.sh0000775000175000017500000000021314650736301013366 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:=.}/mysql-asyn.sh rsyslog-8.2412.0/tests/execonlywhenprevsuspended4.sh0000775000175000017500000000204414650736301016247 #!/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.2412.0/tests/imtuxedoulog_data.sh0000775000175000017500000000435514650736301014370 #!/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.2412.0/tests/imtcp-basic.sh0000775000175000017500000000107614723310736013043 #!/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" 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.2412.0/tests/omhttp-batch-jsonarray-retry.sh0000775000175000017500000000320314650736301016404 #!/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.2412.0/tests/multiple_lookup_tables.sh0000775000175000017500000000310414650736301015417 #!/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.2412.0/tests/sndrcv_dtls_certvalid.sh0000775000175000017500000000513314650736301015227 #!/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=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 export PORT_RCVR="$(get_free_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="'$PORT_RCVR'") 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 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") $imdiagInjectDelayMode full # 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.2412.0/tests/omhttp-basic.sh0000775000175000017500000000141014650736301013231 #!/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.2412.0/tests/imbatchreport_errmsg_regex.match.rename.sh0000775000175000017500000000072014650736301020617 #!/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.2412.0/tests/imtcp-tls-basic.sh0000775000175000017500000000221214650736301013633 #!/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" 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.2412.0/tests/imuxsock_logger_ruleset_ratelimit.sh0000775000175000017500000000222614650736301017663 #!/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=`echo $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.2412.0/tests/failover-rptd.sh0000775000175000017500000000100314650736301013413 #!/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.2412.0/tests/imjournal-basic-vg.sh0000775000175000017500000000011514650736301014331 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/imjournal-basic.sh rsyslog-8.2412.0/tests/imfile-statefile-delete.sh0000775000175000017500000000263514650736301015334 #!/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.2412.0/tests/uxsock_simple.sh0000775000175000017500000000267314650736301013540 #!/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 check_command_available timeout uname if [ $(uname) = "FreeBSD" ] ; then echo "This test currently does not work on FreeBSD." exit 77 fi # 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 ' timeout 30s ./uxsockrcvr -s$RSYSLOG_DYNNAME-testbench-dgram-uxsock -o $RSYSLOG_OUT_LOG -t 60 & BGPROCESS=$! echo background uxsockrcvr process id is $BGPROCESS # 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 # 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 9999 exit_test rsyslog-8.2412.0/tests/pgsql-basic-vg.sh0000775000175000017500000000116514650736301013465 #!/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.2412.0/tests/diagtalker.c0000664000175000017500000000661614650736301012570 /* 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 #if defined(__FreeBSD__) #include #endif static char *targetIP = "127.0.0.1"; static int targetPort = 13500; /* open a single tcp connection */ int openConn(int *fd) { int sock; struct sockaddr_in addr; int port; int retries = 0; if((sock=socket(AF_INET, SOCK_STREAM, 0))==-1) { perror("socket()"); exit(1); } port = targetPort; 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"); exit(1); } while(1) { /* loop broken inside */ if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) { break; } else { if(retries++ == 50) { perror("connect()"); fprintf(stderr, "[%d] connect() failed\n", port); exit(1); } else { fprintf(stderr, "[%d] connect failed, retrying...\n", port); usleep(100000); /* ms = 1000 us! */ } } } if(retries > 0) { fprintf(stderr, "[%d] connection established.\n", port); } *fd = sock; return 0; } /* 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() { int fd; int len; char line[2048]; 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.2412.0/tests/imtcp-tls-input-2certs.sh0000775000175000017500000000256714650736301015126 #!/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" 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.2412.0/tests/imtcp-tls-gtls-x509fingerprint.sh0000775000175000017500000000226214656663250016513 #!/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" 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.2412.0/tests/imtcp-tls-gtls-x509name-legacy.sh0000775000175000017500000000221514650736301016334 #!/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.2412.0/tests/imtcp-tls-ossl-basic-vg.sh0000775000175000017500000000057314650736301015233 #!/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" source ${srcdir:-.}/imtcp-tls-ossl-basic.sh rsyslog-8.2412.0/tests/imtcp-tls-ossl-basic.sh0000775000175000017500000000215714650736301014621 #!/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" 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.2412.0/tests/imptcp-connection-msg-received.sh0000775000175000017500000000202014650736301016636 #!/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=`echo $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.2412.0/tests/omrabbitmq_params_missing1.sh0000775000175000017500000000062414650736301016157 #!/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.2412.0/tests/mmnormalize_regex.sh0000775000175000017500000000220714650736301014370 #!/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=`echo $srcdir/testsuites/mmnormalize_regex.rulebase`) action(type="omfile" file=`echo $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.2412.0/tests/imtcp-tls-ossl-x509fingerprint.sh0000775000175000017500000000225314656663250016522 #!/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" 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.2412.0/tests/mmjsonparse-w-o-cookie-multi-spaces.sh0000775000175000017500000000134114650736301017553 #!/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" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="mmjsonparse" cookie="") if $parsesuccess == "OK" then { action(type="omfile" file=`echo $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.2412.0/tests/dnscache-TTL-0-vg.sh0000775000175000017500000000021214650736301013616 #!/bin/bash # added 2019-04-12 by Rainer Gerhards, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:=.}/dnscache-TTL-0.sh rsyslog-8.2412.0/tests/diskqueue-non-unique-prefix.sh0000775000175000017500000000173614650736301016240 #!/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.2412.0/tests/improg-simul.sh0000775000175000017500000000234214650736301013270 #! /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 [ "x$order" != "xSTART" ]; do read -r order echo $order' Received' >> $ERR echo $0' '$order' Received' >&2 done while [ "x$order" != "xSTOP" ]; 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.2412.0/tests/imfile-readmode2-polling.sh0000775000175000017500000000363014650736301015414 #!/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.2412.0/tests/omtcl.tcl0000664000175000017500000000036414650736301012131 proc 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.2412.0/tests/sndrcv_tls_ossl_certvalid_tlscommand.sh0000775000175000017500000000473614656663250020364 #!/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" 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 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.2412.0/tests/prop-jsonmesg-vg.sh0000775000175000017500000000112114650736301014053 #!/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" 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.2412.0/tests/imhiredis-stream-consumerGroup-ack.sh0000775000175000017500000000304414650736301017514 #!/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.2412.0/tests/test_id.c0000664000175000017500000000147714723322534012114 #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_%04.4x", tv.tv_usec, hash_from_string(argv[1])); return 0; } rsyslog-8.2412.0/tests/dynfile_invalid2.sh0000775000175000017500000000367514650736301014100 #!/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" 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.2412.0/tests/omhttp-batch-retry-metadata-vg.sh0000775000175000017500000000013114650736301016563 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:=.}/omhttp-batch-retry-metadata.sh rsyslog-8.2412.0/tests/imrelp-basic-hup.sh0000775000175000017500000000121514650736301014003 #!/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.2412.0/tests/sndrcv_tls_gtls_servercert_ossl_clientanon.sh0000775000175000017500000000352714650736301021602 #!/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 export PORT_RCVR="$(get_free_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/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="'$PORT_RCVR'" ) $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" generate_conf 2 export TCPFLOOD_PORT="$(get_free_port)" 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.2412.0/tests/linkedlistqueue.sh0000775000175000017500000000114314650736301014051 #!/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.2412.0/tests/no-dynstats-json.sh0000775000175000017500000000166714650736301014107 #!/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.2412.0/tests/rscript_privdropuser.sh0000775000175000017500000000113014650736301015150 #!/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.2412.0/tests/pgsql-template.sh0000775000175000017500000000166514650736301013612 #!/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.2412.0/tests/libdbi-asyn.sh0000775000175000017500000000134414650736301013042 #!/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 15000 $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 startup injectmsg wait_file_lines $RSYSLOG_DYNNAME.syncfile $NUMMESSAGES 2500 shutdown_when_empty wait_shutdown mysql_get_data seq_check exit_test rsyslog-8.2412.0/tests/imfile-wildcards-dirs-multi5.sh0000775000175000017500000000526114650736301016242 #!/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 touch $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.logfile ./inputfilegen -m 1 > $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:00000000:" $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.2412.0/tests/pmnull-basic.sh0000775000175000017500000000224414650736301013233 #!/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" 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.2412.0/tests/msleep_usage_output.sh0000775000175000017500000000042114650736301014731 #!/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.2412.0/tests/pmnormalize-rule_and_rulebase.sh0000775000175000017500000000064614650736301016657 #!/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.2412.0/tests/omusrmsg-noabort.sh0000775000175000017500000000131314650736301014157 #!/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.2412.0/tests/rscript_compare_numstr-numstr-vg.sh0000775000175000017500000000020314650736301017402 #!/bin/bash export USE_VALGRIND="YES" export LOWER_VAL='"1"' export HIGHER_VAL='"2"' source ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2412.0/tests/dynstats_reset-vg.sh0000775000175000017500000000443314650736301014334 #!/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.2412.0/tests/incltest_dir_empty_wildcard.sh0000775000175000017500000000117314650736301016417 #!/bin/bash # This test checks if an empty includeConfig directory causes problems. It # should not, as this is a valid situation that by default exists on many # distros. . ${srcdir:=.}/diag.sh init generate_conf add_conf "\$IncludeConfig ${srcdir}/testsuites/incltest.d/*.conf-not-there " add_conf '$template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")' 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.2412.0/tests/imbatchreport_errmsg_no_params-vg.sh0000775000175000017500000000023714650736301017540 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:-.}/imbatchreport_errmsg_no_params.sh rsyslog-8.2412.0/tests/failover-rptd-vg.sh0000775000175000017500000000140614650736301014034 #!/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.2412.0/tests/rscript_str2num_negative.sh0000775000175000017500000000123014650736301015701 #!/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" 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=`echo $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.2412.0/tests/imuxsock_traillf_syssock.sh0000775000175000017500000000142314650736301016000 #!/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=`echo $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.2412.0/tests/parsertest-parse3.sh0000775000175000017500000000214414650736301014233 #!/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" 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.2412.0/tests/imtcp-tls-basic-verifydepth.sh0000775000175000017500000000200014650736301016155 #!/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" 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.2412.0/tests/mmutf8fix_no_error.sh0000775000175000017500000001407314650736301014504 #!/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" 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.2412.0/tests/imfile-file-not-found-error.sh0000775000175000017500000000223114650736301016061 #!/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.2412.0/tests/rscript_privdropgroupid.sh0000775000175000017500000000117014650736301015647 #!/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.2412.0/tests/imhiredis-queue-vg.sh0000775000175000017500000000030014650736301014345 #!/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" source ${srcdir:=.}/imhiredis-queue.sh rsyslog-8.2412.0/tests/imhttp-post-payload-large.sh0000775000175000017500000000224114650736301015651 #!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf IMHTTP_PORT="$(get_free_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="'$IMHTTP_PORT'") input(type="imhttp" endpoint="/postrequest" ruleset="ruleset") ruleset(name="ruleset") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup 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.2412.0/tests/sndrcv_tls_ossl_serveranon_gtls_clientanon.sh0000775000175000017500000000351614650736301021576 #!/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 export PORT_RCVR="$(get_free_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/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="'$PORT_RCVR'" ) $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" generate_conf 2 export TCPFLOOD_PORT="$(get_free_port)" 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.2412.0/tests/imptcp-basic-hup.sh0000775000175000017500000000131314650736301014006 #!/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.2412.0/tests/rscript_stop2.sh0000775000175000017500000000166514650736301013470 #!/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.2412.0/tests/omhttp-basic-vg.sh0000775000175000017500000000011214650736301013641 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:=.}/omhttp-basic.sh rsyslog-8.2412.0/tests/rscript_unflatten_object.sh0000775000175000017500000000267014650736301015744 #!/bin/bash # added 2020-08-16 by Julien Thomas, released under ASL 2.0 source "${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" 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.2412.0/tests/multiple_lookup_tables-vg.sh0000775000175000017500000000027414650736301016036 #!/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" source ${srcdir:-.}/multiple_lookup_tables.sh rsyslog-8.2412.0/tests/sndrcv_failover.sh0000775000175000017500000000426314650736301014036 #!/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 export PORT_RCVR="$(get_free_port)" add_conf ' # then SENDER sends to this port (not tcpflood!) module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" 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.2412.0/tests/hostname-with-slash-dflt-slash-valid.sh0000775000175000017500000000165314650736301017703 #!/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" 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.2412.0/tests/mmanon_with_debug.sh0000775000175000017500000000515614650736301014340 #!/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" 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.2412.0/tests/imtcp_conndrop_tls-vg.sh0000775000175000017500000000035514650736301015160 #!/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 source ${srcdir:-.}/imtcp_conndrop_tls.sh rsyslog-8.2412.0/tests/array_lookup_table.sh0000775000175000017500000000335214650736301014524 #!/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.2412.0/tests/omazureeventhubs-list.sh0000775000175000017500000001124614650736301015226 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init 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") $imdiagInjectDelayMode full # 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 kafkacat 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.2412.0/tests/imtcp-tls-ossl-basic-stress.sh0000775000175000017500000000301414656663250016143 #!/bin/bash # added 2018-04-27 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 # # List available valid OpenSSL Engines for defaultopensslengine with this command: # openssl engine -t # . ${srcdir:=.}/diag.sh init 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" 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.2412.0/tests/threadingmq.sh0000775000175000017500000000235614650736301013154 #!/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.2412.0/tests/pmsnare-modoverride-udp.sh0000775000175000017500000001256614650736301015425 #!/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.2412.0/tests/imbatchreport_errmsg_glob_dir_not_dir.sh0000775000175000017500000000070114650736301020442 #!/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.2412.0/tests/now-unixtimestamp.sh0000775000175000017500000000160114650736301014351 #!/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" 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.2412.0/tests/imhiredis-queue.sh0000775000175000017500000000204614650736301013744 #!/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.2412.0/tests/imhiredis-queue-lpop.sh0000775000175000017500000000206714650736301014717 #!/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.2412.0/tests/imkafka-hang-on-no-kafka.sh0000775000175000017500000000156714650736301015271 #!/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.2412.0/tests/with_space.mmdb0000664000175000017500000000066014650736301013275                     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.2412.0/tests/pmnull-withparams.sh0000775000175000017500000000230514650736301014327 #!/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" 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.2412.0/tests/imkafka-backgrounded.sh0000775000175000017500000000306614650736301014701 #!/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 kafkacat export KEEP_KAFKA_RUNNING="YES" export TESTMESSAGES=100000 export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1) # 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_kafkacat --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.2412.0/tests/pmsnare-ccbackslash.sh0000775000175000017500000001201014650736301014541 #!/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" 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.2412.0/tests/pmsnare-cccstyle.sh0000775000175000017500000001430214650736301014117 #!/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" 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.2412.0/tests/sndrcv_tls_client_missing_cert.sh0000775000175000017500000000401614656663250017141 #!/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" 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 .* did not provide a certificate," exit_test rsyslog-8.2412.0/tests/stats-cee-vg.sh0000775000175000017500000000242614650736301013151 #!/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, "failed": 0, "suspended": 0, "suspended.duration": 0, "resumed": 0 }' "${RSYSLOG_DYNNAME}.out.stats.log" exit_test rsyslog-8.2412.0/tests/lookup_table-hup-backgrounded.sh0000775000175000017500000000320514650736301016543 #!/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.2412.0/tests/imhttp-post-payload-basic-auth-vg.sh0000775000175000017500000000025214650736301017211 #!/bin/bash export USE_VALGRIND="YES" #export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all" source ${srcdir:-.}/imhttp-post-payload-basic-auth.sh rsyslog-8.2412.0/tests/no-parser-vg.sh0000775000175000017500000000121214650736301013157 #!/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" 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.2412.0/tests/lookup_table.sh0000775000175000017500000000313714650736301013327 #!/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.2412.0/tests/omstdout-basic.sh0000775000175000017500000000130014650736301013572 #!/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" 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.2412.0/tests/rscript_hash64-vg.sh0000775000175000017500000000201214650736301014113 #!/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" 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.2412.0/tests/imhiredis-stream-consumerGroup-reclaim-vg.sh0000775000175000017500000000032714650736301021005 #!/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" source ${srcdir:=.}/imhiredis-stream-consumerGroup-reclaim.sh rsyslog-8.2412.0/tests/timestamp-pgsql.sh0000775000175000017500000000076214650736301013777 #!/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.2412.0/tests/imfile-truncate-2GB-file.sh0000775000175000017500000000341314650736301015221 #!/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 export NUMMESSAGES="$(cat $RSYSLOG_DYNNAME.msgcnt)" 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.2412.0/tests/rscript_set_unset_invalid_var.sh0000775000175000017500000000226514650736301017005 #!/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.2412.0/tests/faketime_common.sh0000664000175000017500000000445214650736301014002 #!/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=$(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.2412.0/tests/sndrcv_relp_tls_chainedcert.sh0000775000175000017500000000356614650736301016411 #!/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 export TB_TEST_MAX_RUNTIME=30 # uncomment for debugging support: # export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" # export RSYSLOG_DEBUGLOG="log" generate_conf export PORT_RCVR="$(get_free_port)" add_conf ' module( load="../plugins/imrelp/.libs/imrelp" tls.tlslib="openssl") # then SENDER sends to this port (not tcpflood!) input(type="imrelp" 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") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup 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.2412.0/tests/rscript_exists-yes2.sh0000775000175000017500000000075414650736301014616 #!/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.2412.0/tests/imuxsock_logger_ratelimit.sh0000775000175000017500000000253614650736301016124 #!/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=`echo $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.2412.0/tests/sndrcv_tls_anon_ipv4.sh0000775000175000017500000000403514650736301015003 #!/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 export PORT_RCVR="$(get_free_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'" 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'.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.2412.0/tests/mysql-actq-mt.sh0000775000175000017500000000132214650736301013352 #!/bin/bash # test for mysql with multithread actionq # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=150000 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="10000" 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.2412.0/tests/dynstats_reset.sh0000775000175000017500000000460314650736301013721 #!/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.2412.0/tests/override_getaddrinfo.c0000664000175000017500000000136514650736301014642 // we need this for dlsym(): #include #include "config.h" #include #include #include #include #include int getaddrinfo(const char *node __attribute__((unused)), const char *service __attribute__((unused)), const struct addrinfo *hints __attribute__((unused)), struct addrinfo **res __attribute__((unused))) { return EAI_MEMORY; } static void __attribute__((constructor)) my_init(void) { /* we currently do not need this entry point, but keep it as * a "template". It can be used, e.g. to emit some diagnostic * information: printf("loaded\n"); * or - more importantly - obtain a pointer to the overriden * API: orig_etry = dlsym(RTLD_NEXT, "original_entry_point"); */ } rsyslog-8.2412.0/tests/rscript_compare_numstr-num.sh0000775000175000017500000000014714650736301016246 #!/bin/bash export LOWER_VAL='"1"' export HIGHER_VAL='2' source ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2412.0/tests/imjournal-basic.sh0000775000175000017500000000334614650736301013730 #!/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") action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' 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' 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.2412.0/tests/imptcp-msg-truncation-on-number2.sh0000775000175000017500000000325414650736301017075 #!/bin/bash # addd 2017-03-01 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init 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.2412.0/tests/da-mainmsg-q.sh0000775000175000017500000000341714650736301013123 #!/bin/bash # Test for DA mode on the main message queue # This test checks if DA mode operates correctly. To do so, # it uses a small in-memory queue size, so that DA mode is initiated # rather soon, and disk spooling used. There is some uncertainty (based # on machine speeds), but in general the test should work rather well. # We add a few messages after the initial run, just so that we can # check everything recovers from DA mode correctly. # added 2009-04-22 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $ModLoad ../plugins/imtcp/.libs/imtcp $MainMsgQueueTimeoutShutdown 10000 input(type="imtcp" 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_file_lines $RSYSLOG_OUT_LOG 50 # 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_file_lines $RSYSLOG_OUT_LOG 2050 # wait to ensure DA queue is "empty" # send another handful injectmsg 2050 50 shutdown_when_empty wait_shutdown seq_check 0 2099 exit_test rsyslog-8.2412.0/tests/mmkubernetes-basic.out.json0000664000175000017500000002661414650736301015576 [{ "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.2412.0/tests/gzipwr_large.sh0000775000175000017500000000242214650736301013337 #!/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" 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.2412.0/tests/omprog-restart-terminated.sh0000775000175000017500000001065514650736301015771 #!/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.2412.0/tests/omhttp-retry-timeout.sh0000775000175000017500000000167314650736301015014 #!/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 port="$(get_free_port)" omhttp_start_server $port --fail-every 1000 --fail-with-delay-secs 2 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%\"}") 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.2412.0/tests/mmjsonparse_localvar.sh0000775000175000017500000000130414650736301015062 #!/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=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m $NUMMESSAGES -j "@cim: " shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2412.0/tests/fac_invld2.sh0000775000175000017500000000114114650736301012647 #!/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" 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.2412.0/tests/imfile-basic-2GB-file.sh0000775000175000017500000000336514650736301014463 #!/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 export NUMMESSAGES="$(cat $RSYSLOG_DYNNAME.msgcnt)" 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.2412.0/tests/omazureeventhubs-basic-url.sh0000775000175000017500000000734014660643541016140 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init 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") $imdiagInjectDelayMode full # 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 kafkacat 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.2412.0/tests/func-substring-invld-startpos.sh0000775000175000017500000000102114650736301016575 #!/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.2412.0/tests/incltest_dir_wildcard.sh0000775000175000017500000000050714650736301015201 #!/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.2412.0/tests/pgsql-basic-cnf6-vg.sh0000775000175000017500000000126014650736301014313 #!/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.2412.0/tests/func-substring-large-neg-endpos.sh0000775000175000017500000000102414650736301016736 #!/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.2412.0/tests/rscript_set_memleak-vg.sh0000775000175000017500000000205714650736301015315 #!/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.2412.0/tests/imtuxedoulog_errmsg_no_params-vg.sh0000775000175000017500000000023614650736301017421 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:-.}/imtuxedoulog_errmsg_no_params.sh rsyslog-8.2412.0/tests/sndrcv_tls_anon_ipv6.sh0000775000175000017500000000437614656663250015025 #!/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 export TCPFLOOD_PORT="$(get_free_port)" # TODO: move to diag.sh 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.2412.0/tests/sndrcv_drvr.sh0000775000175000017500000000006514650736301013200 #!/bin/bash . $srcdir/sndrcv_drvr_noexit.sh $1 $2 $3 rsyslog-8.2412.0/tests/pmrfc3164-tagEndingByColon.sh0000775000175000017500000000222314650736301015453 #!/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" 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.2412.0/tests/pmsnare-ccoff.sh0000775000175000017500000001311414650736301013366 #!/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" 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.2412.0/tests/fieldtest.sh0000775000175000017500000000166214650736301012633 #!/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" 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.2412.0/tests/imbatchreport_errmsg_not_supported3.sh0000775000175000017500000000061614650736301020140 #!/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.2412.0/tests/include-obj-text-vg.sh0000775000175000017500000000104614650736301014433 #!/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" export CONF_SNIPPET=`cat $INCLFILE` 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.2412.0/tests/rscript_exists-not2.sh0000775000175000017500000000103114650736301014603 #!/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.2412.0/tests/mmtaghostname_server.sh0000775000175000017500000000211514650736301015074 #!/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" 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.2412.0/tests/imfile-old-state-file.sh0000775000175000017500000000515114650736301014721 #!/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.2412.0/tests/omrelp-invld-tlslib.sh0000775000175000017500000000070414650736301014543 #!/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.2412.0/tests/timereported-utc.sh0000775000175000017500000000157614650736301014150 #!/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.2412.0/tests/mmanon_both_modes_compatible.sh0000775000175000017500000000202314650736301016527 #!/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.2412.0/tests/imtcp-basic-hup.sh0000775000175000017500000000131314650736301013626 #!/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" 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.2412.0/tests/imfile-basic-legacy.sh0000775000175000017500000000153014650736301014430 #!/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.2412.0/tests/glbl_setenv_2_vars.sh0000775000175000017500000000142414650736301014424 #!/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=`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, 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.2412.0/tests/mysql-actq-mt-withpause.sh0000775000175000017500000000157414650736301015372 #!/bin/bash # test for mysql with multithread actionq # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=150000 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="20000" ) } ' mysql_prep_for_test startup injectmsg 0 50000 wait_queueempty echo waiting for worker threads to timeout ./msleep 3000 injectmsg 50000 50000 wait_queueempty echo waiting for worker threads to timeout ./msleep 2000 injectmsg 100000 50000 shutdown_when_empty wait_shutdown mysql_get_data seq_check mysql_cleanup_test exit_test rsyslog-8.2412.0/tests/improg_prog_confirm_killonclose.sh0000775000175000017500000000133014650736301017277 #!/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 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.2412.0/tests/tcp_forwarding_ns_tpl.sh0000775000175000017500000000344714650736301015242 #!/bin/bash # This test tests tcp forwarding in a network namespace with assigned template. # To do so, a simple tcp listener service is started in a network namespace. # 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 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 ip netns exec rsyslog_test_ns ./minitcpsrv -t127.0.0.1 -p'$TCPFLOOD_PORT' -f $RSYSLOG_OUT_LOG & BGPROCESS=$! echo background minitcpsrvr process id is $BGPROCESS # 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.2412.0/tests/imtcp-tls-ossl-input-basic.sh0000775000175000017500000000212414650736301015750 #!/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" 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.2412.0/tests/template-pos-from-to.sh0000775000175000017500000000103114650736301014631 #!/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" 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.2412.0/tests/clickhouse-retry-error.sh0000775000175000017500000000127714650736301015275 #!/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.2412.0/tests/rscript_parse_json.sh0000775000175000017500000000112714650736301014555 #!/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" 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.2412.0/tests/parsertest-parse-nodate-udp.sh0000775000175000017500000000215714650736301016212 #!/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.2412.0/tests/dircreate_dflt.sh0000775000175000017500000000157114650736301013622 #!/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 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 ' 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.2412.0/tests/tabescape_dflt-udp.sh0000775000175000017500000000137414650736301014376 #!/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.2412.0/tests/mmdb-container.sh0000775000175000017500000000152114650736301013541 #!/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.2412.0/tests/mmdb-multilevel-vg.sh0000775000175000017500000000251614650736301014360 #!/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.2412.0/tests/sndrcv_tls_certvalid.sh0000775000175000017500000000373614650736301015072 #!/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" 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.2412.0/tests/manytcp-too-few-tls-vg.sh0000775000175000017500000000360714656663250015124 #!/bin/bash # test many concurrent tcp connections # released under ASL 2.0 . ${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" 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.2412.0/tests/discard-rptdmsg.sh0000775000175000017500000000122214650736301013727 #!/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" 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.2412.0/tests/rscript_privdropuserid.sh0000775000175000017500000000112114650736301015465 #!/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.2412.0/tests/sndrcv_relp_tls.sh0000775000175000017500000000230714650736301014050 #!/bin/bash # added 2013-12-10 by Rgerhards # testing sending and receiving via relp with TLS enabled # 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 export PORT_RCVR="$(get_free_port)" add_conf ' module(load="../plugins/imrelp/.libs/imrelp") # then SENDER sends to this port (not tcpflood!) input(type="imrelp" port="'$PORT_RCVR'" tls="on") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup 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.2412.0/tests/omjournal-basic-no-template.sh0000775000175000017500000000142014650736301016150 #!/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" 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.2412.0/tests/manyptcp.sh0000775000175000017500000000120114650736301012470 #!/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" 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.2412.0/tests/sndrcv_omudpspoof.sh0000775000175000017500000000420414650736301014415 #!/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.2412.0/tests/sndrcv_tls_priorityString.sh0000775000175000017500000000436714650736301016166 #!/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 export PORT_RCVR="$(get_free_port)" 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" port="'$PORT_RCVR'") 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 export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 export TCPFLOOD_PORT="$(get_free_port)" # TODO: move to diag.sh 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" 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.2412.0/tests/pmnormalize-basic.sh0000775000175000017500000000256014650736301014262 #!/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" 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 export EXPECTED='host: ubuntu, ip: 127.0.0.1, tag: tag1, pri: 189, syslogfacility: 23, syslogseverity: 5 msg: test host: debian, ip: 255.255.255.255, tag: tag2, pri: 112, syslogfacility: 14, syslogseverity: 0 msg: test host: centos, ip: 192.168.0.9, tag: tag3, pri: 177, syslogfacility: 22, syslogseverity: 1 msg: test' cmp_exact exit_test rsyslog-8.2412.0/tests/fac_invld3.sh0000775000175000017500000000113214650736301012650 #!/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" 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.2412.0/tests/rscript_gt_var.sh0000775000175000017500000000275714650736301013706 #!/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.2412.0/tests/imhiredis-subscribe-vg.sh0000775000175000017500000000030414650736301015206 #!/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" source ${srcdir:=.}/imhiredis-subscribe.sh rsyslog-8.2412.0/tests/mysql-actq-mt-withpause-vg.sh0000775000175000017500000000023014650736301015770 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" source ${srcdir:=.}/mysql-actq-mt-withpause.sh rsyslog-8.2412.0/tests/imrelp-manyconn-vg.sh0000775000175000017500000000060314650736301014364 #!/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" source ${srcdir:=.}/imrelp-manyconn.sh rsyslog-8.2412.0/tests/imfile-readmode2-vg.sh0000775000175000017500000000335014650736301014363 #!/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.2412.0/tests/rscript_compare_numstr-num-vg.sh0000775000175000017500000000020114650736301016647 #!/bin/bash export USE_VALGRIND="YES" export LOWER_VAL='"1"' export HIGHER_VAL='2' source ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2412.0/tests/imdocker-new-logs-from-start.sh0000775000175000017500000000317514650736301016273 #!/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 export COOKIE=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 10 | head -n 1) 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.2412.0/tests/lookup_table_rscript_reload.sh0000775000175000017500000000332214650736301016417 #!/bin/bash # test for lookup-table reload by rscript-fn # 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", "reload_failed"); } 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.2412.0/tests/parsertest-parse1-udp.sh0000775000175000017500000001434614650736301015026 #!/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.2412.0/tests/rscript_exists-not1.sh0000775000175000017500000000102314650736301014603 #!/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.2412.0/tests/imfile-statefile-no-delete.sh0000775000175000017500000000227414650736301015745 #!/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.2412.0/tests/sndrcv_udp_nonstdpt.sh0000775000175000017500000000266614650736301014755 #!/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.2412.0/tests/imtcp-drvr-in-input-basic.sh0000775000175000017500000000172714650736301015561 #!/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" 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.2412.0/tests/mmanon_zero_64_ipv6.sh0000775000175000017500000000232014650736301014441 #!/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.2412.0/tests/imtcp-tls-ossl-error-cert.sh0000775000175000017500000000157114650736301015623 #!/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/cert.pem'" ) module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1") input(type="imtcp" 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.2412.0/tests/omrelp_wrong_authmode.sh0000775000175000017500000000116014650736301015241 #!/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.2412.0/tests/rscript_stop.sh0000775000175000017500000000132614650736301013400 #!/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.2412.0/tests/imfile-truncate-line.sh0000775000175000017500000000547214650736301014670 #!/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.2412.0/tests/stop-localvar.sh0000775000175000017500000000165014650736301013433 #!/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" 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.2412.0/tests/imtcp-bigmessage-octetstuffing.sh0000775000175000017500000000303414650736301016745 #!/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 -p'$TCPFLOOD_PORT' -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_testrsyslog-8.2412.0/tests/clickhouse-errorfile.sh0000775000175000017500000000257614650736301014775 #!/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" 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.2412.0/tests/pmrfc3164-msgFirstSpace.sh0000775000175000017500000000207114650736301015040 #!/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" 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.2412.0/tests/imrelp-oversizeMode-truncate.sh0000775000175000017500000000241014650736301016424 #!/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.2412.0/tests/omhttp-httpheaderkey.sh0000775000175000017500000000150514650736301015016 #!/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.2412.0/tests/random.sh0000775000175000017500000000217514650736301012130 #!/bin/bash # Test if rsyslog survives sending truly random data to it... # # added 2010-04-01 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' # The random data will generate TCP framing error messages. We will # not clutter the test output with them. So we disable error messages # to stderr. $ErrorMessagesToStderr off module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%rawmsg%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! *.* /dev/null ' startup # generate random data ./randomgen -f $RSYSLOG_DYNNAME.random.data -s 100000 ls -l $RSYSLOG_DYNNAME.random.data tcpflood -B -I $RSYSLOG_DYNNAME.random.data -c5 -C10 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # and wait for it to terminate # we do not check anything yet, the point is if rsyslog survived ;) # TODO: check for exit message, but we'll notice an abort anyhow, so not that important exit_test rsyslog-8.2412.0/tests/queue-direct-with-params-given.sh0000775000175000017500000000050414650736301016576 #!/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'" queue.mindequeuebatchsize="20") ' startup shutdown_when_empty wait_shutdown content_check "queue is in direct mode, but parameters have been set" exit_test rsyslog-8.2412.0/tests/imbatchreport_delete_success.sh0000775000175000017500000000570614650736301016570 #!/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" delete=".done$ .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.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.2412.0/tests/minitcpsrvr.c0000664000175000017500000002303414705221143013024 /* 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 #if defined(__FreeBSD__) #include #endif #define MAX_CONNECTIONS 10 #define BUFFER_SIZE 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; char *targetIP = NULL; int targetPort = -1; char *portFileName = 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][BUFFER_SIZE]; int buffer_offs[MAX_CONNECTIONS]; static void errout(char *reason) { perror(reason); fprintf(stderr, "minitcpsrv ABORTS!!!\n\n\n"); exit(1); } static void usage(void) { fprintf(stderr, "usage: minitcpsrv -t ip-addr -p port -P portFile -f outfile\n"); exit (1); } static void createListenSocket(void) { struct sockaddr_in srvAddr; unsigned int srvAddrLen; static int portFileWritten = 0; int r; listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (listen_fd < 0) { errout("Failed to create listen socket"); } /* Set SO_REUSEADDR and SO_REUSEPORT options - these are vital for some * Tests. If not both are supported by the OS (e.g. Solaris 10), some tests * will fail. Those need to be excluded. */ int opt = 1; if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { errout("setsockopt failed for SO_REUSEADDR"); } #ifdef SO_REUSEPORT if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) { errout("setsockopt failed for SO_REUSEPORT"); } #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 (listen(listen_fd, MAX_CONNECTIONS) < 0) { errout("Listen failed"); } if (getsockname(listen_fd, (struct sockaddr*)&srvAddr, &srvAddrLen) == -1) { errout("getsockname"); } targetPort = ntohs(srvAddr.sin_port); if(portFileName != NULL && !portFileWritten) { FILE *fp; if (getsockname(listen_fd, (struct sockaddr*)&srvAddr, &srvAddrLen) == -1) { errout("getsockname"); } if((fp = fopen(portFileName, "w+")) == NULL) { errout(portFileName); } fprintf(fp, "%d", ntohs(srvAddr.sin_port)); fclose(fp); portFileWritten= 1; } 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, "aB:D:t:p:P:f:s:S:")) != -1) { switch (opt) { case 'a': // abort listener: act like the server has died (shutdown and re-open listen socket) abortListener = 1; 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 '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; 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(sleepStartup) { printf("minitcpsrv: deliberate sleep of %d seconds\n", sleepStartup); sleep(sleepStartup); printf("minitcpsrv: end sleep\n"); } createListenSocket(); nfds = 1; int bKeepRunning; while (1) { int poll_count = poll(fds, nfds, -1); // -1 means no timeout if (poll_count < 0) { errout("poll"); } bKeepRunning = 0; /* terminate on last connection close */ for (int i = 0; i < nfds; i++) { if (fds[i].revents == 0) continue; if (fds[i].revents != POLLIN) { fprintf(stderr, "Error! revents = %d\n", fds[i].revents); exit(EXIT_FAILURE); } 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; } fds[nfds].fd = conn_fd; fds[nfds].events = POLLIN; 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; } 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; 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]; } 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.2412.0/tests/rscript_unflatten_non_object-vg.sh0000775000175000017500000000013214650736301017217 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/rscript_unflatten_non_object.sh rsyslog-8.2412.0/tests/imbatchreport_errmsg_regex.match.reject.sh0000775000175000017500000000072014650736301020624 #!/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.2412.0/tests/failover-no-rptd-vg.sh0000775000175000017500000000125114650736301014444 #!/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 -a "$(cat $RSYSLOG_OUT_LOG)" != "" ]; then echo "ERROR, output file not empty" cat -n "$RSYSLOG_OUT_LOG" error_exit 1 fi exit_test rsyslog-8.2412.0/tests/imtcp-listen-port-file-2.sh0000775000175000017500000000230514650736301015311 #!/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" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ruleset="rs1") input(type="imtcp" 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.2412.0/tests/template-pos-from-to-missing-jsonvar.sh0000775000175000017500000000126214650736301017766 #!/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" 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.2412.0/tests/allowed-sender-tcp-fail.sh0000775000175000017500000000170514650736301015250 #!/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" 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 -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.2412.0/tests/mmpstrucdata-vg.sh0000775000175000017500000000171314650736301013763 #!/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" 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.2412.0/tests/pmnormalize-neither_rule_rulebase.sh0000775000175000017500000000062214650736301017545 #!/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.2412.0/tests/privdrop_common.sh0000775000175000017500000000627714650736301014074 #!/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=$(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=$(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=$(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=$(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.2412.0/tests/mmanon_zero_128_ipv6.sh0000775000175000017500000000273214650736301014531 #!/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.2412.0/tests/omprog-defaults.sh0000775000175000017500000000405414650736301013756 #!/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.2412.0/tests/tcp_forwarding_dflt_tpl.sh0000775000175000017500000000231714650736301015546 #!/bin/bash # This test tests tcp forwarding with assigned default template. # 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") ' ./minitcpsrv -t127.0.0.1 -p$TCPFLOOD_PORT -f $RSYSLOG_OUT_LOG & BGPROCESS=$! echo background minitcpsrv process id is $BGPROCESS # 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.2412.0/tests/include-obj-text-from-file.sh0000775000175000017500000000061414650736301015677 #!/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.2412.0/tests/tabescape_on.sh0000775000175000017500000000134314650736301013267 #!/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" 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.2412.0/tests/snmptrapreceiver.py0000775000175000017500000000663414650736301014263 # 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 outputFile = open(szOutputfile,"w+") logFile = open(szSnmpLogfile,"a+") # 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() # 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) # Run I/O dispatcher which would receive queries and send confirmations try: snmpEngine.transportDispatcher.runDispatcher() except: snmpEngine.transportDispatcher.closeDispatcher() raise rsyslog-8.2412.0/tests/rscript_hash64.sh0000775000175000017500000000176614650736301013520 #!/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" 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.2412.0/tests/daqueue-invld-qi.sh0000775000175000017500000000315014650736301014014 #!/bin/bash # 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 $MainMsgQueueTimeoutShutdown 1 $MainMsgQueueSaveOnShutdown on input(type="imtcp" 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 LinkedList > ${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 ./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" # 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 -d exit_test rsyslog-8.2412.0/tests/rsf_getenv.sh0000775000175000017500000000133714650736301013011 #!/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.2412.0/tests/msgvar-concurrency-array-event.tags.sh0000775000175000017500000000261014650736301017661 #!/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" 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.2412.0/tests/json_array_looping.sh0000775000175000017500000000421614650736301014544 #!/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.2412.0/tests/ommail_errmsg_no_params.sh0000775000175000017500000000066314650736301015544 #!/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.2412.0/tests/imtcp-maxFrameSize.sh0000775000175000017500000000137114650736301014352 #!/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" 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.2412.0/tests/rscript_unflatten_conflict2.sh0000775000175000017500000000245414650736301016361 #!/bin/bash # added 2021-03-09 by Julien Thomas, released under ASL 2.0 source "${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" 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.2412.0/tests/gzipwr_hup-vg.sh0000775000175000017500000000020314650736301013446 #!/bin/bash export USE_VALGRIND="YES" export NUMMESSAGES=200000 # reduce for slower valgrind run source ${srcdir:-.}/gzipwr_hup.sh rsyslog-8.2412.0/tests/threadingmqaq.sh0000775000175000017500000000310214650736301013464 #!/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.2412.0/tests/imhiredis-stream-consumerGroup-reclaim.sh0000775000175000017500000000432214650736301020372 #!/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.2412.0/tests/rcvr_fail_restore.sh0000775000175000017500000001170414704407366014366 #!/bin/bash # 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" # # 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" 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 export TCPFLOOD_PORT="$(get_free_port)" add_conf ' $WorkDirectory '$RSYSLOG_DYNNAME'.spool $MainMsgQueueSize 2000 $MainMsgQueueLowWaterMark 800 $MainMsgQueueHighWaterMark 1000 $MainMsgQueueDequeueBatchSize 1 $MainMsgQueueMaxFileSize 1g $MainMsgQueueWorkerThreads 1 $MainMsgQueueFileName mainq # 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 injectmsg2 1001 10000 ./msleep 3000 # make sure some retries happen (retry interval is set to 3 second) get_mainqueuesize 2 ls -l ${RSYSLOG_DYNNAME}.spool # # Step 3: restart receiver, wait that the sender drains its queue $InputTCPServerRun '$PORT_RCVR' # 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 injectmsg2 11011 10000 sleep 1 # we need to wait, otherwise we may be so fast that the receiver # comes up before we have finally suspended the action 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.2412.0/tests/imfile-wildcards-dirs-multi3.sh0000775000175000017500000000543414650736301016242 #!/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 touch $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/subdir$j/file.logfile ./inputfilegen -m 1 > $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:00000000:" $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.2412.0/tests/nested-call-shutdown.sh0000775000175000017500000000165714650736301014720 #!/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" 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.2412.0/tests/omprog-transactions-failed-commits.sh0000775000175000017500000001122414650736301017547 #!/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.2412.0/tests/stop_when_array_has_element.sh0000775000175000017500000000201314650736301016407 #!/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" 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.2412.0/tests/empty-ruleset.sh0000775000175000017500000000201714650736301013462 #!/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" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="real") input(type="imtcp" 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.2412.0/tests/proprepltest-rfctag-udp.sh0000775000175000017500000000210514650736301015436 #!/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'") 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 -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.2412.0/tests/rscript_backticks-vg.sh0000775000175000017500000000060114650736301014756 #!/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 #tcpflood -m10 shutdown_when_empty wait_shutdown_vg seq_check 0 999 exit_test rsyslog-8.2412.0/tests/sparse_array_lookup_table.sh0000775000175000017500000000423314650736301016100 #!/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 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" exit_test rsyslog-8.2412.0/tests/omfwd-lb-1target-retry-1_byte_buf-TargetFail.sh0000775000175000017500000000020614704407366021123 #!/bin/bash export OMFWD_IOBUF_SIZE=1000 # triggers edge cases source ${srcdir:-.}/omfwd-lb-1target-retry-test_skeleton-TargetFail.sh rsyslog-8.2412.0/tests/queue-direct-with-no-params.sh0000775000175000017500000000045114650736301016103 #!/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.2412.0/tests/parsertest-parse_invld_regex.sh0000775000175000017500000000174714650736301016546 #!/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" 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.2412.0/tests/include-obj-outside-control-flow-vg.sh0000775000175000017500000000104514650736301017545 #!/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.2412.0/tests/parsertest-parse-nodate.sh0000775000175000017500000000220314650736301015414 #!/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" 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.2412.0/tests/cfg3.cfgtest0000664000175000017500000000072514650736301012513 rsyslogd: 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.2412.0/tests/linux_localtime_r.supp0000664000175000017500000000436514650736301014736 { 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.2412.0/tests/pmrfc3164-defaultTag.sh0000775000175000017500000000204414650736301014346 #!/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" 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.2412.0/tests/sndrcv_tls_certvalid_expired.sh0000775000175000017500000000405614656663250016616 #!/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" 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.2412.0/tests/omhttp-batch-jsonarray-vg.sh0000775000175000017500000000012414650736301015652 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:=.}/omhttp-batch-jsonarray.sh rsyslog-8.2412.0/tests/imfile-endregex.sh0000775000175000017500000000434214650736301013712 #!/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.2412.0/tests/omfile-read-only.sh0000775000175000017500000000232014650736301014003 #!/bin/bash # addd 2016-06-16 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="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} 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 let 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.2412.0/tests/timegenerated-utc-legacy.sh0000775000175000017500000000214714650736301015517 #!/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" 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.2412.0/tests/privdropgroup.sh0000775000175000017500000000147114650736301013570 #!/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.2412.0/tests/glbl_setenv.sh0000775000175000017500000000131514650736301013147 #!/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.2412.0/tests/imhiredis-queue-lpop-vg.sh0000775000175000017500000000030514650736301015322 #!/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" source ${srcdir:=.}/imhiredis-queue-lpop.sh rsyslog-8.2412.0/tests/rscript_gt.sh0000775000175000017500000000131614650736301013024 #!/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=`echo $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.2412.0/tests/action-tx-single-processing.sh0000775000175000017500000000225014650736301016201 #!/bin/bash # part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init 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.2412.0/tests/omhttp-basic-ignorecodes.sh0000775000175000017500000000152314650736301015535 #!/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 port="$(get_free_port)" omhttp_start_server $port --fail-with-401-or-403-after 5000 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.2412.0/tests/no-parser-errmsg.sh0000775000175000017500000000155314650736301014052 #!/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" 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.2412.0/tests/omtcl.sh0000775000175000017500000000132514650736301011762 #!/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 172.20.245.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.2412.0/tests/mmnormalize_processing_test2.sh0000775000175000017500000000651214650736301016556 #!/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" 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=`echo $srcdir/testsuites/mmnormalize_processing_tests.rulebase` useRawMsg="on") if ($!v_file == "") then { set $!v_file=$!v_tag; } action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_file_record") action(type="omfile" File=`echo $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=`echo $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.2412.0/tests/imfile-escapelf.replacement.sh0000775000175000017500000000154514650736301016173 #!/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.2412.0/tests/imhttp-post-payload-compress.sh0000775000175000017500000000202114650736301016406 #!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUG="debug" . ${srcdir:=.}/diag.sh init generate_conf IMHTTP_PORT="$(get_free_port)" add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../contrib/imhttp/.libs/imhttp" ports="'$IMHTTP_PORT'") #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 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.2412.0/tests/daqueue-persist-drvr.sh0000775000175000017500000000324314650736301014740 #!/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" 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.2412.0/tests/imrelp-long-msg.sh0000775000175000017500000000113614650736301013655 #!/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.2412.0/tests/timereported-utc-legacy.sh0000775000175000017500000000146014650736301015402 #!/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.2412.0/tests/stop.sh0000775000175000017500000000137514650736301011636 #!/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" 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.2412.0/tests/parsertest-parse_invld_regex-udp.sh0000775000175000017500000000171114650736301017323 #!/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.2412.0/tests/omprog-close-unresponsive-noterm.sh0000775000175000017500000000311714650736301017313 #!/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.2412.0/tests/parsertest-parse-3164-buggyday-udp.sh0000775000175000017500000000213514650736301017142 #!/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.2412.0/tests/imptcp-NUL.sh0000775000175000017500000000127414650736301012577 #!/bin/bash # addd 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=`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.2412.0/tests/immark.sh0000775000175000017500000000103614650736301012123 #!/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.2412.0/tests/improg_prog_killonclose.sh0000775000175000017500000000127114650736301015566 #!/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 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.2412.0/tests/tcpflood.c0000664000175000017500000017122414650736301012271 /* 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 * -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 * -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 * -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) * -j format message in json, parameter is JSON cookie * -O Use octate-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! * * Part of the testbench for rsyslog. * * Copyright 2009-2019 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 #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_OPENSSL #include #include #include #include /* 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 char *test_rs_strerror_r(int errnum, char *buf, size_t buflen) { #ifndef HAVE_STRERROR_R char *pszErr; pszErr = strerror(errnum); snprintf(buf, buflen, "%s", pszErr); #else # ifdef STRERROR_R_CHAR_P char *p = strerror_r(errnum, buf, buflen); if (p != buf) { strncpy(buf, p, buflen); buf[buflen - 1] = '\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 */ 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 char *MsgToSend = NULL; /* if non-null, this is the actual message to send */ static int bBinaryFile = 0; /* is -I file binary */ static char *dataFile = NULL; /* name of data file, if NULL, generate own data */ 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 *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 */ #ifdef ENABLE_GNUTLS static gnutls_session_t *sessArray; /* array of TLS sessions to use */ static gnutls_certificate_credentials_t tlscred; #endif #ifdef ENABLE_OPENSSL /* Main OpenSSL CTX pointer */ static SSL_CTX *ctx; static SSL **sslArray; 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 /* 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 */ 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 /* RELP subsystem */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-security" static void relp_dbgprintf(char __attribute__((unused)) *fmt, ...) { printf(fmt); } #pragma GCC diagnostic pop 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) { if((udpsockout = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) 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_OPENSSL) 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; } #endif /* open a single tcp connection */ int openConn(int *fd, 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); } *fd = 1; /* mimic "all ok" state */ #endif } else { /* TCP, with or without TLS */ if((sock=socket(AF_INET, SOCK_STREAM, 0))==-1) { perror("\nsocket()"); return(1); } 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(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) { break; } else { if(retries++ == 50) { perror("connect()"); fprintf(stderr, "connect(%d) failed\n", port); return(1); } else { usleep(100000); /* ms = 1000 us! */ } } } *fd = sock; } return 0; } /* open all requested tcp connections * this includes allocating the connection array */ int openConnections(void) { int i; char msgBuf[128]; size_t lenMsg; if(transport == TP_UDP) return setupUDP(); if(bShowProgress) if(write(1, " open connections", sizeof(" open connections")-1)){} # if defined(ENABLE_OPENSSL) sslArray = calloc(numConnections, sizeof(SSL *)); # elif defined(ENABLE_GNUTLS) sessArray = calloc(numConnections, sizeof(gnutls_session_t)); # endif sockArray = calloc(numConnections, sizeof(int)); # if defined(ENABLE_OPENSSL) // 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 for(i = 0 ; i < numConnections ; ++i) { if(i % 10 == 0) { if(bShowProgress) printf("\r%5.5d", i); } if(openConn(&(sockArray[i]), i) != 0) { printf("error in trying to open connection i=%d\n", i); if(softLimitConnections) { printf("Connection limit is soft, continuing with fewer connections\n"); numConnections = i - 1; int close_conn = 10; for(i -= 1 ; close_conn > 0 && i > 1 ; --i, --close_conn) { printf("closing connection %d to make some room\n", i); /* close at least some connections so that * other functionality has a chance to do * at least something. */ if(transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) { #ifdef ENABLE_RELP CHKRELP(relpEngineCltDestruct(pRelpEngine, relpCltArray+i)); #endif } else { /* TCP and TLS modes */ if(transport == TP_TLS) closeTLSSess(i); close(sockArray[i]); } sockArray[i] = -1; } numConnections = i; printf("continuing with %d connections.\n", numConnections); if(numConnections < 1) { fprintf(stderr, "tcpflood could not open at least one " "connection, error-terminating\n"); exit(1); } break; } return 1; } if(transport == TP_TLS) { initTLSSess(i); } } if(bShowProgress) { lenMsg = sprintf(msgBuf, "\r%5.5d open connections\n", i); if(write(1, msgBuf, lenMsg)) {} } 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_OPENSSL) 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 = sprintf(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 = sprintf(msgBuf, "\r%5.5d close connections\n", i); if(write(1, msgBuf, lenMsg)){} } } /* 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 */ 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.8d\"] %s{\"msgnum\":%d}%c", msgPRI, msgNum, jsonCookie, msgNum, frameDelim); } else { *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 172.20.245.8 tag %s{\"msgnum\":%d}%c", msgPRI, jsonCookie, msgNum, 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.8d\"] msgnum:%s%8.8d:%c", msgPRI, msgNum, dynFileIDBuf, msgNum, frameDelim); } else { *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 172.20.245.8 tag " "msgnum:%s%8.8d:%c", msgPRI, dynFileIDBuf, msgNum, 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.8d\"] msgnum:%s%8.8d:%c", msgPRI, msgNum, dynFileIDBuf, msgNum, frameDelim); } else { *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 172.20.245.8 tag msgnum" ":%s%8.8d:%d:%s%c", msgPRI, dynFileIDBuf, msgNum, edLen, extraData, frameDelim); } } } else { /* use fixed message format from command line */ *pLenBuf = snprintf(buf, maxBuf, "%s%c", MsgToSend, frameDelim); } if (octateCountFramed == 1) { snprintf(payloadLen, sizeof(payloadLen), "%zd ", *pLenBuf); payloadStringLen = strlen(payloadLen); memmove(buf + payloadStringLen, buf, *pLenBuf); memcpy(buf, payloadLen, payloadStringLen); *pLenBuf += 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(&(sockArray[socknum]), 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(&(sockArray[socknum]), socknum) != 0) { printf("error in trying to re-open connection %d\n", socknum); exit(1); } initTLSSess(socknum); } 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_OPENSSL) } 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(&(sockArray[socknum]), 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\n", sockArray[socknum], i, inst->numSent); } 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 1 if(transport == TP_TLS && offsSendBuf != 0) { /* send remaining buffer */ lenSend = sendTLS(socknum, sendBuf, offsSendBuf); if(lenSend != offsSendBuf) { fprintf(stderr, "tcpflood: error in send function causes potential " "data loss lenSend %zd, offsSendBuf %d\n", lenSend, offsSendBuf); } offsSendBuf = 0; } #endif ++nConnDrops; close(sockArray[socknum]); sockArray[socknum] = -1; } } if(inst->numSent % batchsize == 0) { usleep(waittime); } ++msgNum; ++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) { 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() { int i; long long msgsThrd; long long starting = 0; 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() { 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 void waitGenerators() { int i; for(i = 0 ; i < numThrds ; ++i) { pthread_join(instarray[i].thread, NULL); /*printf("thread %x stopped\n", (unsigned) instarray[i].thread);*/ } pthread_mutex_destroy(&thrdMgmt); pthread_cond_destroy(&condStarted); pthread_cond_destroy(&condDoRun); } /* 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(); waitGenerators(); 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_OPENSSL) /* OpenSSL implementation of TLS funtions. * alorbach, 2018-06-11 */ long BIO_debug_callback(BIO *bio, int cmd, const char __attribute__((unused)) *argp, int argi, long __attribute__((unused)) argl, long ret) { 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 %ld\n", ret); break; case BIO_CB_RETURN | BIO_CB_WRITE: printf("write return %ld\n", ret); break; case BIO_CB_RETURN | BIO_CB_GETS: printf("gets return %ld\n", ret); break; case BIO_CB_RETURN | BIO_CB_PUTS: printf("puts return %ld\n", ret); break; case BIO_CB_RETURN | BIO_CB_CTRL: printf("ctrl return %ld\n", ret); break; default: printf("bio callback - unknown type (%d)\n", cmd); break; } return (r); } 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) { #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 printf("tcpflood: error openSSL initialization failed!\n"); exit(1); } /* Load readable error strings */ SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); ERR_load_BIO_strings(); ERR_load_crypto_strings(); // Create OpenSSL Context ctx = SSL_CTX_new(method); 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); } SSL_CTX_set_ecdh_auto(ctx, 1); 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) 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); ENGINE_cleanup(); 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(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! */ bio_client = BIO_new_socket(sockArray[i], BIO_CLOSE /*BIO_NOCLOSE*/); 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) { /* Set debug Callback for client BIO as well! */ BIO_set_callback(bio_client, BIO_debug_callback); } /* Blocking socket */ BIO_set_nbio( bio_client, 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) { osslLastSSLErrorMsg(res, sslArray[i], "initTLSSess3"); exit(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) { 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]); } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" static void initDTLSSess() { 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) { /* Set debug Callback for client BIO as well! */ BIO_set_callback(bio_client, BIO_debug_callback); } /* 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); int 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() { 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"); } # 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) { } /* 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); } } } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" static void initTLSSess(int i) { int r; gnutls_init(sessArray + i, GNUTLS_CLIENT); /* Use default priorities */ gnutls_set_default_priority(sessArray[i]); /* 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]); /* Perform the TLS handshake */ r = gnutls_handshake(sessArray[i]); 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) { gnutls_bye(sessArray[i], GNUTLS_SHUT_RDWR); gnutls_deinit(sessArray[i]); } # 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(char *buf, size_t lenBuf) {} 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 = strtok_r(ports, ":", &saveptr); while(port != NULL) { if(i == sizeof(targetPort)/sizeof(int)) { fprintf(stderr, "too many ports specified, max %d\n", (int) (sizeof(targetPort)/sizeof(int))); exit(1); } targetPort[i] = atoi(port); i++; port = strtok_r(NULL, ":", &saveptr); } free(ports); } /* Run the test. * rgerhards, 2009-04-03 */ int main(int argc, char *argv[]) { int ret = 0; int opt; struct sigaction sigAct; struct rlimit maxFiles; static char buf[1024]; 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:i:I:j:k:l:L:m:M:n:OP:p:rR:sS:t:T:u:vW:x:XyYz:Z:")) != -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 '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 'F': frameDelim = atoi(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_OPENSSL) 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_OPENSSL) 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': octateCountFramed = 1; break; case 'v': verbose = 1; break; case 'k': customConfig = optarg; 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(tlsCAFile != NULL && transport != TP_RELP_TLS) { #if !defined(ENABLE_OPENSSL) 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_OPENSSL) # 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_OPENSSL) initTLS(DTLS_client_method()); #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(runTests() != 0) { printf("error running tests\n"); exit(1); } 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(); } exit(ret); } rsyslog-8.2412.0/tests/sndrcv_tls_ossl_servercert_gtls_clientanon.sh0000775000175000017500000000353114650736301021575 #!/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 export PORT_RCVR="$(get_free_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/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="'$PORT_RCVR'" ) $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" generate_conf 2 export TCPFLOOD_PORT="$(get_free_port)" 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.2412.0/tests/mmpstrucdata-invalid-vg.sh0000775000175000017500000000311414650736301015404 #!/bin/bash # the goal here is to detect memleaks when structured data is not # correctly parsed. # 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" 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!\"" shutdown_when_empty wait_shutdown exit_test rsyslog-8.2412.0/tests/fac_authpriv.sh0000775000175000017500000000121614650736301013316 #!/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" 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.2412.0/tests/syslog_caller.c0000664000175000017500000000670214650736301013317 /* A testing tool that just emits a number of * messages to the system log socket. * * Options * * -s severity (0..7 accoding 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 * * 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 #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 num-messages\n"); exit(1); } #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: sprintf(buf, "test message nbr %d, severity=%d", iRun, sev); break; case FMT_SYSLOG_INJECT_L: sprintf(buf, "test\n"); break; case FMT_SYSLOG_INJECT_C: sprintf(buf, "test 1\t2"); break; } } #endif int main(int argc, char *argv[]) { int i; int opt; int bRollingSev = 0; int sev = 6; int msgs = 500; #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:")) != -1) { #else while((opt = getopt(argc, argv, "m:s:")) != -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; #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(); #ifdef HAVE_LIBLOGGING_STDLOG exit(1); #endif break; } } #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.2412.0/tests/dynstats_ctr_reset.sh0000775000175000017500000000476314650736301014600 #!/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.2412.0/tests/rscript_int2Hex.sh0000775000175000017500000000142314650736301013732 #!/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" 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.2412.0/tests/sndrcv_omudpspoof-bigmsg.sh0000775000175000017500000003420014650736301015662 #!/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="$(get_free_port)" add_conf ' module(load="../plugins/imudp/.libs/imudp") global ( maxMessageSize="64k" ) input(type="imudp" port="'$PORT_UDP'" ruleset="rsImudp") $template outfmt,"%msg%\n" ruleset(name="rsImudp") { action( name="UDPOUT" type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup 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.2412.0/tests/failover-no-basic-vg.sh0000775000175000017500000000160714650736301014561 #!/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.2412.0/tests/queue-encryption-disk_keyfile-vg.sh0000775000175000017500000000207614650736301017236 #!/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.2412.0/tests/imfile-symlink.sh0000775000175000017500000000501514650736301013575 #!/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.2412.0/tests/json_var_case.sh0000775000175000017500000000273114650736301013462 #!/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" 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.2412.0/tests/imfile-rename.sh0000775000175000017500000000414314650736301013357 #!/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 let 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.2412.0/tests/omhttp-batch-retry-metadata.sh0000775000175000017500000000421314650736301016156 #!/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 port="$(get_free_port)" omhttp_start_server $port --fail-every 100 --fail-with 207 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 omhttp_validate_metadata_response exit_test rsyslog-8.2412.0/tests/imtcp-tls-ossl-x509valid.sh0000775000175000017500000000223714656663250015274 #!/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" 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.2412.0/tests/rscript_unflatten_arg1_unsuitable-vg.sh0000775000175000017500000000013714650736301020171 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/rscript_unflatten_arg1_unsuitable.sh rsyslog-8.2412.0/tests/imhiredis-stream-consumerGroup-noack-vg.sh0000775000175000017500000000032514650736301020462 #!/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" source ${srcdir:=.}/imhiredis-stream-consumerGroup-noack.sh rsyslog-8.2412.0/tests/rscript_script_error.sh0000775000175000017500000000173214650736301015131 #!/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" 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.2412.0/tests/suspend-omfwd-via-file.sh0000775000175000017500000000306714650736301015136 #!/bin/bash # This tests the action suspension via a file # 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") } ' ./minitcpsrv -t127.0.0.1 -p$TCPFLOOD_PORT -f $RSYSLOG_OUT_LOG & BGPROCESS=$! echo background minitcpsrv process id is $BGPROCESS 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.2412.0/tests/mainq_actq_DA.sh0000775000175000017500000000145314650736301013327 #!/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.2412.0/tests/sndrcv_omsnmpv1_udp.sh0000775000175000017500000000220014650736301014644 #!/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 export PORT_SNMP="$(get_free_port)" # 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.2412.0/tests/imptcp_maxsessions.sh0000775000175000017500000000250714650736301014577 #!/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' wait_too_many_sessions() { test "$(grep "$EXPECTED_STR" "$RSYSLOG_OUT_LOG" | wc -l)" = "$EXPECTED_DROPS" } export QUEUE_EMPTY_CHECK_FUNC=wait_too_many_sessions generate_conf add_conf ' $MaxMessageSize 10k module(load="../plugins/imptcp/.libs/imptcp" maxsessions="'$MAXSESSIONS'") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) $template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n" $OMFileFlushInterval 2 $OMFileIOBufferSize 256k ' startup echo "INFO: RSYSLOG_OUT_LOG: $RSYSLOG_OUT_LOG" echo "About to run tcpflood" tcpflood -c$CONNECTIONS -m$NUMMESSAGES -r -d100 -P129 -A echo "-------> NOTE: CLOSED REMOTELY messages are expected and OK! <-------" echo "done run tcpflood" shutdown_when_empty wait_shutdown content_count_check "$EXPECTED_STR" $EXPECTED_DROPS echo "Got expected drops: $EXPECTED_DROPS, looks good!" exit_test rsyslog-8.2412.0/tests/diskqueue-fail.sh0000775000175000017500000000151214650736301013552 #!/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" 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.2412.0/tests/rscript_compare_numstr-str-vg.sh0000775000175000017500000000020514650736301016664 #!/bin/bash export USE_VALGRIND="YES" export LOWER_VAL='"1"' export HIGHER_VAL='"abc"' source ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2412.0/tests/parsertest-parse-3164-buggyday.sh0000775000175000017500000000216214650736301016354 #!/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" 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.2412.0/tests/diskqueue-multithread-es.sh0000775000175000017500000000407314720125021015560 #!/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 export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz . ${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" 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.2412.0/tests/imfile-endmsg.regex.crio.rulebase0000664000175000017500000000116414650736301016616 version=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.2412.0/tests/allowed-sender-tcp-hostname-ok.sh0000775000175000017500000000136114650736301016560 #!/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" 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.2412.0/tests/cfg4.testin0000664000175000017500000000216014650736301012356 # 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.2412.0/tests/imrelp-tls-cfgcmd.sh0000775000175000017500000000362314650736301014160 #!/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_testrsyslog-8.2412.0/tests/template-json.sh0000775000175000017500000000153314650736301013427 #!/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.2412.0/tests/3.rstest0000664000175000017500000000071014522461111011702 # 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.2412.0/tests/privdropabortonidfail.sh0000775000175000017500000000207714650736301015254 #!/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.2412.0/tests/omkafka.sh0000775000175000017500000000703614704407366012270 #!/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 test_status unreliable 'https://github.com/rsyslog/rsyslog/issues/3197' check_command_available kafkacat export KEEP_KAFKA_RUNNING="YES" export TESTMESSAGES=100000 export TESTMESSAGESFULL=$TESTMESSAGES export RANDTOPIC=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 8 | head -n 1) # 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") $imdiagInjectDelayMode full 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="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" 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 kafkacat receives everything timeoutend=100 timecounter=0 while [ $timecounter -lt $timeoutend ]; do (( timecounter++ )) kafkacat -b localhost: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 [ "x$timecounter" == "x$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 #kafkacat -b localhost:29092 -e -C -o beginning -t $RANDTOPIC -f '%s' > $RSYSLOG_OUT_LOG #kafkacat -b localhost: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.2412.0/tests/imtcp-tls-ossl-basic-brokenhandshake-vg.sh0000775000175000017500000000270014656663250020362 #!/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" 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.2412.0/tests/imptcp_veryLargeOctateCountedMessages.sh0000775000175000017500000000157614650736301020342 #!/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 export NUMMESSAGES=20000 generate_conf add_conf '$MaxMessageSize 10k 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.2412.0/tests/proprepltest-nolimittag.sh0000775000175000017500000000211314650736301015550 #!/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" 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.2412.0/tests/imdtls-sessionbreak.sh0000775000175000017500000000373314650736301014633 #!/bin/bash # added 2020-04-10 by alorbach, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 export USE_VALGRIND="yes" # TODO remote leak check skip and fix memory leaks caused by session break export RS_TESTBENCH_LEAK_CHECK=no export PORT_RCVR="$(get_free_port)" 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 # How many tcpfloods we run at the same tiem for ((i=1;i<=10;i++)); do # How many times tcpflood runs in each threads ./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; 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.2412.0/tests/rscript_compare-common.sh0000775000175000017500000000300614650736301015324 #!/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.2412.0/tests/omhttp-batch-lokirest-retry.sh0000775000175000017500000000320014650736301016225 #!/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.2412.0/tests/imptcp_conndrop.sh0000775000175000017500000000165714650736301014052 #!/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.2412.0/tests/inputfilegen.c0000664000175000017500000001330214650736301013140 /* 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() { 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.2412.0/tests/include-obj-text-from-file-noexist.sh0000775000175000017500000000063514650736301017371 #!/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.2412.0/tests/omfwd-lb-1target-retry-test_skeleton-TargetFail.sh0000775000175000017500000000265114715123246021767 #!/bin/bash # added 2024-02-19 by rgerhards. Released under ASL 2.0 # This test is not meant to be executed independetly. 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 # starting minitcpsrvr receivers so that we can obtain their port # numbers 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 injectmsg shutdown_when_empty wait_shutdown # note: minitcpsrv shuts down automatically if the connection is closed! export SEQ_CHECK_OPTIONS=-d #permit 100 messages to be lost in this extreme test (-m 100) seq_check 0 $((NUMMESSAGES-1)) -m100 exit_test rsyslog-8.2412.0/tests/rscript_optimizer1.sh0000775000175000017500000000136514650736301014521 #!/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.2412.0/tests/mmnormalize_processing_test3.sh0000775000175000017500000000640614650736301016561 #!/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" 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=`echo $srcdir/testsuites/mmnormalize_processing_tests.rulebase` useRawMsg="on") if ($!v_file == "") then { set $!v_file=$!v_tag; } action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="t_file_record") action(type="omfile" File=`echo $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=`echo $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.2412.0/tests/stop-msgvar.sh0000775000175000017500000000165014650736301013127 #!/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" 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.2412.0/tests/rscript_le_var.sh0000775000175000017500000000330714650736301013664 #!/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.2412.0/tests/asynwr_tinybuf.sh0000775000175000017500000000260014650736301013724 #!/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" 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.2412.0/tests/sparse_array_lookup_table-vg.sh0000775000175000017500000000027714650736301016516 #!/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" source ${srcdir:-.}/sparse_array_lookup_table.sh rsyslog-8.2412.0/tests/imtcp-tls-basic-vg.sh0000775000175000017500000000011514650736301014245 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/imtcp-tls-basic.sh rsyslog-8.2412.0/tests/sndrcv_tls_ossl_servercert_ossl_clientanon.sh0000775000175000017500000000353114650736301021604 #!/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 export PORT_RCVR="$(get_free_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/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="'$PORT_RCVR'" ) $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" generate_conf 2 export TCPFLOOD_PORT="$(get_free_port)" 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.2412.0/tests/imhttp-post-payload-vg.sh0000775000175000017500000000023714650736301015176 #!/bin/bash export USE_VALGRIND="YES" #export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all" source ${srcdir:-.}/imhttp-post-payload.sh rsyslog-8.2412.0/tests/arrayqueue.sh0000775000175000017500000000107014650736301013024 #!/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.2412.0/tests/omod-if-array.sh0000775000175000017500000000160014650736301013306 #!/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" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") template(name="outfmt" type="string" string="%PRI%%timestamp%%hostname%%programname%%syslogtag%\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: UDP request discarded from SERVER1/2741 to test_app:255.255.255.255/61601\"" shutdown_when_empty wait_shutdown echo '167Mar 6 16:57:54172.20.245.8%PIX-7-710005%PIX-7-710005:' | 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.2412.0/tests/rscript_hash32-vg.sh0000775000175000017500000000176714650736301014126 #!/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" 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.2412.0/tests/rscript_compare_num-str-vg.sh0000775000175000017500000000020114650736301016127 #!/bin/bash export USE_VALGRIND="YES" export LOWER_VAL='1' export HIGHER_VAL='"b"' source ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2412.0/tests/es-basic-bulk-vg.sh0000775000175000017500000000011314650736301013671 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/es-basic-bulk.sh rsyslog-8.2412.0/tests/stats-json-es.sh0000775000175000017500000000234414650736301013360 #!/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, "failed": 0, "suspended": 0, "suspended!duration": 0, "resumed": 0 }' "${RSYSLOG_DYNNAME}.out.stats.log" custom_assert_content_missing '@cee' "${RSYSLOG_DYNNAME}.out.stats.log" exit_test rsyslog-8.2412.0/tests/allowed-sender-tcp-hostname-fail.sh0000775000175000017500000000243314650736301017063 #!/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" 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 -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.2412.0/tests/sndrcv_dtls_anon_ciphers.sh0000775000175000017500000000337714656663250015742 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${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 export PORT_RCVR="$(get_free_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="'$PORT_RCVR'") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup 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.2412.0/tests/imuxsock_ccmiddle.sh0000775000175000017500000000151614650736301014334 #!/bin/bash # test trailing LF handling in 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 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.2412.0/tests/rulesetmultiqueue.sh0000775000175000017500000000533214650736301014451 #!/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.2412.0/tests/rscript_bare_var_root-empty.sh0000775000175000017500000000133114650736301016367 #!/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" 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.2412.0/tests/imhttp-post-payload-query-params-vg.sh0000775000175000017500000000025514650736301017622 #!/bin/bash export USE_VALGRIND="YES" #export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all" source ${srcdir:-.}/imhttp-post-payload-query-params.sh* rsyslog-8.2412.0/tests/imfile-growing-file-id.sh0000775000175000017500000000505514650736301015076 #!/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.2412.0/tests/template-topos-neg.sh0000775000175000017500000000107214650736301014367 #!/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.2412.0/tests/omfile_hup.sh0000775000175000017500000000156714650736301013003 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Written 2019-06-21 by Rainer Gerhards . ${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" 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 ./tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES & # TCPFlood needs to run async! BGPROCESS=$! for i in $(seq 1 20); do printf '\nsending HUP %d\n' $i issue_HUP --sleep 100 done wait $BGPROCESS shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2412.0/tests/config_enabled-off.sh0000775000175000017500000000111214650736301014325 #!/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.2412.0/tests/imfile-wildcards.sh0000775000175000017500000000664414650736301014074 #!/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.2412.0/tests/pgsql-template-cnf6-vg.sh0000775000175000017500000000177714650736301015062 #!/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.2412.0/tests/pmsnare-cccstyle-udp.sh0000775000175000017500000001353714650736301014716 #!/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.2412.0/tests/lookup_table_rscript_reload_without_stub-vg.sh0000775000175000017500000000031614650736301021651 #!/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" source ${srcdir:-.}/lookup_table_rscript_reload_without_stub.sh rsyslog-8.2412.0/tests/imfile-endregex-timeout-none.sh0000775000175000017500000000317414650736301016335 #!/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.2412.0/tests/imuxsock_traillf.sh0000775000175000017500000000137414650736301014227 #!/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=`echo $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.2412.0/tests/imrelp-maxDataSize-error.sh0000775000175000017500000000126414650736301015475 #!/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.2412.0/tests/imtcp-tls-gtls-x509fingerprint-invld.sh0000775000175000017500000000217614656663250017631 #!/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" 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.2412.0/tests/rscript_ne_var.sh0000775000175000017500000000260614650736301013667 #!/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=`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.2412.0/tests/rfc5424parser.sh0000775000175000017500000000133114650736301013147 #!/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" 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.2412.0/tests/omprog-defaults-vg.sh0000775000175000017500000000131614650736301014366 #!/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.2412.0/tests/glbl-internalmsg_severity-debug-not_shown.sh0000775000175000017500000000111214650736301021131 #!/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.2412.0/tests/failover-double.sh0000775000175000017500000000101414650736301013716 #!/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.2412.0/tests/rscript_ruleset_call.sh0000775000175000017500000000170014650736301015065 #!/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.2412.0/tests/mmanon_random_cons_128_ipv6.sh0000775000175000017500000000610014650736301016045 #!/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.2412.0/tests/es-bulk-errfile-popul-erronly.sh0000775000175000017500000000267214720125021016454 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz 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" searchType="test-type" 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 if [ $? -ne 0 ] then echo "error: Format for error file different! " $? error_exit 1 fi exit_test rsyslog-8.2412.0/tests/func-substring-relative-endpos.sh0000775000175000017500000000103514650736301016712 #!/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.2412.0/tests/func-substring-invld-startpos-vg.sh0000775000175000017500000000013314650736301017212 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/func-substring-invld-startpos.sh rsyslog-8.2412.0/tests/glbl-ruleset-queue-defaults.sh0000775000175000017500000000127014650736301016173 #!/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.2412.0/tests/sndrcv_relp_rebind.sh0000775000175000017500000000305114650736301014506 #!/bin/bash # added 2017-09-29 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${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 export PORT_RCVR="$(get_free_port)" add_conf ' module(load="../plugins/imrelp/.libs/imrelp") # then SENDER sends to this port (not tcpflood!) input(type="imrelp" port="'$PORT_RCVR'") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 export TCPFLOOD_PORT="$(get_free_port)" # TODO: move to diag.sh 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.2412.0/tests/privdropuserid.sh0000775000175000017500000000111214650736301013717 #!/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.2412.0/tests/rscript_field.sh0000775000175000017500000000126014650736301013473 #!/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.2412.0/tests/timestamp-3164.sh0000775000175000017500000000313214650736301013240 #!/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.2412.0/tests/imuxsock_logger.sh0000775000175000017500000000107714650736301014051 #!/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=`echo $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.2412.0/tests/lookup_table_rscript_reload_without_stub.sh0000775000175000017500000000323014650736301021235 #!/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.2412.0/tests/rscript_ipv42num.sh0000775000175000017500000000343414650736301014101 #!/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" 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.2412.0/tests/internal-errmsg-memleak-vg.sh0000775000175000017500000000245414650736301016004 #!/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.2412.0/tests/imdtls-sessionbreak-vg.sh0000775000175000017500000000054014650736301015236 #!/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" source ${srcdir:-.}/imdtls-sessionbreak.sh rsyslog-8.2412.0/tests/omudpspoof_errmsg_no_params.sh0000775000175000017500000000056314650736301016460 #!/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.2412.0/tests/omfile-whitespace-filename.sh0000775000175000017500000000070314650736301016026 #!/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.2412.0/tests/clickhouse-start.sh0000775000175000017500000000166714650736301014141 #!/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.2412.0/tests/imbatchreport_rename_success.sh0000775000175000017500000000572514650736301016576 #!/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.2412.0/tests/imhttp-post-payload-compress-vg.sh0000775000175000017500000000025014650736301017022 #!/bin/bash export USE_VALGRIND="YES" #export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all" source ${srcdir:-.}/imhttp-post-payload-compress.sh rsyslog-8.2412.0/tests/omrabbitmq_error_server3.sh0000775000175000017500000000313714650736301015666 #!/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 172.20.245.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:172.20.245.8, fromhost:127.0.0.1, delivery-mode:transient, expiration:5000, timestamp:OK, app-id:tag, msg:<167>Mar 1 01:00:00 172.20.245.8 tag msgrmq' cmp_exact $RSYSLOG_DYNNAME.amqp.log content_check "Connection closed : reconnect" exit_test rsyslog-8.2412.0/tests/omfile_both_files_set.sh0000775000175000017500000000232114650736301015165 #!/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" 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.2412.0/tests/rscript_parse_json-vg.sh0000775000175000017500000000115314650736301015166 #!/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" 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.2412.0/tests/omhttp-validate-response.py0000664000175000017500000000260714650736301015621 import json import argparse from collections import defaultdict if __name__ == '__main__': parser = argparse.ArgumentParser(description='Archive and delete core app log files') parser.add_argument('--error', action='store', type=str, help='error') parser.add_argument('--response', action='store', type=str, help='response') args = parser.parse_args() messages = defaultdict(dict) with open(args.error, "r") as error_f, open(args.response, "r") as response_f: for line in error_f: json_obj = json.loads(line) # postdata contains a json string of records array records = json.loads(json_obj['request']['postdata']) if records: for i, val in enumerate(records['records']): messages[val['value']['msgnum']]['response'] = json_obj['response'] messages[val['value']['msgnum']]['index'] = i #print (len(messages), "messages:", messages) # validate with responses for line in response_f: json_obj = json.loads(line) msgnum = json_obj['message']['msgnum'] code = json_obj['response']['code'] body = json_obj['response']['body'] batch_index = json_obj['response']['batch_index'] #print('msgnum:', msgnum, 'code:', code, 'body:', body, 'batch_index:', batch_index) assert(msgnum in messages) assert(messages[msgnum]['response']['status'] == code) assert(messages[msgnum]['response']['message'] == body) assert(messages[msgnum]['index'] == batch_index) rsyslog-8.2412.0/tests/imtcp-msg-truncation-on-number2.sh0000775000175000017500000000320714650736301016713 #!/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" 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.2412.0/tests/es-bulk-errfile-popul-def-interleaved.sh0000775000175000017500000000267214720125021020020 #!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export ES_DOWNLOAD=elasticsearch-6.0.0.tar.gz 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" searchType="test-type" 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 if [ $? -ne 0 ] then echo "error: Format for error file different! " $? exit 1 fi exit_test rsyslog-8.2412.0/tests/imfile-readmode2-with-persists-data-during-stop.sh0000775000175000017500000000474214650736301021762 #!/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.2412.0/tests/rscript_ge_var.sh0000775000175000017500000000330714650736301013657 #!/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=`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.2412.0/tests/omprog-single-instance.sh0000775000175000017500000000364014650736301015232 #!/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.2412.0/tests/pgsql-template-vg.sh0000775000175000017500000000151214650736301014213 #!/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.2412.0/tests/clickhouse-load-vg.sh0000775000175000017500000000011514650736301014320 #!/bin/bash export USE_VALGRIND="YES" source ${srcdir:-.}/clickhouse-load.sh rsyslog-8.2412.0/tests/es-basic-vgthread.sh0000775000175000017500000000140014650736301014126 #!/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.2412.0/tests/elasticsearch-error-format-check.py0000664000175000017500000001064414650736301017165 import 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: