pax_global_header00006660000000000000000000000064132117102530014505gustar00rootroot0000000000000052 comment=c6fafc559791b0a4984ef750f1c68271c3cb9a12 syslog-ng-syslog-ng-3.13.2/000077500000000000000000000000001321171025300154355ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/.astylerc000066400000000000000000000011661321171025300172700ustar00rootroot00000000000000# GNU style --style=gnu # convert tabs into spaces --convert-tabs # lines indented using 2 spaces --indent=spaces=2 # max line lenght is 120 chars --max-code-length=120 --max-instatement-indent=60 # pointer is aligned to the name of the variable --align-pointer=name # check files recursively in folder --recursive # do not create backups of formatted files --suffix=none # exclude folders && files # on Travis these submodules are not checked out when cheking the style --ignore-exclude-errors --exclude="lib/ivykis" --exclude="lib/jsonc" --exclude="modules/afamqp/rabbitmq-c" --exclude="modules/afmongodb/mongo-c-driver" syslog-ng-syslog-ng-3.13.2/.gitignore000066400000000000000000000010151321171025300174220ustar00rootroot00000000000000{arch} .arch-ids .arch-inventory .gitcommit.txt autom4te.cache *~ Makefile.in aclocal.m4 config.h.in configure configure.gnu depcomp install-sh missing mkinstalldirs cscope.out ._* config.guess config.sub config.cache stamp-h.in stamp-h ylwrap .*.swp *.pyc ltmain.sh .project .cproject .settings Debug m4/libtool.m4 m4/lt~obsolete.m4 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 m4/pkg.m4 m4/ax*.m4 /compile .deps /lib/cfg-grammar.h /test-driver dbld/build/ dbld/release/ debian/build-tree/ debian/*.log debian/autoreconf.* syslog-ng-syslog-ng-3.13.2/.gitmodules000066400000000000000000000011451321171025300176130ustar00rootroot00000000000000[submodule "lib/ivykis"] path = lib/ivykis url = https://github.com/buytenh/ivykis.git ignore = dirty [submodule "lib/jsonc"] path = lib/jsonc url = https://github.com/json-c/json-c.git ignore = dirty [submodule "modules/afamqp/rabbitmq-c"] path = modules/afamqp/rabbitmq-c url = https://github.com/alanxz/rabbitmq-c.git ignore = dirty [submodule "modules/afmongodb/mongo-c-driver"] path = modules/afmongodb/mongo-c-driver url = https://github.com/mongodb/mongo-c-driver.git branch = 1.2.0-dev ignore = dirty syslog-ng-syslog-ng-3.13.2/.travis.yml000066400000000000000000000124071321171025300175520ustar00rootroot00000000000000language: c git: submodules: false env: B=autotools os: linux cache: apt: true install: - curl -4 http://download.opensuse.org/repositories/home:/laszlo_budai:/syslog-ng/xUbuntu_12.04/Release.key | sudo apt-key add - - echo "deb http://download.opensuse.org/repositories/home:/laszlo_budai:/syslog-ng/xUbuntu_12.04 ./" | sudo tee --append /etc/apt/sources.list.d/syslog-ng-obs.list - sudo apt-get update -qq - sudo apt-get install -qq autoconf-archive bison docbook-xsl flex gradle-2.2.1 libcap-dev libdbd-sqlite3 libdbi0-dev libesmtp-dev libevtlog-dev libgeoip-dev libglib2.0-dev libhiredis-dev libivykis-dev libjson0-dev libnet1-dev libriemann-client-dev libwrap0-dev pkg-config sqlite3 xsltproc criterion-dev libmaxminddb-dev libxml2-utils - sudo pip install -r requirements.txt before_script: - echo 'Europe/Budapest' | sudo tee /etc/timezone - sudo dpkg-reconfigure --frontend noninteractive tzdata - ./autogen.sh - unset PYTHON_CFLAGS # HACK - CONFIGURE_FLAGS=" CFLAGS=-Werror --prefix=$HOME/install/syslog-ng --with-ivykis=internal --with-mongoc=internal --with-librabbitmq=internal --with-jsonc=system --disable-env-wrapper --disable-memtrace --enable-tcp-wrapper --enable-linux-caps --disable-sun-streams --enable-all-modules --disable-sql --enable-pacct --enable-manpages --with-python=2 --with-docbook=/usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl --enable-extra-warnings " - if [ "$CC" = "clang" ]; then CONFIGURE_FLAGS="$CONFIGURE_FLAGS --disable-mongodb" ; fi - ./configure $CONFIGURE_FLAGS script: - . tests/build-log-cflags-propagation.sh; if [ "$CC" = "gcc" ]; then export DISTCHECK_CONFIGURE_FLAGS="$CONFIGURE_FLAGS"; exec_prop_check "make distcheck -j 3 V=1 --keep-going" || { S=$?; make V=1 distcheck; find . -name test-suite.log | xargs cat; return $S; }; else make --keep-going -j 3; S=$?; if [ "$S" = "0" ]; then make install . scripts/get-libjvm-path.sh || return $?; export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$JNI_LIBDIR"; make func-test V=1; elif [ "$S" = "42" ]; then return $S; else make V=1 install; return $S; fi; fi compiler: - gcc - clang matrix: fast_finish: true allow_failures: - os: osx include: - env: B=style-check dist: trusty sudo: required install: - curl -4 http://download.opensuse.org/repositories/home:/laszlo_budai:/syslog-ng/xUbuntu_14.04/Release.key | sudo apt-key add - - echo "deb http://download.opensuse.org/repositories/home:/laszlo_budai:/syslog-ng/xUbuntu_14.04 ./" | sudo tee --append /etc/apt/sources.list.d/syslog-ng-obs.list - sudo apt-get update -qq - sudo apt-get install -qq astyle before_script: script: - scripts/style-checker.sh format - git diff --exit-code - env: B=copyright-check sudo: false compiler: gcc install: before_script: script: - export COPYRIGHTVERBOSITY=1 - tests/copyright/check.sh . . - env: B=trusty-cmake compiler: clang dist: trusty sudo: required before_script: script: - mkdir build - cd build - cmake -DCMAKE_C_FLAGS=-Werror -DCMAKE_INSTALL_PREFIX=$HOME/install/syslog-ng .. - make --keep-going -j 3 install || { S=$?; make V=1 install; return $S; } - env: B=check os: osx osx_image: xcode8 compiler: clang install: - brew update - brew install autoconf-archive binutils bison eventlog geoip geoipupdate glib gradle hiredis libdbi libnet riemann-client - geoipupdate - pip install -r requirements.txt - export PATH=/usr/local/opt/bison/bin:/usr/local/opt/libnet/bin:$PATH - export PKG_CONFIG_PATH=/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH before_script: - ./autogen.sh - ./configure --disable-sun-streams --disable-systemd --disable-pacct --enable-all-modules --disable-smtp - make --keep-going -j 3 || { S=$?; make V=1; return $S; } script: - make --keep-going check || { S=$?; make V=1 check; find . -name test-suite.log | xargs cat; return $S; } branches: except: - /wip/ notifications: irc: channels: - "irc.freenode.org#balabit" webhooks: urls: - https://webhooks.gitter.im/e/1c6e3a6f10348748585a on_success: always # options: [always|never|change] default: always on_failure: always # options: [always|never|change] default: always on_start: true # default: false syslog-ng-syslog-ng-3.13.2/AUTHORS000066400000000000000000000022011321171025300165000ustar00rootroot00000000000000 syslog-ng was written by Balzs Scheidler Contributions under the contrib/ directory were contributed by a number of different people. Code contributions: ------------------- Anthony Lineham - bugfixes Chris Packham - suppressing duplicate messages Jung Christian - BSDTAG macro Roger J. Meier - initgroups bugfix Corinna Vinschen - cygwin packaging files and portability fixes Charles G. Waldman - file source driver fixes Philip Bellino - IPv6 bugfixes Vijay Ramasubramanian - extending time related macros The Regents of the University of California & Chris Torek - strcasestr() Suggestions, good bugreports, helping newbies on the mailing list: ------------------------------------------------------------------ Evan Rempel Roberto Nibali Nate Campi Sandor Geller Valdis Kletnieks Alexander Clouter Hari Sekhon Dave Johnson Brian A. Seklecki John Morrissey Joe Fegan Joe Shaw and probably a lot more. Please note that this list is only updated from time to time, and my memories may not serve me the best, so it is probably inaccurate. If you miss your name from this list, just let me know :) Balazs Scheidler 2008-11-06 syslog-ng-syslog-ng-3.13.2/CMakeLists.txt000066400000000000000000000155611321171025300202050ustar00rootroot00000000000000cmake_minimum_required (VERSION 2.8.12) # use, i.e. don't skip the full RPATH for the build tree SET(CMAKE_SKIP_BUILD_RPATH FALSE) # when building, don't use the install RPATH already # (but later on when installing) SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") set(CMAKE_MACOSX_RPATH 1) # add the automatically determined parts of the RPATH # which point to directories outside the build tree to the install RPATH SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) project (syslog-ng) set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules) set (CMAKE_POSITION_INDEPENDENT_CODE 1) set (BISON_FLAGS "-Wno-other") add_compile_options("-Wno-initializer-overrides") include (CheckIncludeFiles) set (SYSLOG_NG_VERSION_MAJOR 3) set (SYSLOG_NG_VERSION_MINOR 9) set (SYSLOG_NG_VERSION_PATCH 1) set (SYSLOG_NG_VERSION "${SYSLOG_NG_VERSION_MAJOR}.${SYSLOG_NG_VERSION_MINOR}.${SYSLOG_NG_VERSION_PATCH}") set (SYSLOG_NG_COMBINED_VERSION ${SYSLOG_NG_VERSION}) set (SYSLOG_NG_SOURCE_REVISION ${SYSLOG_NG_VERSION}) set (SYSLOG_NG_PATH_PREFIX ${CMAKE_INSTALL_PREFIX}) set (SYSLOG_NG_PATH_SYSCONFDIR "\${prefix}/etc") set (SYSLOG_NG_PATH_DATADIR "\${datarootdir}") set (SYSLOG_NG_PATH_PIDFILEDIR "\${localstatedir}") set (SYSLOG_NG_PATH_LOCALSTATEDIR "\${prefix}/var") set (SYSLOG_NG_MODULE_PATH "\${exec_prefix}/lib/syslog-ng") set (SYSLOG_NG_PATH_EXECPREFIX "\${prefix}") set (SYSLOG_NG_PATH_CONFIG_INCLUDEDIR "\${datadir}/syslog-ng/include") set (SYSLOG_NG_PATH_SCLDIR "\${datadir}/syslog-ng/include/scl") set (SYSLOG_NG_PATH_LIBEXECDIR "\${exec_prefix}/libexec") set (SYSLOG_NG_PATH_DATAROOTDIR "\${prefix}/share") set (SYSLOG_NG_ENABLE_LINUX_CAPS 0) set (SYSLOG_NG_ENABLE_TCP_WRAPPER 0) set (SYSLOG_NG_ENABLE_GPROF 0) set (SYSLOG_NG_ENABLE_MEMTRACE 0) set (SYSLOG_NG_ENABLE_SYSTEMD 0) set (SYSLOG_NG_PATH_MODULEDIR "\${exec_prefix}/lib/syslog-ng") set (SYSLOG_NG_PACKAGE_NAME "${CMAKE_PROJECT_NAME}") set (SYSLOG_NG_PATH_XSDDIR "\${datadir}/syslog-ng/xsd") set (SYSLOG_NG_JAVA_MODULE_PATH "\${exec_prefix}/lib/syslog-ng/java-modules") set (SYSLOG_NG_PATH_TOPSRC_DIR "${CMAKE_SOURCE_DIR}") set (LIBDIR "\${exec_prefix}/lib") set (INCLUDEDIR "\${prefix}/include") set (TOOLSDIR "\${datadir}/syslog-ng/tools") set (SYSLOG_NG_ENABLE_FORCED_SERVER_MODE 1) IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) set (SYSLOG_NG_ENABLE_DEBUG 1) ELSE() set (SYSLOG_NG_ENABLE_DEBUG 0) ENDIF() # CMake will generate tests only if the enable_testing() command has been invoked. # The CTest module invokes the command automatically when the BUILD_TESTING option is ON. enable_testing() include (CheckTypeSize) include (CheckStructMember) include (CheckSymbolExists) include (GenerateYFromYm) include (CheckStructHasMember) add_definitions(-D_GNU_SOURCE=1) include(CheckSockaddrStorage) if (HAVE_STRUCT_SOCKADDR_STORAGE) set (SYSLOG_NG_HAVE_STRUCT_SOCKADDR_STORAGE 1) else() set (SYSLOG_NG_HAVE_STRUCT_SOCKADDR_STORAGE 0) endif() include(CheckCreds) if (HAVE_STRUCT_UCRED OR HAVE_STRUCT_CMSGCRED) set (SYSLOG_NG_HAVE_STRUCT_UCRED 1) else() set (SYSLOG_NG_HAVE_STRUCT_UCRED 0) endif() include(CheckIPv6) option(ENABLE_IPV6 "Enable IPv6" ON) if (ENABLE_IPV6) set(SYSLOG_NG_ENABLE_IPV6 ${HAVE_IPV6}) endif() check_symbol_exists (strtoll stdlib.h SYSLOG_NG_HAVE_STRTOLL) check_symbol_exists (strtoimax inttypes.h SYSLOG_NG_HAVE_STRTOIMAX) check_symbol_exists (inet_aton "sys/socket.h;netinet/in.h;arpa/inet.h" SYSLOG_NG_HAVE_INET_ATON) check_symbol_exists (getutent utmp.h SYSLOG_NG_HAVE_GETUTENT) check_symbol_exists (getutxent utmpx.h SYSLOG_NG_HAVE_GETUTXENT) check_include_files (utmp.h SYSLOG_NG_HAVE_UTMP_H) check_include_files (utmpx.h SYSLOG_NG_HAVE_UTMPX_H) check_struct_has_member("struct utmpx" "ut_type" "utmpx.h" UTMPX_HAS_UT_TYPE LANGUAGE C) check_struct_has_member("struct utmp" "ut_type" "utmp.h" UTMP_HAS_UT_TYPE LANGUAGE C) check_struct_has_member("struct utmpx" "ut_user" "utmpx.h" UTMPX_HAS_UT_USER LANGUAGE C) check_struct_has_member("struct utmp" "ut_user" "utmp.h" UTMP_HAS_UT_USER LANGUAGE C) if ((UTMPX_HAS_UT_TYPE AND UTMPX_HAS_UT_USER) OR (UTMPX_HAS_UT_TYPE AND UTMP_HAS_UT_USER)) set (SYSLOG_NG_HAVE_MODERN_UTMP 1) endif() set (WITH_GETTEXT "" CACHE STRING "Set the prefix where gettext is installed (e.g. /usr)") find_package(BISON 2.4 REQUIRED) find_package(GLIB 2.10.1 REQUIRED) find_package(Ivykis REQUIRED) find_package(Eventlog REQUIRED) find_package(OpenSSL REQUIRED) find_package(FLEX REQUIRED) find_package(LibNet REQUIRED) find_package(Resolv REQUIRED) find_package(Wrap) pkg_check_modules(LIBPCRE REQUIRED libpcre) if (WRAP_FOUND) set(SYSLOG_NG_ENABLE_TCP_WRAPPER 1) endif() if (LIBNET_FOUND) set(SYSLOG_NG_ENABLE_SPOOF_SOURCE 1) endif() if (WITH_GETTEXT) set (CMAKE_PREFIX_PATH ${WITH_GETTEXT}) find_package(Gettext REQUIRED QUIET) set (CMAKE_PREFIX_PATH "") else() find_package(Gettext REQUIRED QUIET) endif() set(CORE_INCLUDE_DIRS ${Eventlog_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} ${Gettext_INCLUDE_DIR} ${Ivykis_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIRS} ${LIBPCRE_INCLUDE_DIRS} ) set(CORE_LIBRARIES ${BISON_LIBRARIES} ${Eventlog_LIBRARIES} ${FLEX_LIBRARIES} ${GLIB_GMODULE_LIBRARIES} ${GLIB_GTHREAD_LIBRARIES} ${GLIB_LIBRARIES} ${Gettext_LIBRARIES} ${Ivykis_LIBRARIES} ${OPENSSL_LIBRARIES} ${RESOLV_LIBRARIES} ${LIBPCRE_LIBRARIES} ) include_directories(SYSTEM ${CORE_INCLUDE_DIRS}) include_directories (${PROJECT_BINARY_DIR}/lib) include_directories (${PROJECT_BINARY_DIR}) include_directories (${PROJECT_SOURCE_DIR}/lib) include_directories (${PROJECT_SOURCE_DIR}) add_subdirectory(Mk) add_subdirectory(scl) add_subdirectory(lib) add_subdirectory(modules) add_subdirectory(scripts) add_subdirectory(syslog-ng) add_subdirectory(syslog-ng-ctl) configure_file (${CMAKE_CURRENT_SOURCE_DIR}/syslog-ng-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/syslog-ng-config.h) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syslog-ng-config.h DESTINATION include/syslog-ng) install(DIRECTORY DESTINATION var) # Package Information for pkg-config set (PKG_CONFIG_EXEC_PREFIX ${SYSLOG_NG_PATH_EXECPREFIX}) set (PKG_CONFIG_DATAROOTDIR ${SYSLOG_NG_PATH_DATAROOTDIR}) set (PKG_CONFIG_DATADIR ${SYSLOG_NG_PATH_DATAROOTDIR}) set (PKG_CONFIG_LIBDIR ${LIBDIR}) set (PKG_CONFIG_INCLUDEDIR ${INCLUDEDIR}) set (PKG_CONFIG_TOOLSDIR ${TOOLSDIR}) set (PKG_CONFIG_MODULEDIR ${SYSLOG_NG_PATH_MODULEDIR}) set (PKG_CONFIG_CONFIG_INCLUDEDIR ${SYSLOG_NG_PATH_CONFIG_INCLUDEDIR}) set (PKG_CONFIG_SCLDIR ${SYSLOG_NG_PATH_SCLDIR}) set (PKG_CONFIG_IVYKIS ${Ivykis_INCLUDE_DIRS}) set (PKG_CONFIG_PACKAGE_VERSION ${SYSLOG_NG_VERSION}) set (PKG_CONFIG_INTERNAL_IVYKIS_CFLAGS ${Ivykis_INCLUDE_DIRS}) set (libdir "\${libdir}") set (includedir "\${includedir}") configure_file (${CMAKE_CURRENT_SOURCE_DIR}/syslog-ng.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/syslog-ng.pc) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/syslog-ng.pc DESTINATION lib/pkgconfig) syslog-ng-syslog-ng-3.13.2/CONTRIBUTING.md000066400000000000000000000132251321171025300176710ustar00rootroot00000000000000# Contributing to syslog-ng syslog-ng is developed as a community project, and relies on volunteers to produce syslog-ng. Reporting bugs, testing changes, writing code, or simply providing feedback are all important contributions. This guide provides guidelines to make contributing easier. ## Table of contents 1. [Issues](#issues) 1. [Reporting issues](#reporting-issues) 2. [Feature requests](#feature-requests) 3. [Testing](#testing) 2. [Patches](#patches) 3. [Additional resources](#additional-resources) ## Issues One of the easiest ways to contribute to the development of syslog-ng is to participate in the discussions about features, bugs and design. Some of these discussions started on the [mailing list][ar:mailing-list], some in the [issue tracker][ar:issue-tracker]. Bugs tagged [`help`][ar:issues:help] are generally good targets to contribute your feedback - but pretty much any open issue can be a good start! We use [waffle.io][ar:waffle] as our story board, to prioritize issues and guide the development. Use this interface for browsing existing issues and pull requests. ### Reporting bugs When you report a bug, it is important to share as much relevant information as you can, including: * version number of syslog-ng used; * the platform (operating system and its version, architecture, etc); * a backtrace from the core file if the issue is a crash (this can be invaluable); * if possible, a configuration that triggers the problem; * a detailed description of the issue. To make it easy to read reports, if you send a configuration snippet, or a backtrace, use [fenced code blocks](https://help.github.com/articles/github-flavored-markdown#fenced-code-blocks) around them. ### Feature requests We use the same [issue tracker][ar:issue-tracker] to handle features requests (they're all tagged with the [`enhancement`](https://github.com/balabit/syslog-ng/labels/enhancement) label. You are welcome to share your ideas on existing requests, or to submit your own. ### Testing An incredibly useful way to contribute is to test patches and pull requests - there's only so much [automated testing][ar:travis] can do. For example, you can help testing on platforms the developers do not have access to, or try configurations not thought of before. ## Patches Of course, we also accept patches. If you want to submit a patch, the guidelines are very, very simple: 1. Open an issue first, if there is none open for the particular issue for the topic already in the [issue tracker][ar:issue-tracker]. That way, other contributors and developers can comment the issue and the patch. 2. If you submit a pull request that fixes an existing issue, mention the issue somewhere in the pull request, so we can close the original issue as well. 3. We are using a coding style very similar to [GNU Coding Standards](https://www.gnu.org/prep/standards/standards.html#Writing-C) for syslog-ng. Please try to follow the existing conventions. 4. Always add a `Signed-off-by` tag to the end of **every** commit message you submit. 5. Always create a separate branch for the pull request, forked off from the appropriate syslog-ng branch. 6. If your patch should be applied to multiple branches, submit against the latest one only, and mention which other branches are affected. There is no need to submit pull requests for each branch. 7. If possible, write tests! We love tests. 8. A well-documented pull request is much easier to review and merge. Before submitting a separate module, please consider submitting it to the [Incubator](https://github.com/balabit/syslog-ng-incubator) first, because it is easier to have your code accepted there. The Incubator is the repository of new and experimental modules. ## Licensing Please ensure that your contribution is clean in respect to licensing and copyright. If your contribution is eligible for copyright, you should also extend the list of copyright holders at the top of the relevant files which carry your modifications. The absolute minimum to specify is the identity of the author entity, which is usually one or more of an e-mail address and your full name or the name of the legal entity who holds the intellectual rights if it is not you. Please make it clear which is the case, because this may depend on your contract if you are employed or are a subcontractor. Note that from time to time, we may rephrase the exact text surrounding attributions, however the specified identities and the license binding a given contribution will not be changed in a legally incompatibly manner. Every new file must carry a standard copyright notice and be compatible with our licensing scheme described in COPYING. You should observe some of the existing files for reference. ## Additional resources For additional information, have a look at the [syslog-ng.org](http://www.syslog-ng.org/) website, which is a recommended starting point for finding out more about syslog-ng. To contact us, visit the [mailing list][ar:mailing-list] where you can ask questions, and discuss your feature requests with a wider audience. We also have an [IRC channel][ar:irc], where developers hang out. We are using [waffle.io][ar:waffle], built on top of [GitHub issues][ar:issue-tracker] to track issues, feature requests and patches. We are also using [Travis CI][ar:travis] for automatic testing. [ar:irc]: irc://chat.freenode.net/#syslog-ng [ar:mailing-list]: http://lists.balabit.com/mailman/listinfo/syslog-ng [ar:issue-tracker]: https://github.com/balabit/syslog-ng/issues [ar:issues:help]: https://github.com/balabit/syslog-ng/labels/help [ar:waffle]: https://waffle.io/balabit/syslog-ng [ar:travis]: https://travis-ci.org/algernon/syslog-ng/ syslog-ng-syslog-ng-3.13.2/COPYING000066400000000000000000000100011321171025300164600ustar00rootroot00000000000000Copyright (c) 2002-2015 Balabit Copyright (c) 1996-2015 Balázs Scheidler syslog-ng is licensed under the combination of the GPL and LGPL licenses. The syslog-ng core contained in the following subdirectories 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 2.1 of the License, or (at your option) any later version (please refer to the file LGPL.txt for more details): lib/ libtest/ syslog-ng/ modules/java-common/ modules/java/(native|proxies|src)/ modules/native/ The syslog-ng modules (modules/ subdirectory except the ones mentioned above) is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation, or (at your option) any later version (please refer to the file LGPL.txt for more details). FAQ: ==== The questions and answers below try to summarize the intentions behind this licensing scheme. Q: Is it possible to create derived works of syslog-ng under the GPL/LGPL licenses? A: Yes, that's exactly the point of open source. Works derived from the plugins will have to use the GPL license, but you can choose to use LGPL for them as well. Q: Do I need to sign a Contributory License Agreement in order for my contribution to be accepted? A: No, starting with syslog-ng 3.2, you don't need to sign a CLA in order to have your contributions accepted. Q: Is it possible to create non-free plugins for syslog-ng? A: Yes. It is our understanding that plugins are derived works of the syslog-ng core but not derived works of other plugins. Thus, non-free plugins are possible, provided they do not link to any of the GPLd plugins explicitly and the only connection between two plugins is via the syslog-ng core. Q: Who is permitted to create non-free plugins for syslog-ng? Is it just BalaBit (the current copyright holder as of the initial 3.2 release)? A: No, everyone including BalaBit. PORTIONS WERE CONTRIBUTED UNDER THE FOLLOWING LICENSES: ====================================================== lib/compat: /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ syslog-ng-syslog-ng-3.13.2/GPL.txt000066400000000000000000000354311321171025300166260ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) 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 this service 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 make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. 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. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the 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 a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE 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. END OF TERMS AND CONDITIONS syslog-ng-syslog-ng-3.13.2/ISSUE_TEMPLATE.md000066400000000000000000000023221321171025300201410ustar00rootroot00000000000000# syslog-ng (Please, remove the unnecessary notes, including this one.) ## Version of syslog-ng ``` output of syslog-ng --version ``` ## Platform (Name and version of OS) ## Debug bundle Create a debug bundle on your system with the syslog-ng-debun script which is included in the syslog-ng package. Overwiew of the CLI options of syslog-ng-debun: -r: run actual information gathering -d: run syslog-ng in debug mode -p: perform packet capture -s: do strace -t: timeout period for running debug/pcap/strace -w: wait period before starting debug mode -l: light information gathering (respects privacy) -R: alternate installation directory for syslog-ng ``` $ syslog-ng-debun -r ``` # Issue ## Failure (Backtrace, error messages or detailed description of failure comes here.) (To create debug bundles, use `syslog-ng-debun`. Details of its usage can be found [on the documentation page](https://www.balabit.com/sites/default/files/documents/syslog-ng-ose-latest-guides/en/syslog-ng-ose-guide-admin/html/syslog-ng-debun.1.html)) ``` $ gdb syslog-ng run ``` ## Steps to reproduce 1. start syslog-ng 2. ... ## Configuration ``` $ cat /path/to/syslog-ng.conf ``` (or gist URL) ## Input and output logs (if possible) syslog-ng-syslog-ng-3.13.2/LGPL.txt000066400000000000000000000636421321171025300167470ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. 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 not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the 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 specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey 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 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 2.1 of the License, or (at your option) any later version. This 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 this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! syslog-ng-syslog-ng-3.13.2/Makefile.am000066400000000000000000000125031321171025300174720ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# SUBDIRS = DIST_SUBDIRS = AM_MAKEFLAGS = --no-print-directory AM_YFLAGS = -Wno-yacc -Wno-other AM_TESTS_ENVIRONMENT = top_srcdir="$(top_srcdir)" ACLOCAL_AMFLAGS = -I m4 --install EXTRA_DIST = ${BUILT_SOURCES} VERSION NEWS.md autogen.sh \ syslog-ng.spec syslog-ng.spec.in \ dist.conf dist.conf.in syslog-ng.pc.in \ syslog-ng-add-contextual-data.pc.in \ CONTRIBUTING.md pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = syslog-ng.pc AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_srcdir)/modules -I$(top_builddir)/lib -I$(top_builddir)/modules AM_CFLAGS = if ENABLE_EXTRA_WARNINGS AM_CFLAGS += \ -Wshadow \ -Wno-initializer-overrides \ -Wno-error=deprecated-declarations endif TEST_CFLAGS = -I$(top_srcdir)/libtest $(AM_CFLAGS) TEST_LDADD = $(top_builddir)/libtest/libsyslog-ng-test.a \ $(top_builddir)/lib/libsyslog-ng.la \ $(TOOL_DEPS_LIBS) if ENABLE_CRITERION TEST_CFLAGS += $(CRITERION_CFLAGS) TEST_LDADD += $(CRITERION_LIBS) endif test_ldflags = -no-install $(NO_PIE_LDFLAG) PREOPEN_SYSLOGFORMAT = -dlpreopen ${top_builddir}/modules/syslogformat/libsyslogformat.la PREOPEN_BASICFUNCS = -dlpreopen ${top_builddir}/modules/basicfuncs/libbasicfuncs.la PREOPEN_CORE = $(PREOPEN_SYSLOGFORMAT) $(PREOPEN_BASICFUNCS) syslog_ng_tools = ${top_srcdir}/lib export top_srcdir export MAKE CLEAN_SUBDIRS = clean-local: ${CLEAN_HOOKS} ${AM_v_at}for dir in ${CLEAN_SUBDIRS}; do \ [ -f $${dir}/Makefile ] && ${MAKE} -C $${dir} clean || true; \ done distclean-local: distclean-ax-prefix-config-h distclean-ax-prefix-config-h: rm -f _configs.sed syslog-ng-config.h local-check: subdir_tests=$(foreach ts,${${check_subdir}_test_subdirs},${${ts}_tests_TESTS}) local-check: current_tests=$(foreach subdir,${check_subdir} ${check_subdir}_tests,${${subdir}_TESTS}) local-check: ${AM_v_at}${MAKE} check check_PROGRAMS="${current_tests} ${subdir_tests}" \ TESTS="${current_tests} ${subdir_tests}" ${check_PROGRAMS}: LDFLAGS+=${test_ldflags} noinst_LIBRARIES = noinst_DATA = noinst_LTLIBRARIES = lib_LTLIBRARIES = pkginclude_HEADERS = syslog-ng-config.h module_LTLIBRARIES = BUILT_SOURCES = CLEANFILES = $(BUILT_SOURCES) check_PROGRAMS = check_SCRIPTS = TESTS = $(check_PROGRAMS) $(check_SCRIPTS) bin_SCRIPTS = dist_sbin_SCRIPTS = bin_PROGRAMS = sbin_PROGRAMS = libexec_PROGRAMS = man_MANS = INSTALL_EXEC_HOOKS = UNINSTALL_HOOKS = CLEAN_HOOKS = AUTOMAKE_OPTIONS = subdir-objects parallel-tests ${top_srcdir}/ChangeLog: (cd $(top_srcdir); git log) > $@ install-exec-hook: ${INSTALL_EXEC_HOOKS} uninstall-hook: ${UNINSTALL_HOOKS} populate-makefiles: $(top_srcdir)/Mk/populate-makefiles.sh style-check: $(top_srcdir)/scripts/style-checker.sh check $(top_srcdir) style-format: $(top_srcdir)/scripts/style-checker.sh format $(top_srcdir) help: @echo "Welcome to the syslog-ng build system!" @echo @echo "All of the standard targets are available:" @echo " all, check, install, dist, distcheck, and clean" @echo @echo "Apart from these, the build system supports various other," @echo "special targets:" @echo @echo " modules Builds all syslog-ng modules." @echo " syslog-ng Build syslog-ng itself, only." @echo " populate-makefiles populate build directory with stub Makefiles" @echo " check-copyright check copyright/license statements in files" @echo " style-check check formatting of source files (astyle)" @echo " style-format reformat source files (astyle)" @echo @echo "One can also build individual modules (and their dependencies)," @echo "using any of the following shortcuts:" @echo @echo "" ${SYSLOG_NG_MODULES} | sed -e 's#\(.\{,72\}\) #\1\n #g' .PHONY: help populate-makefiles install_moduleLTLIBRARIES = install-moduleLTLIBRARIES $(install_moduleLTLIBRARIES): install-libLTLIBRARIES include Mk/lex-rules.am include Mk/Makefile.am include libtest/Makefile.am include lib/Makefile.am include modules/Makefile.am include syslog-ng/Makefile.am include syslog-ng-ctl/Makefile.am include scripts/Makefile.am include tests/Makefile.am include doc/Makefile.am include contrib/Makefile.am include scl/Makefile.am include packaging/debian/Makefile.am include dbld/Makefile.am TEST_EXTENSIONS = .sh @VALGRIND_CHECK_RULES@ VALGRIND_SUPPRESSIONS_FILES = $(top_srcdir)/syslog-ng.supp EXTRA_DIST += syslog-ng.supp syslog-ng-syslog-ng-3.13.2/Mk/000077500000000000000000000000001321171025300160045ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/Mk/CMakeLists.txt000066400000000000000000000000761321171025300205470ustar00rootroot00000000000000install(FILES lex-rules.am DESTINATION share/syslog-ng/tools) syslog-ng-syslog-ng-3.13.2/Mk/Makefile.am000066400000000000000000000003121321171025300200340ustar00rootroot00000000000000EXTRA_DIST += Mk/lex-rules.am \ Mk/find-top-builddir.sh \ Mk/populate-makefiles.sh \ Mk/subdir.mk tools_DATA = \ Mk/lex-rules.am \ lib/cfg-grammar.y tools_SCRIPTS = \ lib/merge-grammar.py syslog-ng-syslog-ng-3.13.2/Mk/find-top-builddir.sh000077500000000000000000000001351321171025300216560ustar00rootroot00000000000000#! /bin/sh while ! test -f config.status || test "$(pwd)" = "/"; do cd .. done pwd syslog-ng-syslog-ng-3.13.2/Mk/lex-rules.am000066400000000000000000000020051321171025300202400ustar00rootroot00000000000000%.y: %.ym $(syslog_ng_tools)/merge-grammar.py $(syslog_ng_tools)/cfg-grammar.y $(AM_V_at) $(mkinstalldirs) $(dir $@) $(AM_V_GEN) $(syslog_ng_tools)/merge-grammar.py $< > $@ .l.c: $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $*.c $(LEX_OUTPUT_ROOT).h $*.h -- $(LEXCOMPILE) | ($(EGREP) -v "(^updating|unchanged)" || true) $(AM_V_at) touch $@ .l.h: $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $*.c $(LEX_OUTPUT_ROOT).h $*.h -- $(LEXCOMPILE) | ($(EGREP) -v "(^updating|unchanged)" || true) $(AM_V_at) touch $@ .y.c: $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE) 2>&1 | ($(EGREP) -v "(warning: ([0-9]+ )?(nonterminal|rule)s? useless in grammar)|(^updating|unchanged)" || true) .y.h: $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE) 2>&1 | ($(EGREP) -v "(warning: ([0-9]+ )?(nonterminal|rule)s? useless in grammar)|(^updating|unchanged)" || true) syslog-ng-syslog-ng-3.13.2/Mk/populate-makefiles.sh000077500000000000000000000011671321171025300221370ustar00rootroot00000000000000#! /bin/sh root=$(cd $(dirname $0) && cd .. && pwd) populate() { mfam="$1" dir="$(dirname ${mfam})" if [ "${dir}" != "." ] && [ "${dir}" != "${root}" ] && [ -d "${dir}" ]; then echo "${root}/Mk/subdir.mk" "=>" "${dir}/Makefile" ln -sf "${root}/Mk/subdir.mk" "${dir}/Makefile" fi if [ -e "${root}/${dir}/Makefile.am" ]; then incs=$(grep "^include" "${root}/${dir}/Makefile.am" | sed -e "s,^include ,,") for inc in ${incs}; do populate "${inc}" done fi } populate ./Makefile.am syslog-ng-syslog-ng-3.13.2/Mk/subdir.mk000066400000000000000000000033111321171025300176230ustar00rootroot00000000000000top_srcdir = $(dir $(shell readlink ${MAKEFILE_LIST}))../ top_builddir = $(shell ${top_srcdir}/Mk/find-top-builddir.sh) self = $(subst ${top_builddir}/,,${CURDIR}) self_sub = $(subst -,_,$(subst /,_,${self})) basedir = $(firstword $(subst /, ,${self})) levelup = ifeq (${self_sub},lib_filter) levelup = 1 else ifeq (${self_sub},lib_logproto) levelup = 1 else ifeq (${self_sub},lib_parser) levelup = 1 else ifeq (${self_sub},lib_rewrite) levelup = 1 endif ifeq (${levelup},1) self = $(subst /,,$(dir $(subst ${top_builddir}/,,${CURDIR}))) endif all: ${AM_v_at}${MAKE} -C ${top_builddir} ${self}/ check: ${AM_v_at}${MAKE} -C ${top_builddir} local-check check_subdir=${self_sub} INSTALL_ARGS = bin_SCRIPTS= \ bin_PROGRAMS= \ sbin_PROGRAMS= \ libexec_PROGRAMS= \ man_MANS= \ tools_DATA= \ xsd_DATA= \ INSTALL_EXEC_HOOKS= ifeq (${basedir},lib) INSTALL_ARGS += module_LTLIBRARIES= else ifeq (${basedir},modules) INSTALL_ARGS += lib_LTLIBRARIES= pkginclude_HEADERS= pkgconfig_DATA= ifneq (${self_sub},modules) ifeq (${self_sub},modules_afsocket) INSTALL_ARGS += module_LTLIBRARIES="modules/afsocket/libafsocket.la" INSTALL_ARGS += INSTALL_EXEC_HOOKS=afsocket-install-exec-hook else ifeq (${self_sub},modules_json) INSTALL_ARGS += module_LTLIBRARIES="modules/json/libjson-plugin.la" else INSTALL_ARGS += module_LTLIBRARIES=${self}/lib$(word 2,$(subst /, ,${self})).la endif endif else INSTALL_ARGS = endif endif install: ifeq (${INSTALL_ARGS},) @echo "Installing from this directory is not supported." else ${AM_v_at}${MAKE} -C ${top_builddir} install ${INSTALL_ARGS} endif clean dist distcheck: ${AM_v_at}${MAKE} -C ${top_builddir} $@ %: ${AM_v_at}${MAKE} -C ${top_builddir} ${self}/$@ syslog-ng-syslog-ng-3.13.2/NEWS.md000066400000000000000000000077331321171025300165450ustar00rootroot000000000000003.13.2 # Fixes * Missing manpages from release tarball (#1793) * Package syslog-ng-mod-json is removed from (#1794) * Drop syslog-ng-abi virtual packages (#1797) # Credits syslog-ng is developed as a community project, and as such it relies on volunteers, to do the work necessarily to produce syslog-ng. Reporting bugs, testing changes, writing code or simply providing feedback are all important contributions, so please if you are a user of syslog-ng, contribute. We would like to thank the following people for their contribution: Andras Mitzki, Gergely Nagy, Laszlo Budai, Laszlo Varady, Peter Czanik. 3.13.1 # Features * Add app-parser() framework (automatic parsing of log messages) (#1689) * Support microseconds in Riemann destination (#1710) * Add osquery destination as an SCL plugin (#1728) * Add network load balancer destination (#1706) * Add possibility to only signal re-open of file handles (SIGUSR1) (#1530) * It is possible from now to limit the number of registered dynamic counters (#1743) * Add $(binary) template function (#1679) * Add experimental transport for transferring messages in whole between syslog-ng instances (EWMM) (#1689) * Docker based build and debian package generation (#1783) * Add auto-parse(yes/no) to app-paser(), system() and default-network-drivers() (#1788) * Add Graylog2 destination and $(format-gelf) template function (#1680) # Bugfixes * Exit when a read fails on an included config file instead of starting up with an empty configuration. (#1721) * Fix double free (#1720) * Add missing discarded counter to groupingby (#1748) * Fix a reference leak in Python destination (#1716) * Fix timezone issue in snmptrapd parser (#1746) * Fix potential crash in stdin driver (#1741) * Fix a crash when initializing new config fails for socket with keep_alive off (#1723) * Fix filter evaluation in case of contexts with multiple elements (#1718) * Various grouping-by fixes (#1718) * Fix potential use after free around dns-cache during shutdown (#1666) * Fix access to indirect values within Java destination (#1732) * Fix a crash in affile (#1725) * Fix a memory leak (#1724) * Fix a crash when getent is used empty group (#1691) * Fix jvm-options() (#1704) * Fix a crash in Python language binding (#1694) * Fix a crash in afmongodb (#1765) * Fix a memory leak in afmongodb (#1766) * Fix name-to-GID calculation in the $(getent) template function (#1764) * Fix a crash when redis is configured without the command() option (#1767) * Fix a race condition in kv-parser() (#1789) # Other changes * Cleanup diskq related warning messages (#1752) * Provide tls block for tls options in amqp(), http(), riemann() destination drivers (#1715) * It it possible from now to register blocks and generators as plugins (#1657) * Drop compatiblity with configurations below 3.0 (#1709) * Do not change permissions of a file by default (#1782) * Allow source files to specify permissions locally (#1782) * Minor performance improvement (#1729) * The current config version can be queried with "--version" (#1740) * Increase the performance of kv-parser() (#1789) # Notes to the developers * Change configure default option for jsonc and mongoc from auto to internal (#1735) * Disable ASLR when running unit tests (#1753) # Credits syslog-ng is developed as a community project, and as such it relies on volunteers, to do the work necessarily to produce syslog-ng. Reporting bugs, testing changes, writing code or simply providing feedback are all important contributions, so please if you are a user of syslog-ng, contribute. We would like to thank the following people for their contribution: Andras Mitzki, Antal Nemes, Attila Szalay, Balazs Scheidler, Gabor Nagy, Jakub Jankowski, Janos Szigetvari, Laszlo Budai, Laszlo Varady, Laszlo Szemere, Marton Illes, Mate Farkas, Peter Kokai, Pontus Andersson, Sam Stephenson, Sebastian Roland, Viktor Juhasz, Zoltan Pallagi. syslog-ng-syslog-ng-3.13.2/README.md000066400000000000000000000142751321171025300167250ustar00rootroot00000000000000[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/balabit/syslog-ng?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) [![Build Status](https://travis-ci.org/balabit/syslog-ng.svg?branch=master)](https://travis-ci.org/balabit/syslog-ng) syslog-ng ========= syslog-ng is an enhanced log daemon, supporting a wide range of input and output methods: syslog, unstructured text, message queues, databases (SQL and NoSQL alike) and more. Quickstart ========== The easiest configuration that accepts system logs on /dev/log (from applications or forwarded by systemd) and writes everything to a single file: ``` @version: 3.13 @include "scl.conf" log { source { system(); }; destination { file("/var/log/syslog"); }; }; ``` This one also processes logs from the network (TCP/514 by default): ``` @version: 3.13 @include "scl.conf" log { source { system(); network(); }; destination { file("/var/log/syslog"); }; }; ``` Structured/application logging, local submission via JSON, output in key=value format. ``` @version: 3.13 @include "scl.conf" log { source { system(); }; destination { file("/var/log/app.log" template("$(format-welf --subkeys .cim.)\n")); }; }; ``` Here's how to submit a structured message using "logger": ``` $ logger '@cim: {"name1":"value1", "name2":"value2"}' ``` and the result will be: ``` name1=value1 name2=value2 ``` Features ======== * receive and send [RFC3164](https://tools.ietf.org/html/rfc3164) and [RFC5424](https://tools.ietf.org/html/rfc5424) style syslog messages * work with any kind of unstructured data * receive and send [JSON](http://json.org/) formatted messages * classify and structure logs with builtin parsers (csv-parser(), db-parser(), kv-parser(), ...) * normalize, crunch and process logs as they flow through the system * hand on messages for further processing using message queues (like [AMQP](http://www.amqp.org/)), files or databases (like [PostgreSQL](http://www.postgresql.org/) or [MongoDB](http://www.mongodb.org/)), and * forward log messages to big data tools like [Elasticsearch](https://www.elastic.co/), [Apache Kafka](http://kafka.apache.org/), or [Apache Hadoop](http://hadoop.apache.org/). Performance: * syslog-ng provides performance levels comparable to a large cluster while running on a single node. * In the simplest use-case it scales up 600-800k messages per second. * But classification, parsing and filtering still produces several tens of thousands messages per second. Community: * syslog-ng is developed by a community of volunteers, the best way to connect us is via our [github project page](http://github.com/balabit/syslog-ng) project, our [gitter channel](https://gitter.im/balabit/syslog-ng) or our [mailing list](https://lists.balabit.hu/mailman/listinfo/syslog-ng) * syslog-ng is integrated into almost all Linux distributions & BSDs, it is also incorporated into a number of products, see our [powered by syslog-ng] page for more details. Sponsors: * [Balabit](http://www.balabit.com/) is the original creator and the largest current sponsor of the syslog-ng project, they provide support, professional services and addons you might be interested in. Feedback ======== We are really interested in who uses our software, so if you do and you like what you see, please tell us about it. A "star" on github, an email with "thanks" in it is lots already, but learning about your usecase, experience, things to improve would be most appreciated. Just send an email to feedback (at) syslog-ng.org. Should not take more than a minute, right? Now go ahead. Please. # FeedbackPowersOpenSource. Installation from Source ======================== Releases and tarballs ready to compile are are made available at [GitHub][github-repo]. [github-repo]: https://github.com/balabit/syslog-ng/releases To compile from source, the usual drill applies (assuming you have the required dependencies): $ ./configure && make && make install If you don't have a configure script (because of cloning from git, for example), run `./autogen.sh` to generate it. Some of the functionality is compiled only in case the required development libraries are present. The configure script displays a summary of enabled features at the end of its run. For details, see the [syslog-ng compiling instructions](https://www.balabit.com/sites/default/files/documents/syslog-ng-ose-latest-guides/en/syslog-ng-ose-guide-admin/html/compiling-syslog-ng.html) Installation from Binaries ========================== Binaries are available in various Linux distributions and contributors maintain packages of the latest and greatest syslog-ng version for various OSes. Debian/Ubuntu ------------- Simply invoke the following command as root: # apt-get install syslog-ng Latest versions of syslog-ng are available for a wide range of Debian and Ubuntu releases and architectures from an [unofficial repository](https://build.opensuse.org/project/show/home:laszlo_budai:syslog-ng). [madhouse-repo]: http://asylum.madhouse-project.org/projects/debian/ Fedora ------ syslog-ng is available as a Fedora package that you can install using yum: # yum install syslog-ng You can download packages for the latest versions from [here](https://copr.fedoraproject.org/coprs/czanik/). Others ------ Binaries for other platforms are listed at the official [third party page][3rd-party]. [3rd-party]: https://syslog-ng.org/3rd-party-binaries/ Documentation ============ The documentation of the latest released version of syslog-ng Open Source Edition is available [here](https://www.balabit.com/sites/default/files/documents/syslog-ng-ose-latest-guides/en/syslog-ng-ose-guide-admin/html/index.html). For earlier versions, see the [Balabit Documentation Page](https://www.balabit.com/support/documentation). For ancient versions, see the [Balabit Documentation Archive](https://my.balabit.com/downloads/archived_documents). Contributing =========== If you want to modify the source of syslog-ng, for example, to correct a bug or develop a new module, the [syslog-ng gitbook](https://syslog-ng.gitbooks.io/getting-started/content/) helps you to take the first steps with the code base. syslog-ng-syslog-ng-3.13.2/VERSION000066400000000000000000000000071321171025300165020ustar00rootroot000000000000003.13.2 syslog-ng-syslog-ng-3.13.2/autogen.sh000077500000000000000000000071711321171025300174440ustar00rootroot00000000000000#!/bin/sh ############################################################################# # Copyright (c) 2007-2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # # This script is needed to setup build environment from checked out # source tree. # SUBMODULES="lib/ivykis modules/afmongodb/mongo-c-driver/src/libbson modules/afmongodb/mongo-c-driver modules/afamqp/rabbitmq-c lib/jsonc" GIT=`which git` include_automake_from_dir_if_exists() { local dir=$1 if [ -f "$1/Makefile.am" ]; then grep "include $dir/Makefile.am" Makefile.am if [ "$?" -eq "1" ]; then last_include=$(grep ^include Makefile.am|grep Makefile.am|tail -n 1) sed -i s@"$last_include"@"$last_include\ninclude $dir/Makefile.am"@g Makefile.am fi fi } autogen_submodules() { origdir=`pwd` submod_initialized=1 for submod in $SUBMODULES; do if [ ! -f $submod/configure.gnu ]; then submod_initialized=0 fi done if [ -n "$GIT" ] && [ -f .gitmodules ] && [ -d .git ] && [ $submod_initialized = 0 ]; then # only clone submodules if none of them present git submodule update --init sed -e "s#git://#https://#" \ < modules/afamqp/rabbitmq-c/.gitmodules \ > modules/afamqp/rabbitmq-c/.gitmodules.new && \ mv modules/afamqp/rabbitmq-c/.gitmodules.new modules/afamqp/rabbitmq-c/.gitmodules git submodule update --init --recursive fi for submod in $SUBMODULES; do echo "Running autogen in '$submod'..." cd "$submod" if [ -x autogen.sh ]; then # NOCONFIGURE needed by mongo-c-driver NOCONFIGURE=1 ./autogen.sh elif [ -f configure.in ] || [ -f configure.ac ]; then autoreconf -i else echo "Don't know how to bootstrap submodule '$submod'" >&2 exit 1 fi CONFIGURE_OPTS="--disable-shared --enable-static --with-pic" # kludge needed by make distcheck in mongo-c-driver CONFIGURE_OPTS="$CONFIGURE_OPTS --enable-man-pages --disable-shm-counters --with-libbson=bundled" sed -e "s/@__CONFIGURE_OPTS__@/${CONFIGURE_OPTS}/g" ${origdir}/sub-configure.sh >configure.gnu cd "$origdir" done } if [ -z "$skip_submodules" ]; then autogen_submodules fi # bootstrap syslog-ng itself case `uname -s` in "Darwin") LIBTOOLIZE="glibtoolize" ;; *) LIBTOOLIZE="libtoolize" ;; esac $LIBTOOLIZE --force --copy aclocal -I m4 --install sed -i -e 's/PKG_PROG_PKG_CONFIG(\[0\.16\])/PKG_PROG_PKG_CONFIG([0.14])/g' aclocal.m4 include_automake_from_dir_if_exists debian include_automake_from_dir_if_exists tgz2build autoheader automake --foreign --add-missing --copy autoconf if grep AX_PREFIX_CONFIG_H configure > /dev/null; then cat < # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. INCLUDE(CheckCSourceCompiles) MACRO (CHECK_STRUCT_MEMBER _STRUCT _MEMBER _HEADER _RESULT) SET(_INCLUDE_FILES) FOREACH (it ${_HEADER}) SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n") ENDFOREACH (it) SET(_CHECK_STRUCT_MEMBER_SOURCE_CODE " ${_INCLUDE_FILES} int main() { static ${_STRUCT} tmp; if (sizeof(tmp.${_MEMBER})) return 0; return 0; } ") CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT}) ENDMACRO (CHECK_STRUCT_MEMBER) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindCurl.cmake000066400000000000000000000026311321171025300226370ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # Copyright (c) 2016 Todd C. Miller # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# include(LibFindMacros) libfind_pkg_check_modules(Curl_PKGCONF libcurl) libfind_pkg_detect(Curl libcurl FIND_PATH curl.h PATH_SUFFIXES curl FIND_LIBRARY curl) set(Curl_PROCESS_INCLUDES Curl_INCLUDE_DIR) set(Curl_PROCESS_LIBS Curl_LIBRARY) # silence warnings set(Curl_FIND_QUIETLY 1) libfind_process(Curl QUIET) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindESMTP.cmake000066400000000000000000000042251321171025300226230ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # Origin: https://raw.githubusercontent.com/ckruse/cforum_cpp/master/cmake/modules/FindESMTP.cmake # - Try to find the libesmtp library # Once done this will define # # ESMTP_FOUND - system has the libesmtp library # ESMTP_CONFIG # ESMTP_INCLUDE_DIR - the libesmtp include directory # ESMTP_LIBRARIES - The libraries needed to use libesmtp # # Based on FindPCRE.cmake # Distributed under the BSD license. if (ESMTP_INCLUDE_DIR AND ESMTP_LIBRARIES) # Already in cache, be silent set(ESMTP_FIND_QUIETLY TRUE) endif (ESMTP_INCLUDE_DIR AND ESMTP_LIBRARIES) FIND_PROGRAM(ESMTP_CONFIG libesmtp-config) IF (ESMTP_CONFIG) FIND_PATH(ESMTP_INCLUDE_DIR libesmtp.h ) EXEC_PROGRAM(${ESMTP_CONFIG} ARGS --libs OUTPUT_VARIABLE _ESMTP_LIBRARIES) string(REGEX REPLACE "[\r\n]" " " _ESMTP_LIBRARIES "${_ESMTP_LIBRARIES}") set (ESMTP_LIBRARIES ${_ESMTP_LIBRARIES} CACHE STRING "The libraries needed for ESMTP") ENDIF (ESMTP_CONFIG) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(ESMTP DEFAULT_MSG ESMTP_INCLUDE_DIR ESMTP_LIBRARIES ) MARK_AS_ADVANCED(ESMTP_INCLUDE_DIR ESMTP_LIBRARIES) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindEventlog.cmake000066400000000000000000000025501321171025300235150ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# include(LibFindMacros) libfind_pkg_check_modules(Eventlog_PKGCONF eventlog) libfind_pkg_detect(Eventlog eventlog FIND_PATH evtlog.h PATH_SUFFIXES eventlog FIND_LIBRARY evtlog) set(Eventlog_PROCESS_INCLUDES Eventlog_INCLUDE_DIR) set(Eventlog_PROCESS_LIBS Eventlog_LIBRARY) libfind_process(Eventlog) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindFLEX.cmake000066400000000000000000000166351321171025300225010ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # - Find flex executable and provides a macro to generate custom build rules # # The module defines the following variables: # FLEX_FOUND - true is flex executable is found # FLEX_EXECUTABLE - the path to the flex executable # FLEX_VERSION - the version of flex # FLEX_LIBRARIES - The flex libraries # FLEX_INCLUDE_DIRS - The path to the flex headers # # The minimum required version of flex can be specified using the # standard syntax, e.g. find_package(FLEX 2.5.13) # # # If flex is found on the system, the module provides the macro: # FLEX_TARGET(Name FlexInput FlexOutput [COMPILE_FLAGS ]) # which creates a custom command to generate the file from # the file. If COMPILE_FLAGS option is specified, the next # parameter is added to the flex command line. Name is an alias used to # get details of this custom command. Indeed the macro defines the # following variables: # FLEX_${Name}_DEFINED - true is the macro ran successfully # FLEX_${Name}_OUTPUTS - the source file generated by the custom rule, an # alias for FlexOutput # FLEX_${Name}_INPUT - the flex source file, an alias for ${FlexInput} # # Flex scanners oftenly use tokens defined by Bison: the code generated # by Flex depends of the header generated by Bison. This module also # defines a macro: # ADD_FLEX_BISON_DEPENDENCY(FlexTarget BisonTarget) # which adds the required dependency between a scanner and a parser # where and are the first parameters of # respectively FLEX_TARGET and BISON_TARGET macros. # # ==================================================================== # Example: # # find_package(BISON) # find_package(FLEX) # # BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp) # FLEX_TARGET(MyScanner lexer.l ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp) # ADD_FLEX_BISON_DEPENDENCY(MyScanner MyParser) # # include_directories(${CMAKE_CURRENT_BINARY_DIR}) # add_executable(Foo # Foo.cc # ${BISON_MyParser_OUTPUTS} # ${FLEX_MyScanner_OUTPUTS} # ) # ==================================================================== #============================================================================= # Copyright 2009 Kitware, Inc. # Copyright 2006 Tristan Carel # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) find_program(FLEX_EXECUTABLE NAMES flex win_flex DOC "path to the flex executable") mark_as_advanced(FLEX_EXECUTABLE) find_library(FL_LIBRARY NAMES fl DOC "Path to the fl library") find_path(FLEX_INCLUDE_DIR FlexLexer.h DOC "Path to the flex headers") mark_as_advanced(FL_LIBRARY FLEX_INCLUDE_DIR) set(FLEX_INCLUDE_DIRS ${FLEX_INCLUDE_DIR}) set(FLEX_LIBRARIES ${FL_LIBRARY}) if(FLEX_EXECUTABLE) execute_process(COMMAND ${FLEX_EXECUTABLE} --version OUTPUT_VARIABLE FLEX_version_output ERROR_VARIABLE FLEX_version_error RESULT_VARIABLE FLEX_version_result OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT ${FLEX_version_result} EQUAL 0) if(FLEX_FIND_REQUIRED) message(SEND_ERROR "Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}") else() message("Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}\nFLEX_VERSION will not be available") endif() else() # older versions of flex printed "/full/path/to/executable version X.Y" # newer versions use "basename(executable) X.Y" get_filename_component(FLEX_EXE_NAME_WE "${FLEX_EXECUTABLE}" NAME_WE) get_filename_component(FLEX_EXE_EXT "${FLEX_EXECUTABLE}" EXT) string(REGEX REPLACE "^.*${FLEX_EXE_NAME_WE}(${FLEX_EXE_EXT})?\"? (version )?([0-9]+[^ ]*)( .*)?$" "\\3" FLEX_VERSION "${FLEX_version_output}") unset(FLEX_EXE_EXT) unset(FLEX_EXE_NAME_WE) endif() #============================================================ # FLEX_TARGET (public macro) #============================================================ # macro(FLEX_TARGET Name Input Output OutputHeader) set(FLEX_TARGET_usage "FLEX_TARGET( [COMPILE_FLAGS ]") if(${ARGC} GREATER 3) if(${ARGC} EQUAL 6) if("${ARGV4}" STREQUAL "COMPILE_FLAGS") set(FLEX_EXECUTABLE_opts "${ARGV5}") separate_arguments(FLEX_EXECUTABLE_opts) else() message(SEND_ERROR ${FLEX_TARGET_usage}) endif() endif() endif() add_custom_command( OUTPUT ${Output} ${OutputHeader} COMMAND ${FLEX_EXECUTABLE} ARGS ${FLEX_EXECUTABLE_opts} -o${Output} --header-file=${OutputHeader} ${Input} COMMAND mv lex.yy.c ${Output} COMMAND mv lex.yy.h ${OutputHeader} DEPENDS ${Input} COMMENT "[FLEX][${Name}] Building scanner with flex ${FLEX_VERSION}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) set(FLEX_${Name}_DEFINED TRUE) set(FLEX_${Name}_OUTPUTS ${Output}) set(FLEX_${Name}_INPUT ${Input}) set(FLEX_${Name}_COMPILE_FLAGS ${FLEX_EXECUTABLE_opts}) endmacro() #============================================================ #============================================================ # ADD_FLEX_BISON_DEPENDENCY (public macro) #============================================================ # macro(ADD_FLEX_BISON_DEPENDENCY FlexTarget BisonTarget) if(NOT FLEX_${FlexTarget}_OUTPUTS) message(SEND_ERROR "Flex target `${FlexTarget}' does not exists.") endif() if(NOT BISON_${BisonTarget}_OUTPUT_HEADER) message(SEND_ERROR "Bison target `${BisonTarget}' does not exists.") endif() set_source_files_properties(${FLEX_${FlexTarget}_OUTPUTS} PROPERTIES OBJECT_DEPENDS ${BISON_${BisonTarget}_OUTPUT_HEADER}) endmacro() #============================================================ endif() include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(FLEX REQUIRED_VARS FLEX_EXECUTABLE VERSION_VAR FLEX_VERSION) # FindFLEX.cmake ends here syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindGLIB.cmake000066400000000000000000000054721321171025300224550ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # some parts have been copied from https://raw.githubusercontent.com/WebKit/webkit/master/Source/cmake/FindGLIB.cmake include(LibFindMacros) libfind_pkg_check_modules(GLIB_GTHREAD_PKGCONF gthread-2.0) libfind_pkg_check_modules(GLIB_GMODULE_PKGCONF gmodule-2.0) libfind_pkg_check_modules(GLIB_PKGCONF glib-2.0) find_path(GLIB_INCLUDE_DIR NAMES glib.h PATHS ${GLIB_PKGCONF_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0 ) find_path(GLIBCONFIG_INCLUDE_DIR NAMES glibconfig.h HINTS ${GLIB_PKGCONF_INCLUDE_DIRS} ${GLIB_PKGCONF_INCLUDE_DIRS}/include PATH_SUFFIXES glib-2.0/include ) find_library(GLIB_LIBRARY NAMES glib-2.0 PATHS ${GLIB_PKGCONF_LIBRARY_DIRS} ) find_library(GLIB_GTHREAD_LIBRARIES NAMES gthread-2.0 PATHS ${GLIB_PKGCONF_LIBRARY_DIRS} ) find_library(GLIB_GMODULE_LIBRARIES NAMES gmodule-2.0 PATHS ${GLIB_PKGCONF_LIBRARY_DIRS} ) # Version detection file(READ "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h" GLIBCONFIG_H_CONTENTS) string(REGEX MATCH "#define GLIB_MAJOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") set(GLIB_VERSION_MAJOR "${CMAKE_MATCH_1}") string(REGEX MATCH "#define GLIB_MINOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") set(GLIB_VERSION_MINOR "${CMAKE_MATCH_1}") string(REGEX MATCH "#define GLIB_MICRO_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") set(GLIB_VERSION_MICRO "${CMAKE_MATCH_1}") set(GLIB_VERSION "${GLIB_VERSION_MAJOR}.${GLIB_VERSION_MINOR}.${GLIB_VERSION_MICRO}") # Set the include dir variables and the libraries and let libfind_process do the rest. # NOTE: Singular variables for this library, plural for libraries this this lib depends on. set(GLIB_PROCESS_INCLUDES GLIB_INCLUDE_DIR GLIBCONFIG_INCLUDE_DIR) set(GLIB_PROCESS_LIBS GLIB_LIBRARY GLIB_GTHREAD_LIBRARY GLIB_GMODULE_LIBRARY) libfind_process(GLIB) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindGettext.cmake000066400000000000000000000046021321171025300233560ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # Origin: https://fossies.org/linux/darktable/cmake/modules/FindGettext.cmake # - Try to find Gettext # Once done, this will define # # Gettext_FOUND - system has Gettext # Gettext_INCLUDE_DIRS - the Gettext include directories # Gettext_LIBRARIES - link these to use Gettext # # See documentation on how to write CMake scripts at # http://www.cmake.org/Wiki/CMake:How_To_Find_Libraries include(LibFindMacros) # On Linux there is no pkgconfig script, but with this we force # Gettext_PKGCONF_INCLUDE_DIRS to "". The situation is the same on # FreeBSD and OS X: Gettext comes without a pkgconfig file. if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|FreeBSD|Darwin)$") set(Gettext_PKGCONF_INCLUDE_DIRS "") else(CMAKE_SYSTEM_NAME MATCHES "^(Linux|FreeBSD|Darwin)$") libfind_pkg_check_modules(Gettext_PKGCONF Gettext) endif(CMAKE_SYSTEM_NAME MATCHES "^(Linux|FreeBSD|Darwin)$") if(WIN32 OR APPLE) set(Gettext_LIBRARY_SEARCH_DIRS /opt/local/lib /sw/local/lib ) find_library(Gettext_LIBRARY NAMES intl PATHS ${Gettext_LIBRARY_SEARCH_DIRS} HINTS ${Gettext_PKGCONF_LIBRARY_DIRS} ) set(Gettext_PROCESS_LIBS Gettext_LIBRARY) endif() find_path(Gettext_INCLUDE_DIR NAMES libintl.h HINTS ${Gettext_PKGCONF_INCLUDE_DIRS} PATHS /opt/local/include ) set(Gettext_PROCESS_INCLUDES Gettext_INCLUDE_DIR) libfind_process(Gettext) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindGradle.cmake000066400000000000000000000032651321171025300231340ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# include(FindPackageHandleStandardArgs) find_program(GRADLE_EXECUTABLE NAMES gradle PATHS $ENV{GRADLE_HOME}/bin NO_CMAKE_FIND_ROOT_PATH) if (GRADLE_EXECUTABLE) execute_process(COMMAND gradle --version COMMAND grep Gradle COMMAND head -1 COMMAND sed "s/.*\\ \\(.*\\)/\\1/" OUTPUT_VARIABLE GRADLE_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ) endif() find_package_handle_standard_args(Gradle FOUND_VAR GRADLE_FOUND REQUIRED_VARS GRADLE_EXECUTABLE VERSION_VAR GRADLE_VERSION) mark_as_advanced(GRADLE_EXECUTABLE) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindHiredis.cmake000066400000000000000000000040261321171025300233210ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # FindHiredis.cmake - Try to find the Hiredis library # Once done this will define # # HIREDIS_FOUND - System has Hiredis # HIREDIS_INCLUDE_DIR - The Hiredis include directory # HIREDIS_LIBRARIES - The libraries needed to use Hiredis # HIREDIS_DEFINITIONS - Compiler switches required for using Hiredis # use pkg-config to get the directories and then use these values # in the FIND_PATH() and FIND_RARY() calls FIND_PACKAGE(PkgConfig) PKG_SEARCH_MODULE(PC_HIREDIS hiredis) SET(HIREDIS_DEFINITIONS ${PC_HIREDIS_CFLAGS_OTHER}) FIND_PATH(HIREDIS_INCLUDE_DIR NAMES hiredis/hiredis.h HINTS ${PC_HIREDIS_INCLUDEDIR} ${PC_HIREDIS_INCLUDE_DIRS} PATH_SUFFIXES hiredis ) FIND_LIBRARY(HIREDIS_LIBRARIES NAMES hiredis HINTS ${PC_HIREDIS_DIR} ${PC_HIREDIS_LIBRARY_DIRS} ) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Hiredis DEFAULT_MSG HIREDIS_LIBRARIES HIREDIS_INCLUDE_DIR) MARK_AS_ADVANCED(HIREDIS_INCLUDE_DIR HIREDIS_LIBRARIES) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindIvykis.cmake000066400000000000000000000024731321171025300232140ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# include(LibFindMacros) libfind_pkg_check_modules(Ivykis_PKGCONF ivykis) libfind_pkg_detect(Ivykis ivykis FIND_PATH iv.h FIND_LIBRARY ivykis) set(Ivykis_PROCESS_INCLUDES Ivykis_INCLUDE_DIR) set(Ivykis_PROCESS_LIBS Ivykis_LIBRARY) libfind_process(Ivykis) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindJsonC.cmake000066400000000000000000000034371321171025300227530ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # Origin: https://github.com/SirCmpwn/sway/blob/master/CMake/FindJsonC.cmake # - Find json-c # Find the json-c libraries # # This module defines the following variables: # JSONC_FOUND - True if JSONC is found # JSONC_LIBRARIES - JSONC libraries # JSONC_INCLUDE_DIRS - JSONC include directories # find_package(PkgConfig) pkg_check_modules(PC_JSONC QUIET JSONC) find_path(JSONC_INCLUDE_DIRS NAMES json.h HINTS ${PC_JSONC_INCLUDE_DIRS} PATH_SUFFIXES json-c json) find_library(JSONC_LIBRARIES NAMES json-c HINTS ${PC_JSONC_LIBRARY_DIRS}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(JSONC DEFAULT_MSG JSONC_LIBRARIES JSONC_INCLUDE_DIRS) mark_as_advanced(JSONC_LIBRARIES JSONC_INCLUDE_DIRS) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindLibDBI.cmake000066400000000000000000000042001321171025300227510ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # Origin: https://github.com/hhetter/smbtatools/blob/master/FindLibDBI.cmake # Try to find libdbi # Once done this will define: # LIBDBI_FOUND - System has Libdbi # LIBDBI_INCLUDE_DIRS - libdbi include directories # LIBDBI_LIBRARIES - libraries need to use libdbi # LIBDBI_DEFINITIONS - compiler switches for libdbi # 2011 by Holger Hetterich # find_package(PkgConfig) pkg_check_modules(PC_LIBDBI QUIET libdbi) set(LIBDBI_DEFINITIONS ${PC_LIBDBI_CFLAGS_OTHER}) find_path(LIBDBI_INCLUDE_DIR dbi.h HINTS ${PC_LIBDBI_INCLUDE_DIR} ${PC_LIBDBI_INCLUDE_DIRS} PATH_SUFFIXES dbi ) find_library(LIBDBI_LIBRARY NAMES dbi libdbi HINTS ${PC_LIBDBI_LIBDIR} ${PC_LIBDBI_LIBRARY_DIRS}) set(LIBDBI_LIBRARIES ${LIBDBI_LIBRARY} ) set(LIBDBI_INCLUDE_DIRS ${LIBDBI_INCLUDE_DIR}) include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRES arguments and set LIBDBI_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(LibDbi DEFAULT_MSG LIBDBI_LIBRARY LIBDBI_INCLUDE_DIR) mark_as_advanced(LIBDBI_INCLUDE_DIR LIBDBI_LIBRARY) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindLibGeoIP.cmake000066400000000000000000000062201321171025300233220ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # origin: https://raw.githubusercontent.com/bro/cmake/master/FindLibGeoIP.cmake # - Try to find GeoIP headers and libraries # # Usage of this module as follows: # # find_package(LibGeoIP) # # Variables used by this module, they can change the default behaviour and need # to be set before calling find_package: # # LibGeoIP_ROOT_DIR Set this variable to the root installation of # libGeoIP if the module has problems finding the # proper installation path. # # Variables defined by this module: # # LIBGEOIP_FOUND System has GeoIP libraries and headers # LibGeoIP_LIBRARY The GeoIP library # LibGeoIP_INCLUDE_DIR The location of GeoIP headers # HAVE_GEOIP_COUNTRY_EDITION_V6 Whether the API support IPv6 country edition # HAVE_GEOIP_CITY_EDITION_REV0_V6 Whether the API supports IPv6 city edition find_path(LibGeoIP_ROOT_DIR NAMES include/GeoIPCity.h ) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # the static version of the library is preferred on OS X for the # purposes of making packages (libGeoIP doesn't ship w/ OS X) set(libgeoip_names libGeoIp.a GeoIP) else () set(libgeoip_names GeoIP) endif () find_library(LibGeoIP_LIBRARY NAMES ${libgeoip_names} HINTS ${LibGeoIP_ROOT_DIR}/lib ) find_path(LibGeoIP_INCLUDE_DIR NAMES GeoIPCity.h HINTS ${LibGeoIP_ROOT_DIR}/include ) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LibGeoIP DEFAULT_MSG LibGeoIP_LIBRARY LibGeoIP_INCLUDE_DIR ) if (LIBGEOIP_FOUND) include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_INCLUDES ${LibGeoIP_INCLUDE_DIR}) check_cxx_source_compiles(" #include int main() { GEOIP_COUNTRY_EDITION_V6; return 0; } " HAVE_GEOIP_COUNTRY_EDITION_V6) check_cxx_source_compiles(" #include int main() { GEOIP_CITY_EDITION_REV0_V6; return 0; } " HAVE_GEOIP_CITY_EDITION_REV0_V6) set(CMAKE_REQUIRED_INCLUDES) endif () mark_as_advanced( LibGeoIP_ROOT_DIR LibGeoIP_LIBRARY LibGeoIP_INCLUDE_DIR ) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindLibNet.cmake000066400000000000000000000044171321171025300231130ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # - Try to find the libnet library # Once done this will define # # LIBNET_FOUND - system has the libnet library # LIBNET_CONFIG # LIBNET_LIBRARIES - The libraries needed to use libnet # # Based on FindESMTP.cmake # Distributed under the BSD license. if (LIBNET_LIBRARIES) # Already in cache, be silent set(LIBNET_FIND_QUIETLY TRUE) endif (LIBNET_LIBRARIES) FIND_PROGRAM(LIBNET_CONFIG libnet-config) IF (LIBNET_CONFIG) EXEC_PROGRAM(${LIBNET_CONFIG} ARGS --libs OUTPUT_VARIABLE _LIBNET_LIBRARIES) EXEC_PROGRAM(${LIBNET_CONFIG} ARGS --defines OUTPUT_VARIABLE _LIBNET_DEFINES) string(REGEX REPLACE "[\r\n]" " " _LIBNET_LIBRARIES "${_LIBNET_LIBRARIES}") string(REGEX REPLACE "[\r\n]" " " _LIBNET_DEFINES "${_LIBNET_DEFINES}") set (LIBNET_LIBRARIES ${_LIBNET_LIBRARIES} CACHE STRING "The libraries needed for LIBNET") set (LIBNET_DEFINES ${_LIBNET_DEFINES} CACHE STRING "The #defines needed for LIBNET") set (LIBNET_FOUND TRUE CACHE BOOL "LibNet is found") ELSE(LIBNET_CONFIG) set (LIBNET_FOUND FALSE CACHE BOOL "LibNet is found") ENDIF() include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBNET DEFAULT_MSG LIBNET_LIBRARIES LIBNET_DEFINES LIBNET_FOUND) MARK_AS_ADVANCED(LIBNET_LIBRARIES) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindPackageMessage.cmake000066400000000000000000000057471321171025300246050ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # FIND_PACKAGE_MESSAGE( "message for user" "find result details") # # This macro is intended to be used in FindXXX.cmake modules files. # It will print a message once for each unique find result. # This is useful for telling the user where a package was found. # The first argument specifies the name (XXX) of the package. # The second argument specifies the message to display. # The third argument lists details about the find result so that # if they change the message will be displayed again. # The macro also obeys the QUIET argument to the find_package command. # # Example: # # if(X11_FOUND) # FIND_PACKAGE_MESSAGE(X11 "Found X11: ${X11_X11_LIB}" # "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]") # else() # ... # endif() #============================================================================= # Copyright 2008-2009 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) function(FIND_PACKAGE_MESSAGE pkg msg details) # Avoid printing a message repeatedly for the same find result. if(NOT ${pkg}_FIND_QUIETLY) string(REGEX REPLACE "[\n]" "" details "${details}") set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg}) if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}") # The message has not yet been printed. message(STATUS "${msg}") # Save the find details in the cache to avoid printing the same # message again. set("${DETAILS_VAR}" "${details}" CACHE INTERNAL "Details about finding ${pkg}") endif() endif() endfunction() syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindResolv.cmake000066400000000000000000000021431321171025300232020ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# find_library (RESOLV_LIBRARIES resolv) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindRiemannClient.cmake000066400000000000000000000031331321171025300244600ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# include(LibFindMacros) # Use pkg-config to get hints about paths libfind_pkg_check_modules(Riemann_PKGCONF riemann-client) # Finally the library itself find_library(Riemann_LIBRARY NAMES riemann-client PATHS ${Riemann_PKGCONF_LIBRARY_DIRS} ) # Set the include dir variables and the libraries and let libfind_process do the rest. # NOTE: Singular variables for this library, plural for libraries this this lib depends on. set(Riemann_PROCESS_LIBS Riemann_LIBRARY) # silence warnings set(Riemann_FIND_QUIETLY 1) libfind_process(Riemann) syslog-ng-syslog-ng-3.13.2/cmake/Modules/FindWrap.cmake000066400000000000000000000035771321171025300226550ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # Find wrap library # # Released under BSD license # # WRAP_INCLUDE_DIRS - where to find tcpd.h, etc # WRAP_LIBRARIES - Lists of libraries when using libwrap # WRAP_FOUND - True if wrap found INCLUDE(FindPackageHandleStandardArgs) # Look for the header file FIND_PATH(WRAP_INCLUDE_DIR NAMES tcpd.h) MARK_AS_ADVANCED(WRAP_INCLUDE_DIR) # Look for the library SET(WRAP_LIBS wrap) FIND_LIBRARY(WRAP_LIBRARY NAMES ${WRAP_LIBS}) MARK_AS_ADVANCED(WRAP_LIBRARY) FIND_PACKAGE_HANDLE_STANDARD_ARGS(WRAP REQUIRED_VARS WRAP_LIBRARY WRAP_INCLUDE_DIR) # Copy the result to output variables IF(WRAP_FOUND) SET(WRAP_LIBRARIES ${WRAP_LIBRARY}) SET(WRAP_INCLUDE_DIRS ${WRAP_INCLUDE_DIR}) ELSE(WRAP_FOUND) SET(WRAP_LIBS) SET(WRAP_LIBRARY) SET(WRAP_LIBRARIES) SET(WRAP_INCLUDE_DIR) SET(WRAP_INCLUDE_DIRS) ENDIF(WRAP_FOUND) syslog-ng-syslog-ng-3.13.2/cmake/Modules/Findsystemd.cmake000066400000000000000000000026661321171025300234320ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# include(LibFindMacros) libfind_pkg_check_modules(Libsystemd_PKGCONF libsystemd) libfind_pkg_detect(Libsystemd libsystemd FIND_PATH sd-daemon.h PATH_SUFFIXES systemd FIND_LIBRARY systemd) set(Libsystemd_PROCESS_INCLUDES Libsystemd_INCLUDE_DIR) set(Libsystemd_PROCESS_LIBS Libsystemd_LIBRARY) # silence warnings set(Libsystemd_FIND_QUIETLY 1) libfind_process(Libsystemd QUIET) syslog-ng-syslog-ng-3.13.2/cmake/Modules/GenerateYFromYm.cmake000066400000000000000000000036761321171025300241600ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # This function is syslog-ng specific function(generate_y_from_ym FileWoExt) if (${ARGC} EQUAL 1) add_custom_command (OUTPUT ${PROJECT_BINARY_DIR}/${FileWoExt}.y COMMAND ${PROJECT_SOURCE_DIR}/lib/merge-grammar.py ${PROJECT_SOURCE_DIR}/${FileWoExt}.ym > ${PROJECT_BINARY_DIR}/${FileWoExt}.y DEPENDS ${PROJECT_SOURCE_DIR}/lib/cfg-grammar.y ${PROJECT_SOURCE_DIR}/${FileWoExt}.ym) elseif(${ARGC} EQUAL 2) add_custom_command (OUTPUT ${PROJECT_BINARY_DIR}/${ARGV1}.y COMMAND ${PROJECT_SOURCE_DIR}/lib/merge-grammar.py ${PROJECT_SOURCE_DIR}/${FileWoExt}.ym > ${PROJECT_BINARY_DIR}/${ARGV1}.y DEPENDS ${PROJECT_SOURCE_DIR}/lib/cfg-grammar.y ${PROJECT_SOURCE_DIR}/${FileWoExt}.ym) else() message(SEND_ERROR "Wrong usage of generate_y_from_ym() function") endif() endfunction() syslog-ng-syslog-ng-3.13.2/cmake/Modules/LibFindMacros.cmake000066400000000000000000000271461321171025300236150ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # Origin: https://raw.githubusercontent.com/Tronic/cmake-modules/master/LibFindMacros.cmake # Version 2.2 # Public Domain, originally written by Lasse Kärkkäinen # Maintained at https://github.com/Tronic/cmake-modules # Please send your improvements as pull requests on Github. # Find another package and make it a dependency of the current package. # This also automatically forwards the "REQUIRED" argument. # Usage: libfind_package( [extra args to find_package]) macro (libfind_package PREFIX PKG) set(${PREFIX}_args ${PKG} ${ARGN}) if (${PREFIX}_FIND_REQUIRED) set(${PREFIX}_args ${${PREFIX}_args} REQUIRED) endif() find_package(${${PREFIX}_args}) set(${PREFIX}_DEPENDENCIES ${${PREFIX}_DEPENDENCIES};${PKG}) unset(${PREFIX}_args) endmacro() # A simple wrapper to make pkg-config searches a bit easier. # Works the same as CMake's internal pkg_check_modules but is always quiet. macro (libfind_pkg_check_modules) find_package(PkgConfig QUIET) if (PKG_CONFIG_FOUND) pkg_check_modules(${ARGN} QUIET) endif() endmacro() # Avoid useless copy&pasta by doing what most simple libraries do anyway: # pkg-config, find headers, find library. # Usage: libfind_pkg_detect( FIND_PATH [other args] FIND_LIBRARY [other args]) # E.g. libfind_pkg_detect(SDL2 sdl2 FIND_PATH SDL.h PATH_SUFFIXES SDL2 FIND_LIBRARY SDL2) function (libfind_pkg_detect PREFIX) # Parse arguments set(argname pkgargs) foreach (i ${ARGN}) if ("${i}" STREQUAL "FIND_PATH") set(argname pathargs) elseif ("${i}" STREQUAL "FIND_LIBRARY") set(argname libraryargs) else() set(${argname} ${${argname}} ${i}) endif() endforeach() if (NOT pkgargs) message(FATAL_ERROR "libfind_pkg_detect requires at least a pkg_config package name to be passed.") endif() # Find library libfind_pkg_check_modules(${PREFIX}_PKGCONF ${pkgargs}) if (pathargs) find_path(${PREFIX}_INCLUDE_DIR NAMES ${pathargs} HINTS ${${PREFIX}_PKGCONF_INCLUDE_DIRS}) endif() if (libraryargs) find_library(${PREFIX}_LIBRARY NAMES ${libraryargs} HINTS ${${PREFIX}_PKGCONF_LIBRARY_DIRS}) endif() endfunction() # Extracts a version #define from a version.h file, output stored to _VERSION. # Usage: libfind_version_header(Foobar foobar/version.h FOOBAR_VERSION_STR) # Fourth argument "QUIET" may be used for silently testing different define names. # This function does nothing if the version variable is already defined. function (libfind_version_header PREFIX VERSION_H DEFINE_NAME) # Skip processing if we already have a version or if the include dir was not found if (${PREFIX}_VERSION OR NOT ${PREFIX}_INCLUDE_DIR) return() endif() set(quiet ${${PREFIX}_FIND_QUIETLY}) # Process optional arguments foreach(arg ${ARGN}) if (arg STREQUAL "QUIET") set(quiet TRUE) else() message(AUTHOR_WARNING "Unknown argument ${arg} to libfind_version_header ignored.") endif() endforeach() # Read the header and parse for version number set(filename "${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") if (NOT EXISTS ${filename}) if (NOT quiet) message(AUTHOR_WARNING "Unable to find ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") endif() return() endif() file(READ "${filename}" header) string(REGEX REPLACE ".*#[ \t]*define[ \t]*${DEFINE_NAME}[ \t]*\"([^\n]*)\".*" "\\1" match "${header}") # No regex match? if (match STREQUAL header) if (NOT quiet) message(AUTHOR_WARNING "Unable to find \#define ${DEFINE_NAME} \"\" from ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") endif() return() endif() # Export the version string set(${PREFIX}_VERSION "${match}" PARENT_SCOPE) endfunction() # Do the final processing once the paths have been detected. # If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain # all the variables, each of which contain one include directory. # Ditto for ${PREFIX}_PROCESS_LIBS and library files. # Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES. # Also handles errors in case library detection was required, etc. function (libfind_process PREFIX) # Skip processing if already processed during this configuration run if (${PREFIX}_FOUND) return() endif() set(found TRUE) # Start with the assumption that the package was found # Did we find any files? Did we miss includes? These are for formatting better error messages. set(some_files FALSE) set(missing_headers FALSE) # Shorthands for some variables that we need often set(quiet ${${PREFIX}_FIND_QUIETLY}) set(required ${${PREFIX}_FIND_REQUIRED}) set(exactver ${${PREFIX}_FIND_VERSION_EXACT}) set(findver "${${PREFIX}_FIND_VERSION}") set(version "${${PREFIX}_VERSION}") # Lists of config option names (all, includes, libs) unset(configopts) set(includeopts ${${PREFIX}_PROCESS_INCLUDES}) set(libraryopts ${${PREFIX}_PROCESS_LIBS}) # Process deps to add to foreach (i ${PREFIX} ${${PREFIX}_DEPENDENCIES}) if (DEFINED ${i}_INCLUDE_OPTS OR DEFINED ${i}_LIBRARY_OPTS) # The package seems to export option lists that we can use, woohoo! list(APPEND includeopts ${${i}_INCLUDE_OPTS}) list(APPEND libraryopts ${${i}_LIBRARY_OPTS}) else() # If plural forms don't exist or they equal singular forms if ((NOT DEFINED ${i}_INCLUDE_DIRS AND NOT DEFINED ${i}_LIBRARIES) OR ({i}_INCLUDE_DIR STREQUAL ${i}_INCLUDE_DIRS AND ${i}_LIBRARY STREQUAL ${i}_LIBRARIES)) # Singular forms can be used if (DEFINED ${i}_INCLUDE_DIR) list(APPEND includeopts ${i}_INCLUDE_DIR) endif() if (DEFINED ${i}_LIBRARY) list(APPEND libraryopts ${i}_LIBRARY) endif() else() # Oh no, we don't know the option names message(FATAL_ERROR "We couldn't determine config variable names for ${i} includes and libs. Aieeh!") endif() endif() endforeach() if (includeopts) list(REMOVE_DUPLICATES includeopts) endif() if (libraryopts) list(REMOVE_DUPLICATES libraryopts) endif() string(REGEX REPLACE ".*[ ;]([^ ;]*(_INCLUDE_DIRS|_LIBRARIES))" "\\1" tmp "${includeopts} ${libraryopts}") if (NOT tmp STREQUAL "${includeopts} ${libraryopts}") message(AUTHOR_WARNING "Plural form ${tmp} found in config options of ${PREFIX}. This works as before but is now deprecated. Please only use singular forms INCLUDE_DIR and LIBRARY, and update your find scripts for LibFindMacros > 2.0 automatic dependency system (most often you can simply remove the PROCESS variables entirely).") endif() # Include/library names separated by spaces (notice: not CMake lists) unset(includes) unset(libs) # Process all includes and set found false if any are missing foreach (i ${includeopts}) list(APPEND configopts ${i}) if (NOT "${${i}}" STREQUAL "${i}-NOTFOUND") list(APPEND includes "${${i}}") else() set(found FALSE) set(missing_headers TRUE) endif() endforeach() # Process all libraries and set found false if any are missing foreach (i ${libraryopts}) list(APPEND configopts ${i}) if (NOT "${${i}}" STREQUAL "${i}-NOTFOUND") list(APPEND libs "${${i}}") else() set (found FALSE) endif() endforeach() # Version checks if (found AND findver) if (NOT version) message(WARNING "The find module for ${PREFIX} does not provide version information, so we'll just assume that it is OK. Please fix the module or remove package version requirements to get rid of this warning.") elseif (version VERSION_LESS findver OR (exactver AND NOT version VERSION_EQUAL findver)) set(found FALSE) set(version_unsuitable TRUE) endif() endif() # If all-OK, hide all config options, export variables, print status and exit if (found) foreach (i ${configopts}) mark_as_advanced(${i}) endforeach() if (NOT quiet) message(STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}") if (LIBFIND_DEBUG) message(STATUS " ${PREFIX}_DEPENDENCIES=${${PREFIX}_DEPENDENCIES}") message(STATUS " ${PREFIX}_INCLUDE_OPTS=${includeopts}") message(STATUS " ${PREFIX}_INCLUDE_DIRS=${includes}") message(STATUS " ${PREFIX}_LIBRARY_OPTS=${libraryopts}") message(STATUS " ${PREFIX}_LIBRARIES=${libs}") endif() set (${PREFIX}_INCLUDE_OPTS ${includeopts} PARENT_SCOPE) set (${PREFIX}_LIBRARY_OPTS ${libraryopts} PARENT_SCOPE) set (${PREFIX}_INCLUDE_DIRS ${includes} PARENT_SCOPE) set (${PREFIX}_LIBRARIES ${libs} PARENT_SCOPE) set (${PREFIX}_FOUND TRUE PARENT_SCOPE) endif() return() endif() # Format messages for debug info and the type of error set(vars "Relevant CMake configuration variables:\n") foreach (i ${configopts}) mark_as_advanced(CLEAR ${i}) set(val ${${i}}) if ("${val}" STREQUAL "${i}-NOTFOUND") set (val "") elseif (val AND NOT EXISTS ${val}) set (val "${val} (does not exist)") else() set(some_files TRUE) endif() set(vars "${vars} ${i}=${val}\n") endforeach() set(vars "${vars}You may use CMake GUI, cmake -D or ccmake to modify the values. Delete CMakeCache.txt to discard all values and force full re-detection if necessary.\n") if (version_unsuitable) set(msg "${PREFIX} ${${PREFIX}_VERSION} was found but") if (exactver) set(msg "${msg} only version ${findver} is acceptable.") else() set(msg "${msg} version ${findver} is the minimum requirement.") endif() else() if (missing_headers) set(msg "We could not find development headers for ${PREFIX}. Do you have the necessary dev package installed?") elseif (some_files) set(msg "We only found some files of ${PREFIX}, not all of them. Perhaps your installation is incomplete or maybe we just didn't look in the right place?") if(findver) set(msg "${msg} This could also be caused by incompatible version (if it helps, at least ${PREFIX} ${findver} should work).") endif() else() set(msg "We were unable to find package ${PREFIX}.") endif() endif() # Fatal error out if REQUIRED if (required) set(msg "REQUIRED PACKAGE NOT FOUND\n${msg} This package is REQUIRED and you need to install it or adjust CMake configuration in order to continue building ${CMAKE_PROJECT_NAME}.") message(FATAL_ERROR "${msg}\n${vars}") endif() # Otherwise just print a nasty warning if (NOT quiet) message(WARNING "WARNING: MISSING PACKAGE\n${msg} This package is NOT REQUIRED and you may ignore this warning but by doing so you may miss some functionality of ${CMAKE_PROJECT_NAME}. \n${vars}") endif() endfunction() syslog-ng-syslog-ng-3.13.2/configure.ac000066400000000000000000002110231321171025300177220ustar00rootroot00000000000000############################################################################# # Copyright (c) 2016 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# dnl Process this file with autoconf to produce a configure script. dnl dnl There are a couple of environment defined variables which this script dnl makes use of in addition to the standard CFLAGS/LDFLAGS/etc. These are: dnl dnl RELEASE_TAG - Debian release tag which is put to debian/changelog dnl SNAPSHOT_VERSION - snapshot version to add to version number dnl BINARY_BRANCH - the value is added to all source/binary packages dnl SOURCE_REVISION - Revision of the source-tree, will added to the version string dnl AC_INIT([syslog-ng], m4_esyscmd([tr -d '\n' < VERSION])) AC_CONFIG_SRCDIR([syslog-ng/main.c]) AC_CONFIG_MACRO_DIR([m4]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) dnl *************************************************************************** dnl dependencies GLIB_MIN_VERSION="2.10.1" OPENSSL_MIN_VERSION="0.9.8" LIBDBI_MIN_VERSION="0.9.0" LIBRABBITMQ_MIN_VERSION="0.5.3" IVYKIS_MIN_VERSION="0.36.1" JSON_C_MIN_VERSION="0.9" PCRE_MIN_VERSION="6.1" LMC_MIN_VERSION="1.0.0" LRMQ_MIN_VERSION="0.0.1" LRC_MIN_VERSION="1.6.0" JOURNALD_MIN_VERSION="195" LIBSYSTEMD_MIN_VERSION="209" JAVA_MIN_VERSION="1.7" GRADLE_MIN_VERSION="2.2" HIREDIS_MIN_VERSION="0.11.0" CRITERION_MIN_VERSION="2.2.1" dnl *************************************************************************** dnl Initial setup ostype=`uname -s` if test -r $srcdir/dist.conf; then # read defaults, dist.conf does not change # values for parameters that are already set . $srcdir/dist.conf fi if test -z "$RELEASE_TAG"; then RELEASE_TAG=unstable fi if test "`uname -s`" = "Linux";then CURRDATE=`date -R` else CURRDATE=`date +"%a, %d %b %Y %H:%M:%S %Z"` fi AM_INIT_AUTOMAKE([foreign no-define subdir-objects]) _AM_PROG_TAR([ustar]) if test -n "$SNAPSHOT_VERSION"; then PACKAGE_VERSION=$PACKAGE_VERSION+$SNAPSHOT_VERSION fi dnl *************************************************************************** dnl script snippet to generate user friendly version strings according to the dnl new versioning policy. All needed code are here to allow easy moving dnl between projects. if test -z "$RELEASE_TYPE"; then RELEASE_TYPE=stable fi if test -z "$BROCHURE_VERSION"; then _MAJOR=`echo $VERSION | cut -f1 -d'.'` _MINOR=`echo $VERSION | cut -f2 -d'.'` case "$RELEASE_TYPE" in stable) BROCHURE_VERSION="$_MAJOR";; feature) BROCHURE_VERSION="$_MAJOR F$_MINOR";; *) BROCHURE_VERSION="$VERSION dogfood edition. Please contact your syslog-ng release manager to fix the configure scritpt";; esac fi if test -z "$COMBINED_VERSION"; then COMBINED_VERSION="$BROCHURE_VERSION ($VERSION)" fi TECHNICAL_VERSION=$VERSION AC_DEFINE_UNQUOTED(RELEASE_TYPE, "$RELEASE_TYPE", [type of syslog-ng release. stable or feature]) AC_DEFINE_UNQUOTED(BROCHURE_VERSION, "$BROCHURE_VERSION", [pretty version for users depends on the release type]) AC_DEFINE_UNQUOTED(COMBINED_VERSION, "$COMBINED_VERSION", [normal and brochure version combined]) AC_DEFINE_UNQUOTED(SOURCE_REVISION, "$SOURCE_REVISION", [source revision]) AC_SUBST(RELEASE_TYPE) AC_SUBST(BROCHURE_VERSION) AC_SUBST(COMBINED_VERSION) AC_SUBST(TECHNICAL_VERSION) dnl *************************************************************************** if test "x$prefix" = "xNONE"; then prefix=$ac_default_prefix fi if test "x$exec_prefix" = "xNONE"; then exec_prefix='${prefix}' fi pidfiledir='${localstatedir}' moduledir='${exec_prefix}/lib/syslog-ng' toolsdir='${datadir}/syslog-ng/tools' xsddir='${datadir}/syslog-ng/xsd' config_includedir='${datadir}/syslog-ng/include' scldir="${config_includedir}/scl" abs_topsrcdir=`(cd $srcdir && pwd)` AC_CONFIG_HEADERS(config.h) dnl *************************************************************************** dnl Arguments AC_ARG_WITH(libnet, [ --with-libnet=path use path to libnet-config script], , [with_libnet=""]) AC_ARG_WITH(pidfile-dir, [ --with-pidfile-dir=path Use path as the directory for storing pidfiles], pidfiledir=$with_pidfile_dir) AC_ARG_WITH(module-dir, [ --with-module-dir=path Use path as the directory to install modules into], moduledir=$with_module_dir) AC_ARG_WITH(module-path, [ --with-module-path=path Use path as the list of ':' separated directories looked up when searching for modules], module_path=$with_module_path) AC_ARG_WITH(timezone-dir, [ --with-timezone-dir=path Use path as the directory to get the timezone files], timezonedir=$with_timezone_dir) AC_ARG_WITH(ld-library-path, [ --with-ld-library-path=path Set LD_LIBRARY_PATH during runtime to the value given], env_ld_library_path=$with_ld_library_path) AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])) AC_ARG_WITH(package_name, [ --with-package-name=package name Package name is printed out when syslog-ng started with --version], PACKAGE_NAME=$with_package_name) AC_ARG_ENABLE(forced_server_mode, [ --enable-forced-server-mode Enable forced server mode.],, enable_forced_server_mode="yes") AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging code.],, enable_debug="no") AC_ARG_ENABLE(extra-warnings, [ --enable-extra-warnings Enable extra compiler warnings (recommended).],, enable_extra_warnings="no") AC_ARG_ENABLE(env-wrapper, [ --enable-env-wrapper Enable wrapper program to set up various environment variables],, enable_env_wrapper=auto) AC_ARG_ENABLE(gprof, [ --enable-gprof Enable gcc profiling.],, enable_gprof="no") AC_ARG_ENABLE(memtrace, [ --enable-memtrace Enable alternative leak debugging code.]) AC_ARG_ENABLE(dynamic-linking, [ --enable-dynamic-linking Link everything dynamically.],,enable_dynamic_linking="auto") AC_ARG_ENABLE(mixed-linking, [ --enable-mixed-linking Link 3rd party libraries statically, system libraries dynamically],,enable_mixed_linking="auto") AC_ARG_ENABLE(ipv6, [ --enable-ipv6 Enable support for IPv6.],,enable_ipv6="auto") AC_ARG_ENABLE(tcp-wrapper, [ --enable-tcp-wrapper Enable support for TCP wrappers.],,enable_tcp_wrapper="auto") AC_ARG_ENABLE(spoof-source, [ --enable-spoof-source Enable support for spoofed source addresses.] ,,enable_spoof_source="auto") AC_ARG_ENABLE(sun-streams, [ --enable-sun-streams Enable support for Solaris /dev/log STREAMS device.] ,,enable_sun_streams="auto") AC_ARG_ENABLE(sql, [ --enable-sql Enable support for SQL destinations. (default: auto)] ,,enable_sql="auto") AC_ARG_ENABLE(pacct, [ --enable-pacct Enable support for reading Process Accounting files (EXPERIMENTAL, Linux only).] ,,enable_pacct="no") AC_ARG_ENABLE(linux-caps, [ --enable-linux-caps Enable support for managing Linux capabilities (default: auto)] ,,enable_linux_caps="auto") AC_ARG_ENABLE(gcov, [ --enable-gcov Enable coverage profiling (default: no)] ,,enable_gcov="no") AC_ARG_ENABLE(mongodb, [ --enable-mongodb Enable mongodb destination (default: auto)] ,,enable_mongodb="auto") AC_ARG_WITH(mongoc, [ --with-mongoc=[system/internal/auto/no] Link against the system supplied or the built-in mongo-c-driver library. (default: auto)] ,,with_mongoc="internal") AC_ARG_ENABLE(legacy-mongodb-options, [ --enable-legacy-mongodb-options=[yes/no] Support libmongo-client non-URI MongoDB options. (default: yes)] ,,enable_legacy_mongodb_options="yes") AC_ARG_WITH(jsonc, [ --with-jsonc=[system/internal/auto/no] Link against the system supplied or the built-in jsonc library or explicitly disable it. (default:auto)] ,,with_jsonc="internal") AC_ARG_ENABLE(json, [ --enable-json=[yes/no] Enable JSON support (default: yes)] ,[if test "x$enableval" != "xno"; then with_jsonc="system"; else with_jsonc="no"; fi],) AC_ARG_ENABLE(amqp, [ --enable-amqp Enable amqp destination (default: auto)] ,,enable_amqp="auto") AC_ARG_WITH(librabbitmq-client, [ --with-librabbitmq-client=[system/internal] Link against the system supplied or the built-in librabbitmq library.] ,,with_librabbitmq_client="internal") AC_ARG_ENABLE(stomp, [ --enable-stomp Enable stomp destination (default: yes)] ,,enable_stomp="yes") AC_ARG_WITH(ivykis, [ --with-ivykis=[system/internal] Link against the system supplied or the built-in ivykis library.] ,,with_ivykis="internal") AC_ARG_ENABLE(smtp, [ --disable-smtp Disable SMTP support (default: auto)] ,,enable_smtp="auto") AC_ARG_WITH(libesmtp, AC_HELP_STRING([--with-libesmtp=DIR], [use libesmtp library from (prefix) directory DIR]),,) AC_ARG_ENABLE(http, [ --disable-http Disable http support (default: auto)] ,,enable_http="auto") AC_ARG_WITH(libcurl, AC_HELP_STRING([--with-libcurl=DIR], [use libcurl library from (prefix) directory DIR]),,) AC_ARG_ENABLE(redis, [ --disable-redis Disable REDIS support (default: auto)] ,,enable_redis="auto") AC_ARG_WITH(libhiredis, AC_HELP_STRING([--with-libhiredis=DIR], [use libhiredis library from (prefix) directory DIR]),,) AC_ARG_ENABLE(systemd, [ --enable-systemd Enable systemd support (default: auto)] ,,enable_systemd="auto") AC_ARG_ENABLE(geoip, [ --enable-geoip Enable GeoIP support (default: auto)] ,,enable_geoip="auto") AC_ARG_ENABLE(geoip2, [ --enable-geoip2 Enable GeoIP2 support (default: auto)] ,,enable_geoip2="auto") AC_ARG_ENABLE(riemann, [ --disable-riemann Disable riemann destination] ,,enable_riemann="auto") AC_ARG_WITH(compile-date, [ --without-compile-date Do not include the compile date in the binary] ,wcmp_date="${withval}", wcmp_date="yes") AC_ARG_WITH(systemd-journal, [ --with-systemd-journal=[system/optional/auto] Link against the system supplied or the wrapper library. (default: auto)] ,,with_systemd_journal="auto") AC_ARG_ENABLE(python, [ --disable-python Disable python destination] ,,enable_python="auto") AC_ARG_WITH(python, [ --with-python=VERSION Build with a specific version of python] ,,with_python="auto") AC_ARG_WITH(docbook-dir, AC_HELP_STRING([--with-docbook-dir=DIR], [compiling manpages using docbook in the specified path, if not set online version will be used from http://docbook.sourceforge.net]), [ XSL_STYLESHEET=$with_docbook_dir ], [ XSL_STYLESHEET=http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl ] ) AC_ARG_ENABLE(manpages, AC_HELP_STRING([ --enable-manpages], [ Enable generation of manpages (default: no)]), , [enable_manpages="no"; XSL_STYLESHEET=""]) AC_ARG_ENABLE(java, [ --enable-java Enable java destination (default: auto)],, enable_java="auto") AC_ARG_ENABLE(java-modules, [ --enable-java-modules Compile all Java modules (default: auto)],, enable_java_modules="auto") AC_ARG_ENABLE(native, [ --enable-native Enable native bindings (default: auto)] ,,enable_native="auto") AC_ARG_ENABLE(all-modules, [ --enable-all-modules Forcibly enable all modules. (default: auto)] ,,enable_all_modules="auto") if test "x$enable_all_modules" != "xauto"; then state="$enable_all_modules" MODULES="spoof_source sun_streams sql pacct mongodb json amqp stomp \ redis systemd geoip geoip2 riemann ipv6 smtp native python java java_modules" for mod in ${MODULES}; do modstate=$(eval echo \$enable_${mod}) if test "x$modstate" = "xauto"; then eval enable_${mod}=${state} fi done fi if test "x$wcmp_date" != "xno"; then wcmp_date="1" else wcmp_date="0" fi patheval() { OLD=$1 NEW=`eval echo $1` while test "x$OLD" != "x$NEW" do OLD=$NEW NEW=`eval echo $OLD` done echo $OLD } dnl *************************************************************************** dnl Checks for programs. AC_PROG_CC AC_PROG_CC_C99 AM_PROG_CC_C_O if test "x$ac_cv_prog_cc_c99" = "xno"; then AC_MSG_ERROR("C99 standard compliant C compiler required. Try GCC 3.x or later.") fi AC_PROG_YACC AM_PROG_LEX AC_PROG_MAKE_SET PKG_PROG_PKG_CONFIG LT_INIT([dlopen disable-static]) AC_PATH_PROG(PYTHON, python) if test -z "${PYTHON}"; then AC_MSG_ERROR([Python interpreter is required]) fi dnl *************************************************************************** dnl Validate yacc yacc_ok=0 if echo "$YACC" | grep -q bison; then # NOTE: m4 removes [], that's why it needs to be escaped bison_version=`$YACC --version | head -n 1 | sed 's/@<:@^0-9.@:>@*//'` bison_version_major=`echo $bison_version | cut -d. -f1` bison_version_minor=`echo $bison_version | cut -d. -f2` if test "$bison_version_major" -ge 2 -a "$bison_version_minor" -ge 4; then yacc_ok=1 fi if test "$bison_version_major" -gt 2; then yacc_ok=1 fi fi if test $yacc_ok = 0; then if test -f $srcdir/lib/cfg-grammar.c || test -f lib/cfg-grammar.c; then AC_MSG_WARN([No proper bison found, you'll not be able to change lib/cfg-grammar.y]) else AC_MSG_ERROR([syslog-ng requires bison 2.4 or later (traditional yacc is not enough). Your source tree seems to be from git, which doesn't have lib/cfg-grammar.c. Please install bison or use a distribution tarball.]) fi fi dnl *************************************************************************** dnl Validate flex if $LEX --version | grep "flex" >/dev/null; then lex_ok=1 else lex_ok=0 fi if test $lex_ok = 0 ; then if test -f $srcdir/lib/cfg-lex.c || test -f lib/cfg-lex.c; then AC_MSG_WARN([No flex found, you'll not be able to change lib/cfg-lex.l]) else AC_MSG_ERROR([syslog-ng requires flex in order to generate its config lexer. Your source tree seems to be from git, which doesn't have lib/cfg-lex.c. Please install flex or use a distribution tarball.]) fi fi dnl *************************************************************************** dnl Set up NO_PIE_LDFLAG: -no-pie is compatible with $CC. old_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -no-pie" AC_LINK_IFELSE([AC_LANG_SOURCE([int main(void) {return 0;}])], [no_pie_option_available=yes], [no_pie_option_available=no]) LDFLAGS="$old_LDFLAGS" if test "$no_pie_option_available" = "yes"; then NO_PIE_LDFLAG="-no-pie" fi AC_SUBST([NO_PIE_LDFLAG]) dnl *************************************************************************** dnl Set up CFLAGS if test "x$ac_compiler_gnu" = "xyes"; then CFLAGS="${CFLAGS} -Wall" if test "x$enable_debug" = "xyes"; then CFLAGS="${ac_cv_env_CFLAGS_value} -Wall -g" fi if test "x$enable_gprof" = "xyes"; then CFLAGS="${CFLAGS} -pg" fi if test "x$enable_gcov" = "xyes"; then CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage" fi else enable_extra_warnings="no" fi CFLAGS="${CFLAGS} -pthread" AX_CFLAGS_GCC_OPTION(-Wno-pointer-sign, CFLAGS_NOWARN_POINTER_SIGN) AC_SYS_LARGEFILE # FIXME: skip tests on unsupported platforms/architectures... case "$ostype" in HP-UX) if $CC -v 2>&1 | grep gcc > /dev/null; then CFLAGS="${CFLAGS} -U_XOPEN_SOURCE -U_XOPEN_SOURCE_EXTENDED -D_HPUX_SOURCE" LDFLAGS="${LDFLAGS} -lcl" AC_DEFINE(HAVE_BROKEN_PREAD, 1, [define if your platform has a broken pread/pwrite (e.g. HP-UX)]) AC_MSG_WARN([NOTE: on HP-UX with gcc, you might need to edit sys/socket.h manually or you'll get compilation errors]) fi ;; AIX) if test "$ac_cv_sys_large_files" -ne 0; then CFLAGS="${CFLAGS} -D_LARGE_FILES=1" fi # NOTE: The -brtl option to the linker must be set before calling the # configure script, as otherwise the generated libtool will behave # differently. We need the runtime linker during execution (hence the # -brtl) to load external modules. Also, please note that with -brtl the # linker behaves similarly to what is expected on other UNIX systems, # without it, it refuses to link an .so in if there's no reference from # the main program, even if there is a proper -llibname option. LDFLAGS="$LDFLAGS -Wl,-brtl" MODULE_LDFLAGS="-avoid-version -module" ;; Darwin) MODULE_LDFLAGS="-avoid-version -dylib" ;; OSF1) CFLAGS="${CFLAGS} -D_XOPEN_SOURCE=500 -D_XOPEN_SOURCE_EXTENDED -D_OSF_SOURCE -D_POSIX_C_SOURCE" ;; esac if test "$enable_dynamic_linking" = "auto" -a "$enable_mixed_linking" = "auto"; then enable_dynamic_linking="yes" enable_mixed_linking="no" fi linkopts=0 if test "x$enable_dynamic_linking" = "xyes"; then linkopts=`expr $linkopts + 1` fi if test "x$enable_mixed_linking" = "xyes"; then linkopts=`expr $linkopts + 1` fi if test "$linkopts" -gt 1; then AC_MSG_ERROR([You cannot specify multiple linking options at the same time (--enable-dynamic-linking, --enable-mixed-linking).]) fi if test "x$enable_dynamic_linking" = "xyes"; then enable_dynamic_linking="yes" enable_mixed_linking="no" linking_mode="dynamic" elif test "x$enable_mixed_linking" = "xyes"; then enable_dynamic_linking="no" enable_mixed_linking="yes" linking_mode="mixed" fi dnl *************************************************************************** dnl Check for --whole-archive flag dnl *************************************************************************** if test $ostype = "Darwin"; then WHOLE_ARCHIVE_OPT="-all_load" NO_WHOLE_ARCHIVE_OPT="-noall_load" else WHOLE_ARCHIVE_OPT="--whole-archive" NO_WHOLE_ARCHIVE_OPT="--no-whole-archive" fi dnl *************************************************************************** dnl Is the __thread keyword available? dnl *************************************************************************** AC_LINK_IFELSE([AC_LANG_PROGRAM( [[#include __thread int a; ]], [a=0;])], [ac_cv_have_tls=yes; AC_DEFINE_UNQUOTED(HAVE_THREAD_KEYWORD, 1, "Whether Transport Layer Security is supported by the system")]) dnl *************************************************************************** dnl How to do static linking? dnl *************************************************************************** AC_MSG_CHECKING(how to enable static linking for certain libraries) ldversion=`ld -V 2>&1 | head -n 1` if echo $ldversion | egrep "GNU|Solaris" > /dev/null; then LD_START_STATIC="-Wl,-Bstatic" LD_END_STATIC="-Wl,-Bdynamic" AC_MSG_RESULT(GNU or Solaris) elif test $ostype = "HP-UX" > /dev/null; then LD_START_STATIC="-Wl,-a,archive" LD_END_STATIC="-Wl,-a,shared_archive" AC_MSG_RESULT(HP-UX) elif test "$ostype" = "AIX"; then LD_START_STATIC="-Wl,-bstatic" LD_END_STATIC="-Wl,-bdynamic" AC_MSG_RESULT(AIX) else LD_START_STATIC="" LD_END_STATIC="" AC_MSG_RESULT([no clues, linking everything dynamically, please send appropriate ld arguments to syslog-ng@lists.balabit.hu]) fi dnl *************************************************************************** dnl Miscellanneous headers dnl *************************************************************************** AC_HEADER_STDC AC_CHECK_HEADER(dmalloc.h) AC_CHECK_HEADERS(strings.h \ getopt.h \ stropts.h \ sys/strlog.h \ door.h \ sys/capability.h \ sys/prctl.h \ utmp.h \ utmpx.h) AC_CHECK_HEADERS(tcpd.h) AC_CHECK_TYPES([struct ucred, struct cmsgcred], [], [], [#define _GNU_SOURCE 1 #define _DEFAULT_SOURCE 1 #include #include ]) dnl *************************************************************************** dnl Header checks dnl *************************************************************************** dnl Checks for typedefs, structures, and compiler characteristics. AC_STRUCT_TM AC_CACHE_CHECK(for SO_ACCEPTCONN, blb_cv_c_so_acceptconn, [AC_EGREP_CPP(SO_ACCEPTCONN, [ #include #include SO_ACCEPTCONN ], blb_cv_c_so_acceptconn=no, blb_cv_c_so_acceptconn=yes)]) if test "x$blb_cv_c_so_acceptconn" = "xyes"; then AC_DEFINE(HAVE_SO_ACCEPTCONN, 1, [SO_ACCEPTCONN is present]) fi AC_CHECK_MEMBER(struct tm.tm_gmtoff,AC_DEFINE(HAVE_STRUCT_TM_TM_GMTOFF,1,[Whether you have tm_gmtoff field in struct tm]),,[ #if TM_IN_SYS_TIME #include #else #include #endif]) AC_CHECK_MEMBER(struct msghdr.msg_control,AC_DEFINE(HAVE_CTRLBUF_IN_MSGHDR,1,[Whether you have msg_control field in msghdr in socket.h]),,[ #include ]) AC_CACHE_CHECK(for I_CONSLOG, blb_cv_c_i_conslog, [AC_EGREP_CPP(I_CONSLOG, [ #include I_CONSLOG ], blb_cv_c_i_conslog=no, blb_cv_c_i_conslog=yes)]) old_CPPFLAGS=$CPPFLAGS CPPFLAGS="-D_GNU_SOURCE -D_DEFAULT_SOURCE" AC_CACHE_CHECK(for O_LARGEFILE, blb_cv_c_o_largefile, [AC_EGREP_CPP(O_LARGEFILE, [ #include O_LARGEFILE ], blb_cv_c_o_largefile=no, blb_cv_c_o_largefile=yes)]) CPPFLAGS=$old_CPPFLAGS if test "x$blb_cv_c_o_largefile" = "xyes"; then AC_DEFINE(HAVE_O_LARGEFILE, 1, [O_LARGEFILE is present]) fi AC_CACHE_CHECK(for struct sockaddr_storage, blb_cv_c_struct_sockaddr_storage, [AC_EGREP_HEADER([sockaddr_storage], sys/socket.h, blb_cv_c_struct_sockaddr_storage=yes,blb_cv_c_struct_sockaddr_storage=no)]) if test "$blb_cv_c_struct_sockaddr_storage" = "yes"; then AC_DEFINE(HAVE_STRUCT_SOCKADDR_STORAGE,[1],[struct sockaddr_storage is present on your system]) fi AC_CACHE_CHECK(for struct sockaddr_in6, blb_cv_c_struct_sockaddr_in6, [AC_EGREP_HEADER([sockaddr_in6], netinet/in.h, blb_cv_c_struct_sockaddr_in6=yes,blb_cv_c_struct_sockaddr_in6=no)]) AC_CACHE_CHECK(for PR_SET_KEEPCAPS, blb_cv_keepcaps, [AC_EGREP_CPP(PR_SET_KEEPCAPS, [ #include PR_SET_KEEPCAPS ], blb_cv_keepcaps=no, blb_cv_keepcaps=yes)]) if test "x$blb_cv_keepcaps" = "xyes"; then AC_DEFINE(HAVE_PR_SET_KEEPCAPS, 1, [have PR_SET_KEEPCAPS]) fi if test "$ostype" != "Darwin" ; then AC_DEFINE(HAVE_ENVIRON, [1], [Specifies whether the environ global variable exists]) fi AC_CACHE_CHECK(for modern utmp, blb_cv_c_modern_utmp, [AC_TRY_COMPILE([ #ifdef HAVE_UTMPX_H #include #else #include #endif ], [ #ifdef HAVE_UTMPX_H struct utmpx ut; #else struct utmp ut; #endif return sizeof(ut.ut_type) & sizeof(ut.ut_user); ], blb_cv_c_modern_utmp=yes, blb_cv_c_modern_utmp=no)]) if test "x$blb_cv_c_modern_utmp" = "xyes"; then AC_DEFINE(HAVE_MODERN_UTMP, 1, [have modern utmp/utmpx format]) fi dnl *************************************************************************** dnl Checks for libraries AC_CHECK_LIB(door, door_create, BASE_LIBS="$BASE_LIBS -ldoor") AC_CHECK_LIB(socket, socket, BASE_LIBS="$BASE_LIBS -lsocket") AC_CHECK_LIB(rt, nanosleep, BASE_LIBS="$BASE_LIBS -lrt") AC_CHECK_LIB(nsl, gethostbyname, BASE_LIBS="$BASE_LIBS -lnsl") AC_CHECK_LIB(regex, regexec, REGEX_LIBS="-lregex") AC_CHECK_LIB(resolv, res_init, RESOLV_LIBS="-lresolv") AC_CHECK_FUNCS(strdup \ strtol \ strtoll \ strtoimax \ inet_aton \ inet_ntoa \ getopt_long \ getaddrinfo \ getnameinfo \ getutent \ getutxent \ pread \ pwrite \ strcasestr \ memrchr \ localtime_r \ gmtime_r \ strtok_r) old_LIBS=$LIBS LIBS=$BASE_LIBS AC_CHECK_FUNCS(clock_gettime) LIBS=$old_LIBS dnl *************************************************************************** dnl check inotify dnl *************************************************************************** AC_CHECK_FUNCS([inotify_init]) dnl *************************************************************************** dnl libevtlog headers/libraries dnl *************************************************************************** EVTLOG_LIBS="-Wl,${WHOLE_ARCHIVE_OPT} -L\$(top_builddir)/lib/eventlog/src -levtlog -Wl,${NO_WHOLE_ARCHIVE_OPT}" EVTLOG_NO_LIBTOOL_LIBS="-Wl,${WHOLE_ARCHIVE_OPT} -L\$(top_builddir)/lib/eventlog/src/.libs -levtlog -Wl,${NO_WHOLE_ARCHIVE_OPT}" EVTLOG_CFLAGS="-I\$(top_srcdir)/lib/eventlog/src -I\$(top_builddir)/lib/eventlog/src" dnl *************************************************************************** dnl libwrap headers/libraries dnl *************************************************************************** old_LIBS=$LIBS AC_CACHE_CHECK(for TCP wrapper library, blb_cv_c_lwrap, for libwrap in "-lwrap" "/usr/local/lib/libwrap.a"; do LIBS="$old_LIBS $libwrap" [AC_TRY_LINK(, [ } int allow_severity; int deny_severity; extern int hosts_access(void); int foo(void) { hosts_access(); ], [blb_cv_c_lwrap=$libwrap break], blb_cv_c_lwrap="") done ]) LIBS=$old_LIBS LIBWRAP_LIBS=$blb_cv_c_lwrap if test "x$enable_tcp_wrapper" = "xauto"; then AC_MSG_CHECKING(whether to enable TCP wrapper support) if test "x$ac_cv_header_tcpd_h" = "xyes" -a "x$blb_cv_c_lwrap" != "x"; then enable_tcp_wrapper=yes AC_MSG_RESULT(yes) else LIBWRAP_LIBS="" AC_MSG_RESULT(no) enable_tcp_wrapper=no fi elif test "x$enable_tcp_wrapper" != "xyes"; then LIBWRAP_LIBS="" fi dnl *************************************************************************** dnl -ldl dnl *************************************************************************** AC_CHECK_LIB(dl, dlsym, DL_LIBS="-ldl") dnl *************************************************************************** dnl libdbi headers/libraries dnl *************************************************************************** if test "x$enable_sql" = "xyes" || test "x$enable_sql" = "xauto"; then PKG_CHECK_MODULES(LIBDBI, dbi >= $LIBDBI_MIN_VERSION, with_libdbi="1", with_libdbi="0") if test "$with_libdbi" -eq 0; then dnl if libdbi has no .pc file (e.g., Ubuntu Precise), try it without one AC_CHECK_LIB(dbi, dbi_initialize_r, LIBDBI_LIBS="-ldbi"; LIBDBI_CFLAGS="-I/usr/include/dbi"; with_libdbi="1") fi AC_MSG_CHECKING(whether to enable SQL support) if test "$with_libdbi" -eq 1; then enable_sql="yes" AC_MSG_RESULT(yes) elif test "x$enable_sql" = "xyes"; then AC_MSG_RESULT(no) enable_sql="no" AC_MSG_ERROR([Could not find libdbi, and SQL support was explicitly enabled.]) else AC_MSG_RESULT(no) fi fi dnl *************************************************************************** dnl GLib headers/libraries dnl *************************************************************************** GLIB_ADDONS="gmodule-2.0 gthread-2.0" PKG_CHECK_MODULES(GLIB, glib-2.0 >= $GLIB_MIN_VERSION $GLIB_ADDONS,,) if test "$linking_mode" != "dynamic"; then # strip out -ldl & -lrt as it cannot be linked statically GLIB_LIBS=`echo $GLIB_LIBS | tr ' ' '\n' | egrep -v "^(-ldld?)|(-lrt)$" | tr '\n' ' '` old_LIBS=$LIBS LIBS="$LD_START_STATIC $GLIB_LIBS $LD_END_STATIC $BASE_LIBS" AC_CHECK_FUNC(g_hash_table_new, blb_cv_static_glib=yes, blb_cv_static_glib=no) LIBS=$old_LIBS fi old_CPPFLAGS=$CPPFLAGS CPPFLAGS="$GLIB_CFLAGS" old_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $GLIB_LIBS" old_LIBS=$LIBS LIBS="$LIBS $GLIB_LIBS" AC_CHECK_FUNCS(g_mapped_file_unref g_list_copy_deep) LIBS=$old_LIBS AC_CACHE_CHECK(sanity checking Glib headers, blb_cv_glib_sane, [AC_TRY_RUN([ #include int main() { if (sizeof(long) != GLIB_SIZEOF_LONG) return 1; return 0; } ], blb_cv_glib_sane=yes, blb_cv_glib_sane=no, blb_cv_glib_sane=yes)]) CPPFLAGS=$old_CPPFLAGS LDFLAGS=$old_LDFLAGS if test "x$blb_cv_glib_sane" = "xno"; then AC_MSG_ERROR([Glib headers inconsistent with current compiler setting. You might be using 32 bit Glib with a 64 bit compiler, check PKG_CONFIG_PATH]) fi if test "x$linking_mode" != "xdynamic" -a "x$blb_cv_static_glib" = "xno"; then AC_MSG_ERROR([static GLib libraries not found (a file named libglib-2.0.a), either link GLib dynamically using the --enable-dynamic-linking or install a static GLib]) fi dnl *************************************************************************** dnl geoip headers/libraries dnl *************************************************************************** if test "x$enable_geoip" = "xyes" || test "x$enable_geoip" = "xauto"; then if test "x$GEOIP_LIBS" != "x"; then AC_MSG_CHECKING([for GEOIP]) AC_MSG_RESULT([yes (GEOIP_LIBS set, will use that.)]) with_geoip="yes" else PKG_CHECK_MODULES(GEOIP, geoip, with_geoip="yes", with_geoip="no") fi if test "x$with_geoip" = "xno" && test "x$enable_geoip" = "xyes"; then AC_MSG_ERROR([Could not find libgeoip, and geoip support was explicitly enabled.]) fi enable_geoip="$with_geoip" fi dnl *************************************************************************** dnl geoip2 headers/libraries dnl *************************************************************************** if test "x$enable_geoip2" = "xyes" || test "x$enable_geoip2" = "xauto"; then if test "x$MAXMINDDB_LIBS" != "x"; then AC_MSG_CHECKING([for MAXMINDDB]) AC_MSG_RESULT([yes (MAXMINDDB_LIBS set, will use that.)]) with_maxminddb="yes" else AC_MSG_CHECKING([for MAXMINDDB]) AC_CHECK_LIB(maxminddb, MMDB_open, MAXMINDDB_LIBS="-lmaxminddb"; with_maxminddb="yes", with_maxminddb="no") AC_SUBST(MAXMINDDB_LIBS) fi if test "x$with_maxminddb" = "xno" && test "x$enable_geoip2" = "xyes"; then AC_MSG_ERROR([Could not find libmaxminddb, and geoip2 support was explicitly enabled.]) fi if test "x$with_maxminddb" = "xyes"; then AC_CONFIG_LINKS([modules/geoip2/tests/test.mmdb:modules/geoip2/tests/test.mmdb]) fi enable_geoip2="$with_maxminddb" fi dnl *************************************************************************** dnl pcre headers/libraries dnl *************************************************************************** if test "x$linking_mode" = "xmixed"; then # check if we have a pcre bundled in glib. In case glib is # dynamic it doesn't matter as glib doesn't export those # symbols. But in case glib is static, linking it through # glib and through libpcre would clash. old_LIBS="$LIBS" LIBS="$LD_START_STATIC $GLIB_LIBS $LD_END_STATIC $LIBS" AC_CHECK_FUNC(pcre_compile2, AC_MSG_ERROR([You cannot use a GLib embedded PCRE in mixed linking mode])) LIBS="$old_LIBS" fi PKG_CHECK_MODULES(PCRE, libpcre >= $PCRE_MIN_VERSION,, PCRE_LIBS="") if test -z "$PCRE_LIBS"; then AC_MSG_ERROR(Cannot find pcre version >= $PCRE_MIN_VERSION it is a hard dependency from syslog-ng 3.6 onwards) fi dnl *************************************************************************** dnl OpenSSL headers/libraries dnl *************************************************************************** # openssl is needed for: # * TLS support dnl check OpenSSL static linking PKG_CHECK_MODULES(OPENSSL, openssl >= $OPENSSL_MIN_VERSION,, AC_MSG_ERROR(Cannot find OpenSSL libraries with version >= $OPENSSL_MIN_VERSION it is a hard dependency from syslog-ng 3.7 onwards)) if test -n "$OPENSSL_LIBS" -a "$linking_mode" != "dynamic"; then dnl required for openssl, but only when linking statically AC_CHECK_LIB(z, inflate, ZLIB_LIBS="-lz") dnl Remove -ldl as it cannot be linked statically on some platforms, it'll be present in DL_LIBS OPENSSL_LIBS=`echo $OPENSSL_LIBS | tr ' ' '\n' | egrep -v "^-ldld?$" | tr '\n' ' '` old_LIBS=$LIBS LIBS="$LD_START_STATIC $OPENSSL_LIBS $ZLIB_LIBS $LD_END_STATIC $DL_LIBS" AC_CHECK_FUNC(SSL_library_init, blb_cv_static_openssl=yes, blb_cv_static_openssl=no) LIBS=$old_LIBS fi CPPFLAGS_SAVE="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $OPENSSL_CFLAGS" AC_CHECK_DECLS([SSL_CTX_get0_param],[], [], [[#include ]]) AC_CHECK_DECLS([X509_STORE_CTX_get0_cert],[], [], [[#include ]]) AC_CHECK_DECLS([X509_get_extension_flags], [], [], [[#include ]]) AC_CHECK_DECLS([EVP_MD_CTX_reset], [], [], [[#include ]]) AC_CHECK_DECLS([ASN1_STRING_get0_data], [], [], [[#include ]]) AC_CHECK_DECLS([DH_set0_pqg], [], [], [[#include ]]) CPPFLAGS="$CPPFLAGS_SAVE" dnl dnl Right now, openssl is never linked statically as it is only used by the dnl TLS build of the afsocket plugin which is loaded dynamically anyway. dnl dnl The static check remains though, because the core may need openssl in the dnl future, in which case it becomes relevant again. dnl dnl if test "x$linking_mode" != "xdynamic" -a "x$blb_cv_static_openssl" = "xno"; then dnl AC_MSG_ERROR([static OpenSSL libraries not found (libssl.a, libcrypto.a and their external dependencies like libz.a), either link OpenSSL statically using the --enable-dynamic-linking, or install a static OpenSSL]) dnl fi dnl *************************************************************************** dnl libnet headers/libraries dnl *************************************************************************** AC_MSG_CHECKING(for LIBNET) if test "x$with_libnet" = "x"; then LIBNET_CONFIG="`which libnet-config`" else LIBNET_CONFIG="$with_libnet/libnet-config" fi if test -n "$LIBNET_CONFIG" -a -x "$LIBNET_CONFIG"; then LIBNET_CFLAGS="`$LIBNET_CONFIG --defines`" LIBNET_LIBS="`$LIBNET_CONFIG --libs`" AC_MSG_RESULT(yes) else LIBNET_LIBS= AC_MSG_RESULT(no) fi if test "x$enable_spoof_source" = "xauto"; then AC_MSG_CHECKING(whether to enable spoof source support) if test "x$LIBNET_LIBS" != "x"; then enable_spoof_source=yes AC_MSG_RESULT(yes) else enable_spoof_source=no LIBNET_LIBS= LIBNET_CFLAGS= AC_MSG_RESULT(no) fi elif test "x$enable_spoof_source" = "xyes"; then if test "x$LIBNET_LIBS" = "x"; then AC_MSG_ERROR([Could not find libnet, and spoof source support was explicitly enabled.]) fi elif test "x$enable_spoof_source" = "xno"; then LIBNET_CFLAGS="" LIBNET_LIBS="" enable_spoof_source=no else AC_MSG_ERROR([Invalid value ($enable_spoof_source) for enable-spoof-source]) fi dnl *************************************************************************** dnl Criterion headers/libraries dnl *************************************************************************** PKG_CHECK_MODULES(CRITERION, criterion >= $CRITERION_MIN_VERSION, [with_criterion="system"], [AC_MSG_WARN([pkg-config was not able to find Criterion >= $CRITERION_MIN_VERSION]); with_criterion="no"]) dnl *************************************************************************** dnl ivykis headers/libraries dnl *************************************************************************** IVYKIS_INTERNAL_SOURCE_EXISTS="test -f $srcdir/lib/ivykis/src/iv_main_posix.c" if $IVYKIS_INTERNAL_SOURCE_EXISTS; then AC_CONFIG_SUBDIRS([lib/ivykis]) IVYKIS_SUBDIRS=lib/ivykis fi INTERNAL_IVYKIS_CFLAGS="" if test "x$with_ivykis" = "xinternal"; then if $IVYKIS_INTERNAL_SOURCE_EXISTS; then # these can only be used in lib as it assumes # the current directory just one below ivykis IVYKIS_LIBS="-Wl,${WHOLE_ARCHIVE_OPT} -L\$(top_builddir)/lib/ivykis/src -livykis -Wl,${NO_WHOLE_ARCHIVE_OPT}" IVYKIS_CFLAGS="-I\$(top_srcdir)/lib/ivykis/src/include -I\$(top_builddir)/lib/ivykis/src/include" INTERNAL_IVYKIS_CFLAGS="-I\${includedir}/syslog-ng/ivykis" # LIBS to use when libtool is not applicable (when linking the main syslog-ng executable in mixed linking mode) IVYKIS_NO_LIBTOOL_LIBS="-Wl,${WHOLE_ARCHIVE_OPT} -L\$(top_builddir)/lib/ivykis/src/.libs -livykis -Wl,${NO_WHOLE_ARCHIVE_OPT}" else AC_MSG_ERROR([Internal ivykis sources not found in lib/ivykis. This is a hard dependency, unable to build syslog-ng without them.]) fi else with_ivykis="system" PKG_CHECK_MODULES(IVYKIS, ivykis >= $IVYKIS_MIN_VERSION,,) # in case we're using a system installed ivykis, we can link against # it even without libtool and without extra linker arguments (as # we're linking dynamically) IVYKIS_NO_LIBTOOL_LIBS="$IVYKIS_LIBS" fi dnl *************************************************************************** dnl json headers/libraries dnl *************************************************************************** enable_json="no" if test "x$with_jsonc" = "xsystem" -o "x$with_jsonc" = "xauto"; then enable_json="yes" PKG_CHECK_EXISTS(json-c, json_module_name="json-c", PKG_CHECK_EXISTS(json, json_module_name="json")) PKG_CHECK_MODULES(JSON, $json_module_name >= $JSON_C_MIN_VERSION,[with_jsonc="system"], [JSON_LIBS=""; enable_json="no"]) if test "x$with_jsonc" = "xsystem" -a "x$enable_json" = "xno"; then AC_MSG_ERROR([json-c library development files cannot be not found on system!]) fi fi if test "x$with_jsonc" = "xinternal" -o "x$with_jsonc" = "xauto"; then AC_MSG_CHECKING(for JSON) if test -f "$srcdir/lib/jsonc/json.h"; then AC_CONFIG_SUBDIRS([lib/jsonc]) JSON_LIBS="\$(top_builddir)/lib/jsonc/libjson-c.la" JSON_DEPENDENCY="$JSON_LIBS" JSON_CFLAGS="-I\$(top_srcdir)/lib/jsonc -I\$(top_builddir)/lib/jsonc" JSON_SUBDIRS="lib/jsonc" enable_json="yes" with_jsonc="internal" else AC_MSG_WARN([Internal jsonc sources not found in lib/jsonc]) enable_json="no" fi AC_MSG_RESULT($enable_json) fi dnl *************************************************************************** dnl mongo-c-driver headers/libraries dnl *************************************************************************** if test x"$enable_legacy_mongodb_options" = x"no"; then enable_legacy_mongodb_options_bit=0 else enable_legacy_mongodb_options_bit=1 fi AC_DEFINE_UNQUOTED(ENABLE_LEGACY_MONGODB_OPTIONS, [$enable_legacy_mongodb_options_bit], [Support libmongo-client non-URI MongoDB options]) if test "x$with_mongoc" = "xauto"; then with_mongoc="system" PKG_CHECK_MODULES(LIBMONGO, libmongoc-1.0 >= $LMC_MIN_VERSION,,with_mongoc="auto-internal") elif test "x$with_mongoc" = "xsystem"; then PKG_CHECK_MODULES(LIBMONGO, libmongoc-1.0 >= $LMC_MIN_VERSION) fi if test "x$with_mongoc" = "xinternal" || test "x$with_mongoc" = "xauto-internal"; then with_mongoc="internal" if test -f "$srcdir/modules/afmongodb/mongo-c-driver/src/mongoc/mongoc.h"; then AC_CONFIG_SUBDIRS([modules/afmongodb/mongo-c-driver]) # these can only be used in modules/mongodb as it assumes # the current directory just one below mongo-c-driver LIBMONGO_LIBS="\ -L\$(top_builddir)/modules/afmongodb/mongo-c-driver \ -L\$(top_builddir)/modules/afmongodb/mongo-c-driver/src/libbson \ -lmongoc-1.0 -lbson $OPENSSL_LIBS" LIBMONGO_CFLAGS="\ -I\$(top_srcdir)/modules/afmongodb/mongo-c-driver/src/mongoc \ -I\$(top_srcdir)/modules/afmongodb/mongo-c-driver/src/libbson/src/bson \ -I\$(top_builddir)/modules/afmongodb/mongo-c-driver/src/libbson/src/bson \ -I\$(top_builddir)/modules/afmongodb/mongo-c-driver/src/mongoc \ " LIBMONGO_SUBDIRS="modules/afmongodb/mongo-c-driver" AC_CHECK_LIB(sasl2, prop_get, LIBMONGO_LIBS="$LIBMONGO_LIBS -lsasl2") else AC_MSG_WARN([Internal mongo-c-driver sources not found in modules/afmongodb/mongo-c-driver]) with_mongoc="no" fi fi if test "x$with_mongoc" = "xno"; then if test "x$enable_mongodb" = "xyes"; then AC_MSG_ERROR([Could not find mongo-c-driver, and MongoDB support was explicitly enabled.]) fi enable_mongodb="no" fi dnl *************************************************************************** dnl libesmtp headers/libraries dnl *************************************************************************** if test "x$enable_smtp" != "xno" && test "x$with_libesmtp" != "xno"; then libesmtp="yes" if test "x$with_libesmtp" != "xyes" && test "x$with_libesmtp" != "x"; then CPPFLAGS_SAVE="$CPPFLAGS" LDFLAGS_SAVE="$LDFLAGS" CPPFLAGS="$CPPFLAGS -I$with_libesmtp/include" LDFLAGS="$LDFLAGS -L$with_libesmtp/lib" AC_CHECK_HEADER(libesmtp.h, [LIBESMTP_CFLAGS="-I$with_libesmtp/include" LIBESMTP_LIBS="-L$with_libesmtp/lib -lesmtp"], [libesmtp=no]) CPPFLAGS="$CPPFLAGS_SAVE" LDFLAGS="$LDFLAGS_SAVE" else AC_MSG_CHECKING(for libESMTP) if libesmtp-config --version >/dev/null 2>&1; then AC_MSG_RESULT(yes) LIBESMTP_CFLAGS="`libesmtp-config --cflags`" LIBESMTP_LIBS="`libesmtp-config --libs`" else AC_MSG_RESULT(no) libesmtp=no fi fi if test "x$enable_smtp" = "xyes" && test "x$libesmtp" = "xno"; then AC_MSG_ERROR(libESMTP not found) fi enable_smtp=$libesmtp fi dnl *************************************************************************** dnl libcurl headers/libraries dnl *************************************************************************** if test "x$enable_http" != "xno" && test "x$with_libcurl" != "xno"; then libcurl="yes" if test "x$with_libcurl" != "xyes" && test "x$with_libcurl" != "x"; then CPPFLAGS_SAVE="$CPPFLAGS" LDFLAGS_SAVE="$LDFLAGS" CPPFLAGS="$CPPFLAGS -I$with_libcurl/include" LDFLAGS="$LDFLAGS -L$with_libcurl/lib" AC_CHECK_HEADER(curl/curl.h, [LIBCURL_CFLAGS="-I$with_libcurl/include" LIBCURL_LIBS="-L$with_libcurl/lib -lcurl"], [libcurl=no]) CPPFLAGS="$CPPFLAGS_SAVE" LDFLAGS="$LDFLAGS_SAVE" else AC_MSG_CHECKING(for libcurl) if curl-config --version >/dev/null 2>&1; then AC_MSG_RESULT(yes) LIBCURL_CFLAGS="`curl-config --cflags`" LIBCURL_LIBS="`curl-config --libs`" else AC_MSG_RESULT(no) libcurl=no fi fi if test "x$enable_http" = "xyes" && test "x$libcurl" = "xno"; then AC_MSG_ERROR(libcurl not found) fi enable_http=$libcurl fi dnl *************************************************************************** dnl libhiredis headers/libraries dnl *************************************************************************** if test "x$enable_redis" != "xno" && test "x$with_redis" != "xno"; then hiredis="yes" if test "x$with_libhiredis" != "xyes" && test "x$with_libhiredis" != "x"; then CFLAGS_SAVE="$CFLAGS" LDFLAGS_SAVE="$LDFLAGS" CFLAGS="$CFLAGS -I$with_libhiredis/include" LDFLAGS="$LDFLAGS -L$with_libhiredis/lib" AC_CHECK_HEADER(hiredis/hiredis.h, [HIREDIS_CFLAGS="-I$with_libhiredis/include" HIREDIS_LIBS="-L$with_libhiredis/lib -lhiredis"], [hiredis=no]) CFLAGS="$CFLAGS_SAVE" LDFLAGS="$LDFLAGS_SAVE" else hiredis="yes" PKG_CHECK_MODULES(HIREDIS, hiredis >= $HIREDIS_MIN_VERSION, , [AC_MSG_WARN([pkg-config was not able to find hiredis >= $HIREDIS_MIN_VERSION]) PKG_CHECK_MODULES(HIREDIS, libhiredis >= $HIREDIS_MIN_VERSION,, [AC_MSG_WARN([pkg-config was not able to find libhiredis >= $HIREDIS_MIN_VERSION]) hiredis=no])]) fi if test "x$enable_redis" = "xyes" && test "x$hiredis" = "xno"; then AC_MSG_ERROR(libHIREDIS not found) fi enable_redis=$hiredis fi dnl *************************************************************************** dnl rabbitmq-c headers/libraries dnl *************************************************************************** LIBRABBITMQ_INTERNAL_SOURCE_EXISTS="test -f $srcdir/modules/afamqp/rabbitmq-c/librabbitmq/amqp.h" if $LIBRABBITMQ_INTERNAL_SOURCE_EXISTS; then PYTHON_VERSION=`python -V 2>&1 | cut -d ' ' -f 2` PYTHON_MAJOR=`echo $PYTHON_VERSION | cut -d '.' -f 1` PYTHON_MINOR=`echo $PYTHON_VERSION | cut -d '.' -f 2` if test $PYTHON_MAJOR -eq 2 && test $PYTHON_MINOR -lt 5; then AC_MSG_WARN([Was about to execute rabbitmq configure script, but that requires Python >= 2.5, which you don't seem to have, reverting to system rabbitmq]) with_librabbitmq_client="system" else AC_CONFIG_SUBDIRS([modules/afamqp/rabbitmq-c]) LIBRABBITMQ_SUBDIRS="modules/afamqp/rabbitmq-c" fi fi if test "x$with_librabbitmq_client" = "xinternal"; then if $LIBRABBITMQ_INTERNAL_SOURCE_EXISTS; then # these can only be used in modules/amqp as it assumes # the current directory just one below rabbitmq-c LIBRABBITMQ_LIBS="-L\$(top_builddir)/modules/afamqp/rabbitmq-c/librabbitmq -lrabbitmq" LIBRABBITMQ_CFLAGS="-I\$(top_srcdir)/modules/afamqp/rabbitmq-c/librabbitmq -I\$(top_builddir)/modules/afamqp/rabbitmq-c/librabbitmq" else AC_MSG_WARN([Internal librabbitmq-client sources not found in modules/afamqp/rabbitmq-c]) with_librabbitmq_client="no" fi elif test "x$with_librabbitmq_client" = "xsystem"; then PKG_CHECK_MODULES(LIBRABBITMQ, librabbitmq >= $LIBRABBITMQ_MIN_VERSION,, enable_amqp="no") fi if test "x$with_librabbitmq_client" = "xno"; then if test "x$enable_amqp" = "xyes"; then AC_MSG_ERROR([Could not find librabbitmq-client, and AMQP support was explicitly enabled.]) fi enable_amqp="no" fi if test "x$enable_amqp" = "xno"; then with_librabbitmq_client="no" fi if test "x$enable_native" = "xyes" -o "x$enable_native" = "xauto"; then AC_CONFIG_FILES([syslog-ng-native-connector.pc]) fi dnl *************************************************************************** dnl riemann-client headers/libraries dnl *************************************************************************** if test "$enable_riemann" != "no"; then PKG_CHECK_MODULES(RIEMANN_CLIENT, riemann-client >= $LRC_MIN_VERSION,,riemann_found="no") if test "$riemann_found" = "no" && test "$enable_riemann" = "yes"; then AC_MSG_ERROR([Dependency for Riemann not found!]) fi if test "$riemann_found" = "no"; then enable_riemann="no"; else enable_riemann="yes"; fi if test "$enable_riemann" = "yes"; then old_CFLAGS=$CFLAGS CFLAGS=`pkg-config --cflags riemann-client` AC_CHECK_DECLS(RIEMANN_EVENT_FIELD_TIME_MICROS, [riemann_micros="yes"], [riemann_micros="no"], [[#include ]]) CFLAGS=$old_CFLAGS fi fi dnl *************************************************************************** dnl python checks dnl *************************************************************************** if test "x$enable_python" != "xno"; then if test "x$with_python" = "xauto"; then PKG_CHECK_MODULES(PYTHON, python3, python_found="yes", python_found="no") if test "$python_found" = "no"; then PKG_CHECK_MODULES(PYTHON, python2, python_found="yes", python_found="no") if test "$python_found" = "no"; then PKG_CHECK_MODULES(PYTHON, python, python_found="yes", python_found="no") fi fi else case "$with_python" in [[0-9]]) with_python="python${with_python}" ;; [[0-9]].[[0-9]]) with_python="python-${with_python}" ;; esac PKG_CHECK_MODULES(PYTHON, $with_python, python_found="yes", python_found="no") fi if test "x$python_found" = "xyes"; then old_LIBS=$LIBS LIBS="$LIBS $PYTHON_LIBS" AC_CHECK_FUNCS(PyUnicode_AsUTF8, with_python=python3, with_python=python2) LIBS=$old_LIBS fi if test "x$enable_python" = "xyes" -a "x$python_found" = "xno"; then AC_MSG_ERROR([Could not find the requested Python development libraries]) fi enable_python="$python_found" else with_python="" fi dnl *************************************************************************** dnl java headers/libraries dnl *************************************************************************** if test "x$enable_java" = "xauto" || test "x$enable_java" = "xyes"; then if test "x$enable_java" = "xauto"; then AC_CHECK_JAVA_VERSION([$JAVA_MIN_VERSION], [enable_java=yes], [enable_java=no]) else AC_CHECK_JAVA_VERSION([$JAVA_MIN_VERSION], [enable_java=yes], [AC_MSG_ERROR([Java not found])]) fi fi if test "x$enable_java" = "xyes"; then if test "x$enable_java_modules" = "xauto" || test "x$enable_java_modules" = "xyes"; then if test "x$enable_java_modules" = "xauto"; then AC_CHECK_GRADLE_VERSION([$GRADLE_MIN_VERSION], [enable_java_modules=yes], [enable_java_modules=no]) else AC_CHECK_GRADLE_VERSION([$GRADLE_MIN_VERSION], [enable_java_modules=yes], [AC_MSG_ERROR([Gradle not found])]) fi fi else if test "x$enable_java_modules" = "xyes"; then AC_MSG_ERROR([Could not build Java modules without Java]) elif test "x$enable_java_modules" = "xauto"; then AC_MSG_WARN([Could not build Java modules without Java]) enable_java_modules=no fi fi dnl *************************************************************************** dnl misc features to be enabled dnl *************************************************************************** if test "x$ac_cv_lib_door_door_create" = "xyes"; then AC_CHECK_HEADERS(pthread.h) AC_CHECK_LIB(pthread, pthread_create) fi AC_MSG_CHECKING(whether to enable Sun STREAMS support) if test "x$ac_cv_header_stropts_h" = "xyes" -a \ "x$ac_cv_header_sys_strlog_h" = "xyes" -a \ "x$enable_sun_streams" != "xno" -a \ "x$blb_cv_c_i_conslog" != "xno"; then enable_sun_streams=yes AC_MSG_RESULT(yes) else enable_sun_streams=no AC_MSG_RESULT(no) fi if test "x$enable_env_wrapper" = "xauto"; then if test "x$env_ld_library_path" != "x"; then enable_env_wrapper="yes" else enable_env_wrapper="no" fi fi if test "x$enable_ipv6" = "xauto"; then AC_MSG_CHECKING(whether to enable IPv6 support) if test "x$blb_cv_c_struct_sockaddr_in6" = "xyes"; then enable_ipv6=yes AC_MSG_RESULT(yes) else enable_ipv6=no AC_MSG_RESULT(no) fi fi if test "x$enable_linux_caps" = "xyes" -o "x$enable_linux_caps" = "xauto"; then if test "x$ac_cv_header_sys_capability_h" = "xyes"; then AC_CHECK_LIB(cap, cap_set_proc, LIBCAP_LIBS="-lcap"; has_linux_caps="yes", has_linux_caps="no") else has_linux_caps="no" fi AC_MSG_CHECKING(whether to enable Linux capability support) AC_MSG_RESULT([$has_linux_caps]) if test "x$enable_linux_caps" = "xyes" -a "x$has_linux_caps" = "xno"; then AC_MSG_ERROR([Cannot enable Linux capability support.]) fi enable_linux_caps="$has_linux_caps" fi if test "x$enable_mongodb" = "xauto"; then AC_MSG_CHECKING(whether to enable mongodb destination support) if test "x$with_mongoc" != "xno"; then enable_mongodb="yes" else enable_mongodb="no" fi AC_MSG_RESULT([$enable_mongodb]) fi if test "x$enable_amqp" = "xauto"; then AC_MSG_CHECKING(whether to enable amqp destination support) if test "x$with_librabbitmq_client" != "xno"; then enable_amqp="yes" else enable_amqp="no" fi AC_MSG_RESULT([$enable_amqp]) fi if test "x$enable_systemd" = "xauto"; then if test "$ostype" = "Linux" -a "$blb_cv_c_so_acceptconn" = "yes"; then enable_systemd=yes else enable_systemd=no fi fi if test "x$enable_systemd" != "xyes"; then if test "x$with_systemd_journal" = "xauto"; then with_systemd_journal=no fi fi if test "x$enable_systemd" = "xyes"; then PKG_CHECK_MODULES(libsystemd, libsystemd >= ${LIBSYSTEMD_MIN_VERSION}, have_libsystemd="yes", have_libsystemd="no") if test "x$with_systemdsystemunitdir" = "xyes"; then # no arguments, just --with-systemdsystemunitdir systemdsystemunitdir=`$PKG_CONFIG --variable=systemdsystemunitdir systemd` if test "$systemdsystemunitdir" = ""; then AC_MSG_ERROR([Error autodetecting systemdsystemunitdir, systemd pkg-config file not found?]) fi elif test "$systemdsystemunitdir" = "no"; then # --without-systemdsystemunitdir was specified systemdsystemunitdir="" else systemdsystemunitdir="$with_systemdsystemunitdir" fi if test "x$have_libsystemd" = "xno"; then PKG_CHECK_MODULES(libsystemd_daemon, libsystemd-daemon >= 31,enable_systemd="yes",enable_systemd="no") if test "x$with_systemd_journal" = "xauto"; then PKG_CHECK_MODULES(LIBSYSTEMD_JOURNAL, libsystemd-journal >= $JOURNALD_MIN_VERSION, with_systemd_journal=system, with_systemd_journal=optional) elif test "x$with_systemd_journal" = "xsystem"; then PKG_CHECK_MODULES(LIBSYSTEMD_JOURNAL, libsystemd-journal >= $JOURNALD_MIN_VERSION,, AC_MSG_ERROR([Detecting system related systemd-journal library failed])) fi libsystemd_CFLAGS="${LIBSYSTEMD_JOURNAL_CFLAGS} ${libsystemd_daemon_CFLAGS}" libsystemd_LIBS="${LIBSYSTEMD_JOURNAL_LIBS} ${libsystemd_daemon_LIBS}" AC_SUBST(libsystemd_CFLAGS) AC_SUBST(libsystemd_LIBS) else if test "x$with_systemd_journal" = "xauto"; then with_systemd_journal="system" fi fi fi PKG_CHECK_MODULES(UUID, uuid, enable_libuuid="yes", enable_libuuid="no") dnl *************************************************************************** dnl check if we have timezone variable in dnl *************************************************************************** AC_VAR_TIMEZONE_EXTERNALS dnl *************************************************************************** dnl default modules to be loaded dnl *************************************************************************** ### The default set of modules are those that provide functionality that ### were provided in syslog-ng 3.2 and prior, unless explicitly overridden ### by the user. ### ### New plugins can be loaded by explicit "@module foo" lines in the ### configuration file, or by the autoloading mechanism. if test "x$module_path" = "x"; then module_path="$moduledir" java_module_path="$moduledir"/java-modules fi CPPFLAGS="$CPPFLAGS $GLIB_CFLAGS $EVTLOG_CFLAGS $PCRE_CFLAGS $OPENSSL_CFLAGS $LIBNET_CFLAGS $LIBDBI_CFLAGS $IVYKIS_CFLAGS -D_GNU_SOURCE -D_DEFAULT_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" ######################################################## ## NOTES: on how syslog-ng is linked # # There are two major linking modes currently: # 1) dynamic: all libraries are linked dynamically, and assumed to be available as dynamic libraries # # 2) mixed: typical system provided libraries are linked dynamicaly, the # rest is linked statically (Glib etc). Please note that _only_ the # main syslog-ng executable is linked this way so that it can be # started early during startup, tools and unit tests are linked # dynamically the same way. # # The following variables are introduced and AC_SUBSTed to be used in Makefiles: # # SYSLOGNG_DEPS_LIBS: # includes all dependendent libraries used by binary that can be linked in mixed mode (e.g. only the syslog-ng binary). # # TOOL_DEPS_LIBS: # executables (e.g. tools & unit test programs) that link against # libsyslog-ng.so should be linked with this set of libraries. other # tools that do not use libsyslog-ng.so can use the _LIBS variables # directly. # # CORE_DEPS_LIBS: # libsyslog-ng.so is linked with this set of libraries. # # MODULE_DEPS_LIBS: # The set of libraries that modules should be linked against. Only to # satisfy their "core" dependency, any other libs that the core doesn't # depend on must be linked explicitly. # # MODULE_LDFLAGS: # The LDFLAGS to be passed when linking modules (may not contain # library references -l and such, only linker flags) # # Modules should be linked against libsyslog-ng.la and libraries that are # _NOT_ linked into libsyslog-ng.la no need to define a LIBS variable for # that. if test -z "$MODULE_LDFLAGS"; then MODULE_LDFLAGS="-avoid-version -module -no-undefined" fi MODULE_DEPS_LIBS="\$(top_builddir)/lib/libsyslog-ng.la" if test "x$linking_mode" = "xdynamic"; then SYSLOGNG_DEPS_LIBS="$LIBS $BASE_LIBS $GLIB_LIBS $EVTLOG_LIBS $RESOLV_LIBS $LIBCAP_LIBS $PCRE_LIBS $REGEX_LIBS $DL_LIBS" if test "x$with_ivykis" = "xinternal"; then # when using the internal ivykis, we're linking it statically into libsyslog-ng.so TOOL_DEPS_LIBS="$SYSLOGNG_DEPS_LIBS" CORE_DEPS_LIBS="$SYSLOGNG_DEPS_LIBS $IVYKIS_LIBS" else # otherwise everything needs to link against libivykis.so SYSLOGNG_DEPS_LIBS="$SYSLOGNG_DEPS_LIBS $IVYKIS_LIBS" TOOL_DEPS_LIBS="$SYSLOGNG_DEPS_LIBS" CORE_DEPS_LIBS="$SYSLOGNG_DEPS_LIBS" fi # syslog-ng binary is linked with the default link command (e.g. libtool) SYSLOGNG_LINK='$(LINK)' else SYSLOGNG_DEPS_LIBS="$LIBS $BASE_LIBS $RESOLV_LIBS $LD_START_STATIC -Wl,${WHOLE_ARCHIVE_OPT} $GLIB_LIBS $EVTLOG_NO_LIBTOOL_LIBS $PCRE_LIBS $REGEX_LIBS -Wl,${NO_WHOLE_ARCHIVE_OPT} $IVYKIS_NO_LIBTOOL_LIBS $LD_END_STATIC $LIBCAP_LIBS $DL_LIBS " TOOL_DEPS_LIBS="$LIBS $BASE_LIBS $GLIB_LIBS $EVTLOG_LIBS $RESOLV_LIBS $LIBCAP_LIBS $PCRE_LIBS $REGEX_LIBS $IVYKIS_LIBS $DL_LIBS" CORE_DEPS_LIBS="" # bypass libtool in case we want to do mixed linking because it # doesn't support -Wl,-Bstatic -Wl,-Bdynamic on a per-library basis. SYSLOGNG_LINK='$(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@' fi YFLAGS="-d" enable_value() { if test "x$1" = "xyes" ; then echo 1 else echo 0 fi } journald_mode() { if test "x$with_systemd_journal" = "xno"; then echo SYSLOG_NG_JOURNALD_OFF elif test "x$with_systemd_journal" = "xsystem"; then echo SYSLOG_NG_JOURNALD_SYSTEM else echo SYSLOG_NG_JOURNALD_OPTIONAL fi } AC_DEFINE_UNQUOTED(JOURNALD_OFF, 0, ["Disable systemd-journal source"]) AC_DEFINE_UNQUOTED(JOURNALD_OPTIONAL, 1, ["Enable systemd-journal source if journald is available"]) AC_DEFINE_UNQUOTED(JOURNALD_SYSTEM, 2, ["Force systemd-journal source to use system's journald"]) AC_DEFINE_UNQUOTED(VERSION, "$PACKAGE_VERSION", [version number]) AC_DEFINE_UNQUOTED(SOURCE_REVISION, "$SOURCE_REVISION", [source revision]) AC_DEFINE_UNQUOTED(LICENSE_VERSION, "$LICENSE_VERSION", [Required license version]) AC_DEFINE_UNQUOTED(PATH_PREFIX, "$prefix", [prefix directory]) AC_DEFINE_UNQUOTED(PATH_EXECPREFIX, "$exec_prefix", [execprefix directory]) AC_DEFINE_UNQUOTED(PATH_SYSCONFDIR, "$sysconfdir", [sysconfdir]) AC_DEFINE_UNQUOTED(PATH_LOCALSTATEDIR, "$localstatedir", [local state directory]) AC_DEFINE_UNQUOTED(PATH_PIDFILEDIR, "$pidfiledir", [local state directory]) AC_DEFINE_UNQUOTED(PATH_DATAROOTDIR, "$datarootdir", [data root directory]) AC_DEFINE_UNQUOTED(PATH_DATADIR, "$datadir", [data directory]) AC_DEFINE_UNQUOTED(PATH_CONFIG_INCLUDEDIR, "$config_includedir", [include directory]) AC_DEFINE_UNQUOTED(PATH_SCLDIR, "$scldir", [SCL directory]) AC_DEFINE_UNQUOTED(PATH_XSDDIR, "$xsddir", [XSD directory]) AC_DEFINE_UNQUOTED(PATH_LIBEXECDIR, "$libexecdir", [libexec directory]) if test -n "$timezonedir"; then AC_DEFINE_UNQUOTED(PATH_TIMEZONEDIR, "$timezonedir", [timezone base directory]) fi if test -n "$env_ld_library_path"; then AC_DEFINE_UNQUOTED(ENV_LD_LIBRARY_PATH, "$env_ld_library_path", [set LD_LIBRARY_PATH to this value]) fi AC_DEFINE_UNQUOTED(PATH_MODULEDIR, "$moduledir", [module installation directory]) AC_DEFINE_UNQUOTED(MODULE_PATH, "$module_path", [module search path]) AC_DEFINE_UNQUOTED(JAVA_MODULE_PATH, "$java_module_path", [java module search path]) AC_DEFINE_UNQUOTED(PATH_TOPSRC_DIR, "$abs_topsrcdir", [self-defined top_srcdir path]) AC_DEFINE_UNQUOTED(PACKAGE_NAME, "$PACKAGE_NAME", [package name]) AC_DEFINE_UNQUOTED(WITH_COMPILE_DATE, $wcmp_date, [Include the compile date in the binary]) AC_DEFINE_UNQUOTED(ENABLE_FORCED_SERVER_MODE, `enable_value $enable_forced_server_mode`, [Enable forced server mode]) AC_DEFINE_UNQUOTED(ENABLE_DEBUG, `enable_value $enable_debug`, [Enable debugging]) AC_DEFINE_UNQUOTED(ENABLE_LIBUUID, `enable_value $enable_libuuid`, [Enable libuuid support]) AC_DEFINE_UNQUOTED(ENABLE_GPROF, `enable_value $enable_gprof`, [Enable gcc profiling]) AC_DEFINE_UNQUOTED(ENABLE_MEMTRACE, `enable_value $enable_memtrace`, [Enable memtrace]) AC_DEFINE_UNQUOTED(ENABLE_SPOOF_SOURCE, `enable_value $enable_spoof_source`, [Enable spoof source support]) AC_DEFINE_UNQUOTED(ENABLE_IPV6, `enable_value $enable_ipv6`, [Enable IPv6 support]) AC_DEFINE_UNQUOTED(ENABLE_TCP_WRAPPER, `enable_value $enable_tcp_wrapper`, [Enable TCP wrapper support]) AC_DEFINE_UNQUOTED(ENABLE_LINUX_CAPS, `enable_value $enable_linux_caps`, [Enable Linux capability management support]) AC_DEFINE_UNQUOTED(ENABLE_ENV_WRAPPER, `enable_value $enable_env_wrapper`, [Enable environment wrapper support]) AC_DEFINE_UNQUOTED(ENABLE_SYSTEMD, `enable_value $enable_systemd`, [Enable systemd support]) AC_DEFINE_UNQUOTED(SYSTEMD_JOURNAL_MODE, `journald_mode`, [Systemd-journal support mode]) AC_DEFINE_UNQUOTED(HAVE_INOTIFY, `enable_value $ac_cv_func_inotify_init`, [Have inotify]) AC_DEFINE_UNQUOTED(ENABLE_PYTHONv2, `(echo "$with_python" | grep -Eq "python-?2.*") && echo 1 || echo 0`, [Python2 c api]) AC_DEFINE_UNQUOTED(ENABLE_PYTHONv3, `(echo "$with_python" | grep -Eq "python-?3.*") && echo 1 || echo 0`, [Python3 c api]) AC_DEFINE_UNQUOTED(HAVE_RIEMANN_MICROSECONDS, `enable_value $riemann_micros`, [Riemann microseconds support]) AM_CONDITIONAL(ENABLE_ENV_WRAPPER, [test "$enable_env_wrapper" = "yes"]) AM_CONDITIONAL(ENABLE_SYSTEMD, [test "$enable_systemd" = "yes"]) AM_CONDITIONAL(ENABLE_SYSTEMD_UNIT_INSTALL, [test "$systemdsystemunitdir" != ""]) AM_CONDITIONAL(ENABLE_SQL, [test "$enable_sql" = "yes"]) AM_CONDITIONAL(ENABLE_SUN_STREAMS, [test "$enable_sun_streams" = "yes"]) AM_CONDITIONAL(ENABLE_PACCT, [test "$enable_pacct" = "yes"]) AM_CONDITIONAL(ENABLE_MONGODB, [test "$enable_mongodb" = "yes"]) AM_CONDITIONAL(ENABLE_SMTP, [test "$enable_smtp" = "yes"]) AM_CONDITIONAL(ENABLE_HTTP, [test "$enable_http" = "yes"]) AM_CONDITIONAL(ENABLE_AMQP, [test "$enable_amqp" = "yes"]) AM_CONDITIONAL(ENABLE_STOMP, [test "$enable_stomp" = "yes"]) AM_CONDITIONAL(ENABLE_JSON, [test "$enable_json" = "yes"]) AM_CONDITIONAL(ENABLE_GEOIP, [test "$enable_geoip" = "yes"]) AM_CONDITIONAL(ENABLE_GEOIP2, [test "$enable_geoip2" = "yes"]) AM_CONDITIONAL(ENABLE_REDIS, [test "$enable_redis" = "yes"]) AM_CONDITIONAL(IVYKIS_INTERNAL, [test "x$with_ivykis" = "xinternal"]) AM_CONDITIONAL(JSON_INTERNAL, [test "x$JSON_SUBDIRS" != "x"]) AM_CONDITIONAL(LIBMONGO_INTERNAL, [test "x$LIBMONGO_SUBDIRS" != "x"]) AM_CONDITIONAL(LIBRABBITMQ_INTERNAL, [test "x$with_librabbitmq_client" = "xinternal"]) AM_CONDITIONAL(ENABLE_RIEMANN, [test "$enable_riemann" != "no"]) AM_CONDITIONAL(ENABLE_JOURNALD, [test "$with_systemd_journal" != "no"]) AM_CONDITIONAL(ENABLE_PYTHON, [test "$enable_python" != "no"]) AM_CONDITIONAL(ENABLE_JAVA, [test "$enable_java" = "yes"]) AM_CONDITIONAL(ENABLE_JAVA_MODULES, [test "$enable_java_modules" = "yes"]) AM_CONDITIONAL(ENABLE_MANPAGES, [test "$enable_manpages" != "no"]) AM_CONDITIONAL(ENABLE_NATIVE, [test "$enable_native" != "no"]) AM_CONDITIONAL(ENABLE_EXTRA_WARNINGS, [test "$enable_extra_warnings" = "yes"]) AM_CONDITIONAL(ENABLE_LEGACY_MONGODB_OPTIONS, [test x"$enable_legacy_mongodb_options" != x"no"]) AM_CONDITIONAL(ENABLE_CRITERION, [test "$with_criterion" != "no"]) AM_CONDITIONAL([HAVE_INOTIFY], [test x$ac_cv_func_inotify_init = xyes]) AC_SUBST(timezonedir) AC_SUBST(pidfiledir) AC_SUBST(moduledir) AC_SUBST(toolsdir) AC_SUBST(config_includedir) AC_SUBST(scldir) AC_SUBST(xsddir) AC_SUBST(systemdsystemunitdir) AC_SUBST(SYSLOGNG_LINK) AC_SUBST(SYSLOGNG_DEPS_LIBS) AC_SUBST(TOOL_DEPS_LIBS) AC_SUBST(CORE_DEPS_LIBS) AC_SUBST(MODULE_DEPS_LIBS) AC_SUBST(MODULE_LDFLAGS) AC_SUBST(BASE_LIBS) AC_SUBST(YFLAGS) AC_SUBST(LIBNET_LIBS) AC_SUBST(LIBNET_CFLAGS) AC_SUBST(LIBWRAP_LIBS) AC_SUBST(LIBWRAP_CFLAGS) AC_SUBST(ZLIB_LIBS) AC_SUBST(ZLIB_CFLAGS) AC_SUBST(LIBDBI_LIBS) AC_SUBST(LIBDBI_CFLAGS) AC_SUBST(LIBMONGO_LIBS) AC_SUBST(LIBMONGO_CFLAGS) AC_SUBST(LIBMONGO_SUBDIRS) AC_SUBST(LIBESMTP_CFLAGS) AC_SUBST(LIBESMTP_LIBS) AC_SUBST(LIBCURL_CFLAGS) AC_SUBST(LIBCURL_LIBS) AC_SUBST(LIBRABBITMQ_LIBS) AC_SUBST(LIBRABBITMQ_CFLAGS) AC_SUBST(LIBRABBITMQ_SUBDIRS) AC_SUBST(JSON_LIBS) AC_SUBST(JSON_CFLAGS) AC_SUBST(JSON_SUBDIRS) AC_SUBST(JSON_DEPENDENCY) AC_SUBST(IVYKIS_SUBDIRS) AC_SUBST(RESOLV_LIBS) AC_SUBST(CFLAGS_NOWARN_POINTER_SIGN) AC_SUBST(UUID_CFLAGS) AC_SUBST(UUID_LIBS) AC_SUBST(CURRDATE) AC_SUBST(RELEASE_TAG) AC_SUBST(SNAPSHOT_VERSION) AC_SUBST(SOURCE_REVISION) AC_SUBST(with_ivykis) AC_SUBST(INTERNAL_IVYKIS_CFLAGS) AC_SUBST(LIBSYSTEMD_JOURNAL_CFLAGS) AC_SUBST(LIBSYSTEMD_JOURNAL_LIBS) AC_SUBST(XSL_STYLESHEET) AX_PREFIX_CONFIG_H(syslog-ng-config.h, "SYSLOG_NG") AX_VALGRIND_CHECK AC_OUTPUT(dist.conf Makefile syslog-ng.spec syslog-ng.pc syslog-ng-add-contextual-data.pc libtest/syslog-ng-test.pc scripts/update-patterndb ) echo echo "syslog-ng Open Source Edition $PACKAGE_VERSION configured" echo " Edition settings:" echo " Release type : $RELEASE_TYPE" echo " Pretty version : $BROCHURE_VERSION" echo " Combined vers. : $COMBINED_VERSION" echo " Package name : $PACKAGE_NAME" echo " Compiler options:" echo " compiler : $CC" echo " compiler options : $CFLAGS $CPPFLAGS" echo " linker flags : $LDFLAGS $LIBS" echo " prefix : $prefix" echo " linking mode : $linking_mode" echo " embedded crypto : ${with_embedded_crypto:=no}" echo " __thread keyword : ${ac_cv_have_tls:=no}" echo " Test dependencies:" echo " Criterion : ${with_criterion:=no}" echo " Submodules:" echo " ivykis : $with_ivykis" echo " mongoc : $with_mongoc" echo " librabbitmq : $with_librabbitmq_client" echo " jsonc : $with_jsonc" echo " Features:" echo " Forced server mode : ${enable_forced_server_mode:=yes}" echo " Debug symbols : ${enable_debug:=no}" echo " GCC profiling : ${enable_gprof:=no}" echo " Memtrace : ${enable_memtrace:=no}" echo " IPV6 support : ${enable_ipv6:=no}" echo " spoof-source support : ${enable_spoof_source:=no}" echo " tcp-wrapper support : ${enable_tcp_wrapper:=no}" echo " Linux capability support : ${has_linux_caps:=no}" echo " Env wrapper support : ${enable_env_wrapper:=no}" echo " systemd support : ${enable_systemd:=no} (unit dir: ${systemdsystemunitdir:=none})" echo " systemd-journal support : ${with_systemd_journal:=no}" echo " libmongo-client options : ${enable_legacy_mongodb_options}" echo " Modules:" echo " Module search path : ${module_path}" echo " Sun STREAMS support (module): ${enable_sun_streams:=no}" echo " SQL support (module) : ${enable_sql:=no}" echo " PACCT module (EXPERIMENTAL) : ${enable_pacct:=no}" echo " MongoDB destination (module): ${enable_mongodb:=no}" echo " JSON support (module) : ${enable_json:=no}" echo " SMTP support (module) : ${enable_smtp:=no}" echo " HTTP support (module) : ${enable_http:=no}" echo " AMQP destination (module) : ${enable_amqp:=no}" echo " STOMP destination (module) : ${enable_stomp:=no}" echo " GEOIP support (module) : ${enable_geoip:=no}" echo " GEOIP2 support (module) : ${enable_geoip2:=no}" echo " Redis support (module) : ${enable_redis:=no}" echo " Riemann destination (module): ${enable_riemann:=no}, microseconds: ${riemann_micros:=no}" echo " python : ${enable_python:=no} (pkg-config package: ${with_python:=none})" echo " java : ${enable_java:=no}" echo " java modules : ${enable_java_modules:=no}" echo " native bindings : ${enable_native:=no}" syslog-ng-syslog-ng-3.13.2/contrib/000077500000000000000000000000001321171025300170755ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/Makefile.am000066400000000000000000000047011321171025300211330ustar00rootroot00000000000000dist_sbin_SCRIPTS += \ contrib/syslog-ng-debun EXTRA_DIST += \ contrib/README \ \ contrib/README.syslog-ng-debun \ contrib/syslog-ng-debun \ \ contrib/init.d.solaris \ contrib/init.d.HP-UX \ contrib/init.d.RedHat \ contrib/init.d.SuSE \ contrib/init.d.SunOS \ contrib/init.d.solaris \ contrib/init.d.RedHat-7.3 \ \ contrib/syslog-ng.conf.HP-UX \ contrib/syslog-ng.conf.RedHat \ contrib/syslog-ng.conf.SunOS \ \ contrib/syslog2ng \ contrib/syslog-ng.vim \ \ contrib/syslog-ng.conf.doc \ contrib/relogger.pl \ \ contrib/fedora-packaging/syslog-ng.conf \ contrib/fedora-packaging/syslog-ng.init \ contrib/fedora-packaging/syslog-ng.sysconfig \ contrib/fedora-packaging/syslog-ng.logrotate \ \ contrib/rhel-packaging/syslog-ng.conf \ contrib/rhel-packaging/syslog-ng.init \ contrib/rhel-packaging/syslog-ng.logrotate \ \ contrib/aix-packaging/syslog-ng.conf \ \ contrib/hpux-packaging/syslog-ng.conf \ contrib/hpux-packaging/syslog-ng.init \ \ contrib/lfs-packaging/Makefile.lfs \ contrib/lfs-packaging/README.lfs \ contrib/lfs-packaging/syslog-ng.init.lfs \ \ contrib/cygwin-packaging/cygwin-postinstall \ contrib/cygwin-packaging/syslog-ng-config \ \ contrib/solaris-packaging/solaris10_install.txt \ contrib/solaris-packaging/syslog-ng.example.xml \ contrib/solaris-packaging/syslog-ng-sol11-smf.example.xml \ contrib/solaris-packaging/syslog-ng.method \ \ contrib/freebsd-packaging/syslog-ng.rc.d \ contrib/freebsd-packaging/syslog-ng.conf.example \ \ contrib/selinux/README \ contrib/selinux/labels.txt \ contrib/selinux/syslog_ng.sh \ contrib/selinux/src/syslog_ng.el67.te.in \ contrib/selinux/src/root_unsafe/syslog_ng.el7.fc.in \ contrib/selinux/src/root_unsafe/syslog_ng.el6.fc.in \ contrib/selinux/src/root_unsafe/syslog_ng.el5.fc.in \ contrib/selinux/src/root_safe/syslog_ng.el7.fc.in \ contrib/selinux/src/root_safe/syslog_ng.el6.fc.in \ contrib/selinux/src/root_safe/syslog_ng.el5.fc.in \ contrib/selinux/src/syslog_ng.el5.te.in \ contrib/selinux/src/syslog_ng.el6.0to4.te.in \ \ contrib/apparmor/opt.syslog-ng.sbin.syslog-ng \ \ contrib/balabit-initscripts/init.d \ contrib/balabit-initscripts/init.d.freebsd \ contrib/balabit-initscripts/init-functions \ \ contrib/upstart/syslog-ng.conf.upstart \ contrib/systemd/syslog-ng@.service \ contrib/systemd/syslog-ng@default \ \ contrib/valgrind/syslog-ng.supp if ENABLE_SYSTEMD_UNIT_INSTALL systemdsystemunit_DATA = contrib/systemd/syslog-ng@.service endif syslog-ng-syslog-ng-3.13.2/contrib/README000066400000000000000000000020151321171025300177530ustar00rootroot00000000000000This directory contains unsorted user contributions of syslog-ng. They are not maintained, nor supported, but may be useful to some. NOTE: these were simply copied from syslog-ng 1.6 distribution, therefore might not work out-of-the-box for syslog-ng 2.0. init.d.HP-UX - sample init script for HP-UX init.d.RedHat - sample init script for RedHat GNU/Linux init.d.SunOS - sample init script for Sun Solaris init.d.solaris - another sample init script for Sun Solaris syslog-ng.conf.HP-UX - sample configuration for HP-UX syslog-ng.conf.RedHat - sample configuration for RedHat GNU/Linux syslog-ng.conf.SunOS - sample configuration for SunOS syslog-ng.conf.doc - sample configuration file with inline documentation as comments syslog-ng.vim - vim syntax file for syslog-ng.conf syslog2ng - script to convert old syslog.conf to syslog-ng.conf relogger.pl - script to replay syslog messages at the original rate fedora-packaging - directory containing files related to Fedora packaging syslog-mc - syslog multicast client syslog-ng-syslog-ng-3.13.2/contrib/README.syslog-ng-debun000066400000000000000000000044011321171025300227700ustar00rootroot00000000000000README for syslog-ng-debun, the Syslog-ng DEBUg buNdle generator The main purpose of this software is to collect and save information about your syslog-ng installation / implementation for that case, if you want to ask help about your syslog-ng related problem. usage examples: # syslog-ng-debun -r Create a simple debug bundle, collecting about your environmental information. eg. list of packages, which contains the word: syslog ldd of your syslog-binary, etc. # syslog-ng-debun -r -l Like previuos, but left out some information, which may you think harm your privacy. Eg fstab, df's output, mount info, ip / network interface configuration, DNS resolv info, and process tree is NOT collected. # syslog-ng-debun -r -d Besides collecting information, it stops system's syslog-ng, then start in debug mode with -Fedv --enable-core, and until you do not press enter, it stays in that mode. Debug's output is collected into a separate file, and also collected. # syslog-ng-debun -r -p Will run packet capture with filter: "port 514 or port 601 or port 53" Also wait for pressing enter, like debug mode. # syslog-ng-debun -r -p -t 10 Like the previous one, but do not wait for pressing enter, it will exit from tcpdump mode after 10 seconds. (noninteractive debug mode) # syslog-ng-debun -r -P "host 1.2.3.4" -D "-Fev --enable-core" packet capturing's filter will be changed from default to host 1.2.3.4 Debugging paramters will be changed from default to -Fev --enable-core And, since a timout is not given, it will wait for pressing enter. # syslog-ng-debun -r -p -d -w 5 -t 10 Collect pcap and debug mode output following this scenario: * start packet capture with default params * wait 5 seconds * stop system's syslog-ng * start syslog-ng in debug mode with default params, syslog's debug messages are also appearing on your console * wait 10 seconds * stop syslog-ng debuging * start system's syslog-ng * stops packet capturing # syslog-ng-debun -r -W /var/tmp -P /usr/local Collect debug info, but the temporary files, and the result will be in /var/tmp instead of /tmp and don't try to search syslog-ng in /opt/syslog-ng, it will search in /usr/local # syslog-ng-debun -r -s -t 10 Collect debug info, start tracing, and exit tracing after 10 seconds syslog-ng-syslog-ng-3.13.2/contrib/aix-packaging/000077500000000000000000000000001321171025300216005ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/aix-packaging/syslog-ng.conf000066400000000000000000000041641321171025300243760ustar00rootroot00000000000000# # sample configuration file for syslog-ng on AIX # users should customize to fit their needs # # log syslog-ng's own messages to /var/log/syslog-ng.log source s_internal { internal(); }; destination d_syslognglog { file("/var/log/syslog-ng.log" owner("root") group("adm") perm(0640)); }; log { source(s_internal); destination(d_syslognglog); }; # log everything to /var/log/messages source s_local { unix-dgram("/dev/log"); }; destination d_messages { file("/var/log/messages" owner("root") group("adm") perm(0640)); }; log { source(s_local); destination(d_messages); }; # Remote logging # #source s_remote { # tcp(ip(0.0.0.0) port(514)); # udp(ip(0.0.0.0) port(514)); #}; # #destination d_separatedbyhosts { # file("/var/log/syslog-ng/$HOST/messages" owner("root") group("root") perm(0640) dir_perm(0750) create_dirs(yes)); #}; # #log { # source(s_remote); # destination(d_separatedbyhosts); #}; # # Local filters examples # #filter f_messages { level(info..emerg); }; #filter f_secure { facility(authpriv); }; #filter f_mail { facility(mail); }; #filter f_cron { facility(cron); }; #filter f_emerg { level(emerg); }; #filter f_spooler { level(crit..emerg) and facility(uucp, news); }; #filter f_local7 { facility(local7); }; # # Local destination examples # #destination d_secure { file("/var/log/secure"); }; #destination d_maillog { file("/var/log/maillog"); }; #destination d_cron { file("/var/log/cron"); }; #destination d_console { usertty("root"); }; #destination d_spooler { file("/var/log/spooler"); }; #destination d_bootlog { file("/var/log/boot.log"); }; # # Local log examples - order DOES matter ! # #log { source(s_local); filter(f_emerg); destination(d_console); }; #log { source(s_local); filter(f_secure); destination(d_secure); flags(final); }; #log { source(s_local); filter(f_maillog); destination(d_maillog); flags(final); }; #log { source(s_local); filter(f_cron); destination(d_cron); flags(final); }; #log { source(s_local); filter(f_spooler); destination(d_spooler); }; #log { source(s_local); filter(f_local7); destination(d_bootlog); }; #log { source(s_local); filter(f_messages); destination(d_messages); }; syslog-ng-syslog-ng-3.13.2/contrib/apparmor/000077500000000000000000000000001321171025300207165ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/apparmor/opt.syslog-ng.sbin.syslog-ng000066400000000000000000000022031321171025300262340ustar00rootroot00000000000000# $Id: opt.syslog-ng.sbin.syslog-ng 12 2008-08-19 16:68:41Z folti $ # ------------------------------------------------------------------ # # Copyright (C) 2002-2005 Novell/SUSE # # This program is free software; you can redistribute it and/or # modify it under the terms of version 2 of the GNU General Public # License published by the Free Software Foundation. # # ------------------------------------------------------------------ #include /opt/syslog-ng/sbin/syslog-ng { #include #include #include capability sys_admin, capability sys_tty_config, capability dac_override, capability dac_read_search, /dev/log wl, /var/lib/*/dev/log wl, /dev/tty* w, /dev/xconsole rw, /etc/syslog.conf r, /boot/System.map* r, /proc/kmsg r, /opt/syslog-ng/sbin/syslog-ng rmix, /var/log/** rw, /var/run/syslog-ng.pid rwl, /var/run/utmp rw, /var/spool/compaq/nic/messages_fifo rw, } syslog-ng-syslog-ng-3.13.2/contrib/balabit-initscripts/000077500000000000000000000000001321171025300230445ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/balabit-initscripts/init-functions000066400000000000000000000117231321171025300257440ustar00rootroot00000000000000# /lib/lsb/init-functions replacement for syslog-ng Premium Edition RED= YELLOW= NORMAL= FANCYTTY= PSOPTS= ECHO=echo OS=`uname -s` # LSB Functions # ripped from ubuntu/debian lsb log_use_fancy_output() { case "$TERM" in dumb|raw|serial|vt*|cons*|unknown) return 1 ;; *) if [ -n "$FANCYTTY" ] && [ $FANCYTTY -ne 1 ]; then return 1 fi RED="\033[31m" YELLOW="\033[33m" NORMAL="\033[0m" return 0 ;; esac return 1 } log_success_msg() { $ECHO "$@" } log_failure_msg() { log_use_fancy_output $ECHO "${RED}$@${NORMAL}" } log_warning_msg() { log_use_fancy_output $ECHO "${YELLOW}$@${NORMAL}" } # NON-LSB Functions log_begin_msg() { if [ -z "$1" ]; then return 1 fi $ECHO "$@\c " } log_daemon_msg() { if [ -z "$1" ];then return 1 fi if [ -z "$2" ]; then $ECHO "$1:\c " return fi $ECHO "$1: $2\c " } log_progress_msg() { if [ -z "$1" ]; then return 1 fi if [ $1 -eq 0 ]; then $ECHO "." else $ECHO " failed" fi } log_end_msg() { if [ -z "$1" ]; then return 1 fi log_fancy_output if [ $1 -eq 0 ];then $ECHO "." else $ECHO "${RED}failed!${NORMAL}" fi return $1 } log_action_msg() { $ECHO "$@." } log_action_begin_msg() { $ECHO "$@...\c " } log_action_cont_msg() { $ECHO "$@...\c " } log_action_end_msg() { if [ -z "$2" ]; then end="." else end=" ($2)." fi log_fancy_output if [ $1 -eq 0 ]; then $ECHO "done${end}" else $ECHO "${RED}failed${end}${NORMAL}" fi } # overide log_*_msg if the init-functions file exits on the system [ -f /lib/lsb/init-functions ] && . /lib/lsb/init-functions # in these three cases we have to use our functions unalias start_daemon 2>/dev/null unalias killproc 2>/dev/null unalias pidofproc 2>/dev/null disable_xpg_echo() { # \X chars only passed to echo under bash, if xpg_echo enabled or echo -e # used on Linux. if [ -n "$BASH_VERSION" ];then shopt -s xpg_echo fi } case $OS in # default ps -e cuts the process' name at 8 characters, so we have to list it # in a long form SunOS) PSOPTS=" -o pid -o tty -o time -o comm" disable_xpg_echo ;; Linux) if [ -z "$BASH_VERSION" ]; then # beware of dash's builtin echo ... ECHO="/bin/echo -e" fi ;; *) disable_xpg_echo ;; esac _checkpid() { _pid=$1 _proc=$2 for _ret in `ps -e $PSOPTS | grep "$_proc" | sed -e 's/^ *//' -e 's/ .*//'`; do if [ -n "$_ret" ] && [ "$_ret" = "$_pid" ]; then return 0 fi done return 1 } _pid_from_pidfile() { pidfile=$1 procname=$2 pid= if [ -f "$pidfile" ];then pid=`head -1 $pidfile 2> /dev/null` if [ $? -ne 0 ]; then # on slow machines (or ones under high load) the pidfile could be # erased between -f and `head` ... return 3 fi if _checkpid $pid $procname; then return 0 fi return 1 # pidfile exist, but proc not running fi return 3 # proc not running } pidofproc() { proc= pidfile= if [ "$1" = "-p" ];then pidfile=$2 shift shift fi if [ -z "$1" ];then echo "Usage: pidofproc [-p pidfile] {program}" return 1 fi proc=$1 shift base=`basename ${proc}` if [ -z "${pidfile}" ]; then pidfile=/var/run/${base}.pid fi if [ -f ${pidfile} ];then _pid_from_pidfile "${pidfile}" "${base}" _ret=$? if [ $_ret -eq 0 ]; then if kill -0 ${pid} 2> /dev/null; then echo "$pid" return 0 fi else return $_ret fi fi return 4 } start_daemon() { proc= pidfile= force= nice= if [ "$1" = "-f" ]; then force="force" shift fi if [ "$1" = "-n" ];then nice="nice $2" shift shift fi if [ "$1" = "-p" ];then pidfile=$2 shift shift fi if [ -z "$1" ];then echo "Usage: start_daemon [-f] [-n nicelevel] [-p pidfile] {program} [args]" return 1 fi proc=$1 shift base=`basename ${proc}` if [ -z "${pidfile}" ]; then pidfile=/var/run/${base}.pid fi _pid_from_pidfile "${pidfile}" "${base}" if [ -n "$pid" ] && [ -z "$force" ];then return fi $nice $proc $* return $? } killproc() { proc= signal=-15 pidfile= if [ "$1" = "-p" ];then pidfile=$2 shift shift fi if [ -z "$1" ];then echo "Usage: killproc [-p pidfile] {program}" return 1 fi proc=$1 shift if [ -n "$1" ];then signal=$1 echo "${signal}" | grep '^-' >/dev/null 2>&1 if [ $? -ne 0 ]; then signal="-${signal}" fi fi base=`basename $proc` if [ -z "${pidfile}" ]; then pidfile=/var/run/${base}.pid fi _pid_from_pidfile "${pidfile}" "${base}"; _ret=$? if [ $_ret -ne 0 ];then rm -f ${pidfile} return $_ret fi if [ -n "$pid" ]; then kill $signal $pid _status="$?" if [ $_status -eq 0 ];then pidofproc -p "${pidfile}" "$proc" >/dev/null || rm -f "${pidfile}" fi fi return $_retval } # vim: ft=sh ts=2 expandtab syslog-ng-syslog-ng-3.13.2/contrib/balabit-initscripts/init.d000066400000000000000000000156241321171025300241640ustar00rootroot00000000000000#!/bin/sh # syslog-ng This starts and stops syslog-ng # # chkconfig: - 12 88 # processname: /opt/syslog-ng/sbin/syslog-ng # config: /opt/syslog-ng/etc/syslog-ng.conf # config: /etc/sysconfig/syslog-ng # pidfile: /var/run/syslog-ng.pid ### BEGIN INIT INFO # Provides: syslog # Description: reads and logs messages to the system console, log \ # files, other machines and/or users as specified by \ # its configuration file. # Short-Description: Next-generation syslog server. Proprietary edition. # Required-Start: $local_fs # Required-Stop: $local_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 ### END INIT INFO OS=`uname -s` DEFAULTFILE=/etc/default/syslog-ng [ -f ${DEFAULTFILE} ] && . ${DEFAULTFILE} SYSLOGNG_PREFIX=${SYSLOGNG_PE_PREFIX:-/opt/syslog-ng} export SYSLOGNG_PREFIX SYSLOGNG="$SYSLOGNG_PREFIX/sbin/syslog-ng" CONFFILE=$SYSLOGNG_PREFIX/etc/syslog-ng.conf PIDFILE=$SYSLOGNG_PREFIX/var/run/syslog-ng.pid SYSLOGPIDFILE="/var/run/syslog.pid" SLNG_INIT_FUNCTIONS=$SYSLOGNG_PREFIX/lib/init-functions MAXWAIT=30 # for RedHat... SUBSYSDIR=/var/lock/subsys retval=0 # in HPUX, PATH for init scripts does not contain standard dirs for binaries if [ "$OS" = "HP-UX" ]; then PATH=$PATH:/bin:/usr/bin:/sbin:/usr/sbin fi # OS specific I-didn't-do-anything exit function. exit_noop() { case $OS in HP-UX) exit 2 ;; *) exit 0 ;; esac } # Platform specific echo -n implementation. echo_n() { case "$OS" in SunOS) echo "$@\c " ;; HP-UX) echo " $@\c " ;; *) echo -n "$@" ;; esac } test -x ${SYSLOGNG} || exit_noop test -r ${CONFFILE} || exit_noop if [ -f /etc/lsb-release ]; then . /etc/lsb-release fi if [ -f "/etc/redhat-release" ];then # redhat uses a different syslogd pidfile... SYSLOGPIDFILE="/var/run/syslogd.pid" fi if [ "$OS" = "SunOS" ] || [ "$OS" = "Solaris" ];then if [ "`uname -r`" = "5.8" ];then SYSLOGPIDFILE="/etc/syslog.pid" fi fi . $SLNG_INIT_FUNCTIONS case "$OS" in Linux) SYSLOGNG_OPTIONS="--no-caps" ;; esac #we source /etc/default/syslog-ng if exists [ -r /etc/default/syslog-ng ] && . /etc/default/syslog-ng # Source config on RPM systems [ -r /etc/sysconfig/syslog-ng ] && . /etc/sysconfig/syslog-ng #we source /etc/default/syslog-ng if exists [ -r $SYSLOGNG_PREFIX/etc/default/syslog-ng ] && \ . $SYSLOGNG_PREFIX/etc/default/syslog-ng create_xconsole() { if grep -v '^#' $CONFFILE | grep /dev/xconsole >/dev/null 2>&1; then if [ ! -e /dev/xconsole ]; then mknod -m 640 /dev/xconsole p fi fi } check_syntax() { ${SYSLOGNG} --no-caps --syntax-only _rval=$? [ $_rval -eq 0 ] || exit $_rval } slng_waitforpid() { _pid=$1 _process=$2 _cnt=$MAXWAIT # no pid, return... [ -z "$_pid" ] && return 0 _procname=`basename $_process` while [ $_cnt -gt 0 ]; do _numproc=`ps -p $_pid $PSOPTS | grep $_procname | wc -l` if [ $_numproc -eq 0 ]; then return 0 fi _cnt=`expr $_cnt - 1` sleep 1 done return 1 } returnmessage() { _rval=$1 is_debian=0 case "$OS" in Linux) res=`cat /etc/issue | grep Debian` is_debian=$? ;; esac if [ $_rval -ne 0 ];then if [ $is_debian -eq 0 ];then log_failure_msg "failed" else log_failure_msg fi else if [ $is_debian -eq 0 ];then log_success_msg "OK" else log_success_msg fi fi } syslogng_start() { echo_n "Starting syslog-ng: " PID=`pidofproc -p ${PIDFILE} ${SYSLOGNG} | head -1` if [ -n "$PID" ] && [ $PID -gt 0 ] ;then log_success_msg "already running: $PID" return $retval fi rm -f ${PIDFILE} start_daemon -f -p ${PIDFILE} ${SYSLOGNG} ${SYSLOGNG_OPTIONS} retval=$? returnmessage $retval if [ $retval -eq 0 ];then if [ "$OS" = "Linux" ] && [ -d $SUBSYSDIR ];then touch $SUBSYSDIR/syslog-ng fi # remove symlinks if [ -h $SYSLOGPIDFILE ];then rm -f $SYSLOGPIDFILE fi if [ ! -f $SYSLOGPIDFILE ];then ln -s $PIDFILE $SYSLOGPIDFILE fi fi return $retval } # Can't name the function stop, because HP-UX has a default alias named stop... syslogng_stop() { echo_n "Stopping syslog-ng: " PID=`pidofproc -p ${PIDFILE} ${SYSLOGNG} | head -1` retval=$? if [ $retval -ne 0 ] || [ -z "$PID" ];then return $retval fi killproc -p ${PIDFILE} ${SYSLOGNG} retval=$? if [ $retval -eq 0 ];then slng_waitforpid "$PID" ${SYSLOGNG} if [ $? -ne 0 ]; then retval=$? log_failure_msg " Timeout" killproc -p ${PIDFILE} ${SYSLOGNG} -KILL else returnmessage $retval fi fi if [ $retval -eq 0 ];then rm -f $SUBSYSDIR/syslog-ng ${PIDFILE} if [ -h $SYSLOGPIDFILE ];then rm -f $SYSLOGPIDFILE fi fi return $retval } syslogng_restart() { check_syntax echo_n "Restarting syslog-ng: " syslogng_stop syslogng_start return $retval } syslogng_reload() { echo_n "Reloading syslog-ng's config file: " check_syntax killproc -p ${PIDFILE} ${SYSLOGNG} -HUP retval=$? returnmessage $retval return $retval } syslogng_status() { echo_n "Checking for syslog-ng service: " pid=`pidofproc -p ${PIDFILE} ${SYSLOGNG}` retval=$? if [ $retval -ne 0 ];then msg= case $retval in 1) msg="dead but pidfile exists." ;; *) msg="stopped" ;; esac log_failure_msg "$msg" else log_success_msg "$pid running" fi return $retval } syslogng_probe() { if [ ${CONFFILE} -nt ${PIDFILE} ]; then echo reload fi } case $OS in Linux) case "x$CONSOLE_LOG_LEVEL" in x[1-8]) dmesg -n $CONSOLE_LOG_LEVEL ;; x) ;; *) echo "CONSOLE_LOG_LEVEL is of unaccepted value." ;; esac create_xconsole ;; SunOS) # # Before syslog-ng starts, save any messages from previous # crash dumps so that messages appear in chronological order. # if [ -r /dev/dump ]; then /usr/bin/savecore -m fi if [ -r /etc/dumpadm.conf ]; then . /etc/dumpadm.conf if [ -n "$DUMPADM_DEVICE" ] && [ -r "$DUMPADM_DEVICE" ] && \ [ "x$DUMPADM_DEVICE" != xswap ]; then /usr/bin/savecore -m -f $DUMPADM_DEVICE fi fi ;; HP-UX) # /etc/default/syslog-ng, the HP-UX way. [ -r /etc/rc.config.d/syslog-ng ] && . /etc/rc.config.d/syslog-ng ;; esac case "$1" in start_msg) echo "Start syslog-ng system message logging daemon" ;; stop_msg) echo "Stop syslog-ng system message logging daemon" ;; start|stop|restart|reload|probe) syslogng_$1 ;; force-reload) syslogng_restart ;; reload-or-restart) PID=`pidofproc -p ${PIDFILE} ${SYSLOGNG} | head -1` if [ -n "$PID" ] && [ $PID -gt 0 ] ;then syslogng_reload else syslogng_start fi ;; status) syslogng_status ;; condrestart|try-restart) [ ! -f $lockfile ] || syslogng_restart ;; rotate) syslogng_reload ;; *) echo "Usage: $0 {start|stop|status|restart|try-restart|reload|force-reload|probe}" exit 2 ;; esac exit $retval # vim: ts=2 ft=sh noexpandtab syslog-ng-syslog-ng-3.13.2/contrib/balabit-initscripts/init.d.freebsd000066400000000000000000000040761321171025300255740ustar00rootroot00000000000000#!/bin/sh # startup script for FreeBSD 6.x. # Written by Tamas Pal # PROVIDE: syslogd # REQUIRE: mountcritremote cleanvar newsyslog # BEFORE: SERVERS # Enabling syslog-ng: # * copy this script to /etc/rc.d or /usr/local/etc/rc.d # * Edit /etc/rc.conf and add the following lines: # ----- CUT HERE ----- # syslogd_enable="NO" # syslogng_enable="YES" # syslogng_flags="" # ----- CUT HERE ----- # * Add your extra flags to syslogng_flags EXCEPT the -p and -f # flags. These are added automatically by this script. To set # their value, change the value of the conf_file and pidfile variables below # BalaBit's platform independent variables. Please do not modify. SYSLOGNG_PREFIX=/opt/syslog-ng . "/etc/rc.subr" # FreeBSD rc specific variables. Please do not modify. name="syslogng" rcvar=`set_rcvar` pidfile="$SYSLOGNG_PREFIX/var/run/syslog-ng.pid" command="$SYSLOGNG_PREFIX/sbin/syslog-ng" required_files="$SYSLOGNG_PREFIX/etc/syslog-ng.conf" start_precmd="syslog_ng_start_precmd" start_postcmd="syslog_ng_start_postcmd" stop_postcmd="syslog_ng_stop_postcmd" reload_precmd="syslog_ng_reload_precmd" extra_commands="reload" # get original syslog pidfile from initscript. _syslogd_pidfile=`sed -n -e 's/^pidfile="\([^"]*\)"/\1/p' /etc/rc.d/syslogd 2> /dev/null` syslog_ng_start_precmd() { if [ ! -L /dev/log ]; then ln -s /var/run/log /dev/log fi } syslog_ng_reload_precmd() { $command --syntax-only _rval=$? if [ $_rval -ne 0 ];then exit $_rval fi } syslog_ng_start_postcmd() { if [ -n "$_syslogd_pidfile" ]; then # remove symlinks if [ -h $_syslogd_pidfile ]; then rm -f $_syslogd_pidfile fi if [ ! -f $_syslogd_pidfile ]; then ln -s "$pidfile" "$_syslogd_pidfile" fi fi } syslog_ng_stop_postcmd() { if [ -n "$_syslogd_pidfile" ]; then if [ -h $_syslogd_pidfile ]; then rm -f "$_syslogd_pidfile" fi fi } load_rc_config "$name" case $1 in start) # Reportedly needed on 7.x. PATH=$PATH:$SYSLOGNG_PREFIX/sbin export PATH syslogng_flags="${syslog_ng_flags}" ;; esac run_rc_command "$1" # vim: ft=sh syslog-ng-syslog-ng-3.13.2/contrib/cygwin-packaging/000077500000000000000000000000001321171025300223175ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/cygwin-packaging/cygwin-postinstall000077500000000000000000000037761321171025300261340ustar00rootroot00000000000000#!/bin/bash if [ -z "$1" ] then echo "Usage: $0 DESTDIR" exit 1 fi DESTDIR="$1" if [ ! -d "contrib/cygwin-packaging" ] then echo "Please run 'contrib/cygwin-packaging/cygwin-postinstall' from the top-level source directory." exit 1 fi if [ ! -f "${DESTDIR}/usr/sbin/syslog-ng.exe" ] then echo "Please run 'make install-strip' first." exit 2 fi if [ ! -f "config.log" ] then echo "Please run './configure' first." echo "Have a look into 'contrib/cygwin-packaging/cygwin-postinstall' how to do it." exit 3 fi pushd "${DESTDIR}" || exit 4 mkdir -p etc/defaults/etc etc/postinstall mv etc/syslog-ng etc/defaults/etc cd usr/lib rm *.a *.la if [ -d bin ] then mv bin/* syslog-ng rmdir bin fi cd syslog-ng rm *.a *.la *.so ln -s cygafsocket-tls.dll cygafsocket.dll popd cp contrib/cygwin-packaging/syslog-ng-config "${DESTDIR}/usr/bin/" cp contrib/cygwin-packaging/syslog-ng.sh "${DESTDIR}/etc/postinstall/" mkdir -p "${DESTDIR}/usr/share/doc/Cygwin" cat > "${DESTDIR}/usr/share/doc/Cygwin/syslog-ng.README" <<'EOF' If you want to use syslog-ng, just run the /usr/bin/syslog-ng-config script. This script will create a default configuration file /etc/syslog-ng.conf and it will install syslog-ng as a service on NT systems on request. Please note that you cannot use syslogd from the inetutils package and syslog-ng together. Only one syslog daemon should run at a time. The syslog-ng-config script, as well as the latest version of the syslogd-config script are taking care of this when requested to install as service. The syslog-ng package has been created using the following command sequence from the top level source dir: ./configure \ --prefix=/usr \ --sysconfdir=/etc/syslog-ng \ --libexecdir='${prefix}/lib' \ --localstatedir=/var/lib/syslog-ng \ --datadir='${prefix}/share/syslog-ng' make mkdir /tmp/syslog-ng make install-strip DESTDIR=/tmp/syslog-ng contrib/cygwin-packaging/cygwin-postinstall /tmp/syslog-ng tar -cjf syslog-ng-VERSION.tar.bz2 -C /tmp/syslog-ng etc usr EOF syslog-ng-syslog-ng-3.13.2/contrib/cygwin-packaging/syslog-ng-config000077500000000000000000000101071321171025300254310ustar00rootroot00000000000000#!/bin/sh # # syslog-ng-config, Copyright 2005, 2006, 2010 Corinna Vinschen # # This file is part of the Cygwin port of syslog-ng. # set -x # Subdirectory where the new package is being installed PREFIX="/usr" # Directory where the config files are stored SYSCONFDIR="/etc/syslog-ng" # Paths of the config files starting with 3.2.1. SYSCONFFILE="${SYSCONFDIR}/syslog-ng.conf" SCLFILE="${SYSCONFDIR}/scl.conf" MODULESFILE="${SYSCONFDIR}/modules.conf" # Directory in which the templates are stored. DEFAULTDIR="/etc/defaults" progname=$0 auto_answer="" request() { if [ "${auto_answer}" = "yes" ] then return 0 elif [ "${auto_answer}" = "no" ] then return 1 fi answer="" while [ "X${answer}" != "Xyes" -a "X${answer}" != "Xno" ] do echo -n "$1 (yes/no) " read answer done if [ "X${answer}" = "Xyes" ] then return 0 else return 1 fi } # Check options while : do case $# in 0) break ;; esac option=$1 shift case "$option" in -d | --debug ) set -x ;; -y | --yes ) auto_answer=yes ;; -n | --no ) auto_answer=no ;; *) echo "usage: ${progname} [OPTION]..." echo echo "This script creates a basic syslog-ng configuration." echo echo "Options:" echo " --debug -d Enable shell's debug output." echo " --yes -y Answer all questions with \"yes\" automatically." echo " --no -n Answer all questions with \"no\" automatically." echo exit 1 ;; esac done # Check for ${SYSCONFDIR} directory if [ -e "${SYSCONFDIR}" -a ! -d "${SYSCONFDIR}" ] then echo echo "${SYSCONFDIR} is existant but not a directory." echo "Cannot create global configuration files." echo exit 1 fi # Create it if necessary [ ! -e "${SYSCONFDIR}" ] && mkdir -p "${SYSCONFDIR}" if [ ! -e "${SYSCONFDIR}" ] then echo echo "Creating ${SYSCONFDIR} directory failed." echo exit 1 fi setfacl -m u:system:rwx "${SYSCONFDIR}" # Only offer to overwrite if template files exist. if [ -f "${DEFAULTDIR}${SYSCONFFILE}" ] then # Check if syslog-ng.conf exists. If yes, ask for overwriting if [ -f "${SYSCONFFILE}" ] then if request "Overwrite existing ${SYSCONFFILE} file?" then mv -f "${SYSCONFFILE}" "${SYSCONFFILE}.old" if [ -f "${SYSCONFFILE}" ] then echo "Can't overwrite. ${SYSCONFFILE} is write protected." else echo "${SYSCONFFILE} has been renamed to ${SYSCONFFILE}.old." fi fi fi if [ ! -f "${SYSCONFFILE}" ] then echo "Creating default syslog-ng configuration files in ${SYSCONFDIR}" cp "${DEFAULTDIR}${SYSCONFFILE}" "${SYSCONFFILE}" setfacl -m u:system:rw- "${SYSCONFFILE}" if [ -f "${DEFAULTDIR}${SCLFILE}" ] then cp "${DEFAULTDIR}${SCLFILE}" "${SCLFILE}" setfacl -m u:system:rw- "${SCLFILE}" fi if [ -f "${DEFAULTDIR}${MODULESFILE}" ] then cp "${DEFAULTDIR}${MODULESFILE}" "${MODULESFILE}" setfacl -m u:system:rw- "${MODULESFILE}" fi fi fi # Check if syslogd is installed and remove on user request. if cygrunsrv -Q syslogd > /dev/null 2>&1 then echo "Warning: The syslogd service is already installed. You can not" echo "run both, syslogd and syslog-ng in parallel." echo if request "Do you want to deinstall the syslogd service in favor of syslog-ng?" then cygrunsrv -E syslogd cygrunsrv -R syslogd fi fi # Install syslog-ng service if it is not already installed if ! cygrunsrv -Q syslog-ng > /dev/null 2>&1 then echo echo echo "Warning: The following function requires administrator privileges!" echo echo "Do you want to install syslog-ng as service?" if request "(Say \"no\" if it's already installed as service)" then if cygrunsrv -I syslog-ng -d "CYGWIN syslog-ng" -p /usr/sbin/syslog-ng -a "-F" then echo echo "The service has been installed under LocalSystem account." echo "To start the service, call \`net start syslog-ng' or \`cygrunsrv -S syslog-ng'." echo echo "Check ${SYSCONFDIR}/syslog-ng.conf first, if it suits your needs." fi fi fi echo echo "Configuration finished. Have fun!" syslog-ng-syslog-ng-3.13.2/contrib/cygwin-packaging/syslog-ng.sh000077500000000000000000000032631321171025300246040ustar00rootroot00000000000000#!/bin/bash # # syslog-ng.sh, postinstall script for Cygwin # # This file is part of the Cygwin port of syslog-ng. # Directory where the config files are stored SYSCONFDIR="/etc/syslog-ng" # Old config file, up to 3.0.1. OLDSYSCONFFILE="/etc/syslog-ng.conf" # Paths of the config files starting with 3.2.1. SYSCONFFILE="${SYSCONFDIR}/syslog-ng.conf" SCLFILE="${SYSCONFDIR}/scl.conf" MODULESFILE="${SYSCONFDIR}/modules.conf" # Directory in which the templates are stored. DEFAULTDIR="/etc/defaults" # Directory to keep state information LOCALSTATEDIR=/var/lib/syslog-ng # If an old syslog-ng.conf file exists, but no new one, move the old # one over to the new configuration directory. if [ -f "${OLDSYSCONFFILE}" -a ! -f "${SYSCONFFILE}" ] then # Check for ${SYSCONFDIR} directory, create it if necessary. [ -e "${SYSCONFDIR}" -a ! -d "${SYSCONFDIR}" ] && exit 1 [ ! -e "${SYSCONFDIR}" ] && mkdir -p "${SYSCONFDIR}" [ ! -e "${SYSCONFDIR}" ] && exit 2 setfacl -m u:system:rwx "${SYSCONFDIR}" mv -f "${OLDSYSCONFFILE}" "${SYSCONFFILE}" setfacl -m u:system:rw- "${SYSCONFFILE}" # Always copy template files to ${SYSCONFDIR} and add a ".new" suffix # to the ${SYSCONFFILE} template so the admin knows something has changed. cp "${DEFAULTDIR}${SYSCONFFILE}" "${SYSCONFFILE}.new" cp "${DEFAULTDIR}${SCLFILE}" "${SCLFILE}" cp "${DEFAULTDIR}${MODULESFILE}" "${MODULESFILE}" fi # Make sure /var/lib/syslog-ng exists. if [ -e "${LOCALSTATEDIR}" -a ! -d "${LOCALSTATEDIR}" ] then rm -f "${LOCALSTATEDIR}" [ -e "${LOCALSTATEDIR}" ] && exit 3 fi [ ! -e "${LOCALSTATEDIR}" ] && mkdir -p "${LOCALSTATEDIR}" [ ! -d "${LOCALSTATEDIR}" ] && exit 4 setfacl -m u:system:rwx "${LOCALSTATEDIR}" exit 0 syslog-ng-syslog-ng-3.13.2/contrib/fedora-packaging/000077500000000000000000000000001321171025300222575ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/fedora-packaging/syslog-ng.conf000066400000000000000000000054251321171025300250560ustar00rootroot00000000000000# syslog-ng configuration file. # # This should behave pretty much like the original syslog on RedHat. But # it could be configured a lot smarter. # # See syslog-ng(8) and syslog-ng.conf(5) for more information. # # 20000925 gb@sysfive.com # # Updated by Frank Crawford () - 10 Aug 2002 # - for Red Hat 7.3 # - totally do away with klogd # - add message "kernel:" as is done with klogd. # # Updated by Frank Crawford () - 22 Aug 2002 # - use the log_prefix option as per Balazs Scheidler's email # # Updated by Jose Pedro Oliveira () - 05 Apr 2003 # - corrected filters 'f_filter2' and 'f_filter6' # these filters were only allowing messages of one specific # priority level; they should be allowing messages from that # priority and upper levels. # # Updated by Jose Pedro Oliveira () - 25 Jan 2005 # - Don't sync the d_mail destination # # Updated by Jose Pedro Oliveira () - 01 Feb 2005 # - /proc/kmsg is a file not a pipe. # (https://lists.balabit.hu/pipermail/syslog-ng/2005-February/006963.html) # options { sync (0); time_reopen (10); log_fifo_size (1000); long_hostnames (off); use_dns (no); use_fqdn (no); create_dirs (no); keep_hostname (yes); }; source s_sys { file ("/proc/kmsg" program_override("kernel")); unix-stream ("/dev/log"); internal(); # udp(ip(0.0.0.0) port(514)); }; destination d_cons { file("/dev/console"); }; destination d_mesg { file("/var/log/messages"); }; destination d_auth { file("/var/log/secure"); }; destination d_mail { file("/var/log/maillog" sync(10)); }; destination d_spol { file("/var/log/spooler"); }; destination d_boot { file("/var/log/boot.log"); }; destination d_cron { file("/var/log/cron"); }; destination d_mlal { usertty("*"); }; #filter f_filter1 { facility(kern); }; filter f_filter2 { level(info..emerg) and not facility(mail,authpriv,cron); }; filter f_filter3 { facility(authpriv); }; filter f_filter4 { facility(mail); }; filter f_filter5 { level(emerg); }; filter f_filter6 { facility(uucp) or (facility(news) and level(crit..emerg)); }; filter f_filter7 { facility(local7); }; filter f_filter8 { facility(cron); }; #log { source(s_sys); filter(f_filter1); destination(d_cons); }; log { source(s_sys); filter(f_filter2); destination(d_mesg); }; log { source(s_sys); filter(f_filter3); destination(d_auth); }; log { source(s_sys); filter(f_filter4); destination(d_mail); }; log { source(s_sys); filter(f_filter5); destination(d_mlal); }; log { source(s_sys); filter(f_filter6); destination(d_spol); }; log { source(s_sys); filter(f_filter7); destination(d_boot); }; log { source(s_sys); filter(f_filter8); destination(d_cron); }; syslog-ng-syslog-ng-3.13.2/contrib/fedora-packaging/syslog-ng.init000066400000000000000000000031061321171025300250660ustar00rootroot00000000000000#!/bin/sh # # syslog-ng This starts and stops syslog-ng # # chkconfig: 2345 12 88 # description: reads and logs messages to the system console, log \ # files, other machines and/or users as specified by \ # its configuration file. # processname: /sbin/syslog-ng # config: /etc/syslog-ng/syslog-ng.conf # config: /etc/sysconfig/syslog-ng # pidfile: /var/run/syslog-ng.pid # ### BEGIN INIT INFO # Provides: $syslog ### END INIT INFO # Source function library. . /etc/rc.d/init.d/functions exec="/sbin/syslog-ng" prog=$(basename $exec) [ -f $exec ] || exit 0 # Source config [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog lockfile=/var/lock/subsys/$prog umask 077 start() { echo -n $"Starting $prog: " daemon $exec $SYSLOGNG_OPTIONS retval=$? echo [ $retval -eq 0 ] && touch $lockfile return $retval } stop() { echo -n $"Stopping $prog: " killproc $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile return $retval } restart() { stop start } reload() { echo -n $"Reloading syslog-ng.conf file: " killproc $prog -HUP retval=$? echo return $retval } force_reload() { restart } fdr_status() { status $prog } case "$1" in start|stop|restart|reload) $1 ;; force-reload) force_reload ;; status) fdr_status ;; condrestart|try-restart) [ ! -f $lockfile ] || restart ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|reload|force-reload}" exit 2 esac syslog-ng-syslog-ng-3.13.2/contrib/fedora-packaging/syslog-ng.logrotate000066400000000000000000000003461321171025300261260ustar00rootroot00000000000000/var/log/messages /var/log/secure /var/log/maillog /var/log/spooler /var/log/boot.log /var/log/cron { sharedscripts postrotate /bin/kill -HUP `cat /var/run/syslog-ng.pid 2> /dev/null` 2> /dev/null || true endscript } syslog-ng-syslog-ng-3.13.2/contrib/fedora-packaging/syslog-ng.sysconfig000066400000000000000000000001431321171025300261250ustar00rootroot00000000000000#--- # Syslog-ng command line options # See syslog-ng(8) for more details #--- SYSLOGNG_OPTIONS="" syslog-ng-syslog-ng-3.13.2/contrib/freebsd-packaging/000077500000000000000000000000001321171025300224315ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/freebsd-packaging/syslog-ng.conf.example000066400000000000000000000104441321171025300266570ustar00rootroot00000000000000# defauld syslogd config converted from freebsd 6.1 options { dir_perm(0755); perm(0644); chain_hostnames(no); keep_hostname(yes); }; # Default local source. source local { unix-dgram("/var/run/log"); unix-dgram("/var/run/logpriv" perm(0600)); file("/dev/klog"); udp(ip(0.0.0.0) port(514)); internal(); }; # FILTERS: START # Filter LEGO bricks to build your castle :) # syslog level filters filter f_crit_emerg { level(crit..emerg); }; filter f_err_emerg { level(err..emerg); }; filter f_warn_emerg { level(warning..emerg); }; filter f_debug_emerg { level(debug..emerg); }; filter f_notice_emerg { level(notice..emerg); }; filter f_info_emerg { level(info..emerg); }; filter f_info { level(info); }; filter f_not_authpriv { not facility(authpriv); }; filter f_debug { level(debug); }; filter f_emerg { level(emerg); }; # Facility filters filter f_mail { facility(mail); }; filter f_kern { facility(kern); }; filter f_auth { facility(auth); }; filter f_lpr { facility(lpr); }; filter f_news { facility(news); }; filter f_kern { facility(kern); }; filter f_security { facility(security); }; filter f_auth{ facility(auth); }; filter f_authpriv { facility(authpriv); }; filter f_ftp { facility(ftp); }; filter f_cron { facility(cron); }; # program filters filter f_startslip { program("startslip"); }; filter f_ppp { program("ppp"); }; ## FILTERS: END # DESTINATIONS: START destination d_devconsole { file("/dev/console" create_dirs(yes)); }; destination d_messages { file("/var/log/messages" create_dirs(yes)); }; destination d_maillog { file("/var/log/maillog" create_dirs(yes)); }; destination d_security { file("/var/log/security" create_dirs(yes)); }; destination d_authlog { file("/var/log/auth.log" create_dirs(yes)); }; destination d_ldperr { file("/var/log/lpd-errs" create_dirs(yes)); }; destination d_xferlog { file("/var/log/xferlog" create_dirs(yes)); }; destination d_cron { file("/var/log/cron" create_dirs(yes)); }; destination d_debuglog { file("/var/log/debug.log" create_dirs(yes)); }; destination d_usertty { usertty("*"); }; destination d_slip { file("/var/log/slip.log" create_dirs(yes)); }; destination d_ppp { file("/var/log/ppp.log" create_dirs(yes)); }; # DESTINATIONS: END # LOGS: START # *.err;kern.warning;auth.notice;mail.crit /dev/console log { source(local); filter(f_mail); filter(f_crit_emerg); destination(d_devconsole); }; log { source(local); filter(f_err_emerg); destination(d_devconsole); }; log { source(local); filter(f_kern); filter(f_warn_emerg); destination(d_devconsole); }; log { source(local); filter(f_auth); filter(f_notice_emerg); destination(d_devconsole); }; # *.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err /var/log/messages log { source(local); filter(f_notice_emerg); filter(f_not_authpriv); destination(d_messages); }; log { source(local); filter(f_lpr); filter(f_info); destination(d_messages); }; log { source(local); filter(f_mail); filter(f_crit_emerg); destination(d_messages); }; log { source(local); filter(f_news); filter(f_err_emerg); destination(d_messages); }; log { source(local); filter(f_kern); filter(f_debug_emerg); destination(d_messages); }; # mail.info /var/log/maillog log { source(local); filter(f_mail); filter(f_info_emerg); destination(d_maillog); }; ## security.* /var/log/security log { source(local); filter(f_security); filter(f_debug_emerg); destination(d_security); }; # auth.info;authpriv.info /var/log/auth.log log { source(local); filter(f_auth); filter(f_info_emerg); destination(d_authlog); }; log { source(local); filter(f_authpriv); filter(f_info_emerg); destination(d_authlog); }; # lpr.info /var/log/lpd-errs log { source(local); filter(f_lpr); filter(f_info); destination(d_ldperr); }; # ftp.info /var/log/xferlog log { source(local); filter(f_ftp); filter(f_info_emerg); destination(d_xferlog); }; # cron.* /var/log/cron log { source(local); filter(f_cron); filter(f_debug_emerg); destination(d_cron); }; ## *.=debug /var/log/debug.log log { source(local); filter(f_debug); destination(d_debuglog); }; ## *.emerg * log { source(local); filter(f_emerg); destination(d_usertty); }; # !starslip # *.* /var/log/slip.log log { source(local); filter(f_startslip); destination(d_slip); }; # !ppp # *.* /var/log/ppp.log log { source(local); filter(f_ppp); destination(d_ppp); }; # LOGS: END syslog-ng-syslog-ng-3.13.2/contrib/freebsd-packaging/syslog-ng.rc.d000066400000000000000000000026741321171025300251340ustar00rootroot00000000000000#!/bin/sh # startup script for FreeBSD 6.x. # Written by Tamas Pal # PROVIDE: syslogd # REQUIRE: mountcritremote cleanvar newsyslog # BEFORE: SERVERS # Enabling syslog-ng: # * copy this script to /etc/rc.d or /usr/local/etc/rc.d # * Edit /etc/rc.conf and add the following lines: # ----- CUT HERE ----- # syslogd_enable="NO" # syslogng_enable="YES" # syslogng_flags="" # ----- CUT HERE ----- # * Add your extra flags to syslogng_flags EXCEPT the -p and -f # flags. These are added automatically by this script. To set # their value, change the value of the conf_file and pidfile variables below . "/etc/rc.subr" name="syslogng" rcvar=`set_rcvar` pidfile="/var/run/syslog-ng.pid" ## CONFIG OPTIONS: START # modify them according to your environment. installdir="/opt/syslog-ng" localstatedir="${installdir}/var" libpath="${installdir}/lib" conf_file="${installdir}/etc/syslog-ng.conf" ## CONFIG OPTIONS: END command="${installdir}/sbin/syslog-ng" required_files="$conf_file" start_precmd="syslog_ng_precmd" extra_commands="reload" LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$libpath export LD_LIBRARY_PATH syslog_ng_precmd() { if [ ! -d ${localstatedir} ]; then mkdir -p ${localstatedir} fi if [ ! -L /dev/log ]; then ln -s /var/run/log /dev/log fi } load_rc_config "$name" case $1 in start) syslogng_flags=" -p ${pidfile} -f ${conf_file} ${syslog_ng_flags}" ;; esac run_rc_command "$1" # vim: ft=sh syslog-ng-syslog-ng-3.13.2/contrib/hpux-packaging/000077500000000000000000000000001321171025300220035ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/hpux-packaging/syslog-ng.conf000066400000000000000000000042331321171025300245760ustar00rootroot00000000000000# # sample configuration file for syslog-ng on HP-UX # users should customize to fit their needs # # log syslog-ng's own messages to /var/log/syslog-ng.log source s_internal { internal(); }; destination d_syslognglog { file("/var/adm/syslog/syslog-ng.log" owner("root") group("adm") perm(0640)); }; log { source(s_internal); destination(d_syslognglog); }; # log everything to /var/adm/syslog/messages source s_local { pipe("/dev/log" pad_size(2048)); }; destination d_messages { file("/var/adm/syslog/messages" owner("root") group("adm") perm(0640)); }; log { source(s_local); destination(d_messages); }; # Remote logging # #source s_remote { # tcp(ip(0.0.0.0) port(514)); # udp(ip(0.0.0.0) port(514)); #}; # #destination d_separatedbyhosts { # file("/var/adm/syslog/syslog-ng/$HOST/messages" owner("root") group("root") perm(0640) dir_perm(0750) create_dirs(yes)); #}; # #log { # source(s_remote); # destination(d_separatedbyhosts); #}; # # Local filters examples # #filter f_messages { level(info..emerg); }; #filter f_secure { facility(authpriv); }; #filter f_mail { facility(mail); }; #filter f_cron { facility(cron); }; #filter f_emerg { level(emerg); }; #filter f_spooler { level(crit..emerg) and facility(uucp, news); }; #filter f_local7 { facility(local7); }; # # Local destination examples # #destination d_secure { file("/var/log/secure"); }; #destination d_maillog { file("/var/log/maillog"); }; #destination d_cron { file("/var/log/cron"); }; #destination d_console { usertty("root"); }; #destination d_spooler { file("/var/log/spooler"); }; #destination d_bootlog { file("/var/log/boot.log"); }; # # Local log examples - order DOES matter ! # #log { source(s_local); filter(f_emerg); destination(d_console); }; #log { source(s_local); filter(f_secure); destination(d_secure); flags(final); }; #log { source(s_local); filter(f_maillog); destination(d_maillog); flags(final); }; #log { source(s_local); filter(f_cron); destination(d_cron); flags(final); }; #log { source(s_local); filter(f_spooler); destination(d_spooler); }; #log { source(s_local); filter(f_local7); destination(d_bootlog); }; #log { source(s_local); filter(f_messages); destination(d_messages); }; syslog-ng-syslog-ng-3.13.2/contrib/hpux-packaging/syslog-ng.init000066400000000000000000000065261321171025300246230ustar00rootroot00000000000000#!/bin/sh ################################################################################ # # Program: syslog-ng init script # # Description: # # This is an init script for syslog-ng on the HP-UX platform. # # To start the service, we check if the daemon program is executable. # Accordingly, the preferred way to disable the service PERMANENTLY # is to rename the binary or remove execute permissions. # Ideally, you would remove the software from your system entirely. # # The lowest PID of a running instance of the executable is logged to a # file. This PID is used for killing the daemon. This is a best guess of # course, it is much better to use built-in shutdown functions if the # daemon has those. # # # Platforms (tested): HP-UX (B.10.20) # # # Author: Gregor Binder # # Last Changed: October 10, 2000 # # Copyright (c) 2000 by sysfive.com GmbH, All rights reserved. # ################################################################################ ################################################################################ # configuration # INIT_PROG="/opt/syslog-ng/sbin/syslog-ng" # FULL path to daemon required for fuser INIT_OPTS="" # options passed to daemon INIT_HOOK="1" # in case you want to use /etc/rc.config.d # comment this out and edit code below INIT_RDIR="/var/run" PATH=/bin:/sbin:/usr/bin:/usr/sbin INIT_NAME=`basename "$INIT_PROG"` INIT_RPID="${INIT_RDIR}/${INIT_NAME}.pid" ################################################################################ # init # INIT_RETURN=0 umask 077 # Error Handling the HP way # set_return () { x=$? if [ $x -ne 0 ]; then echo "EXIT CODE: $x" INIT_RETURN=1 # always 1 so that 2 can be used for other reasons fi } case "$1" in 'start_msg') echo "Start $INIT_NAME" ;; 'stop_msg') echo "Stopping $INIT_NAME" ;; 'start') # Remove comments to enable reading config files # # if [ -f /etc/rc.config ] ; then # . /etc/rc.config # else # echo "ERROR: /etc/rc.config defaults file MISSING" # fi if [ "$INIT_HOOK" -eq 1 -a -x $INIT_PROG ] ; then $INIT_PROG $INIT_OPTS && echo "$INIT_NAME" set_return else INIT_RETURN=2 fi ;; 'stop') # Remove comments to enable reading config files # # if [ -f /etc/rc.config ] ; then # . /etc/rc.config # else # echo "ERROR: /etc/rc.config defaults file MISSING" # fi # Determine PID of process(es) to stop # if [ "$INIT_HOOK" -ne 1 ] ; then INIT_RETURN=2 else [ -r "$INIT_RPID" ] && { INIT_CPID=`cat "$INIT_RPID"` INIT_CPRG="`ps -ef | awk '$2 == '"$INIT_CPID"' { print $8 }'`" set_return [ "${INIT_CPRG:="unknown"}" = "$INIT_PROG" ] || { echo "process ID mismatch: [$INIT_CPID] is $INIT_CPRG" INIT_RETURN=1 } [ $INIT_RETURN -eq 0 ] && kill "$INIT_CPID" set_return [ $INIT_RETURN -eq 0 ] && rm -f "$INIT_RPID" set_return if [ $INIT_RETURN -eq 0 ]; then echo "$INIT_NAME stopped" else echo "Unable to stop $INIT_NAME" fi } fi ;; *) echo "usage: $0 {start|stop}" INIT_RETURN=1 ;; esac exit $INIT_RETURN syslog-ng-syslog-ng-3.13.2/contrib/init.d.HP-UX000066400000000000000000000065031321171025300210510ustar00rootroot00000000000000: ################################################################################ # # Program: syslog-ng init script # # Description: # # This is an init script for syslog-ng on the HP-UX platform. # # To start the service, we check if the daemon program is executable. # Accordingly, the preferred way to disable the service PERMANENTLY # is to rename the binary or remove execute permissions. # Ideally, you would remove the software from your system entirely. # # The lowest PID of a running instance of the executable is logged to a # file. This PID is used for killing the daemon. This is a best guess of # course, it is much better to use built-in shutdown functions if the # daemon has those. # # # Platforms (tested): HP-UX (B.10.20) # # # Author: Gregor Binder # # Last Changed: October 10, 2000 # # Copyright (c) 2000 by sysfive.com GmbH, All rights reserved. # ################################################################################ ################################################################################ # configuration # INIT_PROG="/path_to/syslog-ng" # FULL path to daemon required for fuser INIT_OPTS="" # options passed to daemon INIT_HOOK="1" # in case you want to use /etc/rc.config.d # comment this out and edit code below INIT_RDIR="/var/run" PATH=/bin:/sbin:/usr/bin:/usr/sbin INIT_NAME=`basename "$INIT_PROG"` INIT_RPID="${INIT_RDIR}/${INIT_NAME}.pid" ################################################################################ # init # INIT_RETURN=0 umask 077 # Error Handling the HP way # set_return () { x=$? if [ $x -ne 0 ]; then echo "EXIT CODE: $x" INIT_RETURN=1 # always 1 so that 2 can be used for other reasons fi } case "$1" in 'start_msg') echo "Start $INIT_NAME" ;; 'stop_msg') echo "Stopping $INIT_NAME" ;; 'start') # Remove comments to enable reading config files # # if [ -f /etc/rc.config ] ; then # . /etc/rc.config # else # echo "ERROR: /etc/rc.config defaults file MISSING" # fi if [ "$INIT_HOOK" -eq 1 -a -x $INIT_PROG ] ; then $INIT_PROG $INIT_OPTS && echo "$INIT_NAME" set_return else INIT_RETURN=2 fi ;; 'stop') # Remove comments to enable reading config files # # if [ -f /etc/rc.config ] ; then # . /etc/rc.config # else # echo "ERROR: /etc/rc.config defaults file MISSING" # fi # Determine PID of process(es) to stop # if [ "$INIT_HOOK" -ne 1 ] ; then INIT_RETURN=2 else [ -r "$INIT_RPID" ] && { INIT_CPID=`cat "$INIT_RPID"` INIT_CPRG="`ps -ef | awk '$2 == '"$INIT_CPID"' { print $9 }'`" set_return [ "${INIT_CPRG:="unknown"}" = "$INIT_PROG" ] || { echo "process ID mismatch: [$INIT_CPID] is $INIT_CPRG" INIT_RETURN=1 } [ $INIT_RETURN -eq 0 ] && kill "$INIT_CPID" set_return [ $INIT_RETURN -eq 0 ] && rm -f "$INIT_RPID" set_return if [ $INIT_RETURN -eq 0 ]; then echo "$INIT_NAME stopped" else echo "Unable to stop $INIT_NAME" fi } fi ;; *) echo "usage: $0 {start|stop}" INIT_RETURN=1 ;; esac exit $INIT_RETURN syslog-ng-syslog-ng-3.13.2/contrib/init.d.RedHat000066400000000000000000000034321321171025300213550ustar00rootroot00000000000000: ################################################################################ # # Program: syslog-ng init script # # Description: # # This is an init script for syslog-ng on the Linux platform. # # It totally relies on the Redhat function library and works the same # way as other typical Redhat init scripts. # # # Platforms (tested): Linux (Redhat 6.1) # # # Author: Gregor Binder # # Last Changed: October 10, 2000 # # Copyright (c) 2000 by sysfive.com GmbH, All rights reserved. # ################################################################################ ################################################################################ # configuration # INIT_PROG="/path_to/syslog-ng" # Full path to daemon INIT_OPTS="" # options passed to daemon PATH=/bin:/sbin:/usr/bin:/usr/sbin INIT_NAME=`basename "$INIT_PROG"` # Source Redhat function library. # . /etc/rc.d/init.d/functions # Uncomment this if you are on Redhat and think this is useful # #. /etc/sysconfig/network # #if [ ${NETWORKING} = "no" ] #then # exit 0 #fi RETVAL=0 umask 077 ulimit -c 0 # See how we were called. case "$1" in start) echo -n "Starting $INIT_NAME: " daemon --check $INIT_PROG "$INIT_PROG $INIT_OPTS" RETVAL=$? echo -n "Starting Kernel Logger: " [ -x "/sbin/klogd" ] && daemon klogd echo [ $RETVAL -eq 0 ] && touch "/var/lock/subsys/${INIT_NAME}" ;; stop) echo -n "Stopping $INIT_NAME: " killproc $INIT_PROG RETVAL=$? echo -n "Stopping Kernel Logger: " [ -x "/sbin/klogd" ] && killproc klogd echo [ $RETVAL -eq 0 ] && rm -f "/var/lock/subsys/${INIT_NAME}" ;; status) status $INIT_PROG RETVAL=$? ;; restart|reload) $0 stop $0 start RETVAL=$? ;; *) echo "Usage: $0 {start|stop|status|restart|reload}" exit 1 esac exit $RETVAL syslog-ng-syslog-ng-3.13.2/contrib/init.d.RedHat-7.3000066400000000000000000000075251321171025300216710ustar00rootroot00000000000000################################################################################ # # Program: syslog-ng init script for Red Hat # ################################################################################ # the following information is for use by chkconfig # if you are want to manage this through chkconfig (as you should), you must # first must add syslog-ng to chkconfig's list of startup scripts it # manages by typing: # # chkconfig --add syslog-ng # # DO NOT CHANGE THESE LINES (unless you know what you are doing) # chkconfig: 2345 12 88 # description: syslog-ng is the next generation of the syslog daemon. \ # syslog-ng gives you the flexibility of logging not only by facility and \ # severity, but also by host, message content, date, etc. it can also replace \ # klogd's function of logging kernel messages # # This following block of lines is correct, do not change! (for more info, see # http://www.linuxbase.org/spec/refspecs/LSB_1.1.0/gLSB/facilname.html) ### BEGIN INIT INFO # Provides: $syslog ### END INIT INFO ################################################################################ # # This is an init script for syslog-ng on the Linux platform. # # It totally relies on the Redhat function library and works the same # way as other typical Redhat init scripts. # # # Platforms (tested): Linux (Redhat 7.3) # # # Author: Gregor Binder # Changed: October 10, 2000 # # Last Changed: September 27, 2002 # Updated by: Diane Davidowicz # changes: Brought the start script up to snuff as far as compliance # with managing the startup script through chkconfig; # added PATH variable ability to hook in path to syslog-ng (if # its necessary); converted init script format to the # standard init script format in Red Hat (7.3 to be exact) # including using the /etc/sysconfig/syslog-ng file to # managed the arguments to syslog-ng without changing this # script, and disabled klogd but noted where and under what # conditions it should be enabled. HAPPY LOGGING. # # Copyright (c) 2000 by sysfive.com GmbH, All rights reserved. # # ################################################################################ # # configuration # INIT_PROG=syslog-ng # # Source Redhat function library. # . /etc/rc.d/init.d/functions # Tack on path to syslog-ng if not already in PATH SYSLOGNG_PATH=":/usr/local/sbin" PATH=$PATH$SYSLOGNG_PATH export PATH # /etc/sysconfig/ is the standard way to pull in options for a daemon to use. # Source config if [ -f /etc/sysconfig/syslog-ng ] ; then . /etc/sysconfig/syslog-ng else SYSLOGNG_OPTIONS= fi RETVAL=0 umask 077 ulimit -c 0 # See how we were called. start() { echo -n "Starting $INIT_PROG: " daemon $INIT_PROG $SYSLOGNG_OPTIONS RETVAL=$? echo # syslog-ng can handle kernel messages. If you do this, don't # run klogd. Consult the following FAQ question to find out why. # # http://www.campin.net/syslog-ng/faq.html#klogd # # If you still prefer to run klogd without syslog-ng handling # kernel messages, uncomment the following block of lines #echo -n $"Starting kernel logger: " #daemon klogd $KLOGD_OPTIONS #echo [ $RETVAL -eq 0 ] && touch "/var/lock/subsys/${INIT_PROG}" return $RETVAL } stop() { # Same here concerning klogd. Uncomment the following block of # code if you are needing to run it #echo -n $"Shutting down kernel logger: " #killproc klogd #echo echo -n "Stopping $INIT_PROG: " killproc $INIT_PROG RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f "/var/lock/subsys/${INIT_PROG}" return $RETVAL } rhstatus() { status $INIT_PROG } restart() { stop start } case "$1" in start) start ;; stop) stop ;; status) rhstatus ;; restart|reload) restart ;; condrestart) [ -f /var/lock/subsys/syslog-ng ] && restart || : ;; *) echo $"Usage: $0 {start|stop|status|restart|reload}" exit 1 esac exit $? syslog-ng-syslog-ng-3.13.2/contrib/init.d.SuSE000066400000000000000000000060271321171025300210300ustar00rootroot00000000000000#! /bin/sh # # original Authors of /etc/init.d/syslog: # Florian La Roche , 1996 # Werner Fink , 1998 # # hacked for syslog-ng from above dudes' syslog script # Darth Elmo , 13 Sept 2001 # # updated for OpenSuse 10 by # Tamas Pal , 3, Nov 2006 # NOTES: # # Add the new variable SYSLOGNG_PARAMS to /etc/rc.config. Set it equal to # any syslog-ng startup flags/options you need (for most users it may be # left empty, but it's good to have it there anyhow. :-) # # Also, if you haven't already, copy the sample syslog-ng.config # files from $syslog-ng-source-dir/contrib and $syslog-ng-src-dir/doc # to /etc/syslog-ng/ (you'll need to "mkdir /etc/syslog-ng" first). Editing # one of these to meet your needs is less work than starting from scratch. # Just make sure that one is named "syslog-ng.conf", or that you point a # symbolic link called "syslog-ng.conf" to the one you want to use. # # Finally, add symbolic links to this script in /etc/rc.2, /etc/rc.3, # and /etc/rc.5. Rename init.d/syslog to something like init.d/syslog.use-ng # (easier than removing *its* symlinks from rc.2 et al, and easier to reenable # should you foolishly abandon syslog-ng later on). # # Have a whole butt-load o' fun, # Darth Elmo # # /sbin/init.d/syslog-ng # ### BEGIN INIT INFO # Provides: syslog-ng # Required-Start: $network # Required-Stop: $network # Default-Start: 2 3 5 # Default-Stop: 0 1 6 # Description: Start the system logging daemons ### END INIT INFO . /etc/rc.status || exit 1 NGBINDIR=/sbin BINDIR=/sbin test -x ${NGBINDIR}/syslog-ng || exit 0 test -x ${BINDIR}/klogd || exit 0 return=$rc_done case "$1" in start) checkproc ${BINDIR}/klogd && \ killproc ${BINDIR}/klogd 2> /dev/null checkproc ${NGBINDIR}/syslog-ng && { killproc ${NGBINDIR}/syslog-ng 2> /dev/null echo -n "Re-" } echo -n "Starting syslog-ng services" test -z "$KERNEL_LOGLEVEL" && KERNEL_LOGLEVEL=1 startproc ${NGBINDIR}/syslog-ng $SYSLOGNG_PARAMS || return=$rc_failed sleep 1 startproc ${BINDIR}/klogd -c $KERNEL_LOGLEVEL || return=$rc_failed echo -e "$return" ;; stop) echo -n "Shutting down syslog-ng services" killproc -TERM ${BINDIR}/klogd || return=$rc_failed killproc -TERM ${NGBINDIR}/syslog-ng || return=$rc_failed echo -e "$return" ;; restart) $0 stop && $0 start || return=$rc_failed ;; reload) echo -n "Reload syslog service" killproc -TSTP ${BINDIR}/klogd || return=$rc_failed killproc -HUP ${NGBINDIR}/syslog-ng || return=$rc_failed killproc -CONT ${BINDIR}/klogd || return=$rc_failed killproc -USR2 ${BINDIR}/klogd || return=$rc_failed echo -e "$return" ;; status) echo -n "Checking for service syslog-ng:" checkproc ${NGBINDIR}/syslog-ng && echo OK || echo No process ;; probe) test /etc/syslog-ng/syslog-ng.conf -nt /var/run/syslog-ng.pid && echo reload ;; *) echo "Usage: $0 {start|stop|restart|reload|probe}" exit 1 ;; esac test "$return" = "$rc_done" || exit 1 exit 0 syslog-ng-syslog-ng-3.13.2/contrib/init.d.SunOS000066400000000000000000000051061321171025300212150ustar00rootroot00000000000000: ################################################################################ # # Program: syslog-ng init script # # Description: # # This is an init script for syslog-ng on the Solaris platform. # # To start the service, we check if the config file exists and the daemon # program is executable. Accordingly, the preferred way to disable the # service PERMANENTLY is to rename the binary and/or configuration file # to filename.OFF. This avoids accidental execution. # # The lowest PID of a running instance of the executable is logged to a # file. This PID is used for killing the daemon. This is a best guess of # course, it is much better to use built-in shutdown functions if the # daemon has those. # # # Platforms (tested): SunOS (Solaris 2.6) # # # Author: Gregor Binder # # Last Changed: October 10, 2000 # # Copyright (c) 2000 by sysfive.com GmbH, All rights reserved. # ################################################################################ ################################################################################ # configuration # INIT_CONF="/etc/syslog-ng/syslog-ng.conf" # this file has to exist INIT_PROG="/path_to/syslog-ng" # FULL path to daemon required (fuser) INIT_OPTS="" # options passed to daemon INIT_NAME=`basename "$0"` INIT_RDIR="/var/run" INIT_RPID="${INIT_RDIR}/${INIT_NAME}.pid" PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt//bin:/opt//sbin ################################################################################ # init # INIT_RETURN=0 umask 077 ulimit -c 0 [ -d "$INIT_RDIR" ] || mkdir -p "$INIT_RDIR" || \ echo "Cannot make directory: $INIT_RDIR" INIT_RETURN=$? ################################################################################ # arguments processing # case "$1" in start) test -f "$INIT_CONF" -a -x "$INIT_PROG" || exit 0 "$INIT_PROG" "$INIT_OPTS" INIT_RETURN=$? ;; stop) [ -r "$INIT_RPID" ] && INIT_CPID=`cat "$INIT_RPID"` [ -z "$INIT_CPID" ] || \ INIT_CPRG="`ps -ef | awk '$2 == '"$INIT_CPID"' { print $9 }'`" INIT_RETURN=$? set ${INIT_CPRG:="unknown"} [ "$INIT_CPRG" = "$INIT_PROG" ] || { \ echo "process ID mismatch: [$INIT_CPID] is $INIT_CPRG" INIT_RETURN=1 } [ $INIT_RETURN -eq 0 ] && kill ${INIT_SIG:="-TERM"} $INIT_CPID INIT_RETURN=$? [ $INIT_RETURN -eq 0 ] && rm -f "$INIT_RPID" INIT_RETURN=$? ;; restart) INIT_SIG="-HUP" $0 stop $0 start INIT_RETURN=$? ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 esac exit $INIT_RETURN syslog-ng-syslog-ng-3.13.2/contrib/init.d.solaris000066400000000000000000000025241321171025300216630ustar00rootroot00000000000000#!/bin/sh # # $Id: init.d.solaris,v 1.3 2003/04/11 13:37:47 bazsi Exp $ # # adapted to syslog-ng by BJ, Aug, 7th 2000 # cleaned up by Bazsi, Oct, 12th 2000 # minor fix by Bojan Zdrnja, Apr, 11th 2003 # added nicer options field # DAEMON=/usr/local/sbin/syslog-ng OPTIONS="-f /etc/syslog-ng/syslog-ng.conf" case "$1" in start) if [ -f /etc/syslog-ng/syslog-ng.conf -a -f /usr/local/sbin/syslog-ng ]; then echo 'syslog-ng service starting.' # # Before syslog-ng starts, save any messages from previous # crash dumps so that messages appear in chronological order. # /usr/bin/savecore -m if [ -r /etc/dumpadm.conf ]; then . /etc/dumpadm.conf [ "x$DUMPADM_DEVICE" != xswap ] && \ /usr/bin/savecore -m -f $DUMPADM_DEVICE fi $DAEMON $OPTIONS -p /etc/syslog-ng/syslog-ng.pid fi ;; stop) if [ -f /etc/syslog-ng/syslog-ng.pid ]; then syspid=`/usr/bin/cat /etc/syslog-ng/syslog-ng.pid` [ "$syspid" -gt 0 ] && kill -15 $syspid && rm /etc/syslog-ng/syslog-ng.pid fi ;; *) echo "Usage: $0 { start | stop }" exit 1 ;; esac syslog-ng-syslog-ng-3.13.2/contrib/lfs-packaging/000077500000000000000000000000001321171025300216035ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/lfs-packaging/Makefile.lfs000066400000000000000000000057061321171025300240360ustar00rootroot00000000000000# makefile to handle Syslog-NG install/uninstall on a LFS Linux system. # # INSTALL/UNINSTALL: # Use make -f Makefile.lfs install|uninstall to install and register or # uninstall Syslog-NG's init scripts. # # START/STOP Sysklogd or Syslog-NG # Starting Syslog-NG: make -f Makefile.lfs slng-start # Stopping Syslog-NG: make -f Makefile.lfs slng-stop # # Starting sysklogd: make -f Makefile.lfs sysklogd-start # Stopping sysklogd: make -f Makefile.lfs sysklogd-stop # ETCDIR=/etc EXTDIR=${DESTDIR}${ETCDIR} MODE=754 DIRMODE=755 CONFMODE=644 all: install create-dirs: install -d -m ${DIRMODE} ${EXTDIR}/rc.d/rc0.d install -d -m ${DIRMODE} ${EXTDIR}/rc.d/rc1.d install -d -m ${DIRMODE} ${EXTDIR}/rc.d/rc2.d install -d -m ${DIRMODE} ${EXTDIR}/rc.d/rc3.d install -d -m ${DIRMODE} ${EXTDIR}/rc.d/rc4.d install -d -m ${DIRMODE} ${EXTDIR}/rc.d/rc5.d install -d -m ${DIRMODE} ${EXTDIR}/rc.d/rc6.d install -d -m ${DIRMODE} ${EXTDIR}/rc.d/rcsysinit.d install -d -m ${DIRMODE} ${EXTDIR}/rc.d/init.d install -d -m ${DIRMODE} ${EXTDIR}/sysconfig install: create-dirs install -m ${MODE} syslog-ng.init.lfs ${EXTDIR}/rc.d/init.d/syslog-ng ln -sf ../init.d/syslog-ng ${EXTDIR}/rc.d/rc0.d/K90syslog-ng ln -sf ../init.d/syslog-ng ${EXTDIR}/rc.d/rc1.d/K90syslog-ng ln -sf ../init.d/syslog-ng ${EXTDIR}/rc.d/rc2.d/K90syslog-ng ln -sf ../init.d/syslog-ng ${EXTDIR}/rc.d/rc3.d/S10syslog-ng ln -sf ../init.d/syslog-ng ${EXTDIR}/rc.d/rc4.d/S10syslog-ng ln -sf ../init.d/syslog-ng ${EXTDIR}/rc.d/rc5.d/S10syslog-ng ln -sf ../init.d/syslog-ng ${EXTDIR}/rc.d/rc6.d/K90syslog-ng rm -rf ${EXTDIR}/rc.d/rc0.d/K90sysklogd rm -rf ${EXTDIR}/rc.d/rc1.d/K90sysklogd rm -rf ${EXTDIR}/rc.d/rc2.d/K90sysklogd rm -rf ${EXTDIR}/rc.d/rc3.d/S10sysklogd rm -rf ${EXTDIR}/rc.d/rc4.d/S10sysklogd rm -rf ${EXTDIR}/rc.d/rc5.d/S10sysklogd rm -rf ${EXTDIR}/rc.d/rc6.d/K90sysklogd uninstall: slng-stop ln -sf ../init.d/sysklogd ${EXTDIR}/rc.d/rc0.d/K90sysklogd ln -sf ../init.d/sysklogd ${EXTDIR}/rc.d/rc1.d/K90sysklogd ln -sf ../init.d/sysklogd ${EXTDIR}/rc.d/rc2.d/K90sysklogd ln -sf ../init.d/sysklogd ${EXTDIR}/rc.d/rc3.d/S10sysklogd ln -sf ../init.d/sysklogd ${EXTDIR}/rc.d/rc4.d/S10sysklogd ln -sf ../init.d/sysklogd ${EXTDIR}/rc.d/rc5.d/S10sysklogd ln -sf ../init.d/sysklogd ${EXTDIR}/rc.d/rc6.d/K90sysklogd rm -rf ${EXTDIR}/rc.d/rc0.d/K90syslog-ng rm -rf ${EXTDIR}/rc.d/rc1.d/K90syslog-ng rm -rf ${EXTDIR}/rc.d/rc2.d/K90syslog-ng rm -rf ${EXTDIR}/rc.d/rc3.d/S10syslog-ng rm -rf ${EXTDIR}/rc.d/rc4.d/S10syslog-ng rm -rf ${EXTDIR}/rc.d/rc5.d/S10syslog-ng rm -rf ${EXTDIR}/rc.d/rc6.d/K90syslog-ng rm -rf ${EXTDIR}/rc.d/init.d/syslog-ng sysklogd-stop: ${EXTDIR}/rc.d/init.d/sysklogd stop || true sysklogd-start: ${EXTDIR}/rc.d/init.d/sysklogd start || true slng-stop: ${EXTDIR}/rc.d/init.d/syslog-ng stop || true slng-start: ${EXTDIR}/rc.d/init.d/syslog-ng start || true .PHONY: all create-dirs install \ slng-stop slng-start \ sysklogd-stop sysklogd-start syslog-ng-syslog-ng-3.13.2/contrib/lfs-packaging/README.lfs000066400000000000000000000007711321171025300232530ustar00rootroot00000000000000Installation instructions for Syslog-NG on an Linux From Scratch system. ======================================================================== Installing/uninstalling Syslog-NG's init script use the Makefile.lfs makefile. Further instruction could be found in the said makefile. Before starting Syslog-NG, create or modify a syslog-ng.conf file in /opt/syslog-ng/etc. The syslog-ng.conf files in /opt/syslog-ng/contrib/fedora and /opt/syslog-ng/contrib/redhat-el could be used as a starting pint. syslog-ng-syslog-ng-3.13.2/contrib/lfs-packaging/syslog-ng.init.lfs000077500000000000000000000024461321171025300252060ustar00rootroot00000000000000#!/bin/sh # Inintscript for LFS (Linux From Scratch) systems. # # syslog-ng This starts and stops syslog-ng # # description: reads and logs messages to the system console, log \ # files, other machines and/or users as specified by \ # its configuration file. # processname: /sbin/syslog-ng # config: /etc/syslog-ng/syslog-ng.conf # config: /etc/sysconfig/syslog-ng # pidfile: /var/run/syslog-ng.pid # # Source function library. . /etc/sysconfig/rc . ${rc_functions} root="/opt/syslog-ng" exec="$root/sbin/syslog-ng" conf="$root/etc/syslog-ng.conf" prog=$(basename $exec) export LD_LIBRARY_PATH=$root/lib:$LD_LIBRARY_PATH [ -f $exec ] || exit 0 # Source config [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog umask 077 start() { boot_mesg "Starting $prog: " loadproc $exec -f $conf $SYSLOGNG_OPTIONS } stop() { boot_mesg "Stopping $prog: " killproc $prog } restart() { stop start } reload() { echo -n $"Reloading syslog-ng.conf file: " reloadproc $prog } case "$1" in start|stop|restart|reload) $1 ;; force-reload) restart ;; status) statusproc $exec ;; *) echo $"Usage: $0 {start|stop|status|restart|try-restart|reload|force-reload}" exit 2 esac syslog-ng-syslog-ng-3.13.2/contrib/openbsd-packaging/000077500000000000000000000000001321171025300224515ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/openbsd-packaging/syslog-ng.conf000066400000000000000000000104621321171025300252450ustar00rootroot00000000000000# syslog-ng configuration file for OpenBSD. # This should provide the same behavior as OpenBSD's syslog.conf(5). # 2010-07-18 steven@openbsd.org @version: 3.0 options { use_dns(no); create_dirs(no); keep_hostname(yes); }; source s_local { unix-dgram ("/dev/log"); unix-dgram ("/var/empty/dev/log"); internal(); }; #source s_local_all { # unix-dgram ("/dev/log"); # unix-dgram ("/var/empty/dev/log"); # unix-dgram ("/var/www/dev/log"); # internal(); #}; #source s_net { # udp(port(514)); #}; destination d_console { file("/dev/console"); }; destination d_messages { file("/var/log/messages" perm(0644)); }; destination d_authlog { file("/var/log/authlog"); }; destination d_secure { file("/var/log/secure"); }; destination d_cronlog { file("/var/cron/log"); }; destination d_daemon { file("/var/log/daemon"); }; destination d_xferlog { file("/var/log/xferlog"); }; destination d_lpderrs { file("/var/log/lpd-errs"); }; destination d_maillog { file("/var/log/maillog"); }; destination d_sudolog { file("/var/log/sudo"); }; destination d_chatlog { file("/var/log/chat"); }; destination d_ttyall { usertty("*"); }; destination d_ttyroot { usertty("root"); }; destination d_loghost { udp("loghost" port(514)); }; filter f_notice { level(notice .. emerg) and not(facility(auth,authpriv,cron,ftp,kern,lpr,mail,user)); }; filter f_kerndebug { level(debug .. emerg) and facility(kern); }; filter f_msginfo { level(info .. emerg) and facility(syslog,user); }; filter f_authinfo { level(info .. emerg) and facility(auth); }; filter f_authprivdebug { level(debug .. emerg) and facility(authpriv); }; filter f_croninfo { level(info .. emerg) and facility(cron); }; filter f_daemoninfo { level(info .. emerg) and facility(daemon); }; filter f_ftpinfo { level(info .. emerg) and facility(ftp); }; filter f_lprdebug { level(debug .. emerg) and facility(lpr); }; filter f_mailinfo { level(info .. emerg) and facility(mail); }; filter f_emerg { level(emerg); }; filter f_to_console { not (facility(authpriv)) and ((level(notice .. emerg) and facility(auth)) or (level(debug .. emerg) and facility(kern)) or (level(crit .. emerg) and facility(mail)) or level(err .. emerg)); }; filter f_to_root { (level(debug .. emerg) and facility(auth)) or (level(notice .. emerg)); }; filter f_to_loghost { (level(notice .. emerg) and not (facility(auth,authpriv,cron,ftp,kern,lpr,mail,user))) or (level(info .. emerg) and facility(auth,daemon,syslog,user)) or (level(debug .. emerg) and facility(authpriv,kern)); }; filter f_prog_sudo { program("sudo"); }; filter f_prog_chat { program("chat"); }; log { source(s_local); filter(f_notice); destination(d_messages);}; log { source(s_local); filter(f_kerndebug); destination(d_messages);}; log { source(s_local); filter(f_msginfo); destination(d_messages);}; log { source(s_local); filter(f_authinfo); destination(d_authlog); }; log { source(s_local); filter(f_authprivdebug); destination(d_secure); }; log { source(s_local); filter(f_croninfo); destination(d_cronlog); }; log { source(s_local); filter(f_daemoninfo); destination(d_daemon); }; log { source(s_local); filter(f_ftpinfo); destination(d_xferlog); }; log { source(s_local); filter(f_lprdebug); destination(d_lpderrs); }; log { source(s_local); filter(f_mailinfo); destination(d_maillog); }; # Uncomment this line to send "important" messages to the system # console: be aware that this could create lots of output. #log { source(s_local); filter(f_to_console); destination(d_console); }; # Uncomment this to have all messages of notice level and higher # as well as all authentication messages sent to root. #log { source(s_local); filter(f_to_root); destination(d_ttyroot); }; # Everyone gets emergency messages. log { source(s_local); filter(f_emerg); destination(d_ttyall); }; # Uncomment to log to a central host named "loghost". #log { source(s_local); filter(f_to_loghost); destination(d_loghost); }; # Uncomment to log messages from sudo(8) and chat(8) to their own # respective log files. Matches are done based on the program name. # Program-specific logs: #log { source(s_local); filter(f_prog_sudo); destination(d_sudolog); }; #log { source(s_local); filter(f_prog_chat); destination(d_chatlog); }; # Uncomment to log messages from the network. # Note: it is recommended to specify a different destination here. #log { source(s_net); destination(d_messages); }; syslog-ng-syslog-ng-3.13.2/contrib/relogger.pl000066400000000000000000000115231321171025300212420ustar00rootroot00000000000000#!/usr/local/bin/perl -w # take syslog messages from stdin - push them through syslog again # by Ed Ravin . Made available to the # public courtesy of PANIX (http://www.panix.com). # This script is licensed under the GPL. # Requires Date::Parse and Time::HiRes modules my $usage= "relogger.pl [--facility fac] [--priority pri] [--replayspeed factor]\n"; use strict; use Sys::Syslog qw(:DEFAULT setlogsock); use Getopt::Long; use Date::Parse; # for str2time use Time::HiRes qw ( sleep ); my %opt; die $usage unless GetOptions (\%opt, "debug", "facility=s", "priority=s", "replayspeed=s"); setlogsock('unix') if grep /^ $^O $/xo, ("linux", "openbsd", "freebsd", "netbsd"); my $facility= $opt{'facility'} || "mail"; my $priority= $opt{'priority'} || "info"; my $replayspeed= $opt{'replayspeed'} || 0; my $debug= $opt{'debug'} || 0; die "$0: Option 'replayspeed' must be a valid floating point number\n" unless $replayspeed =~ /^[0-9]*\.?[0-9]*$/; my $progname= ""; # Aug 5 20:28:17 grand-central postfix/qmgr[4389]: AC2BB7F9A: removed # my $thistime= str2time($date); # warn "$0: cannot parse date '$date'\n" if !$thistime; my $lasttimestamp= 0; my $timestamp; my $timestep= 0; while(<>) { if ( ((my ($timestr, $process, $msg))= /^(.*) \S+ ([^ []*)\[\d+\]: (.*)$/ ) == 3) { $timestamp= str2time($timestr) || warn "$0: cannot parse timestamp '$timestr'\n"; if ($progname ne $process) { closelog; openlog "$process", 'ndelay,pid', $facility or die "$0: openlog: $!\n"; $progname= $process; } $timestep= $timestamp - $lasttimestamp; if ($replayspeed and $timestep > 0 and $lasttimestamp > 0) { warn "sleeping for " . $timestep * $replayspeed . " seconds...\n" if $debug; sleep( $timestep * $replayspeed); } syslog $priority, "%s", $msg unless $debug; warn "$process $facility/$priority $msg\n" if $debug; $lasttimestamp= $timestamp; } else { warn "$0: cannot parse input line $.: $_\n"; } } __END__ =head1 NAME relogger.pl - re-inject syslog log files back into syslog =head1 SYNOPSIS B [I<--facility fac>] [I<--priority pri>] [I<--replayspeed factor>] [I<--debug]>] =head1 DESCRIPTION B takes syslog-formatted messages on standard input and re-sends them via the default syslog mechanism. The existing timestamps are stripped off the message before it is re-sent. Delays between messages can be enabled with the I<--replayseed> option (see B below to simulate the arrival times of the original messages. was written to help test configurations for programs like B or B that parse log output and take actions based on what messages appear in the logs. =head1 OPTIONS =item B<--facility> I specify the syslog facility to log the messages to. Standard syslog messages do not store the facility the message was logged on, so this cannot be determined from the input. The default is the B facility. =item B<--priority> I specify the syslog priority to log the messages to. The default is the B priority. As with B<--facility>, this information cannot be discovered from the input. =item B<--replayspeed> I attempt to parse the timestamps of the input messages, and simulate the original arrival times by sleeping between each message. The sleep time is multiplied by I. To send simulated log events with time spacing at the same time as the original arrival times, use a I of 1. To send simulated log events at twice the speed of the original logs, use a I of 0.5 (i.e. sleep only half the original time between log messages). =item B<--debug> send all output to standard error, rather than to syslog. Also prints an extra diagnostic message or two. =head1 BUGS B is a beta-quality tool for testing logging configurations. It is not yet recommended for production use. It would be nice to be able to specify the input filename on the command line, instead of requiring it to be on standard input. It would be nice to be able to control the syslog mechanism on the command line (i.e. specify whether to use a local or remote host) rather than just using the system default. The original PID in the message is replaced by the current PID of B in the simulated message. Also, the PID of B will appear in the simulated message even if the original one did not supply a PID. In spite of using Time::HiRes to enable sleeping in fractional seconds, some environments seem to still round off to seconds. This needs a bit more investigation. =head1 AUTHOR B was written by Ed Ravin , and is made available to the public by courtesy of PANIX (http://www.panix.com). This script is licensed under the GPL. B requires the Date::Parse and the Time::HiRes Perl modules. syslog-ng-syslog-ng-3.13.2/contrib/rhel-packaging/000077500000000000000000000000001321171025300217515ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/rhel-packaging/syslog-ng.conf000066400000000000000000000040361321171025300245450ustar00rootroot00000000000000# # configuration file for syslog-ng, customized for remote logging # source s_internal { internal(); }; destination d_syslognglog { file("/var/log/syslog-ng.log"); }; log { source(s_internal); destination(d_syslognglog); }; # Local sources, filters and destinations are commented out # If you want to replace sysklogd simply uncomment the following # parts and disable sysklogd # # Local sources # #source s_local { # unix-dgram("/dev/log"); # file("/proc/kmsg" program_override("kernel")); #}; # # Local filters # #filter f_messages { level(info..emerg); }; #filter f_secure { facility(authpriv); }; #filter f_mail { facility(mail); }; #filter f_cron { facility(cron); }; #filter f_emerg { level(emerg); }; #filter f_spooler { level(crit..emerg) and facility(uucp, news); }; #filter f_local7 { facility(local7); }; # # Local destinations # #destination d_messages { file("/var/log/messages"); }; #destination d_secure { file("/var/log/secure"); }; #destination d_maillog { file("/var/log/maillog"); }; #destination d_cron { file("/var/log/cron"); }; #destination d_console { usertty("root"); }; #destination d_spooler { file("/var/log/spooler"); }; #destination d_bootlog { file("/var/log/boot.log"); }; # # Local logs - order DOES matter ! # #log { source(s_local); filter(f_emerg); destination(d_console); }; #log { source(s_local); filter(f_secure); destination(d_secure); flags(final); }; #log { source(s_local); filter(f_mail); destination(d_maillog); flags(final); }; #log { source(s_local); filter(f_cron); destination(d_cron); flags(final); }; #log { source(s_local); filter(f_spooler); destination(d_spooler); }; #log { source(s_local); filter(f_local7); destination(d_bootlog); }; #log { source(s_local); filter(f_messages); destination(d_messages); }; # Remote logging source s_remote { tcp(ip(0.0.0.0) port(514)); udp(ip(0.0.0.0) port(514)); }; destination d_separatedbyhosts { file("/var/log/syslog-ng/$HOST/messages" owner("root") group("root") perm(0640) dir_perm(0750) create_dirs(yes)); }; log { source(s_remote); destination(d_separatedbyhosts); }; syslog-ng-syslog-ng-3.13.2/contrib/rhel-packaging/syslog-ng.init000066400000000000000000000023501321171025300245600ustar00rootroot00000000000000#!/bin/bash # # syslog-ng This starts and stops syslog-ng # # chkconfig: 2345 12 88 # description: syslog-ng is an alternative system logger # processname: syslog-ng # pidfile: /var/run/syslog-ng.pid ### BEGIN INIT INFO # Provides: $syslog-ng ### END INIT INFO # Source function library. . /etc/init.d/functions binary="/sbin/syslog-ng" [ -x $binary ] || exit 0 RETVAL=0 start() { echo -n "Starting syslog-ng: " daemon $binary RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/syslog-ng } stop() { echo -n "Shutting down syslog-ng: " killproc syslog-ng RETVAL=$? echo if [ $RETVAL -eq 0 ]; then rm -f /var/lock/subsys/syslog-ng rm -f /var/run/syslog-ng.pid fi } restart() { echo -n "Restarting syslog-ng: " $binary --syntax-only RETVAL=$? echo if [ $RETVAL -eq 0 ]; then stop sleep 2 start fi } reload() { echo -n "Reloading syslog-ng: " $binary --syntax-only RETVAL=$? if [ $RETVAL -eq 0 ]; then killproc syslog-ng -1 fi } case "$1" in start) start ;; stop) stop ;; status) status syslog-ng ;; restart) restart ;; reload) reload ;; condrestart) [ -f /var/lock/subsys/syslog-ng ] && restart ;; *) echo "Usage: $0 {start|stop|status|restart|reload|condrestart}" ;; esac syslog-ng-syslog-ng-3.13.2/contrib/rhel-packaging/syslog-ng.logrotate000066400000000000000000000001771321171025300256220ustar00rootroot00000000000000/var/log/syslog-ng.log { weekly rotate 52 compress postrotate /etc/rc.d/init.d/syslog-ng reload 2>/dev/null endscript } syslog-ng-syslog-ng-3.13.2/contrib/selinux/000077500000000000000000000000001321171025300205645ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/selinux/README000066400000000000000000000045351321171025300214530ustar00rootroot00000000000000SELINUX SUPPORT FOR SYSLOG-NG This directory contains syslog-ng's SELinux policy files. By compiling and loading them into your kernel, your syslog-ng will be able to work with its default configuration in a SELinux enabled environment. SELinux support was added in syslog-ng 5.2 on the following platforms: Red Hat Enterprise Linux/CentOS/Oracle Linux 5 Red Hat Enterprise Linux/CentOS/Oracle Linux 6 Red Hat Enterprise Linux/CentOS/Oracle Linux 7 The installation steps may differ on these operating systems, so you will find RHEL version specific information, too. Root permission is needed to run most commands. You need the following RPM packages preinstalled to be able to compile and load SELinux policy modules: policycoreutils policycoreutils-python policycoreutils-devel (only available on RHEL/CentOS/Oracle Linux 7) If they are not installed on your system, you can install them by the following command: yum install policycoreutils policycoreutils-devel policycoreutils-python The SELinux policy works only if syslog-ng is started by the init daemon. INSTALLATION To compile and load this module, you have to run the 'syslog_ng.sh' script. It compiles and loads the syslog_ng module and restores the right file contexts in syslog-ng's install directory. The changes will be effective after restarting syslog-ng: cd /opt/syslog-ng/share/doc/selinux ./syslog_ng.sh For information about restarting syslog-ng, please read the RESTARTING SYSLOG-NG section. UNINSTALL The module will be active, until you remove it. Then you have to restart syslog-ng. ./syslog_ng.sh --remove For information about restarting syslog-ng, please read the RESTARTING SYSLOG-NG section. RESTARTING SYSLOG-NG You can restart syslog-ng on RHEL5 and RHEL6 by: service syslog-ng restart On RHEL/CentOS/Oracle Linux 7 you have to run: systemctl restart syslog-ng ADDITIONAL INFORMATION Syslog-ng is able to create coredumps and it's disabled by default. You can enable coredumps by setsebool -P daemons_dump_core 1 Please note, that this command enables core dumping for all daemons on your sysmtem, not just for syslog-ng. There is no way to enable per application core dumps in SELinux. If you have problems with SELinux and syslog-ng, you can turn to BalaBit's support team. syslog-ng-syslog-ng-3.13.2/contrib/selinux/labels.txt000066400000000000000000000047071321171025300225770ustar00rootroot00000000000000FILE CONTEXTS: /dev/log: devlog_t /opt/syslog-ng: usr_t /opt/syslog-ng/bin: bin_t /opt/syslog-ng/etc: etc_t /opt/syslog-ng/etc/syslog-ng.conf* syslog_conf_t /opt/syslog-ng/include: usr_t /opt/syslog-ng/lib: lib_t /opt/syslog-ng/libexec: bin_t /opt/syslog-ng/libexec/syslog-ng: syslogd_exec_t /opt/syslog-ng/libexec/syslog-ng-wrapper.sh syslogd_exec_t /opt/syslog-ng/sbin: usr_t /opt/syslog-ng/share: usr_t /opt/syslog-ng/share/man: man_t /opt/syslog-ng/share/include/scl/system/generate-system-source.sh: bin_t /opt/syslog-ng/var: syslogd_var_lib_t /opt/syslog-ng/var/run: syslogd_var_run_t /opt/syslog-ng/var/syslog-ng.persist: syslogd_var_lib_t /etc/rc.d/init.d/syslog-ng: syslogd_initrc_exec_t PROCESS LABEL (RHEL7): when syslog-ng was started by init (by systemctl or during boot): system_u:system_r:syslogd_t:s0 when syslog-ng was started manually (/opt/syslog-ng/sbin/syslog-ng -Fevd): unconfined_u:system_r:unconfined_t:s0-s0:c0.c1023 PROCESS LABEL (RHEL6): when syslog-ng was started by init during boot: system_u:system_r:syslogd_t:s0 when syslog-ng was started by init, but manually (service syslog-ng start) unconfined_u:system_r:syslogd_t:s0 when syslog-ng was started manually (/opt/syslog-ng/sbin/syslog-ng -Fevd) unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 PROCESS LABEL (RHEL5): when syslog-ng was started by init during boot: system_u:system_r:syslogd_t:s0 when syslog-ng was started by init, but manually (service syslog-ng start) root:system_r:syslogd_t:s0 when syslog-ng was started manually (/opt/syslog-ng/sbin/syslog-ng -Fevd) root:system_r:unconfined_t:s0-s0:c0.c1023 syslog-ng-syslog-ng-3.13.2/contrib/selinux/src/000077500000000000000000000000001321171025300213535ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/selinux/src/root_safe/000077500000000000000000000000001321171025300233345ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/selinux/src/root_safe/syslog_ng.el5.fc.in000066400000000000000000000006431321171025300267460ustar00rootroot00000000000000$PATH$/etc/syslog-ng.conf(.*)? -- gen_context(system_u:object_r:syslog_conf_t,s0) $PATH$/var/syslog-ng.* -- gen_context(system_u:object_r:syslogd_var_lib_t,s0) $PATH$/libexec/syslog-ng -- gen_context(system_u:object_r:syslogd_exec_t,s0) /etc/rc\.d/init\.d/syslog-ng -- gen_context(system_u:object_r:initrc_exec_t,s0) $PATH$/share/include/scl/system/generate-system-source.sh -- gen_context(system_u:object_r:bin_t,s0) syslog-ng-syslog-ng-3.13.2/contrib/selinux/src/root_safe/syslog_ng.el6.fc.in000066400000000000000000000006531321171025300267500ustar00rootroot00000000000000$PATH$/etc/syslog-ng.conf(.*)? -- gen_context(system_u:object_r:syslog_conf_t,s0) $PATH$/var/syslog-ng.* -- gen_context(system_u:object_r:syslogd_var_lib_t,s0) $PATH$/libexec/syslog-ng -- gen_context(system_u:object_r:syslogd_exec_t,s0) /etc/rc\.d/init\.d/syslog-ng -- gen_context(system_u:object_r:syslogd_initrc_exec_t,s0) $PATH$/share/include/scl/system/generate-system-source.sh -- gen_context(system_u:object_r:bin_t,s0) syslog-ng-syslog-ng-3.13.2/contrib/selinux/src/root_safe/syslog_ng.el7.fc.in000066400000000000000000000010031321171025300267370ustar00rootroot00000000000000$PATH$/etc/syslog-ng.conf(.*)? -- gen_context(system_u:object_r:syslog_conf_t,s0) $PATH$/var/syslog-ng.* -- gen_context(system_u:object_r:syslogd_var_lib_t,s0) $PATH$/libexec/syslog-ng -- gen_context(system_u:object_r:syslogd_exec_t,s0) $PATH$/libexec/syslog-ng-wrapper.sh -- gen_context(system_u:object_r:syslogd_exec_t,s0) /etc/rc\.d/init\.d/syslog-ng -- gen_context(system_u:object_r:syslogd_initrc_exec_t,s0) $PATH$/share/include/scl/system/generate-system-source.sh -- gen_context(system_u:object_r:bin_t,s0) syslog-ng-syslog-ng-3.13.2/contrib/selinux/src/root_unsafe/000077500000000000000000000000001321171025300236775ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/selinux/src/root_unsafe/syslog_ng.el5.fc.in000066400000000000000000000010611321171025300273040ustar00rootroot00000000000000$PATH$ -d gen_context(system_u:object_r:usr_t,s0) $PATH$/bin(/.*)? gen_context(system_u:object_r:bin_t,s0) $PATH$/sbin(/.*)? gen_context(system_u:object_r:bin_t,s0) $PATH$/etc(/.*)? gen_context(system_u:object_r:etc_t,s0) $PATH$/lib(/.*)? gen_context(system_u:object_r:lib_t,s0) $PATH$/var -d gen_context(system_u:object_r:syslogd_var_lib_t,s0) $PATH$/libexec(/.*)? gen_context(system_u:object_r:bin_t,s0) $PATH$/var/run(/.*)? gen_context(system_u:object_r:syslogd_var_run_t,s0) $PATH$/share/man(/.*)? gen_context(system_u:object_r:man_t,s0) syslog-ng-syslog-ng-3.13.2/contrib/selinux/src/root_unsafe/syslog_ng.el6.fc.in000066400000000000000000000010611321171025300273050ustar00rootroot00000000000000$PATH$ -d gen_context(system_u:object_r:usr_t,s0) $PATH$/bin(/.*)? gen_context(system_u:object_r:bin_t,s0) $PATH$/sbin(/.*)? gen_context(system_u:object_r:bin_t,s0) $PATH$/etc(/.*)? gen_context(system_u:object_r:etc_t,s0) $PATH$/lib(/.*)? gen_context(system_u:object_r:lib_t,s0) $PATH$/var -d gen_context(system_u:object_r:syslogd_var_lib_t,s0) $PATH$/libexec(/.*)? gen_context(system_u:object_r:bin_t,s0) $PATH$/var/run(/.*)? gen_context(system_u:object_r:syslogd_var_run_t,s0) $PATH$/share/man(/.*)? gen_context(system_u:object_r:man_t,s0) syslog-ng-syslog-ng-3.13.2/contrib/selinux/src/root_unsafe/syslog_ng.el7.fc.in000066400000000000000000000010611321171025300273060ustar00rootroot00000000000000$PATH$ -d gen_context(system_u:object_r:usr_t,s0) $PATH$/bin(/.*)? gen_context(system_u:object_r:bin_t,s0) $PATH$/sbin(/.*)? gen_context(system_u:object_r:bin_t,s0) $PATH$/etc(/.*)? gen_context(system_u:object_r:etc_t,s0) $PATH$/lib(/.*)? gen_context(system_u:object_r:lib_t,s0) $PATH$/var -d gen_context(system_u:object_r:syslogd_var_lib_t,s0) $PATH$/libexec(/.*)? gen_context(system_u:object_r:bin_t,s0) $PATH$/var/run(/.*)? gen_context(system_u:object_r:syslogd_var_run_t,s0) $PATH$/share/man(/.*)? gen_context(system_u:object_r:man_t,s0) syslog-ng-syslog-ng-3.13.2/contrib/selinux/src/syslog_ng.el5.te.in000066400000000000000000000010631321171025300250020ustar00rootroot00000000000000policy_module(syslog_ng, 1.0.5) require { type syslogd_t, syslogd_var_run_t, shell_exec_t, bin_t; class file { ioctl read getattr lock execute execute_no_trans }; class sock_file { ioctl read write create getattr setattr lock append unlink link rename }; } allow syslogd_t syslogd_var_run_t:sock_file { ioctl read write create getattr setattr lock append unlink link rename }; allow syslogd_t bin_t:file { ioctl read getattr lock execute execute_no_trans }; allow syslogd_t shell_exec_t:file { read execute getattr execute_no_trans }; syslog-ng-syslog-ng-3.13.2/contrib/selinux/src/syslog_ng.el6.0to4.te.in000066400000000000000000000012561321171025300255740ustar00rootroot00000000000000policy_module(syslog_ng, 1.0.5) require { type syslogd_t, shell_exec_t, bin_t; class file { ioctl read getattr lock execute execute_no_trans open }; class lnk_file { read getattr }; class process { fork sigchld sigkill sigstop signull signal getsched setsched setpgid getcap setcap setrlimit }; } allow syslogd_t shell_exec_t:file { read execute getattr execute_no_trans open }; allow syslogd_t bin_t:file { ioctl read getattr lock execute execute_no_trans open }; allow syslogd_t bin_t:lnk_file { read getattr }; allow syslogd_t syslogd_t : process { fork sigchld sigkill sigstop signull signal getsched setsched setpgid getcap setcap setrlimit } ; syslog-ng-syslog-ng-3.13.2/contrib/selinux/src/syslog_ng.el67.te.in000066400000000000000000000000411321171025300250650ustar00rootroot00000000000000policy_module(syslog_ng, 1.0.5) syslog-ng-syslog-ng-3.13.2/contrib/selinux/syslog_ng.sh000077500000000000000000000156051321171025300231360ustar00rootroot00000000000000#!/bin/bash ### Exit error codes # # 0: everything went fine # 255: invalid command line-option # 254: no root privileges # 253: file or directory does not exist # 252: policy build failed # 251: policy install failed # 250: unsupported os/distribution/version # 249: conflicting parameters # 248: internal error at task selection EL_FC= EL_TE= OS_VERSION= INSTALL_PATH="/opt/syslog-ng" # ports 514/udp, 6514/udp and 6514/tcp are allowed by default # if you wish to add further ports, just add them to the end of the list SYSLOG_NG_TCP_PORTS="601" SYSLOG_NG_UDP_PORTS="601" TASK_SELECTED="install_default" INPUT= query_install_path() { echo -n "Please enter your installation path for Syslog-ng PE: [${INSTALL_PATH}] " read INPUT } check_dir() { if [ -d "${1}" ]; then return 0 else echo "The directory you specified does not exist!" >&2 return 1 fi } verify_input() { INPUT="${INPUT:-${INSTALL_PATH}}" echo -n "You have entered '${INPUT}'. Is this correct? [y/N] " read ACCEPT if [ "x${ACCEPT}x" != "xyx" ]; then return 0; fi check_dir "${INPUT}" && return 1 || return 0 } extract_version_string() { sed -n 's:^[a-zA-Z ]\+\([0-9]\+\.[0-9]\+\)\(.[0-9]\+\)\?[a-zA-Z ()]\+$:\1:p' } detect_os_version() { echo "Detecting RHEL/CentOS/Oracle Linux version..." if [ -x "/usr/bin/lsb_release" ]; then if lsb_release -d | grep -qE "Description:[[:space:]]+(CentOS|Red Hat Enterprise Linux Server|Oracle Linux Server|Enterprise Linux Enterprise Linux Server) release"; then OS_VERSION=$( lsb_release -r | cut -f 2 ) else echo "You don't seem to be running a supported Linux distribution!" >&2 exit 250 fi else # The package redhat-lsb-core is most likely not installed... if [ -f "/etc/redhat-release" ]; then OS_VERSION=$( extract_version_string < "/etc/redhat-release" ) else echo "You don't seem to be running a supported OS!" >&2 exit 250 fi fi } omit_allowed_tcp_ports() { sed -e 's:^601::g' } omit_allowed_udp_ports() { sed -e 's:^601::g' } omit_allowed_ports() { SYSLOG_NG_TCP_PORTS=$( omit_allowed_tcp_ports <<<"${SYSLOG_NG_TCP_PORTS}" ) SYSLOG_NG_UDP_PORTS=$( omit_allowed_udp_ports <<<"${SYSLOG_NG_UDP_PORTS}" ) } setup_vars() { echo "Detected RHEL/CentOS/Oracle Linux ${OS_VERSION}." case "${OS_VERSION}" in 5.*) EL_FC="syslog_ng.el5.fc.in" EL_TE="syslog_ng.el5.te.in" ;; 6.*) EL_FC="syslog_ng.el6.fc.in" local MINORVER MINORVER=$( cut -d. -f 2 <<<"${OS_VERSION}" ) if [ "${MINORVER}" -lt 5 ]; then EL_TE="syslog_ng.el6.0to4.te.in" else EL_TE="syslog_ng.el67.te.in" # 601/tcp and 601/udp are allowed by default on RHEL6.5+, so there is no need to enable them omit_allowed_ports fi ;; 7.*) EL_FC="syslog_ng.el7.fc.in" EL_TE="syslog_ng.el67.te.in" # 601/tcp and 601/udp are allowed by default on RHEL7, so there is no need to enable them omit_allowed_ports ;; *) echo "You don't seem to be running a supported version of RHEL!" >&2 exit 250 ;; esac } substitute_install_path() { sed -e "s:^\\\$PATH\\\$:${INSTALL_PATH}:g" "src/root_unsafe/${EL_FC}" sed -e "s:^\\\$PATH\\\$:${INSTALL_PATH}:g" "src/root_safe/${EL_FC}" } omit_install_path() { sed -e "s:^\\\$PATH\\\$::g" "src/root_safe/${EL_FC}" } prepare_files() { echo "Using '${INSTALL_PATH}'..." if [ "${INSTALL_PATH}" != "/" ]; then substitute_install_path > "syslog_ng.fc" else omit_install_path > "syslog_ng.fc" fi cp "src/${EL_TE}" "syslog_ng.te" } remove_trainling_slash() { # the trailing slash in the install path (if present) breaks file context rules # thus it needs to be removed (provided that the install path is not "/" itself) sed -e 's:^\(.\+\)/$:\1:' } build_module() { echo "Building and Loading Policy" make -f /usr/share/selinux/devel/Makefile syslog_ng.pp || exit 252 } add_ports() { for entry in ${@}; do port=${entry%/*} proto=${entry#*/} semanage port -a -t syslogd_port_t -p ${proto} ${port} 2>/dev/null || \ semanage port -m -t syslogd_port_t -p ${proto} ${port} 2>/dev/null done } install_module() { /usr/sbin/semodule -i syslog_ng.pp -v || exit 251 # set up syslog-ng specific ports PORTS= for port in ${SYSLOG_NG_TCP_PORTS}; do PORTS="${PORTS} ${port}/tcp"; done for port in ${SYSLOG_NG_UDP_PORTS}; do PORTS="${PORTS} ${port}/udp"; done add_ports "${PORTS}" # Fixing the file context /sbin/restorecon -F -Rv "${INSTALL_PATH}" /sbin/restorecon -F -Rv /etc/init.d/syslog-ng /sbin/restorecon -F -Rv /etc/rc.d/init.d/syslog-ng /sbin/restorecon -F -Rv /dev/log echo -e "\nPlease restart syslog-ng. You can find more information about this in the README file." } remove_ports() { for entry in ${@}; do port=${entry%/*} proto=${entry#*/} semanage port -d -t syslogd_port_t -p ${proto} ${port} 2>/dev/null done } remove_module() { if semodule -l | grep -q syslog_ng; then echo -n "Removing Syslog-ng SELinux policy module... " semodule --remove=syslog_ng # unconfigure syslog-ng specific ports PORTS= for port in ${SYSLOG_NG_TCP_PORTS}; do PORTS="${PORTS} ${port}/tcp"; done for port in ${SYSLOG_NG_UDP_PORTS}; do PORTS="${PORTS} ${port}/udp"; done remove_ports "${PORTS}" [ -f syslog_ng.pp ] && rm -f syslog_ng.pp [ -f syslog_ng.te ] && rm -f syslog_ng.te [ -f syslog_ng.fc ] && rm -f syslog_ng.fc [ -f syslog_ng.if ] && rm -f syslog_ng.if [ -d tmp ] && rm -Rf tmp echo "done." else echo "No installed Syslog-ng SELinux policy module was found. Nothing to do..." fi } DIRNAME=$( dirname "${0}" ) cd "${DIRNAME}" USAGE="Usage: $0\t[ --install-dir | --remove | --help ]\n\n$0:\tA tool for building and managing the SELinux policy for the\n\t\tdefault syslog-ng installation." while [ -n "${1}" ]; do case "${1}" in --help) # if --help is supplied, the help message will be printed independently of any other options being specified TASK_SELECTED="showhelp" break ;; --install-dir) [ "${TASK_SELECTED}" = "remove" ] && echo -e "ERROR: Conflicting options!\n\n${USAGE}" >&2 && exit 249 TASK_SELECTED="install" check_dir "${2}" || exit 253 INPUT="${2}" shift 2 ;; --remove) [ "${TASK_SELECTED}" = "install" ] && echo -e "ERROR: Conflicting options!\n\n${USAGE}" >&2 && exit 249 TASK_SELECTED="remove" shift ;; *) echo -e "ERROR: Invalid option: '${1}'\n${USAGE}" >&2 exit 255 ;; esac done case "${TASK_SELECTED}" in showhelp) echo -e "${USAGE}" exit 0 ;; remove) detect_os_version setup_vars remove_module exit 0 ;; install|install_default) if [ $( id -u ) != 0 ]; then echo 'You must be root to run this script!' >&2 exit 254 fi if [ -z "${INPUT}" ]; then query_install_path while verify_input; do query_install_path done fi INSTALL_PATH=$( remove_trainling_slash <<<"${INPUT}" ) detect_os_version setup_vars prepare_files build_module install_module ;; *) echo -e "ERROR: Invalid task: '${TASK_SELECTED}'!" >&2 exit 248 ;; esac syslog-ng-syslog-ng-3.13.2/contrib/solaris-packaging/000077500000000000000000000000001321171025300224735ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/solaris-packaging/solaris10_install.txt000066400000000000000000000120101321171025300265710ustar00rootroot00000000000000Installing syslog-ng on Sun Solaris 10 To successfully install syslog-ng, complete the following simple procedure. Lines starting with # are commands that have to be executed from a command line console. Procedure 4.5. Installing syslog-ng on Sun Solaris 10 1. Use the your username and password received together with your syslog-ng Premium Edition license to download the following binaries. Make sure to download the package specific for the processor architecture of the host. * The syslog-ng Premium Edition package (syslog-ng-premium-edition_) from http://www.balabit.com/downloads/files/syslog-ng/binaries/premium-edition/pool/s/syslog-ng-premium-edition/ * The libdbi8 package from http://www.balabit.com/downloads/files/syslog-ng/binaries/premium-edition/pool/l/libdbi8/ * If you plan to use an SQL destination, download the package corresponding to your database from http://www.balabit.com/downloads/files/syslog-ng/binaries/premium-edition/pool/l/libdbi8-drivers/ Also download the package corresponding to the database, architecture, and Solaris version you plan to use from http://www.sunfreeware.com. The Sunfreeware.com website includes details on installing the database, and any required dependencies. Note The database packages contain the full database applications, but syslog-ng does not use the databases, only the .so file. Installing the database packages does not start the database services. 2. Download or copy the syslog-ng__sparc.pkg.gz package to your computer running Solaris. Download the following packages from the nearest sunfreeware.com mirrors(solaris9 packages): libiconv-1.11-sol9-sparc-local.gz libgcc-3.4.6-sol9-sparc-local.gz 3. Unpack and install the syslog-ng Premium Edition and the libdbi8 package by issuing the following commands from the command line: # libiconv-1.11-sol9-sparc-local.gz # libgcc-3.4.6-sol9-sparc-local.gz # gunzip syslog-ng__sparc.pkg.gz # gunzip libdbi8__.gz # pkgadd -d libiconv-1.11-sol9-sparc-local # pkgadd -d libgcc-3.4.6-sol9-sparc-local # pkgadd -d syslog-ng__sparc.pkg # pkgadd -d libdbi8__.pkg 4. If you use an SQL destination, issue the commands corresponding to the database: * For MySQL: Download and install the following packages from sunfreeware.com: - mysql-5.0.41-sol9-sparc-local - openssl-0.9.8e-sol9-sparc-local # gunzip .gz; pkgadd -d # gunzip libdbd8-mysql__.gz # pkgadd -d libdbd8-mysql__.pkg * For PostgreSQL: Make sure that the SUNWpostgr-libs package has been installed. It's on the Solaris 10 install DVD. # gunzip libdbd8-pgsql__.gz # pkgadd -d libdbd8-pgsql__.pkg * For SQLite: Download and install the sqlite-3.3.6-sol9-sparc-local package from sunfreeware.com. # gunzip sqlite-3.3.6-sol9-sparc-local.gz # pkgadd -d sqlite-3.3.6-sol9-sparc-local # gunzip libdbd8-sqlite__.gz # pkgadd -d libdbd8-sqlite__.pkg 5. Rename the syslog-ng.conf.sample file (located under /opt/syslog-ng/etc/) to syslog-ng.conf. # mv /opt/syslog-ng/etc/syslog-ng.conf.sample \ /opt/syslog-ng/etc/syslog-ng.conf 6. Modify the syslog-ng.conf to suit your needs. For details on how to configure syslog-ng, see The syslog-ng Administrator Guide, Chapter 3, Configuring syslog-ng. 7. Disable the original syslogd application. # svcadm -v disable svc:/system/system-log 8. Copy the following files to their proper places by issuing the following commands and modify them if needed. # cp /contrib/solaris-packaging/syslog-ng.example.xml /var/svc/manifest/system/syslog-ng.xml # cp /contrib/solaris-packaging/syslog-ng.method /lib/svc/method/syslog-ng # cp /contrib/solaris-packaging/syslog-ng@default /etc/default/syslog-ng@default 9. Validate and import the syslog-ng.xml file using svccfg. # svccfg svc:> validate /var/svc/manifest/system/syslog-ng.xml svc:> import /var/svc/manifest/system/syslog-ng.xml svc:> quit 10. Enable and start syslog-ng. # svcadm enable -t svc:/system/syslog-ng:default 11. Verify that syslog-ng is running. # svcs -a | grep syslog You should receive a similar output: online 10:15:01 svc:/system/syslog-ng:default syslog-ng-syslog-ng-3.13.2/contrib/solaris-packaging/syslog-ng-sol11-smf.example.xml000066400000000000000000000060711321171025300303150ustar00rootroot00000000000000 syslog-ng-syslog-ng-3.13.2/contrib/solaris-packaging/syslog-ng.example.xml000066400000000000000000000061531321171025300265760ustar00rootroot00000000000000 syslog-ng-syslog-ng-3.13.2/contrib/solaris-packaging/syslog-ng.method000077500000000000000000000135241321171025300256270ustar00rootroot00000000000000#!/sbin/sh # # $Id: syslog-ng.init.d,v 1.1.2.2 2006/03/02 18:35:45 folti Exp $ # # adapted to syslog-ng by BJ, Aug, 7th 2000 # cleaned up by Bazsi, Oct, 12th 2000 # minor fix by Bojan Zdrnja, Apr, 11th 2003 # added nicer options field # Modified for BalaBit Ltd's syslog-ng package by Tamas Pal Mar, 1st 2006 # Modified for BalaBit's syslog-ng package to make it multi-instance-able by György Pásztor Mar, 21th 2016 # Minor modifications for Syslog-ng OSE by Janos Szigetvari Aug, 15th 2017 . /lib/svc/share/smf_include.sh result=${SMF_EXIT_OK} # Read command line arguments method="$1" # %m instance="$2" # %i # Set defaults; SMF_FMRI should have been set, but just in case. if [ -z "$SMF_FMRI" ]; then SMF_FMRI="svc:/system/syslog-ng:${instance}" fi SYSLOGPID_FILE=/var/run/syslog.pid OTHER_OPTIONS="--enable-core" MAXWAIT=30 DEFAULTFILE=/etc/default/syslog-ng [ -f ${DEFAULTFILE} ] && . ${DEFAULTFILE} [ -f ${DEFAULTFILE}@${instance} ] && . ${DEFAULTFILE}@${instance} SYSLOGNG_PREFIX=${SYSLOGNG_PREFIX:-/usr/local} SYSLOGNG="${SYSLOGNG_PREFIX}/sbin/syslog-ng" if [ "$instance" = "default" ]; then CONFIG_FILE=${CONFIG_FILE:-${SYSLOGNG_PREFIX}/etc/syslog-ng.conf} VAR_DIR=${VAR_DIR:-${SYSLOGNG_PREFIX}/var/lib/syslog-ng} PID_FILE=${PID_FILE:-${SYSLOGPID_FILE}} else CONFIG_FILE=${CONFIG_FILE:-${SYSLOGNG_PREFIX}/etc/syslog-ng@${instance}.conf} VAR_DIR=${VAR_DIR:-${SYSLOGNG_PREFIX}/var/lib/syslog-ng@${instance}} [ -d "${VAR_DIR}" ] || mkdir "${VAR_DIR}" [ -d "${VAR_DIR}/run" ] || mkdir "${VAR_DIR}/run" fi PID_FILE=${PID_FILE:-${VAR_DIR}/run/syslog-ng.pid} PERSIST_FILE=${PERSIST_FILE:-${VAR_DIR}/syslog-ng.persist} CONTROL_FILE=${CONTROL_FILE:-${VAR_DIR}/run/syslog-ng.ctl} METHOD_OPTIONS="--cfgfile=${CONFIG_FILE} --pidfile=${PID_FILE} --persist-file=${PERSIST_FILE} --control=${CONTROL_FILE}" export SYSLOGNG_PREFIX test -x ${SYSLOGNG} || exit $SMF_EXIT_ERR_FATAL test -r ${CONFIG_FILE} || exit $SMF_EXIT_ERR_CONFIG check_syntax() { ${SYSLOGNG} --syntax-only --cfgfile=${CONFIG_FILE} _rval=$? [ $_rval -eq 0 ] || exit $SMF_EXIT_ERR_CONFIG } slng_waitforpid() { _cnt=$MAXWAIT _process=$1 _pid=$2 while [ $_cnt -gt 0 ]; do pgrep $_process | grep $_pid > /dev/null 2>&1 [ $? -ne 0 ] && break _cnt=`expr $_cnt - 1` sleep 1 done return $_cnt } slng_clean_pidfile() { if [ -h $SYSLOGPID_FILE ];then rm -f $SYSLOGPID_FILE fi rm -f $PID_FILE } slng_stop() { # if we have a contract, we should simply use smf_kill_contract to terminate the process contract=`/usr/bin/svcprop -p restarter/contract ${SMF_FMRI}` if [ -n "${contract}" ]; then smf_kill_contract ${contract} TERM 1 $MAXWAIT [ $? -ne 0 ] && exit $SMF_EXIT_ERR_FATAL slng_clean_pidfile return $SMF_EXIT_OK fi [ -f $PID_FILE ] || return $SMF_EXIT_ERR_FATAL syspid=`head -1 $PID_FILE` [ -z "$syspid" ] && return $SMF_EXIT_OK kill -0 $syspid >/dev/null 2>&1 if [ $? -ne 0 ];then return $SMF_EXIT_OK fi kill -TERM $syspid _process=`basename $SYSLOGNG` slng_waitforpid "$_process" $syspid _ret=$? if [ $_ret -eq 0 ]; then kill -KILL $syspid $_ret=$? fi if [ $_ret -eq 0 ] ;then slng_clean_pidfile return $SMF_EXIT_OK fi return $SMF_EXIT_ERR_FATAL } slng_start () { if [ -f $PID_FILE ];then _process=`basename $SYSLOGNG` _pid=`head -1 $PID_FILE` pgrep $_process | grep $_pid > /dev/null 2>&1 if [ $? -eq 0 ]; then echo "syslog-ng already running." exit 1 fi echo "syslog-ng is not running, removing $PID_FILE." /usr/bin/rm -f $PID_FILE fi if [ -f $CONFIG_FILE -a -x $SYSLOGNG ]; then echo 'syslog-ng service starting.' # # Before syslog-ng starts, save any messages from previous # crash dumps so that messages appear in chronological order. # if [ -r /dev/dump ]; then /usr/bin/savecore -m fi if [ -r /etc/dumpadm.conf ]; then . /etc/dumpadm.conf if [ -n "$DUMPADM_DEVICE" ] && [ -r "$DUMPADM_DEVICE" ] && \ [ "x$DUMPADM_DEVICE" != xswap ]; then /usr/bin/savecore -m -f $DUMPADM_DEVICE fi fi check_syntax $SYSLOGNG $OTHER_OPTIONS $METHOD_OPTIONS # remove symlinks if [ -h $SYSLOGPID_FILE ];then rm -f $SYSLOGPID_FILE fi if [ ! -f $SYSLOGPID_FILE ];then ln -s $PID_FILE $SYSLOGPID_FILE fi return $SMF_EXIT_OK fi return $SMF_EXIT_ERR_FATAL } case "$method" in start) slng_start ;; stop) slng_stop ;; refresh) if [ -f $PID_FILE ]; then syspid=`head -1 $PID_FILE` [ "$syspid" -gt 0 ] && kill -1 $syspid && echo "syslog-ng service reloaded" fi ;; restart) slng_stop retval=$? [ $retval -ne 0 ] && exit $retval slng_start ;; *) echo "Usage: $0 { start | stop | restart | refresh }" exit 1 ;; esac exit $? # vim: expandtab ts=8 syslog-ng-syslog-ng-3.13.2/contrib/solaris-packaging/syslog-ng@default000066400000000000000000000004351321171025300260070ustar00rootroot00000000000000SYSLOGNG_PREFIX=/usr/local CONFIG_FILE=/usr/local/etc/syslog-ng.conf VAR_DIR=/usr/local/var/lib/syslog-ng PERSIST_FILE=/usr/local/var/lib/syslog-ng/syslog-ng.persist CONTROL_FILE=/usr/local/var/lib/syslog-ng/run/syslog-ng.ctl PID_FILE=/var/run/syslog.pid OTHER_OPTIONS="--enable-core" syslog-ng-syslog-ng-3.13.2/contrib/syslog-mc000066400000000000000000000135261321171025300207440ustar00rootroot00000000000000#!/usr/bin/perl # # syslog-mc: # This perl script is to be used in conjuction with syslog-ng and it's # multicast feature. # # All you need to do is run the program, pass an IPv4 or IPv6 multicast # address as the first parameter and the script will 'tune in' to the syslog # multicast group and display the syslog lines. # # This helps no end if you want to write local trigger scripts or have a live # view of some daemon without actually having to be logged into the central # syslog server cluster. # # One note to bear in mind is that if you send you logs in the multicast group # to a port number below 1024 then you will need root privileges to run this # script. It's probably a good idea to send your logs to a port number above # 1024 so that you do not need to run things as root. Another recommendation # is to remember to 'seperate' your group addresses by thirty two IP's (for # IPv4) so that you do not receive any unwanted, although it's harmless and # filtered, extra traffic. # # When using the script, you can run it standalone and it will simply print the # syslog messages to STDOUT however you might prefer to pipe it into grep or # some other tool, so to print all the lines containing the word 'cheese': # # $ ./syslog-mc 239.194.253.8 5514 | grep cheese # # -- # Maintained by Alexander Clouter # Written/Copyright 2006 by Alexander Clouter # # This software may be used and distributed according to the terms # of the version two of the GNU General Public License, incorporated herein by # reference. # use strict; use warnings; my $running = 1; use sigtrap 'handler' => sub { $running = 0 }, qw( INT ); # under debian all these dependencies can be met with: # aptitude install libnet-ip-perl libsocket6-perl libio-socket-inet6-perl libparse-syslog-perl use Net::IP; use Socket; use Socket6; use IO::Socket::INET6; # we use IO::Select to avoid the nasty blocking nature of Parse::Syslog use IO::Select; use Parse::Syslog; use POSIX; # enable debugging? use constant DEBUG => 0; if ( DEBUG ) { use Data::Dumper; } my ( $mcGroup, $port ) = ( $ARGV[0], $ARGV[1] ); unless ( $mcGroup ) { print < [port] EOF exit 0; } $mcGroup =~ s/\s*(.+)\s*/$1/; my $ip = Net::IP->new($mcGroup) || die 'First parameter is not a valid IP address'; if ( $ip->version == 4 ) { unless ( Net::IP->new('224.0.0.0/4')->overlaps($ip) != $Net::IP::IP_NO_OVERLAP ) { print STDERR "IPv4 address given is not a multicast address\n"; exit 1; } } elsif ( $ip->version == 6 ) { unless ( Net::IP->new('ff::/120')->overlaps($ip) != $Net::IP::IP_NO_OVERLAP ) { print STDERR "IPv6 address given is not a multicast address\n"; exit 1; } } else { print STDERR "Unknown IP Version\n"; exit 1; } if ( $port ) { $port =~ s/\s*(.+)\s*/$1/; if ( $port =~ /^\d+$/ ) { unless ( $port > 0 && $port < 65536 ) { print STDERR "Invalid port number\n"; exit 1; } } } else { $port = 514; print STDERR "No port number given, assuming 514\n" if ( DEBUG ); } my $sock = &subscribe($mcGroup, $port); unless ( $sock ) { print STDERR "Unable to open socket so bombing out\n"; exit 1; } my $parser = Parse::Syslog->new($sock, arrayref => 1); my $selectPoll = IO::Select->new; $selectPoll->add($sock); while ( $running ) { my ( $select_set ) = IO::Select->select($selectPoll, undef, undef); foreach my $fh ( @$select_set ) { if ( $fh == $sock ) { if ( $sock->eof ) { $running = 0; next; } my $sl = $parser->next; my $timestamp = POSIX::strftime '%b %e %T', gmtime($sl->[0]); my $pid = ( $sl->[3] ) ? $sl->[3] : 'na'; print "$timestamp " . $sl->[1] . ' ' . $sl->[2] . "[$pid]: " . $sl->[4] . "\n"; } } } $selectPoll->remove($sock); &unsubscribe($sock); exit 0; sub subscribe { my $mcGroup = shift; my $port = shift; print STDERR "Trying to join group $mcGroup: " if ( DEBUG ); my @res = getaddrinfo $mcGroup, $port, AF_UNSPEC, SOCK_DGRAM; my $sock = IO::Socket::INET6->new( Domain => $res[0], LocalAddr => $mcGroup, Proto => 'udp', Type => SOCK_DGRAM, LocalPort => $port, ReuseAddr => 1 ) || print STDERR "Can't bind : $@\n"; unless ( $sock && ref $sock eq 'IO::Socket::INET6' ) { print STDERR "Unable to open socket! If using a port number below 1024 you need to be root\n"; return; } my $joinStatus; if ( $sock->sockdomain == AF_INET ) { # struct ip_mreq my $mreq = pack 'a4 a4', inet_pton(AF_INET, $mcGroup), INADDR_ANY; # IP_ADD_MEMBERSHIP = 35 $joinStatus = setsockopt $sock, IPPROTO_IP, 35, $mreq; } elsif ( $sock->sockdomain == AF_INET6 ) { # struct ipv6_mreq my $mreq6 = pack 'a16 N', inet_pton(AF_INET6, $mcGroup), 0; # IPV6_ADD_MEMBERSHIP = 20 $joinStatus = setsockopt $sock, IPPROTO_IPV6, 20, $mreq6; } else { print STDERR "unknown IP version, " if ( DEBUG ); $joinStatus = -1; } if ( $joinStatus == -1 ) { print STDERR "unable to ADD_MEMBERSHIP for $mcGroup\n" if ( DEBUG ); close $sock; return; } print STDERR "successful\n" if ( DEBUG ); return $sock; } sub unsubscribe { my $sock = shift; my $mcGroup = $sock->sockhost; print STDERR "Leaving group $mcGroup: " if ( DEBUG ); my $leaveStatus; if ( $sock->sockdomain == AF_INET ) { my $mreq = pack 'a4 a4', inet_pton(AF_INET, $mcGroup), INADDR_ANY; # IP_DROP_MEMBERSHIP = 36 $leaveStatus = setsockopt $sock, IPPROTO_IP, 36, $mreq; } else { my $mreq6 = pack 'a16 N', inet_pton(AF_INET6, $mcGroup), 0; # IPV6_DROP_MEMBERSHIP = 21 $leaveStatus = setsockopt $sock, IPPROTO_IPV6, 21, $mreq6; } if ( $leaveStatus == -1 ) { print STDERR "warning, unable to DROP_MEMBERSHIP for $mcGroup..." if ( DEBUG ); } close $sock; print STDERR "done\n" if ( DEBUG ); } syslog-ng-syslog-ng-3.13.2/contrib/syslog-ng-debun000077500000000000000000001325041321171025300220450ustar00rootroot00000000000000#!/bin/sh #!/bin/bash ### syslog-ng-debun: syslog debug bundle generator ### Written/Copyright: Gyorgy Pasztor , (c) 2014-2016. ### Further enhancements: Janos Szigetvari - jszigetvari at gmail dot com, (c) 2016-2017. ### This software may be used and distributed according to the terms of GNU GPLv2 ### http://www.gnu.org/licenses/gpl-2.0.html version="0.3.8.20170926" ### Check for "local" variable support if type local >/dev/null; then : elif type bash >/dev/null; then #printf "There is no local, re-exec self in bash\n" >&2 exec bash $0 "$@" else printf "No local variable support on this system\n" >&2 exit 1 fi ### ### Global defaults ### Do not overwrite them, parameters or distro / OS specific detections will do that if neccessary ### argv_backup="${@}" engage=0 os="none" dist="none" default_debug_params="-Fedv --enable-core" default_ldebug_params="-Fev" default_pcap_params="port 514 or port 601 or port 53" extras="" sngallpids="" debugpid=none debugtailpid=none pcappid=none tracepids="" ipconfig="ip addr" routeconfig () { netstat -nr ; } netstatnlp () { netstat -nlp ; } netstatlunp () { netstat -lunp ; } netstatsu="netstat -su" netstatpunt="netstat -punt" binprefix=/opt/syslog-ng workdir=/tmp lsof="lsof -p" pscmd="ps auxwwwwwf" pseao="ps -eao" dfk="df -k" dfh="df -h" dfi="df -i" duks="du -ks" grepq="fgrep -q" lddcmd="ldd" topcmd () { top -b -n 1 -c >"${1}"; } opensslcmd="openssl" sed_equivalent_cmd="sed -E" mount=mount varlimit=1000 myplimit () { echo "Plimit query is not supported on this platform" >&3 ; } distpkgoffile () { echo "Package file search is not supported (yet) on this platform" >&3 ; } distpkgstatus () { echo "Package status query is not (yet) supported on this platform" >&3 ; } selftar="tar cf - ." gzipcmd="gzip -9" showdep="dpkg -S" pcapifparm=-i w=w vmstat=vmstat dmesg=dmesg tcpdumpcmd="tcpdump" tcpdumpopts="-p -s 1500 -w" opensslmajor=0 getsyslogpids () { pidof syslog-ng ; } os_hash_helper () { find . '!' \( -name debun.manifest -o -name syslog-ng.debun.txt \) -type f -print0 | xargs -0 md5sum ; } dfk_parser () { tail -1 | while read FS ALL USED AVAIL UPERC MP; do if echo ${AVAIL} | ${grepq} '%'; then echo ${USED} ; else echo ${AVAIL} ; fi done ; } trace="strace -s256 -ff -ttT -f" initfile="/etc/init.d/syslog-ng" service_stop="${initfile} stop" service_start="${initfile} start" service_status="${initfile} status" #checkpid () { [ -d /proc/"$1" ]; } #some old Unix versions did not have procfs, and kill -0 allows to check whether a PID exists #for reference: http://pubs.opengroup.org/onlinepubs/009695399/functions/kill.html checkpid () { [ -n "$1" ] && kill -0 "$1" 2>/dev/null ; } #mywait () { jobs -p >${tmpdir}/sdn.jobs ; for i in `grep -v "\<$tailpid\>" ${tmpdir}/sdn.jobs` ; do wait $i ; done ; } mywait () { jobs -p >${tmpdir}/sdn.jobs ; for i in `grep -v "^$tailpid\$" ${tmpdir}/sdn.jobs` ; do wait $i ; done ; } is_available () { which "$1" >/dev/null 2>&1; } distpkgoffile_cleanup () { : ; } ### ### Show Usage ### debun_usage () { cat <&2 ; exit 1 ; } [ -z "$tmpdir" ] && { printf "Could not create a temp directory\n" >&2 ; exit 1 ; } # Start redirections #exec 3>&1 >${tmpdir}/syslog-ng.debun.txt 2>${tmpdir}/syslog-ng.debun.txt exec 3>&1 >${tmpdir}/syslog-ng.debun.txt 2>&1 echo "Syslog-NG DEBUg buNdle generator" sync while [ ! -f ${tmpdir}/syslog-ng.debun.txt ] ; do sleep 1 ; done #nohup tail -f ${tmpdir}/syslog-ng.debun.txt >&3 & tail -f ${tmpdir}/syslog-ng.debun.txt >&3 & tailpid=$! #disown } debun_finish_debug () { if [ "${debugpid}" != "none" ]; then if checkpid ${debugpid} ; then kill -INT $debugpid checkpid ${debugpid} && sleep 1 checkpid ${debugpid} && kill -9 $debugpid checkpid ${debugpid} && sleep 1 checkpid ${debugpid} && echo "I gave up... debugger pid doesn't die" fi printf 'Debugpid: "%s"\n' "${debugpid}" ( exec 3>&- ; $service_start ; ) fi if checkpid ${debugtailpid} ; then kill $debugtailpid fi if checkpid ${pcappid} ; then kill -INT $pcappid fi if [ -n "$tracing" ]; then for i in ${tracepids} ; do checkpid $i && kill -INT $i done sleep 2 for i in ${tracepids} ; do checkpid $i && kill -9 $i 2>/dev/null done fi mywait } debun_do_tarball () { cd ${tmpdir} touch ${tmpdir}.tgz chmod 600 ${tmpdir}.tgz ${selftar} | ${gzipcmd} >${tmpdir}.tgz cd .. rm -r "${tmpdir}" printf "Terminating live message watcher: " sync kill ${tailpid} sync sleep 1 } debun_generate_hashes () { cd ${tmpdir} os_hash_helper > debun.manifest } debun_final() { debun_finish_debug [ -n "$service_status" ] && $service_status >${tmpdir}/svc.post printf "\nGenerating hashes..." debun_generate_hashes printf " done.\nDebug Bundle generation: Done.\n" exec >&3 2>&1 debun_do_tarball printf "\n\nYour debug bundle will be stored at %s.tgz\n" "$tmpdir" } add_extra () { extras="${extras}${extras:+ }$@" } ### ###PROCESS HANDLING FUNCTIONS ### getparent () { local self local parent local ret local tmpfile=${tmpdir}/getparent.$$.txt $pseao pid,ppid >$tmpfile # Default value, learned after getchilds()'s forkbomb case unset ret while read self parent ; do [ "$1" = "$self" ] || continue ret=$parent done < $tmpfile rm $tmpfile echo $ret } getchilds () { local childs local dummy local child local tmpfile=${tmpdir}/getchilds.$$.txt $pseao ppid,pid >$tmpfile # Need to initialize it with a default value, since dash allows to inherit the caller's value, even if it's a local variable unset childs while read dummy child ; do [ "$1" = "$dummy" ] || continue childs="${childs}${childs:+ }$child" done < $tmpfile rm $tmpfile echo ${childs} } getallchilds () { local childs local subchilds childs="`getchilds $1`" local i # Default value, learned after getchilds()'s forkbomb case unset subchilds for i in ${childs} ; do subchilds="${subchilds}${subchilds:+ }`getallchilds $i`" done echo ${childs} ${subchilds} } acquire_debun_info () { pwd > ${tmpdir}/debun.pwd echo "${0} ${argv_backup}" > ${tmpdir}/debun.argv echo "${version}" > ${tmpdir}/debun.version id > ${tmpdir}/debun.runas } acquire_system_info () { printf "System's full uname: " uname -a | tee "${tmpdir}/sys.uname" free >${tmpdir}/sys.free vmstat >${tmpdir}/sys.vmstat topcmd "${tmpdir}/sys.top" if is_available ${opensslcmd}; then ${opensslcmd} version >${tmpdir}/sys.openssl.version fi if is_available java; then java -version >${tmpdir}/sys.java.version 2>&1 fi } acquire_network_info () { printf "Getting network-interface information: " if $ipconfig >${tmpdir}/net.ip ; then printf "Success\n" else printf "Failed\n" fi printf "Getting network routes: " if routeconfig >${tmpdir}/net.route ; then printf "Success\n" else printf "Failed\n" fi printf "Getting DNS resolution-related information: " [ -f /etc/nsswitch.conf ] && cp /etc/nsswitch.conf ${tmpdir}/sys.nsswitch.conf [ -f /etc/resolv.conf ] && cp /etc/resolv.conf ${tmpdir}/sys.resolv.conf [ -f /etc/hosts ] && cp /etc/hosts ${tmpdir}/sys.hosts printf "Done\n" } acquire_system_process_info () { echo "List all processes" $pscmd >${tmpdir}/sys.ps } acquire_filesystem_info () { echo "Mount and disk free info collection" $dfk >${tmpdir}/sys.df_k $dfh >${tmpdir}/sys.df_h $dfi >${tmpdir}/sys.df_i 2>/dev/null $mount >${tmpdir}/sys.mount } acquire_system_other_info () { $w >${tmpdir}/sys.w $dmesg >${tmpdir}/sys.dmesg netstatnlp >${tmpdir}/sys.netstat.ltn $netstatpunt >${tmpdir}/sys.netstat.est netstatlunp >${tmpdir}/sys.netstat.lunp $netstatsu >${tmpdir}/sys.netstat.su [ -f /proc/net/udp ] && cp /proc/net/udp ${tmpdir}/sys.proc.net.udp } ### Here comes the general info acquiring parts acquire_general_info () { printf "\nStart general info collection\n" acquire_debun_info acquire_system_info [ -n "$privacy_mode" ] && return acquire_network_info acquire_system_process_info acquire_filesystem_info acquire_system_other_info } pki_is_certificate () { grep "BEGIN CERTIFICATE" "${1}" 2>/dev/null | ${grepq} -v "REQUEST" } pki_count_certificates () { grep -c "BEGIN CERTIFICATE" "${1}" 2>/dev/null } pki_is_private_key () { ${grepq} "PRIVATE KEY" "${1}" 2>/dev/null } pki_is_public_key () { ${grepq} "PUBLIC KEY" "${1}" 2>/dev/null } pki_is_rsa () { ${grepq} "RSA " "${1}" 2>/dev/null } pki_is_dsa () { ${grepq} "DSA " "${1}" 2>/dev/null } pki_is_ecdsa () { ${grepq} " EC " "${1}" 2>/dev/null } pki_is_encrypted () { if ${grepq} "ENCRYPTED" "${1}"; then return 0 else local buffer_error buffer_error=$( ${opensslcmd} rsa -in "${1}" -noout -text 2>&1 >/dev/null ) if echo "${buffer_error}" | ${grepq} "problems getting password"; then return 0 else return 1 fi fi } pki_parse_public_key () { oneline_cert=$( tr -d '\n' | tr -d ' ' ) [ -z "${oneline_cert}" ] && printf "NO_PUBLIC_KEY_COULD_BE_EXTRACTED;" && return if echo "${oneline_cert}" | $grepq "UnabletoloadPublicKey"; then printf "OPENSSL_TOO_OLD|NO_ECDSA_SUPPORT_IN_OPENSSL;" else if echo "${oneline_cert}" | $grepq "PublicKey:X509v3extensions"; then printf "NO_PUBLIC_KEY_COULD_BE_EXTRACTED;" else echo "${oneline_cert}" | ${sed_equivalent_cmd} 's/^.*(Modulus|modulus|pub)(\([0-9]+bit\))?:([a-f0-9:]+).*$/Public Key=\3;/' fi fi } pki_guess_certificate () { local header fsize buffer_pubkey buffer_rest hashopts hashnum fsize=$( wc -c "${1}" | ${sed_equivalent_cmd} 's:^ *([0-9]+) .*$:\1:' ) if [ ${opensslmajor} -gt 0 ]; then hashopts="-subject_hash -subject_hash_old" hashnum="2;" else hashopts="-hash" hashnum="1;" fi certcount=$( pki_count_certificates "${1}" ) [ "${certcount}" -gt 1 ] && header="STACKED_CERTIFICATE(${certcount});${1};" || header="CERTIFICATE;${1};" buffer_pubkey=$( ${opensslcmd} x509 -in "${1}" -text -noout 2>/dev/null | pki_parse_public_key ) buffer_rest=$( ${opensslcmd} x509 -in "${1}" -noout ${hashopts} -serial -dates -fingerprint -subject -issuer | tr '\n' ';' ) printf "${header}${fsize};${buffer_pubkey}${hashnum}${buffer_rest}" } pki_guess_private_key () { local header fsize buffer_pubkey buffer_error fsize=$( wc -c "${1}" | ${sed_equivalent_cmd} 's:^ *([0-9]+) .*$:\1:' ) if pki_is_encrypted "${1}"; then header="PRIVATE_ENCRYPTED;${1};" else if pki_is_rsa "${1}"; then header="PRIVATE_RSA;${1};" buffer_pubkey=$( ${opensslcmd} rsa -in "${1}" -noout -text 2>/dev/null | pki_parse_public_key ) elif pki_is_dsa "${1}"; then header="PRIVATE_DSA;${1};" buffer_pubkey=$( ${opensslcmd} dsa -in "${1}" -noout -text 2>/dev/null | pki_parse_public_key ) elif pki_is_ecdsa "${1}"; then header="PRIVATE_EC;${1};" buffer_error=$( ${opensslcmd} ec -in "${1}" -noout -text 2>&1 >/dev/null ) if echo "${buffer_error}" | ${grepq} "'ec' is an invalid command"; then buffer_pubkey="NO_ECDSA_SUPPORT_IN_OPENSSL;" elif echo "${buffer_error}" | $grepq "unable to load"; then buffer_pubkey="OPENSSL_TOO_OLD;" else buffer_pubkey=$( ${opensslcmd} ec -in "${1}" -noout -text 2>/dev/null | pki_parse_public_key ) fi else header="UNKNOWN_PRIVATE;${1};" buffer_pubkey=";" fi fi printf "${header}${fsize};${buffer_pubkey}" } pki_guess_public_key () { # Public keys do not have their type in the PEM header/footer local header fsize buffer_pubkey buffer_error header="PUBLIC;${1};" fsize=$( wc -c "${1}" | ${sed_equivalent_cmd} 's:^ *([0-9]+) .*$:\1:' ) if [ ${opensslmajor} -gt 0 ]; then buffer_error=$( ${opensslcmd} pkey -pubin -in "${1}" -noout -text 2>&1 >/dev/null ) if echo "${buffer_error}" | ${grepq} "unable to load"; then header="UNKNOWN_PUBLIC;${1};" buffer_pubkey="OPENSSL_TOO_OLD|NO_ECDSA_SUPPORT_IN_OPENSSL;" else buffer_pubkey=$( ${opensslcmd} pkey -pubin -in "${1}" -noout -text 2>/dev/null | pki_parse_public_key ) fi else buffer_error=$( ${opensslcmd} rsa -pubin -in "${1}" -noout -text 2>&1 >/dev/null ) if echo "${buffer_error}" | ${grepq} "expecting an rsa key"; then buffer_error=$( ${opensslcmd} dsa -pubin -in "${1}" -noout -text 2>&1 >/dev/null ) if echo "${buffer_error}" | ${grepq} "expecting a dsa key"; then buffer_error=$( ${opensslcmd} ec -pubin -in "${1}" -noout -text 2>&1 >/dev/null ) if echo "${buffer_error}" | ${grepq} "expecting a ec key"; then header="UNKNOWN_PUBLIC;${1};" buffer_pubkey=";" elif echo "${buffer_error}" | ${grepq} "'ec' is an invalid command"; then header="UNKNOWN_PUBLIC;${1};" buffer_pubkey="NO_ECDSA_SUPPORT_IN_OPENSSL;" else buffer_pubkey=$( ${opensslcmd} ec -pubin -in "${1}" -noout -text 2>/dev/null | pki_parse_public_key ) fi else buffer_pubkey=$( ${opensslcmd} dsa -pubin -in "${1}" -noout -text 2>/dev/null | pki_parse_public_key ) fi elif echo "${buffer_error}" | ${grepq} "unable to load"; then header="UNKNOWN_PUBLIC;${1};" buffer_pubkey="OPENSSL_TOO_OLD|NO_ECDSA_SUPPORT_IN_OPENSSL;" else buffer_pubkey=$( ${opensslcmd} rsa -pubin -in "${1}" -noout -text 2>/dev/null | pki_parse_public_key ) fi fi printf "${header}${fsize};${buffer_pubkey}" } pki_other_file () { local fsize fsize=$( wc -c "${1}" | ${sed_equivalent_cmd} 's:^ *([0-9]+) .*$:\1:' ) printf "OTHER_FILE;${1};${fsize};" } pki_process_file () { local output_buffer if pki_is_certificate "${1}"; then output_buffer=$( pki_guess_certificate "${1}" ) else if pki_is_private_key "${1}"; then output_buffer=$( pki_guess_private_key "${1}" ) elif pki_is_public_key "${1}"; then output_buffer=$( pki_guess_public_key "${1}" ) else output_buffer=$( pki_other_file "${1}" ) fi fi echo "${output_buffer}" } acquire_syslog_pki_info () { printf "Gathering PKI information... " if is_available ${opensslcmd}; then local OPENSSL OPENSSLVER OPENSSLDAY OPENSSLMONTH OPENSSLYEAR REST read OPENSSL OPENSSLVER OPENSSLDAY OPENSSLMONTH OPENSSLYEAR REST <${tmpdir}/sys.openssl.version opensslmajor=${OPENSSLVER%%.*} cd "${confdir}" find . -name '*.0' -o -name '*.1' -o -name '*.key' -o -name '*.crt' -o -name '*.pem' >${tmpdir}/syslog.etc.pki.files 2>/dev/null while read FILE; do pki_process_file "${FILE}" >>${tmpdir}/syslog.etc.pki.info.csv done <${tmpdir}/syslog.etc.pki.files printf "done.\n" else printf "no openssl found in PATH.\n" fi } remove_passwords_from_file () { # # Double quotes are used because escaping single quotes within a single quoted string is ugly. # [ \t\r\n\v\f] class is used for matching whitespaces, because \s is unavailable. # The goal is matching substrings that look like this, to replace the password string, and preserve original formatting: # password ( 'password-string' ) --> password ( '___PASSWORD_REMOVED___' ) ### ${sed_equivalent_cmd} "s|password([ \t\r\n\v\f]*)\(([ \t\r\n\v\f]*)([\"']?)[^)\"']+([\"']?)([ \t\r\n\v\f]*)\)|password\1(\2\3___PASSWORD_REMOVED___\4\5)|g" <"${1}" >"${1}.bak" 2>/dev/null mv "${1}.bak" "${1}" } acquire_syslog_config () { echo "Copy configs from $confdir" cd "${confdir}" mkdir ${tmpdir}/config find . > ${tmpdir}/syslog.etc.files grep '\.key$' ${tmpdir}/syslog.etc.files > ${tmpdir}/syslog.etc.files.removed grep '\.jks$' ${tmpdir}/syslog.etc.files > ${tmpdir}/syslog.etc.files.removed grep -v '\.key$' ${tmpdir}/syslog.etc.files | grep -v '\.jks' | \ while read FILE; do \ if pki_is_private_key "${FILE}" 2>/dev/null; then echo "${FILE}" >> ${tmpdir}/syslog.etc.files.removed else echo "${FILE}" fi done | \ cpio -pd ${tmpdir}/config find ${tmpdir}/config -name "*.conf*" | \ while read FILE; do \ remove_passwords_from_file "${FILE}" done } acquire_syslog_pids () { echo 'Old "getsyslogpids":' >${tmpdir}/syslog.pids getsyslogpids >>${tmpdir}/syslog.pids if [ -r "${piddir}/syslog-ng.pid" ]; then sngpid=`cat ${piddir}/syslog-ng.pid` else # Handle when fhs is "linux"-like sngpid=`cat ${piddir}/syslog-ng.pid` fi ppid=`getparent $sngpid` sngallpids="`getallchilds $sngpid`" echo "SVpid: $ppid SNGpid: $sngpid Chpids: ${sngallpids}" >>${tmpdir}/syslog.pids tail -1 ${tmpdir}/syslog.pids if [ -n "$ppid" ]; then sngallpids="$ppid $sngpid ${sngallpids}" else sngallpids="` getsyslogpids `" fi # drop out the unneeded white spaces, since that disturb the ps command sngallpids=`echo ${sngallpids}` if [ -n "${sngallpids}" ]; then printf 'ps -l -f -p "%s"\n' "${sngallpids}" >>${tmpdir}/syslog.pids ps -l -f -p "${sngallpids}" >>${tmpdir}/syslog.pids fi [ -n "$service_status" ] && $service_status >${tmpdir}/svc.pre } acquire_syslog_info () { ls -la "${binprefix}" > ${tmpdir}/syslog.lsl.install_dir 2>&1 printf "Syslog-ng's exact version: " $syslogbin --version > ${tmpdir}/syslog.version head -1 ${tmpdir}/syslog.version ${syslogbin}-ctl stats > ${tmpdir}/syslog.stats 2>&1 echo ${syslogbin}-ctl stats ${syslogbin}-ctl query get "*" > ${tmpdir}/syslog.query.all 2>/dev/null echo ${syslogbin}-ctl query get "*" if [ -x ${syslogbin}-query ]; then #if we reach this brach, then syslog.query.all - as generated above - will not contain any meaningful data ${syslogbin}-query sum "*" > ${tmpdir}/syslog.query.all 2>/dev/null echo ${syslogbin}-query sum "*" fi if ${syslogbin}-ctl show-license-info > ${tmpdir}/syslog.license-usage 2>&1; then ${syslogbin}-ctl show-license-info --json > ${tmpdir}/syslog.license-usage.json 2>/dev/null fi echo ${syslogbin}-ctl show-license-info for i in ${sngallpids} ; do is_available ${lsof%% *} && $lsof $i >${tmpdir}/syslog.$i.lsof 2>/dev/null || echo "No lsof in path." >${tmpdir}/syslog.$i.lsof myplimit $i >${tmpdir}/syslog.$i.limits done $syslogbin -s --preprocess-into "${tmpdir}/syslog.pp.conf" [ -f "${tmpdir}/syslog.pp.conf" ] && remove_passwords_from_file "${tmpdir}/syslog.pp.conf" } acquire_syslog_var () { ls -laR "${vardir}" >${tmpdir}/syslog.lslR.var 2>&1 $duks "${vardir}/" >${tmpdir}/syslog.duks.var read vardu dir <${tmpdir}/syslog.duks.var mkdir ${tmpdir}/var cd "${vardir}" freek_tmp=$( ${dfk} ${tmpdir} | dfk_parser ) # # low disk-space => only copy the persist file and the pid file ### if [ "${freek_tmp}" -gt "${vardu}" ] ; then if [ "$vardu" -lt "$varlimit" ] ; then find . |grep -v run\\/syslog-ng.ctl$ | cpio -pd ${tmpdir}/var else printf "Size of ${vardir} is larger than $varlimit kilobytes.\n" printf "Do you really want to copy its contents? Type 'YES' with all capitals: " read ans if [ "$ans" = "YES" ]; then find . | grep -v "syslog-ng*\.ctl" | cpio -pd ${tmpdir}/var fi fi else printf "TOO LOW free disk space on the filesystem holding ${tmpdir}\n" printf "to create a full copy of ${vardir}!\nOnly copying most important files.\n" find . \( -name "*.persist" -o -name "*.pid" \) | grep -v "syslog-ng.*\.ctl" | cpio -pd ${tmpdir}/var fi } format_ldd_output () { while read x ; do # libsyslog-ng-5.0.5.so => /opt/syslog-ng/lib/libsyslog-ng-5.0.5.so (0x00007f9b42990000) #/opt/syslog-ng/lib/libsyslog-ng-5.0.5.so (0x00007f9b42990000) x="/${x#*/}" #/opt/syslog-ng/lib/libsyslog-ng-6.0.2.so (0x00007f034c8c0000) #/opt/syslog-ng/lib/libsyslog-ng-6.0.2.so x="${x%% (*}" #AIX: #/opt/syslog-ng/lib/libsyslog-ng.a(libsyslog-ng-5.0.14.so) #/opt/syslog-ng/lib/libsyslog-ng.a x="${x%%(*}" [ "${x}" != "/ " ] && [ -f "${x}" ] && echo "$x" done } acquire_syslog_ldinfo () { $lddcmd $syslogrealbin |grep -v needs >${tmpdir}/syslog.ldd format_ldd_output <${tmpdir}/syslog.ldd >${tmpdir}/syslog.ldfiles for i in `cat ${tmpdir}/syslog.ldfiles ` ; do distpkgoffile $i >>${tmpdir}/syslog.ldpkg done distpkgoffile_cleanup sort <${tmpdir}/syslog.ldpkg | uniq >${tmpdir}/syslog.ldpkg.u mv ${tmpdir}/syslog.ldpkg.u ${tmpdir}/syslog.ldpkg for i in `cat ${tmpdir}/syslog.ldpkg ` ; do distpkgstatus $i >>${tmpdir}/syslog.ldinfos done } acquire_syslog_startup_method () { printf "Detecting init system: " if [ -d "/run/systemd/system" ]; then acquire_syslog_startup_systemdunit elif [ -d "/lib/svc/method" ]; then acquire_syslog_startup_smf else acquire_syslog_startup_initscript fi for i in /etc/default/syslog-ng* ; do [ -f "${i}" ] && cp "${i}" "${tmpdir}/sys.startup.default.${i##*/}" done for i in /etc/sysconfig/syslog-ng* ; do [ -f "${i}" ] && cp "${i}" "${tmpdir}/sys.startup.sysconfig.${i##*/}" done } acquire_syslog_startup_initscript () { if [ -n "${initfile}" ]; then printf "falling back to SystemV init style...\n" cp "${initfile}" "${tmpdir}/sys.startup.init.syslog-ng" chmod 0660 "${tmpdir}/sys.startup.init.syslog-ng" else printf "none.\n" fi } acquire_syslog_startup_systemdunit () { printf "systemd detected...\n" systemctl list-units --type=service --plain --no-legend --no-pager --all | grep syslog | grep -vE '(not-found|masked)' | tee "${tmpdir}/sys.startup.systemd-instances" | \ while read SERVICE LOAD ACTIVE SUB DESCRIPTION ; do output_buffer=$( systemctl show -p FragmentPath ${SERVICE} ) ; echo "${output_buffer##FragmentPath=}" ; done | \ while read UNITFILE; do SUFFIX=$( echo "${UNITFILE}" | tr / . ); cp "${UNITFILE}" "${tmpdir}/sys.startup.systemd-service${SUFFIX}" ; done } acquire_syslog_startup_smf () { printf "Solaris SMF detected...\n" cp "/lib/svc/method/syslog-ng" "${tmpdir}/sys.startup.svc-method.syslog-ng" chmod 0660 "${tmpdir}/sys.startup.svc-method.syslog-ng" cp "/var/svc/manifest/system/syslog-ng.xml" "${tmpdir}/sys.startup.svc-manifest.syslog-ng.xml" svcs -H system/syslog* >"${tmpdir}/sys.startup.svc-instances" } acquire_syslog_all () { printf "\nStart Syslog-specific info collection\n" acquire_syslog_config acquire_syslog_pki_info acquire_syslog_pids acquire_syslog_info acquire_syslog_var acquire_syslog_ldinfo acquire_syslog_startup_method } acquire_syslog_nprv () { printf "\nStart Syslog-specific info collection (light)\n" acquire_syslog_pids acquire_syslog_info acquire_syslog_ldinfo acquire_syslog_startup_method } fhs_set_linux () { confdir=/etc/syslog-ng vardir=/var/lib/syslog-ng piddir=/var/lib/syslog-ng syslogbin=/usr/sbin/syslog-ng syslogrealbin=/usr/sbin/syslog-ng } fhs_set_unix () { : } rpm_verify () { local found=0 for pkg in "${@}"; do if rpm -q "${pkg}" ; then rpm -V "${pkg}" && echo "${pkg}: Package files are intact" ((found+=1)) fi done [ ${found} -eq 0 ] && return 1 || return 0 } ### Here comes the linux & distro specific parts debun_extra_debian () { printf "\nDebian specific checks\n" printf "Check package files integrity\n" cd / md5sum --quiet -c /var/lib/dpkg/info/syslog-ng*.md5sums && printf "Package files are intact\n" printf "list syslog-related packages\n" dpkg -l |grep syslog > ${tmpdir}/deb.packages } debun_extra_redhat () { printf "\nRedhat specific checks\n" printf "Check package files integrity\n" rpm_verify syslog-ng-premium-edition syslog-ng-premium-edition-client syslog-ng-premium-edition-compact || \ printf "No syslog-ng RPM packages have been found!\n" printf "list syslog-related packages\n" rpm -qa |grep syslog > ${tmpdir}/rpm.packages } debun_extra_slackware () { printf "\nSlackware Linux specific checks\n" printf "list syslog-related packages\n" find /var/log/packages -name "*sys*log*" | while read -r FILE; do echo "${FILE##*/}"; done > ${tmpdir}/pkg.packages } debun_extra_suse() { printf "\nSuSE specific checks\n" printf "Check package files integrity\n" rpm_verify syslog-ng-premium-edition syslog-ng-premium-edition-client syslog-ng-premium-edition-compact || \ printf "No syslog-ng RPM packages have been found!\n" printf "list syslog-related packages\n" rpm -qa | grep syslog > ${tmpdir}/rpm.packages #on opensuse "ss utility, iproute2-ss071016" crashes when run with the -punt CLI options if is_available netstat; then #this info should only be collected if the user has not requested privacy mode #we value our customer's sense of privacy if [ -z "$privacy_mode" ]; then netstat -punt >${tmpdir}/sys.netstat.est.noss fi fi } debun_extra_genlinux () { if is_available getenforce; then getenforce >"${tmpdir}/sys.selinux" ${pscmd}Z >"${tmpdir}/sys.ps.selinux" semodule -l >"${tmpdir}/sys.selinux.modules" else echo "No getenforce in path." >"${tmpdir}/sys.selinux" fi if is_available sysstat ; then sysstat -P ALL 1 5 >${tmpdir}/sys.sar.cpu sysstat -d 1 5 >${tmpdir}/sys.sar.disk elif is_available sar ; then sar -P ALL 1 5 >${tmpdir}/sys.sar.cpu sar -d 1 5 >${tmpdir}/sys.sar.disk fi if is_available top; then top -b -H -n 1 -c >${tmpdir}/sys.top.threads fi [ -n "$privacy_mode" ] && return if is_available dmidecode; then dmidecode >"${tmpdir}/sys.dmidecode" fi if is_available lspci; then lspci >"${tmpdir}/sys.lspci" else echo "No lspci in path." >"${tmpdir}/sys.lspci" fi sysctl -a >"${tmpdir}/sys.sysctl.all" 2>/dev/null cp /proc/cpuinfo "${tmpdir}/sys.cpuinfo" } debun_linux () { if [ "$dist" = "Debian" ]; then add_extra debun_extra_debian elif [ "$dist" = "Ubuntu" ]; then add_extra debun_extra_debian elif [ "$dist" = "CentOS" ]; then add_extra debun_extra_redhat elif [ "$dist" = "RedHatEnterpriseServer" ]; then add_extra debun_extra_redhat elif [ "$dist" = "RHEL" ]; then add_extra debun_extra_redhat elif [ "$dist" = "OracleServer" ]; then add_extra debun_extra_redhat elif [ "$dist" = "EnterpriseEnterpriseServer" ]; then add_extra debun_extra_redhat elif [ "$dist" = "SUSE LINUX" ]; then add_extra debun_extra_suse elif [ "$dist" = "Slackware" ]; then add_extra debun_extra_slackware else echo "Unknown Distro, perhaps unsupported" fi add_extra debun_extra_genlinux } debun_extra_gensolaris () { sysdef >${tmpdir}/sys.sysdef kstat >${tmpdir}/sys.kstat cp /etc/release ${tmpdir}/sys.release if is_available showrev ; then showrev >${tmpdir}/sys.showrev fi if is_available sar ; then sar -u 1 5 >${tmpdir}/sys.sar.cpu sar -d 1 5 >${tmpdir}/sys.sar.disk fi if is_available top; then top -b -t -n 1 -c >${tmpdir}/sys.top.threads fi } ### Here comes solaris specific parts debun_solaris () { add_extra debun_extra_gensolaris pkginfo | grep -i syslog > ${tmpdir}/pkg.packages } debun_extra_freebsd() { if is_available top; then top -b -d1 -H >${tmpdir}/sys.top.threads fi } debun_freebsd() { add_extra debun_extra_freebsd } debun_extra_hpux () { sysdef >${tmpdir}/sys.sysdef swlist >${tmpdir}/sys.swlist if is_available sar ; then sar -u 1 5 >${tmpdir}/sys.sar.cpu sar -d 1 5 >${tmpdir}/sys.sar.disk fi } debun_hpux () { add_extra debun_extra_hpux } debun_extra_aix () { alog -o -t console >${tmpdir}/sys.console-log if is_available sar ; then sar -u 1 5 >${tmpdir}/sys.sar.cpu 2>/dev/null sar -b 1 5 >${tmpdir}/sys.sar.disk 2>/dev/null1 fi } debun_aix () { add_extra debun_extra_aix echo "Check package files integrity" rpm_verify syslog-ng-premium-edition syslog-ng-premium-edition-client syslog-ng-premium-edition-compact || \ echo "No syslog-ng RPM packages have been found!" echo "list syslog-related packages" rpm -qa |grep syslog > ${tmpdir}/rpm.packages } detect_env_linux () { if is_available lsb_release ; then lsb_release -a | tee ${tmpdir}/lsb.all dist=`lsb_release -si` elif [ -r /etc/debian_version ]; then dist="Debian" elif [ -r /etc/redhat-release ]; then dist="RHEL" elif [ -r /etc/slackware-version ]; then dist="Slackware" elif [ -r /etc/SuSE-release ]; then dist="SUSE LINUX" fi } detect_env () { ### ### Detecting syslog-ng ver: ose or pe ### echo "Start environment detection" if [ -x /opt/syslog-ng/bin/loggen ] ; then syslogfhs=unix echo "Unix-like FHS detected" elif [ -d /etc/syslog-ng/ ]; then syslogfhs=linux echo "Linux-type FHS detected" else syslogfhs=unknown confdir=/nonexistent echo "No syslog-ng detected" fi os=`uname -s` if [ "$os" = "Linux" ]; then detect_env_linux fi } setup_env_debian () { unset distpkgoffile unset distpkgstatus distpkgoffile () { local tmpfile=${tmpdir}/distpkgoffile.$$.tmp dpkg -S $1 >$tmpfile read x < $tmpfile rm $tmpfile echo "${x%: /*}" } distpkgstatus () { echo "@@@Package info for: ${1}" dpkg -s ${1} echo "" } } setup_env_redhat () { unset distpkgoffile unset distpkgstatus distpkgoffile () { local tmpfile=${tmpdir}/distpkgoffile.$$.tmp rpm -qf $1 >$tmpfile read x < $tmpfile rm $tmpfile echo "$x" } distpkgstatus () { echo "@@@Package info for: ${1}" rpm -qi ${1} echo "" } } setup_env_suse () { unset distpkgoffile unset distpkgstatus distpkgoffile () { local tmpfile=${tmpdir}/distpkgoffile.$$.tmp rpm -qf $1 >$tmpfile read x < $tmpfile rm $tmpfile echo "$x" } distpkgstatus () { echo "@@@Package info for: ${1}" rpm -qi $1 echo "" } } setup_env_slackware () { initfile="/etc/rc.d/rc.syslog" service_start="${initfile} start" service_stop="${initfile} stop" if [ -f "/var/run/syslog-ng.pid" ]; then piddir="/var/run" fi unset service_status unset distpkgoffile unset distpkgstatus distpkgoffile () { local LINKTARGET local PKGLOGFILENAMES local SEARCHSTRING PKGLOGFILE= LINKTARGET=$( readlink -f "${1}" 2>/dev/null ) SEARCHSTRING="${LINKTARGET##/}" PKGLOGFILENAMES=$( \ ( grep -r -m 1 -E "^${SEARCHSTRING}\$" /var/log/packages ; \ [ "${SEARCHSTRING%%/*}" = "lib" ] && grep -r -m 1 -E "^lib/incoming/${SEARCHSTRING#*/}\$" /var/log/packages ; \ [ "${SEARCHSTRING%%/*}" = "lib64" ] && grep -r -m 1 -E "^lib64/incoming/${SEARCHSTRING#*/}\$" /var/log/packages ) | \ while read -r RESULT; do RESULT="${RESULT%%:*}" echo "${RESULT##*/}" done ) if [ -n "${PKGLOGFILENAMES}" ]; then echo "${PKGLOGFILENAMES}" else echo "No installed package for '$1' found!" >&2 fi } distpkgstatus () { local PIVOT local LASTLINE local PKGINFO echo "@@@Package info for: ${1}" PKGINFO=$( \ ( find /var/log/packages/ -name "${1}*" ) | \ while read -r PKGLOGFILE; do PIVOT=$( fgrep -n "FILE LIST:" "${PKGLOGFILE}" ) LASTLINE=$(( ${PIVOT%%:*} - 1 )) 2>/dev/null head -n ${LASTLINE:-16} "${PKGLOGFILE}" echo "" done ) if [ -n "${PKGINFO}" ]; then echo "${PKGINFO}" else echo "The package '${1}' is not installed, or does not exist!" >&2 fi } } setup_env_genlinux () { unset myplimit myplimit () { [ -f "/proc/$1/limits" ] && cat /proc/$1/limits ; } if is_available systemctl ; then service_stop="systemctl stop syslog-ng" service_start="systemctl start syslog-ng" service_status="systemctl status syslog-ng" fi # sed -E uses extended regexes, and normally works on Linux and BSD, where perl is not present by default. # -e and -E patterns use different syntax, but the great thing is that the -E format also works with perl. # However older GNU sed versions do not support the -E option, so we have no other choice but perl in # these cases. if echo "eee" | sed -E 's/eee/fff/g' >/dev/null 2>/dev/null ; then : else sed_equivalent_cmd="perl -p -e" fi } setup_env_linux () { if [ "$dist" = "Debian" ]; then setup_env_debian elif [ "$dist" = "Ubuntu" ]; then setup_env_debian elif [ "$dist" = "CentOS" ]; then setup_env_redhat elif [ "$dist" = "RedHatEnterpriseServer" ]; then setup_env_redhat elif [ "$dist" = "RHEL" ]; then setup_env_redhat elif [ "$dist" = "OracleServer" ]; then setup_env_redhat elif [ "$dist" = "EnterpriseEnterpriseServer" ]; then setup_env_redhat elif [ "$dist" = "SUSE LINUX" ]; then setup_env_suse elif [ "$dist" = "Slackware" ]; then setup_env_slackware else echo "Unknown Distro, perhaps unsupported" fi setup_env_genlinux } setup_env_solaris () { dfi="df -o i" lsof=pfiles ipconfig="ifconfig -a" pscmd="ps -eaf" tcpdumpcmd="snoop" tcpdumpopts="-P -q -o" pcapifparm="-d" trace="truss -r all -w all -u libc:: -f" netstatpunt="netstat -n" netstatsu="netstat -s" grepq="/usr/xpg4/bin/grep -q" sed_equivalent_cmd="perl -p -e" unset -f mypidof unset -f getsyslogpids unset -f netstatlunp unset -f netstatnlp unset -f myplimit unset -f topcmd unset -f free unset -f distpkgoffile unset -f distpkgstatus unset -f is_available unset -f os_hash_helper is_available () { which "$1" | $grepq "no $1 in" && return 1 || return 0 ; } mypidof () { $pseao pid,comm | while read pid bin ; do [ "$bin" = "$1" ] && echo $pid ; done ; } getsyslogpids () { mypidof "${syslogrealbin}" ; } netstatnlp () { netstat -na ; } netstatlunp () { netstat -P udp -na ; } myplimit () { plimit $1 ; } free () { prtconf | grep Mem ; printf Pagesize:\ ; pagesize -a ; } distpkgoffile () { FILE="$1" if [ -L "/lib/64" ]; then FILE=$( perl -sae '$libarch=readlink("/lib/64"); $filename =~ s/lib\/64/lib\/$libarch/; print "$filename\n";' -- -filename="$1" ) fi pkgchk -l -p $FILE | \ perl -ne 'if ( /^Referenced by the/ ) { $p=1; } elsif (/:/ or /^$/ ) { $p=0; } elsif ($p) { s/^\s+//; print ; } else { print "FAIL:".$_; }' } distpkgstatus () { echo "@@@Package info for: ${1}" pkginfo -l $1 echo "" } if is_available top; then topcmd () { top -b -n 1 -c > "${1}" ; } else topcmd () { ( uptime ; echo ; echo "::memstat" | mdb -k ; sar -u 1 1 ; echo ; ps -eao user,pid,ppid,pcpu,pmem,vsz,rss,tty,s,stime,args | head -n 1; ps -eao user,pid,ppid,pcpu,pmem,vsz,rss,tty,s,stime,args | grep -v COMMAND | sort -rn +3 ) >"${1}" 2>/dev/null ; } fi if is_available md5sum; then os_hash_helper () { find . '!' \( -name debun.manifest -o -name syslog-ng.debun.txt \) -type f -print0 | xargs -0 md5sum ; } elif is_available digest; then os_hash_helper () { find . '!' \( -name debun.manifest -o -name syslog-ng.debun.txt \) -type f -exec digest -a md5 -v '{}' \; | sed -e 's:^md5 (\(.*\)) = \([a-z0-9]\{32\}\)$:\2 \1:' } else os_hash_helper () { : ; } fi if is_available svcadm ; then service_stop="svcadm disable system/syslog-ng:default" service_start="svcadm enable system/syslog-ng:default" service_status="svcs system/syslog-ng:default" fi if is_available ${opensslcmd}; then : else [ -x /usr/sfw/bin/openssl ] && opensslcmd="/usr/sfw/bin/openssl" fi } setup_env_freebsd () { netstatpunt="netstat -n" netstatsu="netstat -s" ipconfig="ifconfig -a" pseao="ps xao" trace="truss -a -d -f -s 256" initfile="/etc/rc.d/syslog-ng" service_stop="${initfile} stop" service_start="${initfile} start" service_status="${initfile} status" unset -f free unset -f netstatnlp unset -f netstatlunp unset -f mypidof unset -f topcmd unset -f getsyslogpids unset -f distpkgoffile unset -f distpkgstatus unset -f os_hash_helper free () { top -bt 0 ; } netstatnlp () { sockstat ; } netstatlunp () { netstat -na | grep -E "(Internet|Proto|udp)" ; } topcmd () { top -b -d1 > "${1}" ; } mypidof () { $pseao pid,comm | while read pid bin ; do [ "$bin" = "$1" ] && echo $pid ; done; } getsyslogpids () { mypidof syslog-ng ; } distpkgoffile () { : ; } distpkgstatus () { : ; } os_hash_helper () { find . '!' \( -name debun.manifest -o -name syslog-ng.debun.txt \) -type f -exec md5 '{}' \; | sed -e 's:^MD5 (\(.*\)) = \([a-z0-9]\{32\}\)$:\2 \1:' } } setup_env_hpux () { gzipcmd="/usr/contrib/bin/gzip -9" lddcmd="/usr/ccs/bin/ldd" trace="/usr/local/bin/tusc -p -l -u -f" netstatsu="netstat -s" netstatpunt="netstat -n" ipconfig="netstat -ni" pscmd="ps -eaf" dfh="df" initfile="/sbin/init.d/syslog-ng" service_stop="${initfile} stop" service_start="${initfile} start" service_status="${initfile} status" sed_equivalent_cmd="perl -p -e" unset -f free unset -f netstatnlp unset -f netstatlunp unset -f mypidof unset -f topcmd unset -f os_hash_helper unset -f getsyslogpids unset -f getparent unset -f getchilds unset -f is_available unset -f dfk_parser unset -f distpkgoffile unset -f distpkgstatus unset -f distpkgoffile_cleanup is_available () { which "$1" | $grepq "no $1 in" && return 1 || return 0 ; } free () { swapinfo -tam ; } netstatnlp () { netstat -na | grep -E "(Internet|Proto|LISTEN)" ; } netstatlunp () { netstat -na | grep -E "(Internet|Proto|udp)" ; } topcmd () { top -d 1 -f "${1}" ; } dfk_parser () { grep free | while read AVAIL REST_TEXT; do echo ${AVAIL}; done } os_hash_helper () { find . '!' \( -name debun.manifest -o -name syslog-ng.debun.txt \) -type f -exec md5sum '{}' \; } mypidof () { ps -e -f | while read uid pid ppid c stime tty time command extra ; do if [ "${stime%%:*}" = "${stime}" ] then [ "${extra%% *}" = "$1" ] && echo $pid else [ "${command%% *}" = "$1" ] && echo $pid fi ; done ; } getsyslogpids () { mypidof "${syslogrealbin}" ; } getparent () { local self local parent local ret local tmpfile=${tmpdir}/getparent.$$.txt ps -ef >$tmpfile while read user pid ppid dummy ; do [ "$1" = "$pid" ] || continue ret=$ppid done < $tmpfile rm $tmpfile echo $ret } getchilds () { local childs local dummy local child local tmpfile=${tmpdir}/getchilds.$$.txt ps -ef >$tmpfile while read user pid ppid dummy ; do [ "$1" = "$ppid" ] || continue childs="${childs}${childs:+ }$pid" done < $tmpfile rm $tmpfile echo ${childs} } distpkgoffile () { local tmpfile=${tmpdir}/distpkgoffile.tmp if [ ! -f $tmpfile ]; then swlist -l file > "$tmpfile" fi grep $1 $tmpfile | cut -d : -f 1 | while read x; do echo "$x" done } distpkgstatus () { printf "@@@Package info for fileset/patch: %s\n" "$1" swlist -l fileset -a title -a description $1 | grep -v "^#" | grep -v "^\"" printf "\n" } distpkgoffile_cleanup () { if [ -f "${tmpdir}/distpkgoffile.tmp" ]; then echo "Removing package list cache" rm "${tmpdir}/distpkgoffile.tmp" fi } } setup_env_aix () { ipconfig="ifconfig -a" pscmd="ps -eaf" dfh="df -k" netstatsu="netstat -s" netstatpunt="netstat -n" dmesg="alog -o -t boot" trace="truss -r all -w all -u libc:: -f" initfile= service_stop="/usr/bin/stopsrc -s syslog-ng" service_start="/usr/bin/startsrc -s syslog-ng" service_status="/usr/bin/lssrc -s syslog-ng" sed_equivalent_cmd="perl -p -e" unset -f initfile unset -f netstatnlp unset -f netstatlunp unset -f routeconfig unset -f free unset -f dfk_parser unset -f getsyslogpids unset -f mypidof unset -f topcmd unset -f format_ldd_output unset -f os_hash_helper format_ldd_output () { sed -e 's:^[^/]*\(.*\)$:\1:' -e 's:^\(.*\)(.*)$:\1:'; } netstatnlp () { netstat -na | grep -E "(Active|Proto|LISTEN)" ; } netstatlunp () { netstat -na | grep -E "(Internet|Proto|udp)" ; } dfk_parser () { tail -1 | while read FS ALL AVAIL UPERC IUPERC MP; do echo ${AVAIL}; done } routeconfig () { if netstat -nr 2>&1 | $grepq 'Permission error' ; then echo 'WPAR without its own routing table.' ; else netstat -nr ; fi ; } free () { svmon -G -O unit=KB ; } topcmd () { ( uptime ; svmon -G | head -n 3 ; sar -u 1 1 ; echo ; ps auxwww | head -n 1; ps auxwww | grep -v COMMAND | sort -rn +2 ) >"${1}" 2>/dev/null ; } mypidof () { ps -eaf | while read user pid ppid c stime tty time cmd extra; do if [ "${stime%%:*}" = "${stime}" ] then [ "${extra%% *}" = "$1" ] && echo $pid else [ "${cmd%% *}" = "$1" ] && echo $pid fi ; done ; } getsyslogpids () { mypidof "${syslogrealbin}" ; } unset distpkgoffile unset distpkgstatus distpkgoffile () { local tmpfile=${tmpdir}/distpkgoffile.$$.tmp rpm -qf $1 >$tmpfile read x < $tmpfile rm $tmpfile echo "$x" } distpkgstatus () { printf "@@@Package info for: %s\n" "$1" rpm -qi $1 printf "\n" } os_hash_helper () { find . '!' \( -name debun.manifest -o -name syslog-ng.debun.txt \) -type f -exec csum -h MD5 '{}' \; } } setup_env_generic_pre () { : } setup_env_generic_post () { ### Check if ss is available (should only be present on Linux) if is_available ss ; then unset -f routeconfig unset -f netstatnlp unset -f netstatlunp routeconfig () { ip route show ; } netstatnlp () { ss -nlp ; } netstatlunp () { ss -lunp ; } netstatpunt="ss -punt" fi if is_available netstat; then : else is_available nstat && netstatsu="nstat" fi } setup_env() { setup_env_generic_pre ### ### Decide OS (switch-like) ### printf "\nOperating System Name: %s\n" "$os" if [ "$os" = "Linux" ]; then setup_env_linux elif [ "$os" = "SunOS" ]; then setup_env_solaris elif [ "$os" = "FreeBSD" ]; then setup_env_freebsd elif [ "$os" = "HP-UX" ]; then setup_env_hpux elif [ "$os" = "AIX" ]; then setup_env_aix else printf "Unkonwn or (yet) unhandled system\n" fi setup_env_generic_post } debun_run () { if [ "$os" = "Linux" ]; then debun_linux elif [ "$os" = "SunOS" ]; then debun_solaris elif [ "$os" = "FreeBSD" ]; then debun_freebsd elif [ "$os" = "HP-UX" ]; then debun_hpux elif [ "$os" = "AIX" ]; then debun_aix fi } run_specific_extras () { for i in ${extras}; do $i done } run_debug () { printf "\nStart Debug collection\n" if [ -n "${pcap_params}" ]; then if is_available $tcpdumpcmd ; then echo "Start packet dump in background with filters: ${pcap_params}" ${tcpdumpcmd} ${tcpdumpopts} ${tmpdir}/debug.pcap ${pcap_iface:+$pcapifparm} ${pcap_iface} ${pcap_params} & pcappid=${!} else echo "tcpdump/snoop is not available" >&2 fi fi if [ -n "${tracing}" ] && [ -z "${debug_params}" ]; then if is_available "${trace%% *}"; then for i in ${sngallpids}; do ${trace} -o ${tmpdir}/trace.${i}.txt -p ${i} & tracepids="${tracepids}${tracepids:+ }${!}" done else echo "Tracing was requested but ${trace%% *} was not available!" fi fi if [ -n "${waitforit}" ]; then [ -n "${pcap_params}" ] && sleep 1 echo "Waiting ${waitforit} secs before stop system's syslog-ng, and restart in debug mode." pad='' bs='' for i in `seq 1 ${#waitforit}`; do pad="${pad} " ; bs="\b${bs}" ; done printf "Start countdown: ${pad}" >&3 for i in `seq ${waitforit} -1 1 `; do printf "${bs}${pad:${#i}}$i" >&3 ; sleep 1 ; done print "0\n">&3 touch ${tmpdir}/syslog.debug fi if [ -n "${debug_params}" ]; then ${service_stop} # We should implement a better waiting for the system service's shutdown, sleep 1 works for now sleep 1 echo "Start syslog-ng debug with params: ${debug_params}" if [ -n "$tracing" ]; then if is_available "${trace%% *}"; then ${trace} -o ${tmpdir}/trace.dbg.txt ${syslogbin} ${debug_params} >>${tmpdir}/syslog.debug 2>&1 & i=${!} tracepids="${i}" debugpid="`getchilds ${i}`" echo "Trace: ${i} Debug: ${debugpid}" else echo "Tracing was requested but ${trace%% *} was not available!" ${syslogbin} ${debug_params} >>${tmpdir}/syslog.debug 2>&1 & debugpid=${!} fi else ${syslogbin} ${debug_params} >>${tmpdir}/syslog.debug 2>&1 & debugpid=${!} fi fi [ -n "${timeout}" ] || echo "When you want to stop collecting data, press ENTER" >&3 if [ -n "${waitforit}" ]; then sleep 1 # Let's gave time the user, to read the message about stopping tail -f ${tmpdir}/syslog.debug >&3 & debugtailpid=${!} #disown fi if [ -n "${timeout}" ]; then sleep "${timeout}" else read line fi } ### ### Main program tasks ### debun_init detect_env setup_env debun_run [ "$syslogfhs" = "linux" ] && fhs_set_linux [ "$syslogfhs" = "unix" ] && fhs_set_unix run_specific_extras acquire_general_info if [ -n "$privacy_mode" ]; then acquire_syslog_nprv else acquire_syslog_all fi [ -n "$debug_mode" ] && run_debug debun_final syslog-ng-syslog-ng-3.13.2/contrib/syslog-ng.conf.HP-UX000066400000000000000000000023561321171025300225340ustar00rootroot00000000000000# syslog-ng configuration file. # # This should behave pretty much like the original syslog on HP-UX. But # it could be configured a lot smarter. # # See syslog-ng(8) and syslog-ng.conf(8) for more information. # # 20000925 gb@sysfive.com options { sync (0); time_reopen (10); log_fifo_size (1000); long_hostnames (off); use_dns (no); use_fqdn (no); create_dirs (no); keep_hostname (yes); }; source s_sys { pipe("/dev/log"); internal(); }; destination d_cons { file("/dev/console"); }; destination d_mesg { file("/var/adm/syslog/syslog.log"); }; destination d_mail { file("/var/adm/syslog/mail.log"); }; destination d_mlrt { usertty("root"); }; destination d_mlal { usertty("*"); }; filter f_filter1 { facility(mail) and level(debug); }; filter f_filter2 { (facility(mail) and level(debug)) or level(info); }; filter f_filter3 { level(alert); }; filter f_filter4 { level(emerg); }; log { source(s_sys); filter(f_filter1); destination(d_mail); }; log { source(s_sys); filter(f_filter2); destination(d_mesg); }; log { source(s_sys); filter(f_filter3); destination(d_cons); destination(d_mlrt); }; log { source(s_sys); filter(f_filter4); destination(d_mlal); }; syslog-ng-syslog-ng-3.13.2/contrib/syslog-ng.conf.RedHat000066400000000000000000000052151321171025300230370ustar00rootroot00000000000000# syslog-ng configuration file. # # This should behave pretty much like the original syslog on RedHat. But # it could be configured a lot smarter. # # See syslog-ng(8) and syslog-ng.conf(5) for more information. # # 20000925 gb@sysfive.com # # Updated by Frank Crawford () - 10 Aug 2002 # - for Red Hat 7.3 # - totally do away with klogd # - add message "kernel" as is done with klogd. # # Updated by Frank Crawford () - 22 Aug 2002 # - use the program_override option as per Balazs Scheidler's email # options { sync (0); time_reopen (10); log_fifo_size (1000); long_hostnames (off); use_dns (no); use_fqdn (no); create_dirs (no); keep_hostname (yes); }; # # At around 1999 some distributions have changed from using SOCK_STREAM # to SOCK_DGRAM sockets, see these posts about the issue: # # http://www.security-express.com/archives/bugtraq/1999-q4/0071.html # http://marc.theaimsgroup.com/?l=sysklogd&m=96989685607952&w=2 # # libc and syslog clients generally automatically detect the socket type, # so you are free to decide which of unix-stream or unix-dgram you want to use. # source s_sys { file ("/proc/kmsg" program_override("kernel")); unix-stream ("/dev/log"); internal(); }; destination d_cons { file("/dev/console"); }; destination d_mesg { file("/var/log/messages"); }; destination d_auth { file("/var/log/secure"); }; destination d_mail { file("/var/log/maillog"); }; destination d_spol { file("/var/log/spooler"); }; destination d_boot { file("/var/log/boot.log"); }; destination d_cron { file("/var/log/cron"); }; destination d_mlal { usertty("*"); }; filter f_filter1 { facility(kern); }; filter f_filter2 { level(info) and not (facility(mail) or facility(authpriv) or facility(cron)); }; filter f_filter3 { facility(authpriv); }; filter f_filter4 { facility(mail); }; filter f_filter5 { level(emerg); }; filter f_filter6 { facility(uucp) or (facility(news) and level(crit)); }; filter f_filter7 { facility(local7); }; filter f_filter8 { facility(cron); }; #log { source(s_sys); filter(f_filter1); destination(d_cons); }; log { source(s_sys); filter(f_filter2); destination(d_mesg); }; log { source(s_sys); filter(f_filter3); destination(d_auth); }; log { source(s_sys); filter(f_filter4); destination(d_mail); }; log { source(s_sys); filter(f_filter5); destination(d_mlal); }; log { source(s_sys); filter(f_filter6); destination(d_spol); }; log { source(s_sys); filter(f_filter7); destination(d_boot); }; log { source(s_sys); filter(f_filter8); destination(d_cron); }; syslog-ng-syslog-ng-3.13.2/contrib/syslog-ng.conf.SunOS000066400000000000000000000044241321171025300227000ustar00rootroot00000000000000# syslog-ng configuration file. # # This should behave pretty much like the original syslog on SunOS. But # it could be configured a lot smarter. # # See syslog-ng(8) and syslog-ng.conf(5) for more information. # # 20000925 gb@sysfive.com options { sync (0); time_reopen (10); log_fifo_size (1000); long_hostnames (off); use_dns (no); use_fqdn (no); create_dirs (no); keep_hostname (yes); }; source s_sys { sun-streams ("/dev/log" door("/etc/.syslog_door")); internal(); }; destination d_cons { file("/dev/console"); }; destination d_mesg { file("/var/adm/messages"); }; destination d_mail { file("/var/log/syslog"); }; destination d_auth { file("/var/log/authlog"); }; destination d_mlop { usertty("operator"); }; destination d_mlrt { usertty("root"); }; destination d_mlal { usertty("*"); }; filter f_filter1 { level(err) or (level(notice) and facility (auth, kern)); }; filter f_filter2 { level(err) or (facility(kern) and level(notice)) or (facility(daemon) and level(notice)) or (facility(mail) and level(crit)); }; filter f_filter3 { level(alert) or (facility(kern) and level(err)) or (facility(daemon) and level(err)); }; filter f_filter4 { level(alert); }; filter f_filter5 { level(emerg); }; filter f_filter6 { facility(kern) and level(notice); }; filter f_filter7 { facility(mail) and level(debug); }; filter f_filter8 { facility(user) and level(err); }; filter f_filter9 { facility(user) and level(alert); }; log { source(s_sys); filter(f_filter1); destination(d_cons); }; log { source(s_sys); filter(f_filter2); destination(d_mesg); }; log { source(s_sys); filter(f_filter3); destination(d_mlop); }; log { source(s_sys); filter(f_filter4); destination(d_mlrt); }; log { source(s_sys); filter(f_filter5); destination(d_mlal); }; log { source(s_sys); filter(f_filter6); destination(d_auth); }; log { source(s_sys); filter(f_filter7); destination(d_mail); }; log { source(s_sys); filter(f_filter8); destination(d_cons); destination(d_mesg); }; log { source(s_sys); filter(f_filter9); destination(d_mlop); destination(d_mlrt); }; syslog-ng-syslog-ng-3.13.2/contrib/syslog-ng.conf.doc000066400000000000000000001670711321171025300224460ustar00rootroot00000000000000#---------------------------------------------------------------------- # Program: syslog-ng.conf # Notes: Embedded most of the manual notes within the configuration # file. The original manual can be found at: # # http://www.balabit.com/products/syslog_ng/reference/book1.html # http://www.campin.net/syslog-ng/faq.html # # Many people may find placing all of this information in a # configuration file a bit redundant, but I have found that # with a little bit of extra comments and reference, # maintaining these beasties is much easier. # # This particular log file was taken from the examples that # are given at the different web sites, and made to emulate # the logs of a Mandrake Linux system as much as possible. # Of course, Unix is Unix, is Linux. It should be generic # enough for any Unix system. #---------------------------------------------------------------------- # 16-Mar-03 - REP - Added some extra definitions to the file. # 15-Mar-03 - REP - Added back the comments on filtering. # 27-Feb-03 - REP - Further modified for local environment. # 27-Feb-03 - REP - Updated for new configuration and version 1.6.0 # 12-Dec-02 - REP - Continued updates for writing to databases. # 30-Nov-02 - REP - Initial creation for testing. #---------------------------------------------------------------------- # Options #---------------------------------------------------------------------- # # Name Values Description # ------------------------- ------- ------------------------------------ # bad_hostname reg exp A regexp which matches hostnames # which should not be taken as such. # chain_hostnames y/n Enable or disable the chained # hostname format. # create_dirs y/n Enable or disable directory creation # for destination files. # dir_group groupid # dir_owner userid # dir_perm perm # dns_cache y/n Enable or disable DNS cache usage. # dns_cache_expire num Number of seconds while a successful # lookup is cached. # dns_cache_expire_failed num Number of seconds while a failed # lookup is cached. # dns_cache_size num Number of hostnames in the DNS cache. # gc_busy_threshold num Sets the threshold value for the # garbage collector, when syslog-ng is # busy. GC phase starts when the number # of allocated objects reach this # number. Default: 3000. # gc_idle_threshold num Sets the threshold value for the # garbage collector, when syslog-ng is # idle. GC phase starts when the number # of allocated objects reach this # number. Default: 100. # group groupid # keep_hostname y/n Enable or disable hostname rewriting. # This means that if the log entry had # been passed through at least one other # logging system, the ORIGINAL hostname # will be kept attached to the log. # Otherwise the last logger will be # considered the log entry owner and # the log entry will appear to have # come from that host. # log_fifo_size num The number of lines fitting to the # output queue # log_msg_size num Maximum length of message in bytes. # long_hostnames on/off This options appears to only really # have an affect on the local system. # which removes the source of the log. # As an example, normally the local # logs will state src@hostname, but # with this feature off, the source # is not reported. # mark num The number of seconds between two # MARK lines. NOTE: not implemented # yet. # owner userid # perm perm # stats num The number of seconds between two # STATS. # sync num The number of lines buffered before # written to file # time_reap num The time to wait before an idle # destination file is closed. # time_reopen num The time to wait before a died # connection is reestablished # use_dns y/n Enable or disable DNS usage. # syslog-ng blocks on DNS queries, # so enabling DNS may lead to a # Denial of Service attack. To # prevent DoS, protect your # syslog-ng network endpoint with # firewall rules, and make sure that # all hosts, which may get to # syslog-ng is resolvable. # use_fqdn y/n Add Fully Qualified Domain Name # instead of short hostname. # use_time_recvd y/n Use the time a message is # received instead of the one # specified in the message. #---------------------------------------------------------------------- # 15-Mar-03 - REP - Since some of the clocks are not quite right, we # are going to go ahead and just use the local time # as the master time. # 12-Mar-03 - REP - We have taken a few configuration options from the # newer Solaris configuration because some of the # reasons are valid for us as well. We have increased # the log_msg_size and log_fifo_size to increase the # amount of buffering that we do. While for most # systems this may not have a noticeable affect, it # will for systems that are at the end of a lot of # logging systems. # 20-Dec-02 - REP - Changed the stat() time from the default of 10 # minutes to once an hour. #---------------------------------------------------------------------- options { chain_hostnames(no); create_dirs (no); dir_perm(0755); dns_cache(yes); keep_hostname(yes); log_fifo_size(2048); log_msg_size(8192); long_hostnames(on); perm(0644); stats(3600); sync(0); time_reopen (10); use_dns(yes); use_fqdn(yes); }; #---------------------------------------------------------------------- # Sources #---------------------------------------------------------------------- # # fifo/pipe - The pipe driver opens a named pipe with the # specified name, and listens for messages. It's # used as the native message getting protocol on # HP-UX. # file - Usually the kernel presents its messages in a # special file (/dev/kmsg on BSDs, /proc/kmsg on # Linux), so to read such special files, you'll need # the file() driver. Please note that you can't use # this driver to follow a file like tail -f does. # internal - All internally generated messages "come" from this # special source. If you want warnings, errors and # notices from syslog-ng itself, you have to include # this source in one of your source statements. # sun-streams - Solaris uses its STREAMS API to send messages to # the syslogd process. You'll have to compile # syslog-ng with this driver compiled in (see # ./configure --help). # # Newer versions of Solaris (2.5.1 and above), uses a # new IPC in addition to STREAMS, called door to # confirm delivery of a message. Syslog-ng supports # this new IPC mechanism with the door() option. # # The sun-streams() driver has a single required # argument, specifying the STREAMS device to open and # a single option. # tcp/udp - These drivers let you receive messages from the # network, and as the name of the drivers show, you # can use both UDP and TCP as transport. # # UDP is a simple datagram oriented protocol, which # provides "best effort service" to transfer # messages between hosts. It may lose messages, and # no attempt is made to retransmit such lost # messages at the protocol level. # # TCP provides connection-oriented service, which # basically means a flow-controlled message pipeline. # In this pipeline, each message is acknowledged, and # retransmission is done for lost packets. Generally # it's safer to use TCP, because lost connections can # be detected, and no messages get lost, but # traditionally the syslog protocol uses UDP. # # None of tcp() and udp() drivers require positional # parameters. By default they bind to 0.0.0.0:514, # which means that syslog-ng will listen on all # available interfaces, port 514. To limit accepted # connections to one interface only, use the # localip() parameter as described below. # # Options: # # Name Type Description Default # -------------- ------ -------------------------------- -------- # ip or local ip string The IP address to bind to. Note 0.0.0.0 # that this is not the address # where messages are accepted # from. # keep-alive y/n Available for tcp() only, and yes # specifies whether to close # connections upon the receival # of a SIGHUP signal. # max-connections number Specifies the maximum number of 10 # simultaneous connections. # port or local port number The port number to bind 514 # to. # -------------- ------ -------------------------------- -------- # # unix-stream - unix-dgram - These two drivers behave similarly: # they open the given AF_UNIX socket, and start # listening on them for messages. unix-stream() is # primarily used on Linux, and uses SOCK_STREAM # semantics (connection oriented, no messages are # lost), unix-dgram() is used on BSDs, and uses # SOCK_DGRAM semantics, this may result in lost # local messages, if the system is overloaded. # # To avoid denial of service attacks when using # connection-oriented protocols, the number of # simultaneously accepted connections should be # limited. This can be achieved using the # max-connections() parameter. The default value of # this parameter is quite strict, you might have to # increase it on a busy system. # # Both unix-stream and unix-dgram has a single # required positional argument, specifying the # filename of the socket to create, and several # optional parameters. # # Options: # # Name Type Description Default # -------------- ------ -------------------------------- -------- # group string Set the gid of the socket. root # keep-alive y/n Selects whether to keep yes # connections opened when # syslog-ng is restarted, can be # used only with unix-stream(). # max-connections numb Limits the number of 10 # simultaneously opened # connections. Can be used only # with unix-stream(). # owner string Set the uid of the socket. root # perm num Set the permission mask. For 0666 # octal numbers prefix the number # with '0', e.g. use 0755 for # rwxr-xr-x. #---------------------------------------------------------------------- # Notes: For Linux systems (and especially RedHat derivatives), # they have a second logging process for kernel messages. # This source is /proc/kmsg. If you are running this on a # system that is not Linux, then the source entry for this # should be removed. # # It seems that there is some performance questions related # to what type of source stream should be used for Linux # boxes. The documentation states the /dev/log should use # unix-stream, but from the mailing list it has been # strongly suggested that unix-dgram be used. # # WARNING: TCP wrappers has been enabled for this system, and unless # you also place entries in /etc/hosts.allow for each of the # devices that will be delivering logs via TCP, you will # NOT receive the logs. # # Also note that if there is any form of a local firewall, # this will also need to be altered such that the incoming # and possibly outgoing packets are allowed by the firewall # rules. #---------------------------------------------------------------------- # There has been a lot of debate on whether everything should be put # to a single source, or breakdown all the sources into individual # streams. The greatest flexibility would be in many, but the most # simple is the single. Since we wrote this file, we have chosen the # route of maximum flexibility. # # For those of you that like simplicity, this could have also been # done as the follows: # # source src # { # internal(); # file("/proc/kmsg" program_override("kernel")); # tcp(ip(127.0.0.1) port(4800) keep-alive(yes)); # udp(); # unix-stream("/dev/log"); # }; # # You would also have to change all the log statements to only # reference the now single source stream. #---------------------------------------------------------------------- # 16-Mar-03 - REP - The default number of allowed TCP connects is set # very low for a logserver. This value should only # be set greater than the default for servers that # will actually be serving that many systems. #---------------------------------------------------------------------- source s_dgram { unix-dgram("/dev/log"); }; source s_internal { internal(); }; source s_kernel { file("/proc/kmsg" program_override("kernel")); }; source s_tcp { tcp(port(4800) keep-alive(yes) max_connections(100)); }; #---------------------------------------------------------------------- # Destinations #---------------------------------------------------------------------- # # fifo/pipe - This driver sends messages to a named pipe like # /dev/xconsole # # The pipe driver has a single required parameter, # specifying the filename of the pipe to open, and # no options. # file - The file driver is one of the most important # destination drivers in syslog-ng. It allows you to # output messages to the named file, or as you'll see # to a set of files. # # The destination filename may include macros which # gets expanded when the message is written, thus a # simple file() driver may result in several files # to be created. Macros can be included by prefixing # the macro name with a '$' sign (without the quotes), # just like in Perl/PHP. # # If the expanded filename refers to a directory # which doesn't exist, it will be created depending # on the create_dirs() setting (both global and a per # destination option) # # WARNING: since the state of each created file must # be tracked by syslog-ng, it consumes some memory # for each file. If no new messages are written to a # file within 60 seconds (controlled by the time_reap # global option), it's closed, and its state is freed. # # Exploiting this, a DoS attack can be mounted against # your system. If the number of possible destination # files and its needed memory is more than the amount # your logserver has. # # The most suspicious macro is $PROGRAM, where the # possible variations is quite high, so in untrusted # environments $PROGRAM usage should be avoided. # # Macros: # # Name Description # ----------------- ----------------------------------------------- # DATE Date of the transaction. # DAY The day of month the message was sent. # FACILITY The name of the facility, the message is tagged # as coming from. # FULLDATE Long form of the date of the transaction. # FULLHOST Full hostname of the system that sent the log. # HOST The name of the source host where the message # is originated from. If the message traverses # several hosts, and chain_hostnames() is on, # the first one is used. # HOUR The hour of day the message was sent. # ISODATE Date in ISO format. # MIN The minute the message was sent. # MONTH The month the message was sent. # MSG or MESSAGE Message contents. # PRIORITY or LEVEL The priority of the message. # PROGRAM The name of the program the message was sent by. # SEC The second the message was sent. # TAG The priority and facility encoded as a 2 digit # hexadecimal number. # TZ The time zone or name or abbreviation. e.g. 'PDT' # TZOFFSET The time-zone as hour offset from GMT. e.g. # '-0700' # WEEKDAY The 3-letter name of the day of week the # message was sent, e.g. 'Thu'. # YEAR The year the message was sent. Time expansion # macros can either use the time specified in # the log message, e.g. the time the log message # is sent, or the time the message was received # by the log server. This is controlled by the # use_time_recvd() option. # ----------------- ----------------------------------------------- # # Options: # # Name Type Description Default # -------------- ------ -------------------------------- -------- # compress y/n Compress the resulting logfile global # using zlib. NOTE: this is not setting # implemented as of 1.3.14. # reate_dirs y/n Enable creating non-existing no # directories. # dir_perm num The permission mask of 0600 # directories created by # syslog-ng. Log directories are # only created if a file after # macro expansion refers to a # non-existing directory, and dir # creation is enabled using # create_dirs(). # encrypt y/n Encrypt the resulting file. global # NOTE: this is not implemented as setting # of 1.3.14. # fsync y/n Forces an fsync() call on the # destination fd after each write. # Note: this may degrade # performance seriously # group string Set the group of the created root # filename to the one specified. # log_fifo_size num The number of entries in the global # output fifo. setting # owner string Set the owner of the created root # filename to the one specified. # perm num The permission mask of the file 0600 # if it is created by syslog-ng. # remove_if_older num If set to a value higher than 0, 0 # before writing to a file, # syslog-ng checks whether this # file is older than the specified # amount of time (specified in # seconds). If so, it removes the # existing file and the line to # be written is the first line in # a new file with the same name. # In combination with e.g. the # $WEEKDAY macro, this is can be # used for simple log rotation, # in case not all history need to # be kept. # sync_freq num The logfile is synced when this global # number of messages has been setting # written to it. # template string Specifies a template which # specifies the logformat to be # used in this file. The possible # macros are the same as in # destination filenames. # template_escape y/n Turns on escaping ' and " in yes # templated output files. It is # useful for generating SQL # statements and quoting string # contents so that parts of your # log message don't get # interpreted as commands to the # SQL server. # -------------- ------ -------------------------------- -------- # # program - This driver fork()'s executes the given program with # the given arguments and sends messages down to the # stdin of the child. # # The program driver has a single required parameter, # specifying a program name to start and no options. # The program is executed with the help of the current # shell, so the command may include both file patterns # and I/O redirection, they will be processed. # # NOTE: the program is executed once at startup, and # kept running until SIGHUP or exit. The reason is to # prevent starting up a large number of programs for # messages, which would imply an easy DoS. # tcp/udp - This driver sends messages to another host on the # local intranet or internet using either UDP or TCP # protocol. # # Both drivers have a single required argument # specifying the destination host address, where # messages should be sent, and several optional # parameters. Note that this differs from source # drivers, where local bind address is implied, and # none of the parameters are required. # # Options: # # Name Type Description Default # -------------- ------ -------------------------------- -------- # localip string The IP address to bind to before 0.0.0.0 # connecting to target. # localport num The port number to bind to. 0 # port/destport num The port number to connect to. 514 # -------------- ------ -------------------------------- -------- # usertty - This driver writes messages to the terminal of a # logged-in user. # # The usertty driver has a single required argument, # specifying a username who should receive a copy of # matching messages, and no optional arguments. # unix-dgram - unix-stream - This driver sends messages to a unix # socket in either SOCK_STREAM or SOCK_DGRAM mode. # # Both drivers have a single required argument # specifying the name of the socket to connect to, and # no optional arguments. #---------------------------------------------------------------------- #---------------------------------------------------------------------- # Standard Log file locations #---------------------------------------------------------------------- destination authlog { file("/var/log/auth.log"); }; destination bootlog { file("/var/log/boot.log"); }; destination debug { file("/var/log/debug"); }; destination explan { file("/var/log/explanations"); }; destination messages { file("/var/log/messages"); }; destination routers { file("/var/log/routers.log"); }; destination secure { file("/var/log/secure"); }; destination spooler { file("/var/log/spooler"); }; destination syslog { file("/var/log/syslog"); }; destination user { file("/var/log/user.log"); }; #---------------------------------------------------------------------- # Special catch all destination sorting by host #---------------------------------------------------------------------- destination hosts { file("/var/log/HOSTS/$HOST/$YEAR/$MONTH/$DAY/$FACILITY_$HOST_$YEAR_$MONTH_$DAY" owner(root) group(root) perm(0600) dir_perm(0700) create_dirs(yes)); }; #---------------------------------------------------------------------- # Forward to a loghost server #---------------------------------------------------------------------- #destination loghost { udp("10.1.1.254" port(514)); }; #---------------------------------------------------------------------- # Mail subsystem logs #---------------------------------------------------------------------- destination mail { file("/var/log/mail.log"); }; destination mailerr { file("/var/log/mail/errors"); }; destination mailinfo { file("/var/log/mail/info"); }; destination mailwarn { file("/var/log/mail/warnings"); }; #---------------------------------------------------------------------- # INN news subsystem #---------------------------------------------------------------------- destination newscrit { file("/var/log/news/critical"); }; destination newserr { file("/var/log/news/errors"); }; destination newsnotice { file("/var/log/news/notice"); }; destination newswarn { file("/var/log/news/warnings"); }; #---------------------------------------------------------------------- # Cron subsystem #---------------------------------------------------------------------- destination cron { file("/var/log/cron.log"); }; destination crondebug { file("/var/log/cron/debug"); }; destination cronerr { file("/var/log/cron/errors"); }; destination croninfo { file("/var/log/cron/info"); }; destination cronwarn { file("/var/log/cron/warnings"); }; #---------------------------------------------------------------------- # LPR subsystem #---------------------------------------------------------------------- destination lpr { file("/var/log/lpr.log"); }; destination lprerr { file("/var/log/lpr/errors"); }; destination lprinfo { file("/var/log/lpr/info"); }; destination lprwarn { file("/var/log/lpr/warnings"); }; #---------------------------------------------------------------------- # Kernel messages #---------------------------------------------------------------------- destination kern { file("/var/log/kern.log"); }; destination kernerr { file("/var/log/kernel/errors"); }; destination kerninfo { file("/var/log/kernel/info"); }; destination kernwarn { file("/var/log/kernel/warnings"); }; #---------------------------------------------------------------------- # Daemon messages #---------------------------------------------------------------------- destination daemon { file("/var/log/daemon.log"); }; destination daemonerr { file("/var/log/daemons/errors"); }; destination daemoninfo { file("/var/log/daemons/info"); }; destination daemonwarn { file("/var/log/daemons/warnings"); }; #---------------------------------------------------------------------- # Console warnings #---------------------------------------------------------------------- destination console { file("/dev/tty12"); }; #---------------------------------------------------------------------- # All users #---------------------------------------------------------------------- destination users { usertty("*"); }; #---------------------------------------------------------------------- # Examples of programs that accept syslog messages and do something # programatically with them. #---------------------------------------------------------------------- #destination mail-alert { program("/usr/local/bin/syslog-mail"); }; #destination mail-perl { program("/usr/local/bin/syslog-mail-perl"); }; #---------------------------------------------------------------------- # Piping to Swatch #---------------------------------------------------------------------- #destination swatch { program("/usr/bin/swatch --read-pipe=\"cat /dev/fd/0\""); }; #---------------------------------------------------------------------- # Database notes: # # Overall there seems to be three primary methods of putting data from # syslog-ng into a database. Each of these has certain pros and cons. # # FIFO file: Simply piping the template data into a First In, First # Out file. This will create a stream of data that will # not require any sort of marker or identifier of how # much data has been read. This is the most elegant of # the solutions and probably the most unstable. # # Pros: Very fast data writes and reads. Data being # inserted into a database will be near real # time. # # Cons: Least stable of all the possible solutions, # and could require a lot of custom work to # make function on any particular Unix system. # # Loss of the pipe file will cause complete # data loss, and all following data that would # have been written to the FIFO file. # # Buffer file: While very similar to a FIFO file this is would be a # text file which would buffer all the template # output information. Another program from cron or # similar service would then run and source the buffer # files and process the data into the database. # # Pros: Little chance of losing data since everything # will be written to a physical file much like # the regular logging process. # # This method gives a tremendous amount of # flexibility since there would be yet another # opportunity to filter logs prior to inserting # any data into the database. # # Cons: Because there must be some interval between # the processing of the buffer files, there will # be a lag before the data is inserted in to the # database. # # There is also a slight chance of data corruption # (ie bad insert command) if the system crashes # during a write, although this scenero is very # unlikely. # # Another possible issue is that because multiple # buffer files be written, the previously run # sourcing file could get behind the data # insertion if there is a very large quantity of # logs being written. This will totally depend # on the system that this is running on. # # Program: The least elegant of the solutions. This method is to # send the stream of data through some further interrupter # program such as something in Perl or C. That program # will then take some action based off the data which # could include writing to a database similarly to the # program "sqlsyslogd". # # Pros: Allows complete control of the data, and as much # post processing as required. # # Cons: Slowest of all the forms. Since the data will # have to go through some post processing it will # cause data being written to the database to # remain behind actual log records. This could # cause a race condition in that logging is lost # either due to system crash, or high load on # the logging system. # #---------------------------------------------------------------------- #---------------------------------------------------------------------- # Writing to a MySQL database: # # Assumes a table/database structure of: # # CREATE DATABASE syslog; # USE syslog; # # CREATE TABLE logs ( host varchar(32) default NULL, # facility varchar(10) default NULL, # priority varchar(10) default NULL, # level varchar(10) default NULL, # tag varchar(10) default NULL, # date date default NULL, # time time default NULL, # program varchar(15) default NULL, # msg text, seq int(10) unsigned NOT NULL auto_increment, # PRIMARY KEY (seq), # KEY host (host), # KEY seq (seq), # KEY program (program), # KEY time (time), # KEY date (date), # KEY priority (priority), # KEY facility (facility)) # TYPE=MyISAM; # #---------------------------------------------------------------------- # Piping method #---------------------------------------------------------------------- #destination database { pipe("/tmp/mysql.pipe" # template("INSERT INTO logs (host, facility, # priority, level, tag, date, time, program, # msg) VALUES ( '$HOST', '$FACILITY', '$PRIORITY', # '$LEVEL', '$TAG', '$YEAR-$MONTH-$DAY', # '$HOUR:$MIN:$SEC', '$PROGRAM', '$MSG' );\n") # template-escape(yes)); }; #---------------------------------------------------------------------- # Buffer file method #---------------------------------------------------------------------- destination database { file("/var/log/dblog/fulllog.$YEAR.$MONTH.$DAY.$HOUR.$MIN.$SEC" template("INSERT INTO logs (host, facility, priority, level, tag, date, time, program, msg) VALUES ( '$HOST', '$FACILITY', '$PRIORITY', '$LEVEL', '$TAG', '$YEAR-$MONTH-$DAY', '$HOUR:$MIN:$SEC', '$PROGRAM', '$MSG' );\n") owner(root) group(root) perm(0600) dir_perm(0700) create_dirs(yes) template-escape(yes)); }; #---------------------------------------------------------------------- # Program method (alternate using sqlsyslogd): # # Notes: This is not a bad process, but lacks very much flexibility # unless more changes are made to the source of sqlsyslogd. # This is because sqlsyslogd assumes the data in a larger # object style instead of breaking it down into smaller # columnar pieces. #---------------------------------------------------------------------- #destination database { program("/usr/local/sbin/sqlsyslogd -u # sqlsyslogd -t logs sqlsyslogs2 -p"); }; #---------------------------------------------------------------------- # Since we probably will not be putting ALL of our logs in the database # we better plan on capturing that data that we will be discarding for # later review to insure we did not throw anything away we really # should have captured. #---------------------------------------------------------------------- destination db_discard { file("/var/log/discard.log"); }; #---------------------------------------------------------------------- # Filters #---------------------------------------------------------------------- # # Functions: # # Name Synopsis Description # -------------- ------------------------------ -------------------- # facility facility(facility[,facility]) Match messages # having one of the # listed facility code. # filter Call another filter rule and # evaluate its value # host host(regexp) Match messages by # using a regular # expression against # the hostname field # of log messages. # level/priority level(pri[,pri1..pri2[,pri3]]) Match messages based # on priority. # match Tries to match a regular # expression to the message # itself. # program program(regexp) Match messages by # using a regular # expression against # the program name # field of log messages #---------------------------------------------------------------------- # NOTES: # # Getting filtering to work right can be difficult because while the # syntax is fairly simple, it is not well documented. To illustrate # a brief lesson on filtering and to explain the majority of the # mechanics, we shall use the filter from the PostgreSQL database # how-to page found at: http://www.umialumni.com/~ben/SYSLOG-DOC.html # # This is a perfect and somewhat complex example to use. In its # original form it resembles: # # filter f_postgres { not( # (host("syslogdb") and facility(cron) and level(info)) # or (facility(user) and level(notice) # and ( match(" gethostbyaddr: ") # or match("last message repeated ") # ) # ) # or ( facility(local3) and level(notice) # and match(" SYSMON NORMAL ")) # or ( facility(mail) and level(warning) # and match(" writable directory") # ) # or ( ( host("dbserv1.somecompany.com") # or host("dbserv2.somecompany.com") # ) # and facility(auth) and level(info) # and match("su oracle") and match(" succeeded for root on /dev/") # ) # ); }; # # While in this form, it does not induce a tremendous amount of # insight on what the specific filter is attempting to accomplish. In # reformatting the filter to resemble something a bit more human # readable, it would look like: # # filter f_postgres { not # ( # ( # host("syslogdb") and # facility(cron) and # level(info) # ) or # ( # facility(user) and # level(notice) and # ( # match(" gethostbyaddr: ") or # match("last message repeated ") # ) # ) or # ( # facility(local3) and # level(notice) and # match(" SYSMON NORMAL ") # ) or # ( # facility(mail) and # level(warning) and # match(" writable directory") # ) or # ( # ( # host("dbserv1.somecompany.com") or # host("dbserv2.somecompany.com") # ) and # facility(auth) and # level(info) and # match("su oracle") and # match(" succeeded for root on /dev/") # ) # ); # }; # # Now in this form we can now begin to see what this filter has been # attempting to accomplish. We can now further breakdown each logical # section and explain the different methods: # # [1] As in all statements in syslog-ng, each of the beginnings and # endings must be with a curly bracket "{" "}" to clearly denote # the start and finish. # # In this filter, the entire filter is preferred by a "not" to # indicate that these are the messages that we are NOT interested # in and should be the ones filtered out. All lines of logs that # do not match these lines will be sent to the destination. # # { not # # [2] The first major part of the filter is actually a compound # filter that has two parts. Because the two parts are separated # by an "or", only one of the two parts must be matched for that # line of log to be filtered. # # [2a] In the first part of this filter there are three requirements # to be met for the filter to take affect. These are the host # string "syslogdb". the facility "cron", and the syslog level # of info. # # ( # ( # host("syslogdb") and # facility(cron) and # level(info) # ) or # # [2b] In the second part of the filter, which in itself is a # compound filter, there are three requirements as well. These # are that the facility of "user", and the log level of "notice" # are met in addition to one of the two string matches that are # shown in the example. # # ( # facility(user) and # level(notice) and # ( # match(" gethostbyaddr: ") or # match("last message repeated ") # ) # ) or # # [3] In the section of the filter there are once again three # requirements to fire off a match which are a facility of "level3" # a log level of "notice" and a sting match of " SYSMON NORMAL ". # # ( # facility(local3) and # level(notice) and # match(" SYSMON NORMAL ") # ) or # # [4] This part of the filter is very similar to the previous # filter, but with different search patterns. # # ( # facility(mail) and # level(warning) and # match(" writable directory") # ) or # # [5] The last section of the filter is also a compound filter # that to take affect will require that one of two hosts # are matched, the facility of "auth", and log level of # "info" occur in addition to the two string matches. # # ( # ( # host("dbserv1.somecompany.com") or # host("dbserv2.somecompany.com") # ) and # facility(auth) and # level(info) and # match("su oracle") and # match(" succeeded for root on /dev/") # ) # # [6] As in all command sets in syslog-ng, each of the statements # must be properly closed with the correct ending punctuation # AND a semi-colon. Do not forget both, or you will be faced with # an error. # # ); }; # # While this may not be the most complete example, it does cover the # majority of the options and features that are available within the # current version of syslog-ng. #---------------------------------------------------------------------- #---------------------------------------------------------------------- # Standard filters for the standard destinations. #---------------------------------------------------------------------- filter f_auth { facility(auth, authpriv); }; filter f_authpriv { facility(authpriv); }; filter f_cron { facility(cron); }; filter f_daemon { facility(daemon); }; filter f_kern { facility(kern); }; filter f_local1 { facility(local1); }; filter f_local2 { facility(local2); }; filter f_local3 { facility(local3); }; filter f_local4 { facility(local4); }; filter f_local5 { facility(local5); }; filter f_local6 { facility(local6); }; filter f_local7 { facility(local7); }; filter f_lpr { facility(lpr); }; filter f_mail { facility(mail); }; filter f_messages { facility(daemon, kern, user); }; filter f_news { facility(news); }; filter f_spooler { facility(uucp,news) and level(crit); }; filter f_syslog { not facility(auth, authpriv) and not facility(mail); }; filter f_user { facility(user); }; #---------------------------------------------------------------------- # Other catch-all filters #---------------------------------------------------------------------- filter f_crit { level(crit); }; #filter f_debug { not facility(auth, authpriv, news, mail); }; filter f_debug { level(debug); }; filter f_emergency { level(emerg); }; filter f_err { level(err); }; filter f_info { level(info); }; filter f_notice { level(notice); }; filter f_warn { level(warn); }; #---------------------------------------------------------------------- # Filer for the MySQL database pipe. These are things that we really # do not care to see otherwise they may fill up our database with # garbage. #---------------------------------------------------------------------- #filter f_db { not facility(kern) and level(info, warning) or # not facility(user) and level(notice) or # not facility(local2) and level(debug); }; # #filter f_db { not match("last message repeated ") or # not match("emulate rawmode for keycode"); }; # #filter f_discard { facility(kern) and level(info, warning) or # facility(user) and level(notice) or # facility(local2) and level(debug); }; # #filter f_discard { match("last message repeated ") or # match("emulate rawmode for keycode"); }; #---------------------------------------------------------------------- # Logging #---------------------------------------------------------------------- # # Notes: When applying filters, remember that each subsequent filter # acts as a filter on the previous data flow. This means that # if the first filter limits the flow to only data from the # auth system, a subsequent filter for authpriv will cause # no data to be written. An example of this would be: # # log { source(s_dgram); # source(s_internal); # source(s_kernel); # source(s_tcp); # source(s_udp); filter(f_auth); # filter(f_authpriv); destination(authlog); }; # # So, one can cancel out the other. # # There are also certain flags that can be attached to each of the log # statements: # # Flag Description # -------- ---------------------------------------------------------- # catchall This flag means that the source of the message is ignored, # only the filters are taken into account when matching # messages. # fallback This flag makes a log statement 'fallback'. Being a # fallback statement means that only messages not matching # any 'non-fallback' log statements will be dispatched. # final This flag means that the processing of log statements ends # here. Note that this doesn't necessarily mean that # matching messages will be stored once, as they can be # matching log statements processed prior the current one. #---------------------------------------------------------------------- #---------------------------------------------------------------------- # Standard logging #---------------------------------------------------------------------- log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_auth); destination(authlog); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_local7); destination(bootlog); }; #log{ source(s_dgram); # source(s_internal); # source(s_kernel); # source(s_tcp); # source(s_udp); filter(f_debug); destination(debug); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_local1); destination(explan); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_local5); destination(routers); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_messages); destination(messages); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_authpriv); destination(secure); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_spooler); destination(spooler); }; log { source(s_dgram); source(s_internal); source(s_kernel); source(s_tcp); filter(f_syslog); destination(syslog); }; #log { source(s_dgram); # source(s_internal); # source(s_kernel); # source(s_tcp); # source(s_udp); destination(syslog); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_user); destination(user); }; #---------------------------------------------------------------------- # Special catch all destination sorting by host #---------------------------------------------------------------------- log { source(s_dgram); source(s_internal); source(s_kernel); source(s_tcp); destination(hosts); }; #---------------------------------------------------------------------- # Send to a loghost #---------------------------------------------------------------------- #log { source(s_dgram); # source(s_internal); # source(s_kernel); # source(s_tcp); destination(loghost); }; #---------------------------------------------------------------------- # Mail subsystem logging #---------------------------------------------------------------------- #log { source(s_dgram); # source(s_internal); # source(s_kernel); # source(s_tcp); # source(s_udp); filter(f_mail); destination(mail); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_mail); filter(f_err); destination(mailerr); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_mail); filter(f_info); destination(mailinfo); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_mail); filter(f_notice); destination(mailinfo); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_mail); filter(f_warn); destination(mailwarn); }; #---------------------------------------------------------------------- # INN subsystem logging #---------------------------------------------------------------------- log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_news); filter(f_crit); destination(newscrit); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_news); filter(f_err); destination(newserr); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_news); filter(f_notice); destination(newsnotice); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_news); filter(f_warn); destination(newswarn); }; #---------------------------------------------------------------------- # Cron subsystem logging #---------------------------------------------------------------------- #log { source(s_dgram); # source(s_internal); # source(s_tcp); # source(s_udp); filter(f_cron); destination(crondebug); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_cron); filter(f_err); destination(cronerr); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_cron); filter(f_info); destination(croninfo); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_cron); filter(f_warn); destination(cronwarn); }; #---------------------------------------------------------------------- # LPR subsystem logging #---------------------------------------------------------------------- #log { source(s_dgram); # source(s_internal); # source(s_tcp); # source(s_udp); filter(f_lpr); destination(lpr); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_lpr); filter(f_err); destination(lprerr); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_lpr); filter(f_info); destination(lprinfo); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_lpr); filter(f_warn); destination(lprwarn); }; #---------------------------------------------------------------------- # Kernel subsystem logging #---------------------------------------------------------------------- #log { source(s_dgram); # source(s_internal); # source(s_kernel); # source(s_tcp); # source(s_udp); filter(f_kern); destination(kern); }; log { source(s_dgram); source(s_internal); source(s_kernel); source(s_tcp); filter(f_kern); filter(f_err); destination(kernerr); }; log { source(s_dgram); source(s_internal); source(s_kernel); source(s_tcp); filter(f_kern); filter(f_info); destination(kerninfo); }; log { source(s_dgram); source(s_internal); source(s_kernel); source(s_tcp); filter(f_kern); filter(f_warn); destination(kernwarn); }; #---------------------------------------------------------------------- # Daemon subsystem logging #---------------------------------------------------------------------- #log { source(s_dgram); # source(s_internal); # source(s_tcp); # source(s_udp); filter(f_daemon); destination(daemon); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_daemon); filter(f_err); destination(daemonerr); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_daemon); filter(f_info); destination(daemoninfo); }; log { source(s_dgram); source(s_internal); source(s_tcp); filter(f_daemon); filter(f_warn); destination(daemonwarn); }; #---------------------------------------------------------------------- # Console logging #---------------------------------------------------------------------- # 16-Mar-03 - REP - Removed logging to the console for performance # reasons. Since we are not really going to be # looking at the console all the time, why log there # anyway. #---------------------------------------------------------------------- #log { source(s_dgram); # source(s_internal); # source(s_kernel); # source(s_tcp); filter(f_syslog); destination(console); }; #---------------------------------------------------------------------- # Logging to a database #---------------------------------------------------------------------- #log { source(s_dgram); # source(s_internal); # source(s_kernel); # source(s_tcp); filter(f_db); destination(database); }; #log { source(s_dgram); # source(s_internal); # source(s_kernel); # source(s_tcp); filter(f_discard); destination(db_discard); }; syslog-ng-syslog-ng-3.13.2/contrib/syslog-ng.vim000066400000000000000000000027201321171025300215350ustar00rootroot00000000000000" Vim syntax file " Language: syslog-ng: syslog-ng main configuration file (1.5.5a) " Maintainer: -- " Last change: 2001 Apr 13 " URL: -- " syslog-ng's home: http://www.balabit.hu " Remove any old syntax stuff hanging around syn clear syn case match set iskeyword=a-z,A-Z,48-57,_,-,. syn keyword sysngStatement source destination filter log options syn match sysngComment "#.*$" syn match sysngString +"[^"]*"+ syn match sysngOctNumber "\<0\o\+\>" syn match sysngDecNumber "\<\d\+\>" syn match sysngHexNumber "\<0x\x\+\>" syn keyword sysngBool yes no on off syn match sysngIdentifier "\<[sdf]_\+\>" syn keyword sysngDriver internal remote_control syn keyword sysngDriver file fifo pipe door syn keyword sysngDriver udp tcp syn keyword sysngDriver sun_stream sun_streams sun-stream sun-streams syn keyword sysngDriver unix_dgram unix_stream unix-dgram unix-stream syn keyword sysngDriver usertty program syn keyword sysngFilter not and or .. level priority facility syn keyword sysngFilter program host match DEFAULT if !exists("did_sysng_syntax_inits") let did_sysng_syntax_inits = 1 hi link sysngStatement Statement hi link sysngComment Comment hi link sysngString String hi link sysngOctNumber Number hi link sysngDecNumber Number hi link sysngHexNumber Number hi link sysngBool Constant hi link sysngIdentifier Identifier hi link sysngDriver Type hi link sysngFilter Operator endif let b:current_syntax = "syslog-ng" syslog-ng-syslog-ng-3.13.2/contrib/syslog2ng000077500000000000000000000075071321171025300207630ustar00rootroot00000000000000#!/usr/bin/awk -f # # syslog2ng # # Translator from syslog.conf to syslog-ng.conf # by Jonathan W. Marks # # Rev 2 BEGIN { # Handle the various platforms- determine proper log device "/bin/uname -s" | getline sysname; close("/bin/uname -s"); if (sysname == "SunOS") { LOGDEVTYPE="sun-streams"; } else if (sysname == "AIX") { LOGDEVTYPE="unix-dgram"; } else if (sysname == "Linux") { LOGDEVTYPE="unix-stream"; } else { print "!!! Unsupported system: " sysname "."; exit 1; } # Output the basic options and source statement. print \ "options { dir_perm(0755); perm(0644); chain_hostnames(no);\n" \ " keep_hostname(yes); };\n"; print \ "source local {\n" \ " " LOGDEVTYPE "(\"/dev/log\");\n" \ " udp(ip(0.0.0.0) port(514));\n" \ " internal();\n" \ "};\n"; } $1 !~ /^[:space:]*#/ && NF == 2 { # Output a comment with the line being translated. print "# " $0 "\n"; # Output any new filters to be created, saving filter ID numbers # needed by destination requiredFilterNos = make_filters($1); # Output the destination to be used, saving destination ID number destNo = make_destination($2) # Output the log path, connecting the required filters to the # destination. make_log(destNo, requiredFilterNos); } function make_filters(filterstr, filterNumbers) { # Split the components of the filter specifier. For each component, # generate the appropriate filter, and collect the filter numbers. split(filterstr, termlist, ";"); for (termNo in termlist) { newNum = make_filter(termlist[termNo]); filterNumbers = filterNumbers " " newNum; } return filterNumbers; } function make_filter(spec, negate) { # Find the severity and facility list. dot = index(spec, "."); severity = substr(spec, (dot + 1)); split(substr(spec, 1, (dot - 1)), faclist, ","); if (severity == "none") { negate = 1 }; if (severity == "*") { severity = "debug" }; # Create an ID string using severity and facility list to hash # into all_filters. Then we can tell whether weve already built # a filter like this. filterID = severity; for (facno in faclist) { filterID = filterID " " faclist[facno]; } # If this is a new filter, output the syslog-ng directives for it # and save its ID and number in all_filters. if (! (filterID in all_filters)) { all_filters[filterID] = ++filterNum; printf "filter f_" filterNum " {\n\t"; nPrinted = 0; # If using all facilities, no need to include them all in # filter-- its really only a filter based on severity if (faclist[1] != "*") { printf("%sfacility(", (negate ? "not " : "")); for (facno in faclist) { printf("%s" faclist[facno], \ (nPrinted++ > 0 ? "," : "")); } printf(")%s", (severity != "none" ? " and " : "")); } if (severity != "none") { printf("level(" severity "%s)", (severity == "emerg" ? "" : "..emerg")); } printf(";\n};\n\n"); } return all_filters[filterID]; } function make_destination(d, destNo) { # If weve already built this destination, dont do it again. # Just return the ID number. if (d in destinations) { return destinations[d]; } # Remember the destination ID number in case we need it again. destNo = ++dno; destinations[d] = destNo; # Output the syslog-ng directive for the destination. printf "destination d_" destNo " { \n"; if (d ~ /^\//) { printf "\tfile(\"" d "\" create_dirs(yes));\n"; } else if (d ~ /^@/) { printf "\tudp(\"" substr(d, 2) "\" port(514));\n"; } else { printf "\tusertty(\"" d "\");\n"; } print "};\n"; return destNo; } function make_log(destNo, filterNos) { # Note the destination number and filter numbers, then output # a syslog-ng directive connecting them. n_entries = split(filterNos, filters, " "); printf "log { source(local); " ; for (i = 1; i <= n_entries; i++) { printf "filter(f_" filters[i] "); "; } print "destination(d_" destNo "); };\n"; } syslog-ng-syslog-ng-3.13.2/contrib/systemd/000077500000000000000000000000001321171025300205655ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/systemd/syslog-ng@.service000066400000000000000000000010121321171025300241630ustar00rootroot00000000000000[Unit] Description=System Logger Daemon "%i" instance Documentation=man:syslog-ng(8) Conflicts=emergency.service emergency.target [Service] Type=notify EnvironmentFile=-/etc/default/syslog-ng@%i EnvironmentFile=-/etc/sysconfig/syslog-ng@%i ExecStart=/usr/sbin/syslog-ng -F $OTHER_OPTIONS --cfgfile $CONFIG_FILE --control $CONTROL_FILE --persist-file $PERSIST_FILE --pidfile $PID_FILE ExecReload=/bin/kill -HUP $MAINPID StandardOutput=journal StandardError=journal Restart=on-failure [Install] WantedBy=multi-user.target syslog-ng-syslog-ng-3.13.2/contrib/systemd/syslog-ng@default000066400000000000000000000002761321171025300241040ustar00rootroot00000000000000CONFIG_FILE=/etc/syslog-ng.conf PERSIST_FILE=/var/lib/syslog-ng/syslog-ng.persist CONTROL_FILE=/var/lib/syslog-ng/syslog-ng.ctl PID_FILE=/var/run/syslog-ng.pid OTHER_OPTIONS="--enable-core" syslog-ng-syslog-ng-3.13.2/contrib/upstart/000077500000000000000000000000001321171025300205775ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/upstart/syslog-ng.conf.upstart000066400000000000000000000013131321171025300250670ustar00rootroot00000000000000# syslog-ng - system logging daemon # # syslog-ng is an replacement for the traditional syslog daemon, logging messages from applications description "system logging daemon" start on filesystem stop on runlevel [06] expect fork respawn script CONF="/etc/syslog-ng/syslog-ng.conf" CTRL="/var/lib/syslog-ng/syslog-ng.ctl" OPTS="" # Allow override of command/conf and opts by /etc/default/syslog-ng if [ -f /etc/default/$UPSTART_JOB ]; then . /etc/default/$UPSTART_JOB fi if ! [ -r "$CONF" ] ; then echo "Could not read ${CONF}: exiting" exit 1 fi exec /usr/sbin/syslog-ng --process-mode=background \ -f $CONF -c $CTRL \ -p /var/run/syslog-ng.pid $OPTS end script syslog-ng-syslog-ng-3.13.2/contrib/valgrind/000077500000000000000000000000001321171025300207035ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/contrib/valgrind/syslog-ng.supp000066400000000000000000000065361321171025300235500ustar00rootroot00000000000000## Valgrind suppressions for syslog-ng ## by Gergely Nagy ## ## Some of these suppressions may shadow actual leaks (especially the ## SSL-related ones at the end), use them with caution! ## dlopen() leaks { suppress_dlopen_leak Memcheck:Leak fun:*alloc ... fun:dlopen } { suppress_dlopen_leak2 Memcheck:Leak fun:*alloc ... fun:dl_open_worker fun:_dl_catch_error } ## Miscellaneous non-leaks and false alarms { suppress_journald_open: see https://github.com/systemd/systemd/issues/6539 Memcheck:Leak ... fun:journald_open ... } { suppress_syslog_ng_set_argv_space Memcheck:Leak fun:*alloc ... fun:g_process_set_argv_space } { suppress_syslog_ng_iv_work_pool_create Memcheck:Leak fun:*alloc fun:iv_work_pool_create fun:main_loop_io_worker_init fun:main_loop_init fun:main } { suppress_syslog_ng_app_startup Memcheck:Leak fun:*alloc ... fun:app_startup fun:main } { suppress_syslog_ng_option_context_parse Memcheck:Leak fun:*alloc ... fun:g_option_context_parse fun:main } { suppress_syslog_ng_dlopen_module Memcheck:Leak fun:*alloc ... fun:plugin_dlopen_module } { suppress_syslog_ng_plugin_load_module Memcheck:Leak fun:*alloc ... fun:plugin_load_module } { suppress_syslog_ng_plugin_load_candidate_modules Memcheck:Leak fun:*alloc ... fun:plugin_load_candidate_modules } { suppress_syslog_ng_g_private_set Memcheck:Leak fun:*alloc ... fun:g_private_set ... fun:clone } { suppress_syslog_ng_msg_limit_internal_message Memcheck:Leak fun:*alloc ... fun:msg_limit_internal_message ... fun:main } { suppress_syslog_ng_main_loop_msg_event_create Memcheck:Leak fun:*alloc ... fun:msg_event_create fun:main_loop_run } { supperess_syslog_ng_log_msg_new_internal Memcheck:Leak fun:*alloc ... fun:log_msg_new_internal } { suppress_syslog_ng_g_process_change_limits Memcheck:Leak fun:*alloc ... fun:g_process_change_limits } ################################################################## ### NOTE: These suppressions may shadow actual memory leaks! ### ### Disable them if you wish to debug SSL-related leaks. ### ################################################################## ## libssl/libcrypto leaks we don't care about { suppress_crypto_SSL_leaks Memcheck:Leak fun:*alloc ... obj:*/libcrypto.so.* fun:SSL_* } { suppress_crypto_RSA_leaks Memcheck:Leak fun:*alloc ... obj:*/libcrypto.so.* fun:RSA_* } { suppress_crypto_BIO_leaks Memcheck:Leak fun:*alloc ... obj:*/libcrypto.so.* fun:BIO_* } { suppress_crypto_OCSP_leaks Memcheck:Leak fun:*alloc ... obj:*/libcrypto.so.* fun:OCSP_* } ## TLS/SSL related syslog-ng leaks { suppress_syslog_ng_crypto_leaks Memcheck:Leak fun:*alloc ... obj:*/libcrypto.so.* ... obj:*/libsyslog-ng-crypto.so } { suppress_syslog_ng_afsocket_ssl_leaks Memcheck:Leak fun:*alloc ... obj:*/libssl.so.* ... obj:*/libafsocket-tls.so } { suppress_syslog_ng_afsocket_crypto_leaks Memcheck:Leak fun:*alloc ... obj:*/libcrypto.so.* ... obj:*/libafsocket-tls.so } syslog-ng-syslog-ng-3.13.2/dbld/000077500000000000000000000000001321171025300163425ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/dbld/Makefile.am000066400000000000000000000002461321171025300204000ustar00rootroot00000000000000EXTRA_DIST += \ dbld/tarball \ dbld/pkg-tarball \ dbld/rpm \ dbld/deb \ dbld/generate-rpm-specfile \ dbld/generate-debian-directory \ dbld/shell \ dbld/rules syslog-ng-syslog-ng-3.13.2/dbld/deb000077500000000000000000000007561321171025300170320ustar00rootroot00000000000000#!/bin/bash set -e cd /source VERSION=`cat VERSION` GITREF=`git describe` cd /build rm -rf syslog-ng-${VERSION} tar xf syslog-ng-${VERSION}.tar.gz cp syslog-ng-${VERSION}.tar.gz syslog-ng_${VERSION}.orig.tar.gz cd syslog-ng-${VERSION} if [ ! -d debian ]; then echo "You have no Debian packaging in debian/, this should already by in the tarball at this point" exit 1 fi dpkg-buildpackage -rfakeroot echo "Your debs are in /build, also available on the host in \$(top_srcdir)/dbld/build" syslog-ng-syslog-ng-3.13.2/dbld/generate-debian-directory000077500000000000000000000012411321171025300233020ustar00rootroot00000000000000#!/bin/bash MODE=$1 VERSION=`cat /source/VERSION` cp -r /source/packaging/debian . if [ $MODE = "snapshot" ]; then echo "Generating snapshot version in debian/" DEBEMAIL="dev@null" DEBFULLNAME="syslog-ng snapshot" debchange --newversion ${VERSION}-1+`date +%Y%m%dT%H%M%S` "Snapshot release based on ${GITREF}" elif [ $MODE = "release" ]; then echo "Validating if your debian/ directory matches current version" DEB_VERSION=`dpkg-parsechangelog -S Version | cut -d - -f1` if [ "${DEB_VERSION}" != "${VERSION}" ]; then echo "The version numbers in debian/changelog do not match the current version number. Cannot generate a release tarball this way" exit 1 fi fi syslog-ng-syslog-ng-3.13.2/dbld/generate-rpm-specfile000077500000000000000000000012661321171025300224530ustar00rootroot00000000000000#!/bin/bash MODE=$1 VERSION=`cat /source/VERSION` cp /source/packaging/rhel/* . if [ $MODE = "snapshot" ]; then echo "Generating snapshot version in syslog-ng.spec" sed -e "s/^Version: \([0-9.]\+\)/Version: $VERSION/" \ -e "s/^Release: \([0-9.]\+\)/Release: \1+`date +%Y%m%dT%H%M%S`/" -i syslog-ng.spec elif [ $MODE = "release" ]; then echo "Validating that your RPM specfile matches the current version" RPM_VERSION=`grep ^Version syslog-ng.spec | cut -d ' ' -f2` if [ "${RPM_VERSION}" != "${VERSION}" ]; then echo "The version numbers in syslog-ng.spec do not match the current version number. Cannot generate a release tarball this way" exit 1 fi fi syslog-ng-syslog-ng-3.13.2/dbld/images/000077500000000000000000000000001321171025300176075ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/dbld/images/centos7/000077500000000000000000000000001321171025300211715ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/dbld/images/centos7/Dockerfile000066400000000000000000000025731321171025300231720ustar00rootroot00000000000000FROM centos:7 MAINTAINER Andras Mitzki RUN yum install -y wget epel-release RUN cd /etc/yum.repos.d && wget https://copr.fedorainfracloud.org/coprs/czanik/syslog-ng311/repo/epel-7/czanik-syslog-ng311-epel-7.repo ADD dev-dependencies.txt . RUN cat dev-dependencies.txt | grep -v "#" | xargs yum -y install ADD gradle_installer.sh . RUN ./gradle_installer.sh RUN echo "/usr/lib/jvm/jre/lib/amd64/server" | tee --append /etc/ld.so.conf.d/openjdk-libjvm.conf && ldconfig # # if you want to add further packages, add them to addons.txt to make image # creation faster. If you are done, move them to dev-dependencies and leave # addons.txt empty. The image creation will be faster, as the results of # the original dev-dependencies will be reused by docker. # ADD addons.txt . RUN cat addons.txt | grep -v "#" | xargs -r yum -y install ADD gosu.pubkey /tmp # grab gosu for easy step-down from root RUN (cat /tmp/gosu.pubkey | gpg --import) \ && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/gosu-amd64" \ && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.7/gosu-amd64.asc" \ && gpg --verify /usr/local/bin/gosu.asc \ && rm /usr/local/bin/gosu.asc \ && chmod +x /usr/local/bin/gosu ADD entrypoint.sh / ENTRYPOINT ["/entrypoint.sh"] RUN mkdir /source VOLUME /source VOLUME /build syslog-ng-syslog-ng-3.13.2/dbld/images/centos7/README.md000066400000000000000000000024251321171025300224530ustar00rootroot00000000000000# `balabit/syslog-ng-centos7` This image provides a development environment to build and install syslog-ng from source. You have to clone the source code of [syslog-ng ](https://github.com/balabit/syslog-ng.git) into a directory on your host machine then you can mount it into the container (under `/source`). ## Building syslog-ng from source Assume that we have cloned syslog-ng's source into the `$HOME/syslog-ng` directory. The following commands starts a container mounted with the source: ```bash $ dbld/rules shell-centos7 ``` You can also build an RPM using: ```bash $ dbld/rules rpm-centos7 ``` You can find the resulting RPMs in `$(top_srcdir)/dbld/build`. You can also use this image to hack on syslog-ng by configuring and building manually. ```bash $ cd /source/ $ pip install -r requirements.txt $ ./autogen.sh $ mkdir build $ cd build/ $ ../configure --enable-debug --prefix=/install $ make $ make check $ make install ``` If the compilation and installation was successful you can run syslog-ng with the following command: ```bash $ /install/syslog-ng/sbin/syslog-ng -Fedv ``` The source code and build products are mounted externally in a directory called `/source` (for the sources) `/build` (for build products) and `/install` (for the installed binaries) respectively. syslog-ng-syslog-ng-3.13.2/dbld/images/centos7/addons.txt000066400000000000000000000002621321171025300232020ustar00rootroot00000000000000# Add more tools here over the initial set in dev-dependencies.txt without # ruining the cache. Once everything is tidy, you can move back everything # into dev-dependencies.txt syslog-ng-syslog-ng-3.13.2/dbld/images/centos7/dev-dependencies.txt000066400000000000000000000013501321171025300251330ustar00rootroot00000000000000# required for autogen autoconf autoconf-archive automake libtool pkgconfig # required for configure bison flex libcap-devel libdbi-devel libesmtp-devel glib2-devel libnet-devel python-devel openssl-devel systemd-devel tcp_wrappers-devel libcurl-devel #ivykis-devel json-c-devel ivykis-devel libdbi libdbi-drivers librdkafka riemann-c-client-devel syslog-ng-java-deps autoconf-archive GeoIP-devel python-pep8 libesmtp-devel mongo-c-driver-devel hiredis-devel python-pep8 cyrus-sasl-devel rpm-build java-1.8.0-openjdk-devel libuuid-devel libmaxminddb-devel libmongo-client-devel # required for make make # required for make check #criterion-devel # other tools gdb git lsof strace vim # debian packaging tools docbook-xsl python-nose python-ply syslog-ng-syslog-ng-3.13.2/dbld/images/centos7/entrypoint.sh000077500000000000000000000016021321171025300237420ustar00rootroot00000000000000#!/bin/bash set -e SOURCE_DIR=/source USER_NAME=${USER_NAME_ON_HOST:-dockerguest} USER_ID=`stat -c '%u' $SOURCE_DIR` GROUP_NAME=$USER_NAME GROUP_ID=`stat -c '%g' $SOURCE_DIR` if [[ "$USER_ID" -eq 0 ]]; then "$@" else if ! getent passwd $USER_ID > /dev/null then groupadd --gid $GROUP_ID $GROUP_NAME &>/dev/null || \ groupadd --gid $GROUP_ID dockerguest &>/dev/null || \ echo "Failed to add group $GROUP_NAME/$GROUP_ID in docker entrypoint.sh"; useradd $USER_NAME --uid=$USER_ID --gid=$GROUP_ID &>/dev/null || \ useradd dockerguest --uid=$USER_ID --gid=$GROUP_ID &>/dev/null || \ echo "Failed to add user $USER_NAME/$USER_ID in docker entrypoint.sh"; mkdir -p /home/$USER_NAME chown $USER_NAME:$GROUP_ID /home/$USER_NAME fi chown ${USER_NAME} /source /build exec gosu "${USER_NAME}" "$@" fi syslog-ng-syslog-ng-3.13.2/dbld/images/centos7/gosu.pubkey000066400000000000000000002430531321171025300233760ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- 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 rbsNPURogQESQCxFYMEUqbcA =/1El -----END PGP PUBLIC KEY BLOCK----- syslog-ng-syslog-ng-3.13.2/dbld/images/centos7/gradle_installer.sh000077500000000000000000000005141321171025300250430ustar00rootroot00000000000000#!/bin/bash export GRADLE_HOME=/opt/gradle export GRADLE_VERSION=4.1 wget --no-verbose --output-document=gradle.zip "https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" unzip gradle.zip rm gradle.zip mv "gradle-${GRADLE_VERSION}" "${GRADLE_HOME}/" ln --symbolic "${GRADLE_HOME}/bin/gradle" /usr/bin/gradle syslog-ng-syslog-ng-3.13.2/dbld/images/jessie/000077500000000000000000000000001321171025300210715ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/dbld/images/jessie/Dockerfile000066400000000000000000000027441321171025300230720ustar00rootroot00000000000000FROM debian:jessie MAINTAINER Andras Mitzki RUN apt-get update -qq && apt-get install -y \ wget RUN wget -qO - http://download.opensuse.org/repositories/home:/laszlo_budai:/syslog-ng/Debian_8.0/Release.key | apt-key add - RUN echo 'deb http://download.opensuse.org/repositories/home:/laszlo_budai:/syslog-ng/Debian_8.0 ./' | tee --append /etc/apt/sources.list.d/syslog-ng-obs.list ADD dev-dependencies.txt . RUN apt-get update -qq && cat dev-dependencies.txt | grep -v "#" | xargs apt-get install -y # # if you want to add further packages, add them to addons.txt to make image # creation faster. If you are done, move them to dev-dependencies and leave # addons.txt empty. The image creation will be faster, as the results of # the original dev-dependencies will be reused by docker. # ADD addons.txt . RUN apt-get update -qq && cat addons.txt | grep -v "#" | xargs apt-get install -y ADD gosu.pubkey /tmp # grab gosu for easy step-down from root RUN (cat /tmp/gosu.pubkey | gpg --import) \ && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/gosu-$(dpkg --print-architecture)" \ && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.7/gosu-$(dpkg --print-architecture).asc" \ && gpg --verify /usr/local/bin/gosu.asc \ && rm /usr/local/bin/gosu.asc \ && chmod +x /usr/local/bin/gosu ADD entrypoint.sh / ENTRYPOINT ["/entrypoint.sh"] RUN mkdir /source VOLUME /source VOLUME /build syslog-ng-syslog-ng-3.13.2/dbld/images/jessie/README.md000066400000000000000000000024221321171025300223500ustar00rootroot00000000000000# `balabit/syslog-ng-jessie` This image provides a development environment to build and install syslog-ng from source. You have to clone the source code of [syslog-ng ](https://github.com/balabit/syslog-ng.git) into a directory on your host machine then you can mount it into the container (under `/source`). ## Building syslog-ng from source Assume that we have cloned syslog-ng's source into the `$HOME/syslog-ng` directory. The following commands starts a container mounted with the source: ```bash $ dbld/rules shell-jessie ``` You can also build an RPM using: ```bash $ dbld/rules deb-jessie ``` You can find the resulting debs in `$(top_srcdir)/dbld/build`. You can also use this image to hack on syslog-ng by configuring and building manually. ```bash $ cd /source/ $ pip install -r requirements.txt $ ./autogen.sh $ mkdir build $ cd build/ $ ../configure --enable-debug --prefix=/install $ make $ make check $ make install ``` If the compilation and installation was successful you can run syslog-ng with the following command: ```bash $ /install/syslog-ng/sbin/syslog-ng -Fedv ``` The source code and build products are mounted externally in a directory called `/source` (for the sources) `/build` (for build products) and `/install` (for the installed binaries) respectively. syslog-ng-syslog-ng-3.13.2/dbld/images/jessie/addons.txt000066400000000000000000000002621321171025300231020ustar00rootroot00000000000000# Add more tools here over the initial set in dev-dependencies.txt without # ruining the cache. Once everything is tidy, you can move back everything # into dev-dependencies.txt syslog-ng-syslog-ng-3.13.2/dbld/images/jessie/dev-dependencies.txt000066400000000000000000000012471321171025300250400ustar00rootroot00000000000000# required for autogen autoconf autoconf-archive automake1.11 libtool pkg-config # required for configure bison flex libcap-dev libdbi-dev libesmtp-dev libgeoip-dev libglib2.0-dev libhiredis-dev libnet1-dev libpython-dev libriemann-client-dev libssl-dev libsystemd-dev libwrap0-dev libcurl4-openssl-dev libivykis-dev libmongo-client-dev libjson-c-dev openjdk-7-jdk python-dev uuid-dev xsltproc # required for make make # required for make check criterion-dev libxml2-utils python-pip # other tools gdb git lsof strace vim # debian packaging tools debhelper dh-autoreconf docbook-xsl docbook dh-systemd python-nose python-pep8 python-ply pylint gradle devscripts libmaxminddb-dev syslog-ng-syslog-ng-3.13.2/dbld/images/jessie/entrypoint.sh000077500000000000000000000016101321171025300236410ustar00rootroot00000000000000#!/bin/bash set -e SOURCE_DIR=/source USER_NAME=${USER_NAME_ON_HOST:-dockerguest} USER_ID=`stat -c '%u' $SOURCE_DIR` GROUP_NAME=$USER_NAME GROUP_ID=`stat -c '%g' $SOURCE_DIR` if [[ "$USER_ID" -eq 0 ]]; then "$@" else if ! getent passwd $USER_ID > /dev/null then groupadd --gid $GROUP_ID $GROUP_NAME &>/dev/null || \ groupadd --gid $GROUP_ID dockerguest &>/dev/null || \ echo "Failed to add group $GROUP_NAME/$GROUP_ID in docker entrypoint.sh"; useradd $USER_NAME --uid=$USER_ID --gid=$GROUP_ID &>/dev/null || \ useradd dockerguest --uid=$USER_ID --gid=$GROUP_ID &>/dev/null || \ echo "Failed to add user $USER_NAME/$USER_ID in docker entrypoint.sh"; adduser $USER_NAME root &>/dev/null mkdir -p /home/$USER_NAME chown $USER_NAME:$GROUP_ID /home/$USER_NAME fi exec gosu "${USER_NAME}" "$@" fi syslog-ng-syslog-ng-3.13.2/dbld/images/jessie/gosu.pubkey000066400000000000000000002430531321171025300232760ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- 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 rbsNPURogQESQCxFYMEUqbcA =/1El -----END PGP PUBLIC KEY BLOCK----- syslog-ng-syslog-ng-3.13.2/dbld/images/xenial/000077500000000000000000000000001321171025300210675ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/dbld/images/xenial/Dockerfile000066400000000000000000000027511321171025300230660ustar00rootroot00000000000000FROM ubuntu:16.04 MAINTAINER Andras Mitzki RUN apt-get update -qq && apt-get install -y \ wget RUN wget -qO - http://download.opensuse.org/repositories/home:/laszlo_budai:/syslog-ng/xUbuntu_16.04/Release.key | apt-key add - RUN echo 'deb http://download.opensuse.org/repositories/home:/laszlo_budai:/syslog-ng/xUbuntu_16.04 ./' | tee --append /etc/apt/sources.list.d/syslog-ng-obs.list ADD dev-dependencies.txt . RUN apt-get update -qq && cat dev-dependencies.txt | grep -v "#" | xargs apt-get install -y # # if you want to add further packages, add them to addons.txt to make image # creation faster. If you are done, move them to dev-dependencies and leave # addons.txt empty. The image creation will be faster, as the results of # the original dev-dependencies will be reused by docker. # ADD addons.txt . RUN apt-get update -qq && cat addons.txt | grep -v "#" | xargs apt-get install -y ADD gosu.pubkey /tmp # grab gosu for easy step-down from root RUN (cat /tmp/gosu.pubkey | gpg --import) \ && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/gosu-$(dpkg --print-architecture)" \ && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.7/gosu-$(dpkg --print-architecture).asc" \ && gpg --verify /usr/local/bin/gosu.asc \ && rm /usr/local/bin/gosu.asc \ && chmod +x /usr/local/bin/gosu ADD entrypoint.sh / ENTRYPOINT ["/entrypoint.sh"] RUN mkdir /source VOLUME /source VOLUME /build syslog-ng-syslog-ng-3.13.2/dbld/images/xenial/README.md000066400000000000000000000024221321171025300223460ustar00rootroot00000000000000# `balabit/syslog-ng-xenial` This image provides a development environment to build and install syslog-ng from source. You have to clone the source code of [syslog-ng ](https://github.com/balabit/syslog-ng.git) into a directory on your host machine then you can mount it into the container (under `/source`). ## Building syslog-ng from source Assume that we have cloned syslog-ng's source into the `$HOME/syslog-ng` directory. The following commands starts a container mounted with the source: ```bash $ dbld/rules shell-xenial ``` You can also build an RPM using: ```bash $ dbld/rules deb-xenial ``` You can find the resulting debs in `$(top_srcdir)/dbld/build`. You can also use this image to hack on syslog-ng by configuring and building manually. ```bash $ cd /source/ $ pip install -r requirements.txt $ ./autogen.sh $ mkdir build $ cd build/ $ ../configure --enable-debug --prefix=/install $ make $ make check $ make install ``` If the compilation and installation was successful you can run syslog-ng with the following command: ```bash $ /install/syslog-ng/sbin/syslog-ng -Fedv ``` The source code and build products are mounted externally in a directory called `/source` (for the sources) `/build` (for build products) and `/install` (for the installed binaries) respectively. syslog-ng-syslog-ng-3.13.2/dbld/images/xenial/addons.txt000066400000000000000000000002621321171025300231000ustar00rootroot00000000000000# Add more tools here over the initial set in dev-dependencies.txt without # ruining the cache. Once everything is tidy, you can move back everything # into dev-dependencies.txt syslog-ng-syslog-ng-3.13.2/dbld/images/xenial/dev-dependencies.txt000066400000000000000000000012501321171025300250300ustar00rootroot00000000000000# required for autogen autoconf autoconf-archive automake libtool pkg-config # required for configure bison flex libcap-dev libdbi-dev libesmtp-dev libgeoip-dev libglib2.0-dev libhiredis-dev libnet1-dev libpython-dev libriemann-client-dev libssl-dev libsystemd-dev libwrap0-dev libcurl4-openssl-dev libivykis-dev libmongo-client-dev libjson-c-dev openjdk-8-jdk python-dev uuid-dev xsltproc # required for make make # required for make check criterion-dev libxml2-utils python-pip # other tools gdb git lsof strace vim # debian packaging tools debhelper dh-autoreconf docbook-xsl docbook dh-systemd python-nose python-pep8 pep8 python-ply pylint gradle devscripts libmaxminddb-dev syslog-ng-syslog-ng-3.13.2/dbld/images/xenial/entrypoint.sh000077500000000000000000000016101321171025300236370ustar00rootroot00000000000000#!/bin/bash set -e SOURCE_DIR=/source USER_NAME=${USER_NAME_ON_HOST:-dockerguest} USER_ID=`stat -c '%u' $SOURCE_DIR` GROUP_NAME=$USER_NAME GROUP_ID=`stat -c '%g' $SOURCE_DIR` if [[ "$USER_ID" -eq 0 ]]; then "$@" else if ! getent passwd $USER_ID > /dev/null then groupadd --gid $GROUP_ID $GROUP_NAME &>/dev/null || \ groupadd --gid $GROUP_ID dockerguest &>/dev/null || \ echo "Failed to add group $GROUP_NAME/$GROUP_ID in docker entrypoint.sh"; useradd $USER_NAME --uid=$USER_ID --gid=$GROUP_ID &>/dev/null || \ useradd dockerguest --uid=$USER_ID --gid=$GROUP_ID &>/dev/null || \ echo "Failed to add user $USER_NAME/$USER_ID in docker entrypoint.sh"; adduser $USER_NAME root &>/dev/null mkdir -p /home/$USER_NAME chown $USER_NAME:$GROUP_ID /home/$USER_NAME fi exec gosu "${USER_NAME}" "$@" fi syslog-ng-syslog-ng-3.13.2/dbld/images/xenial/gosu.pubkey000066400000000000000000002430531321171025300232740ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- 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 rbsNPURogQESQCxFYMEUqbcA =/1El -----END PGP PUBLIC KEY BLOCK----- syslog-ng-syslog-ng-3.13.2/dbld/images/zesty/000077500000000000000000000000001321171025300207655ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/dbld/images/zesty/Dockerfile000066400000000000000000000033171321171025300227630ustar00rootroot00000000000000FROM ubuntu:17.04 MAINTAINER Andras Mitzki RUN apt-get update -qq && apt-get install -y \ wget RUN wget -qO - http://download.opensuse.org/repositories/home:/laszlo_budai:/syslog-ng/xUbuntu_17.04/Release.key | apt-key add - RUN echo 'deb http://download.opensuse.org/repositories/home:/laszlo_budai:/syslog-ng/xUbuntu_17.04 ./' | tee --append /etc/apt/sources.list.d/syslog-ng-obs.list ADD dev-dependencies.txt . RUN apt-get update -qq && cat dev-dependencies.txt | grep -v "#" | xargs apt-get install -y --allow-unauthenticated # # if you want to add further packages, add them to addons.txt to make image # creation faster. If you are done, move them to dev-dependencies and leave # addons.txt empty. The image creation will be faster, as the results of # the original dev-dependencies will be reused by docker. # ADD addons.txt . RUN apt-get update -qq && cat addons.txt | grep -v "#" | xargs apt-get install -y RUN cd /tmp && wget http://ftp.de.debian.org/debian/pool/main/libn/libnative-platform-java/libnative-platform-jni_0.11-5_$(dpkg --print-architecture).deb RUN cd /tmp && dpkg -i libnative-platform-jni*.deb ADD gosu.pubkey /tmp # grab gosu for easy step-down from root RUN (cat /tmp/gosu.pubkey | gpg --import) \ && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/gosu-$(dpkg --print-architecture)" \ && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.7/gosu-$(dpkg --print-architecture).asc" \ && gpg --verify /usr/local/bin/gosu.asc \ && rm /usr/local/bin/gosu.asc \ && chmod +x /usr/local/bin/gosu ADD entrypoint.sh / ENTRYPOINT ["/entrypoint.sh"] RUN mkdir /source VOLUME /source VOLUME /build syslog-ng-syslog-ng-3.13.2/dbld/images/zesty/README.md000066400000000000000000000024171321171025300222500ustar00rootroot00000000000000# `balabit/syslog-ng-zesty` This image provides a development environment to build and install syslog-ng from source. You have to clone the source code of [syslog-ng ](https://github.com/balabit/syslog-ng.git) into a directory on your host machine then you can mount it into the container (under `/source`). ## Building syslog-ng from source Assume that we have cloned syslog-ng's source into the `$HOME/syslog-ng` directory. The following commands starts a container mounted with the source: ```bash $ dbld/rules shell-zesty ``` You can also build an RPM using: ```bash $ dbld/rules deb-zesty ``` You can find the resulting debs in `$(top_srcdir)/dbld/build`. You can also use this image to hack on syslog-ng by configuring and building manually. ```bash $ cd /source/ $ pip install -r requirements.txt $ ./autogen.sh $ mkdir build $ cd build/ $ ../configure --enable-debug --prefix=/install $ make $ make check $ make install ``` If the compilation and installation was successful you can run syslog-ng with the following command: ```bash $ /install/syslog-ng/sbin/syslog-ng -Fedv ``` The source code and build products are mounted externally in a directory called `/source` (for the sources) `/build` (for build products) and `/install` (for the installed binaries) respectively. syslog-ng-syslog-ng-3.13.2/dbld/images/zesty/addons.txt000066400000000000000000000002621321171025300227760ustar00rootroot00000000000000# Add more tools here over the initial set in dev-dependencies.txt without # ruining the cache. Once everything is tidy, you can move back everything # into dev-dependencies.txt syslog-ng-syslog-ng-3.13.2/dbld/images/zesty/dev-dependencies.txt000066400000000000000000000013371321171025300247340ustar00rootroot00000000000000# required for autogen autoconf autoconf-archive automake libtool pkg-config # required for configure bison flex libcap-dev libdbi-dev libesmtp-dev libgeoip-dev libglib2.0-dev libhiredis-dev libnet1-dev libpython-dev libriemann-client-dev libssl-dev libsystemd-dev libwrap0-dev libcurl4-openssl-dev libivykis-dev libmongo-client-dev libjson-c-dev openjdk-8-jdk python-dev uuid-dev xsltproc libmaxminddb-dev libmongoc-dev libbson-dev librabbitmq-dev # required for make make # required for make check criterion-dev libxml2-utils python-pip # other tools gdb git lsof strace vim # debian packaging tools debhelper dh-autoreconf docbook-xsl docbook dh-systemd python-nose python-pep8 pep8 python-ply pylint gradle devscripts dh-exec syslog-ng-syslog-ng-3.13.2/dbld/images/zesty/entrypoint.sh000077500000000000000000000016101321171025300235350ustar00rootroot00000000000000#!/bin/bash set -e SOURCE_DIR=/source USER_NAME=${USER_NAME_ON_HOST:-dockerguest} USER_ID=`stat -c '%u' $SOURCE_DIR` GROUP_NAME=$USER_NAME GROUP_ID=`stat -c '%g' $SOURCE_DIR` if [[ "$USER_ID" -eq 0 ]]; then "$@" else if ! getent passwd $USER_ID > /dev/null then groupadd --gid $GROUP_ID $GROUP_NAME &>/dev/null || \ groupadd --gid $GROUP_ID dockerguest &>/dev/null || \ echo "Failed to add group $GROUP_NAME/$GROUP_ID in docker entrypoint.sh"; useradd $USER_NAME --uid=$USER_ID --gid=$GROUP_ID &>/dev/null || \ useradd dockerguest --uid=$USER_ID --gid=$GROUP_ID &>/dev/null || \ echo "Failed to add user $USER_NAME/$USER_ID in docker entrypoint.sh"; adduser $USER_NAME root &>/dev/null mkdir -p /home/$USER_NAME chown $USER_NAME:$GROUP_ID /home/$USER_NAME fi exec gosu "${USER_NAME}" "$@" fi syslog-ng-syslog-ng-3.13.2/dbld/images/zesty/gosu.pubkey000066400000000000000000002430531321171025300231720ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- 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 rbsNPURogQESQCxFYMEUqbcA =/1El -----END PGP PUBLIC KEY BLOCK----- syslog-ng-syslog-ng-3.13.2/dbld/pkg-tarball000077500000000000000000000010731321171025300204710ustar00rootroot00000000000000#!/bin/bash cd /source VERSION=`cat /source/VERSION` MODE=$1 SYSLOGNG_DIR=syslog-ng-${VERSION} SYSLOGNG_TARBALL=${SYSLOGNG_DIR}.tar.gz if [ $MODE = "release" ]; then if ! git diff-index --quiet HEAD; then echo "Your source tree has changed, you can't generate a release tarball this way." exit 1 fi fi cd /build tar xfz $SYSLOGNG_TARBALL cp $SYSLOGNG_TARBALL ${SYSLOGNG_TARBALL}.orig cd $SYSLOGNG_DIR /source/dbld/generate-debian-directory $MODE /source/dbld/generate-rpm-specfile $MODE cd .. tar cfz $SYSLOGNG_TARBALL $SYSLOGNG_DIR syslog-ng-syslog-ng-3.13.2/dbld/rpm000077500000000000000000000006421321171025300170700ustar00rootroot00000000000000#!/bin/bash set -e cd /source VERSION=`cat VERSION` USER=`whoami` RPMBUILD=/home/${USER}/rpmbuild RPMBUILD_SOURCES=$RPMBUILD/SOURCES cd /build mkdir -p $RPMBUILD_SOURCES cp syslog-ng-${VERSION}.tar.gz $RPMBUILD_SOURCES rpmbuild -ta syslog-ng-${VERSION}.tar.gz mv $RPMBUILD/RPMS/*/*.rpm /build mv $RPMBUILD/SRPMS/*.rpm /build echo "Your rpms are in /build, also available on the host in \$(top_srcdir)/dbld/build" syslog-ng-syslog-ng-3.13.2/dbld/rules000077500000000000000000000047151321171025300174310ustar00rootroot00000000000000#!/usr/bin/make -f DOCKER=docker DOCKER_RUN_ARGS=-e USER_NAME_ON_HOST=$(shell whoami) \ --network=host \ -v $(ROOT_DIR):/source \ -v $(DBLD_DIR)/build:/build \ -v $(DBLD_DIR)/install:/install \ -v ~/.gitconfig:/home/$(shell whoami)/.gitconfig ROOT_DIR=$(shell pwd) DBLD_DIR=$(ROOT_DIR)/dbld BUILD_DIR=$(DBLD_DIR)/build RELEASE_DIR=$(DBLD_DIR)/release IMAGE_SHELL=balabit/syslog-ng-jessie VERSION=$(shell cat VERSION) TARBALL=$(BUILD_DIR)/syslog-ng-$(VERSION).tar.gz MODE=snapshot help: @echo "This script allows you to build release/snapshot artifacts, such " @echo "as rpm, deb packages or tarballs." @echo "" @echo "These targets are available:" @echo " image-: generate docker image for building syslog-ng" @echo " images: generate all docker images" @echo " deb-: generate debs in dbld/build for the specified OS" @echo " rpm-: generate rpms in dbld/build for the specified OS" @echo " shell-: start a shell in the specified OS" @echo " tarball: generate a tarball" @echo "" @echo "Supported OSs are: centos7, jessie, zesty, xenial." @echo "" @echo "NOTE: this script requires that debian/rpm packaging are" @echo "already merged to your tree, which is not there by default" @echo "if you work in a git clone. These files live on the 'release'" @echo "branch. Make sure you have that merged, OR work from a release tarball" deb: deb-zesty shell: shell-zesty rpm: rpm-centos7 release: release-deb release-rpm tarball: setup if [ -f $(TARBALL) ]; then \ count=`find $(ROOT_DIR) -newer $(TARBALL) | grep -v "^$(ROOT_DIR)/dbld/" | wc -l`; \ else \ count=1; \ fi; \ [ "$${count}" -gt 0 ] && $(DOCKER) run $(DOCKER_RUN_ARGS) --rm -ti balabit/syslog-ng-zesty /source/dbld/tarball || true pkg-tarball: tarball $(DOCKER) run $(DOCKER_RUN_ARGS) --rm -ti balabit/syslog-ng-zesty /source/dbld/pkg-tarball $(MODE) deb-%: pkg-tarball $(DOCKER) run $(DOCKER_RUN_ARGS) --rm -ti balabit/syslog-ng-$* /source/dbld/deb rpm-%: pkg-tarball $(DOCKER) run $(DOCKER_RUN_ARGS) --rm -ti balabit/syslog-ng-$* /source/dbld/rpm release: MODE=release release: deb-zesty clean: rm -rf $(BUILD_DIR)/* shell-%: setup $(DOCKER) run $(DOCKER_RUN_ARGS) --rm -ti balabit/syslog-ng-$* /source/dbld/shell images: image-jessie image-zesty image-xenial image-centos7 image-%: cd $(DBLD_DIR)/images/$* && docker build --network=host -t balabit/syslog-ng-$* . setup: mkdir -p dbld/build || true mkdir -p dbld/install || true mkdir -p dbld/release || true syslog-ng-syslog-ng-3.13.2/dbld/shell000077500000000000000000000005141321171025300173770ustar00rootroot00000000000000#!/bin/bash echo -e "\n\n\nWelcome to the syslog-ng developer's shell" echo -e "\tYou can find the source in /source, you can build the source using:" echo -e "\t\$ cd /build" echo -e "\t\$ /source/configure" echo -e "\t\$ make" echo -e "\tIf configure is not yet available, run autogen.sh in the source dir" cd /source exec bash syslog-ng-syslog-ng-3.13.2/dbld/tarball000077500000000000000000000004511321171025300177110ustar00rootroot00000000000000#!/bin/bash set -e cd /source VERSION=`cat VERSION` ./autogen.sh cd /build /source/configure --enable-manpages --with-docbook=/usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl make dist echo "Your tarball is in /build, also available on the host in \$(top_srcdir)/dbld/build" syslog-ng-syslog-ng-3.13.2/dev-utils/000077500000000000000000000000001321171025300173515ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/dev-utils/plugin_skeleton_creator/000077500000000000000000000000001321171025300242725ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/dev-utils/plugin_skeleton_creator/create_plugin.sh000077500000000000000000000074041321171025300274570ustar00rootroot00000000000000#!/bin/bash ############################################################################# # Copyright (c) 2016 Balabit # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License version 2 as published # by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# top_srcdir="$(git rev-parse --show-toplevel)" current_year="$(date +%Y)" git_user_name="$(git config --get user.name)" year_and_author="$current_year $git_user_name" function print_help { echo "This script helps to create new plugin by creating a skeleton" echo "Parameters:" echo -e "\t-n\tName of the plugin (required)" echo -e "\t-k\tThe keyword in config file (default: name of the plugin)" echo -e "\t-t\tType of the plugin (default: LL_CONTEXT_DESTINATION)" echo -e "\t-d\tPlugin root dir (default: ${top_srcdir}/modules)" echo -e "\t-h\tPrint this help message" } plugin_name='' plugin_key='' plugin_type=LL_CONTEXT_DESTINATION plugin_root="${top_srcdir}/modules" template_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" help=0 file_list="plugin_template_grammar.ym plugin_template_Makefile.am plugin_template_CMakeLists.txt plugin_template_parser.c plugin_template_parser.h plugin_template_plugin.c" while getopts "k:n:t:d:h" opt; do case ${opt} in h) help=1 ;; n) plugin_name="${OPTARG}" ;; t) plugin_type="${OPTARG}" ;; k) plugin_key="${OPTARG}" ;; d) plugin_root="${OPTARG}" ;; esac done if test "${help}" -gt 0; then print_help exit 0 fi if [ -z "${plugin_name}" ]; then echo "Please set the plugin name" print_help exit 1 fi plugin_dir=${plugin_root}/${plugin_name} if ! [ -d "${plugin_root}" ]; then echo "Plugin root directory does not exists: ${plugin_root}" echo "Please set with -d parameter" print_help exit 1 fi if [ -d "${plugin_dir}" ]; then echo "Plugin already exists: ${plugin_dir}" exit 1 fi if [ -z "${plugin_key}" ]; then plugin_key=${plugin_name} fi echo "plugin name = ${plugin_name}" echo "plugin type = ${plugin_type}" echo "plugin key = ${plugin_key}" mkdir "${plugin_dir}" for filename in ${file_list}; do plugin_name_under_score=$(echo "${plugin_name}" | sed "s/-/_/g") if [ "${filename}" == "plugin_template_Makefile.am" ]; then dst_filename="Makefile.am" elif [ "${filename}" == "plugin_template_CMakeLists.txt" ]; then dst_filename="CMakeLists.txt" else dst_filename=$(echo ${filename} | sed "s/plugin_template_/${plugin_name}-/g") fi dst_filename="${plugin_dir}"/"${dst_filename}" cp "${template_dir}/${filename}" "${dst_filename}" sed -i "s/@PLUGIN_NAME@/${plugin_name}/g" "${dst_filename}" sed -i "s/@PLUGIN_NAME_US@/${plugin_name_under_score}/g" "${dst_filename}" sed -i "s/@PLUGIN_TYPE@/${plugin_type}/g" "${dst_filename}" sed -i "s/@PLUGIN_KEY@/${plugin_key}/g" "${dst_filename}" sed -i "s/@YEAR_AND_AUTHOR@/${year_and_author}/g" "${dst_filename}" done echo "Done: new plugin skeleton is created in ${plugin_dir}" syslog-ng-syslog-ng-3.13.2/dev-utils/plugin_skeleton_creator/plugin_template_CMakeLists.txt000066400000000000000000000016501321171025300323050ustar00rootroot00000000000000set(@PLUGIN_NAME_US@_HEADERS "@PLUGIN_NAME@-parser.h" "${CMAKE_CURRENT_BINARY_DIR}/@PLUGIN_NAME@-grammar.h" ) set(@PLUGIN_NAME_US@_SOURCES "@PLUGIN_NAME@-plugin.c" "@PLUGIN_NAME@-parser.c" "${CMAKE_CURRENT_BINARY_DIR}/@PLUGIN_NAME@-grammar.c" ) generate_y_from_ym(modules/@PLUGIN_NAME@/@PLUGIN_NAME@-grammar) bison_target(@PLUGIN_NAME@Grammar ${CMAKE_CURRENT_BINARY_DIR}/@PLUGIN_NAME@-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/@PLUGIN_NAME@-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) option(ENABLE_@PLUGIN_NAME_US@ "Enable @PLUGIN_NAME@ ON") if (ENABLE_@PLUGIN_NAME_US@) include_directories (${CMAKE_CURRENT_BINARY_DIR}) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) add_library(@PLUGIN_NAME_US@ MODULE ${@PLUGIN_NAME@_SOURCES}) target_link_libraries(@PLUGIN_NAME_US@ PRIVATE syslog-ng) install(TARGETS @PLUGIN_NAME_US@ LIBRARY DESTINATION lib/syslog-ng/ COMPONENT @PLUGIN_NAME_US@) endif() syslog-ng-syslog-ng-3.13.2/dev-utils/plugin_skeleton_creator/plugin_template_Makefile.am000066400000000000000000000022521321171025300316000ustar00rootroot00000000000000module_LTLIBRARIES += modules/@PLUGIN_NAME@/lib@PLUGIN_NAME@.la modules_@PLUGIN_NAME_US@_lib@PLUGIN_NAME_US@_la_SOURCES = \ modules/@PLUGIN_NAME@/@PLUGIN_NAME@-grammar.y \ modules/@PLUGIN_NAME@/@PLUGIN_NAME@-parser.c \ modules/@PLUGIN_NAME@/@PLUGIN_NAME@-parser.h \ modules/@PLUGIN_NAME@/@PLUGIN_NAME@-plugin.c BUILT_SOURCES += \ modules/@PLUGIN_NAME@/@PLUGIN_NAME@-grammar.y \ modules/@PLUGIN_NAME@/@PLUGIN_NAME@-grammar.c \ modules/@PLUGIN_NAME@/@PLUGIN_NAME@-grammar.h EXTRA_DIST += \ modules/@PLUGIN_NAME@/@PLUGIN_NAME@-grammar.ym modules_@PLUGIN_NAME_US@_lib@PLUGIN_NAME_US@_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/@PLUGIN_NAME@ \ -I$(top_builddir)/modules/@PLUGIN_NAME@ modules_@PLUGIN_NAME_US@_lib@PLUGIN_NAME_US@_la_LIBADD = $(MODULE_DEPS_LIBS) modules_@PLUGIN_NAME_US@_lib@PLUGIN_NAME_US@_la_LDFLAGS = $(MODULE_LDFLAGS) modules_@PLUGIN_NAME_US@_lib@PLUGIN_NAME_US@_la_DEPENDENCIES= $(MODULE_DEPS_LIBS) modules/@PLUGIN_NAME@ modules/@PLUGIN_NAME@/ mod-@PLUGIN_NAME@: modules/@PLUGIN_NAME@/lib@PLUGIN_NAME@.la .PHONY: modules/@PLUGIN_NAME@/ mod-@PLUGIN_NAME@ syslog-ng-syslog-ng-3.13.2/dev-utils/plugin_skeleton_creator/plugin_template_grammar.ym000066400000000000000000000030201321171025300315330ustar00rootroot00000000000000/* * Copyright (c) @YEAR_AND_AUTHOR@ * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code top { #include "@PLUGIN_NAME@-parser.h" } %code { #include "cfg-parser.h" #include "@PLUGIN_NAME@-grammar.h" #include "syslog-names.h" #include "messages.h" #include "plugin.h" #include "cfg-grammar.h" #include } %name-prefix "@PLUGIN_NAME_US@_" /* this parameter is needed in order to instruct bison to use a complete * argument list for yylex/yyerror */ %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogDriver **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %% start : @PLUGIN_TYPE@ first_rule { YYACCEPT; } ; first_rule : ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/dev-utils/plugin_skeleton_creator/plugin_template_parser.c000066400000000000000000000030211321171025300311770ustar00rootroot00000000000000/* * Copyright (c) @YEAR_AND_AUTHOR@ * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "driver.h" #include "cfg-parser.h" #include "@PLUGIN_NAME@-grammar.h" extern int @PLUGIN_NAME_US@_debug; int @PLUGIN_NAME_US@_parse(CfgLexer *lexer, LogDriver **instance, gpointer arg); static CfgLexerKeyword @PLUGIN_NAME_US@_keywords[] = { { NULL } }; CfgParser @PLUGIN_NAME_US@_parser = { #if ENABLE_DEBUG .debug_flag = &@PLUGIN_NAME_US@_debug, #endif .name = "@PLUGIN_NAME@", .keywords = @PLUGIN_NAME_US@_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer)) @PLUGIN_NAME_US@_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(@PLUGIN_NAME_US@_, LogDriver **) syslog-ng-syslog-ng-3.13.2/dev-utils/plugin_skeleton_creator/plugin_template_parser.h000066400000000000000000000022111321171025300312040ustar00rootroot00000000000000/* * Copyright (c) @YEAR_AND_AUTHOR@ * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef @PLUGIN_NAME_US@_PARSER_H_INCLUDED #define @PLUGIN_NAME_US@_PARSER_H_INCLUDED #include "cfg-parser.h" #include "driver.h" extern CfgParser @PLUGIN_NAME_US@_parser; CFG_PARSER_DECLARE_LEXER_BINDING(@PLUGIN_NAME_US@_, LogDriver **) #endif syslog-ng-syslog-ng-3.13.2/dev-utils/plugin_skeleton_creator/plugin_template_plugin.c000066400000000000000000000032041321171025300312040ustar00rootroot00000000000000/* * Copyright (c) @YEAR_AND_AUTHOR@ * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "plugin.h" #include "plugin-types.h" extern CfgParser @PLUGIN_NAME_US@_parser; static Plugin @PLUGIN_NAME_US@_plugins[] = { { .type = @PLUGIN_TYPE@, .name = "@PLUGIN_KEY@", .parser = &@PLUGIN_NAME_US@_parser, }, }; gboolean @PLUGIN_NAME_US@_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, @PLUGIN_NAME_US@_plugins, G_N_ELEMENTS(@PLUGIN_NAME_US@_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "@PLUGIN_NAME_US@", .version = SYSLOG_NG_VERSION, .description = "Please fill this description", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = @PLUGIN_NAME_US@_plugins, .plugins_len = G_N_ELEMENTS(@PLUGIN_NAME_US@_plugins), }; syslog-ng-syslog-ng-3.13.2/dist.conf.in000066400000000000000000000005541321171025300176600ustar00rootroot00000000000000# default environment parameters SNAPSHOT_VERSION=${SNAPSHOT_VERSION:-@SNAPSHOT_VERSION@} SOURCE_REVISION=${SOURCE_REVISION:-@SOURCE_REVISION@} BROCHURE_VERSION=${BROCHURE_VERSION:-@BROCHURE_VERSION@} COMBINED_VERSION=${COMBINED_VERSION:-@COMBINED_VERSION@} TECHNICAL_VERSION=${TECHNICAL_VERSION:-@TECHNICAL_VERSION@} RELEASE_TYPE=${RELEASE_TYPE:-@RELEASE_TYPE@} syslog-ng-syslog-ng-3.13.2/doc/000077500000000000000000000000001321171025300162025ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/doc/ChangeLog.0000066400000000000000000000425001321171025300201130ustar00rootroot000000000000002005-01-16 Balazs Scheidler * configure.in: take CFLAGS environment variable into consideration when running configure, link eventlog and glib statically * src/fdread.c, src/fdwrite.c: handle EINTR by repeating the read system call * src/logreader, src/logwriter.c: handle EAGAIN correctly 2005-01-15 Balazs Scheidler * src/afsocket.c (afsocket_sd_accept): added g_fd_set_nonblock for new sockets 2005-01-09 Balazs Scheidler * src/logsource.c: new file, separated flow control related functions from logreader * src/logreader.c: LogReader is derived from LogSource * src/afinter.c: substituted the pipe used for internal messages with a GQueue 2005-01-05 Balazs Scheidler * configure.in: added checks for -ldoor, -lsocket, -lnsl and getopt.h * other files: fixed a couple of Solaris specific warnings 2004-12-31 Balazs Scheidler * src/macros.c: added PRI and MSGONLY macros * src/templates.c: added support for braces around macros for $example: "{MSG}" 2004-12-29 Balazs Scheidler * src/afprog.c (afprogram_dd_init): call setsid before launching child, (afprogram_dd_deinit): deinit & unref self->writer here instead of in afprogram_dd_free, * src/center.c (log_center_queue): do not supply self as user_data pointer to the ack_block callback as that would require adding a reference to self * src/dgroup.c (log_dest_group_queue): do not supply self as user_data pointer to the ack_block callback as that would require adding a reference to self * src/logreader.c: instead of using self->window_size use self->options->window_size so that the window is shared between all LogReaders using the same options, (log_reader_handle_line): add reference to self before supplying it as an argument to the ack_block callback function, (log_reader_msg_ack): unref the supplied logreader argument 2004-12-27 Balazs Scheidler * src/afsocket.c (afsocket_sd_deinit): break circular reference between self->reader and self, (afsocket_sd_notify): do not destroy/unref sender in NC_CLOSE, as afsocket_sd_close_connection already does that, (afsocket_sd_init, afsocket_sd_deinit): removed static, (afsocket_sd_free_instance): renamed from afsocket_sd_free, removed static, created a new afsocket_sd_free function at the same time which is set as the free_fn of AFSocketSourceDriver * src/afunix.c: implemented user/group/perm settings * src/cfg-grammar.y: added support for log-prefix * src/cfg.c: changed default timestamp format to BSD for compatibility * src/filter.c: fixed AND and OR operator evaluation, the operands were not correctly saved at initialization time, thus NULL was referenced at evaluation time * src/logreader.c: added log_prefix support for all log readers * src/logwriter.c: use log_msg_drop instead of a simple log_msg_unref * src/main.c: fixed SIGCHLD handling, loop while waitpid returns > 0, added tzset() call 2004-12-27 Balazs Scheidler * src/affile.c (affile_sd_deinit): make sure to break circular reference between self->reader and self, fixes possible memory leak, (affile_sd_free): call log_drv_free_instance * src/afinter.c (afinter_sd_deinit): break circular reference between self->reader and self * src/afprog.c (afprog_sd_free): added log_drv_free_instance * src/afsocket.c (afsocket_sd_deinit): break circular reference between self->reader and self, (afsocket_sd_free): added log_drv_free_instance, (afsocket_dd_free): -"- * src/afuser.c (afuser_dd_queue): free queued message, (afuser_dd_free): added log_drv_free_instance * src/cfg-grammar.y: unref log driver after appending to avoid memory leaks * src/cfg.c (cfg_reload_config): fixed possible memory leak when cfg_init fails (free persist), (persist_config_free): added missing free for hashtable * src/dgroup.c (log_dest_group_queue): make sure each driver gets its own reference to msg as each will free it on its own, also added an explicit unref at the end of the function (log_dest_group_new): added missing call to log_pipe_init_instance * src/gsockaddr.c: removed all low-level g_message invocation, errors should be reported by the caller * src/logpipe.c: added assertions to _ref and _unref * src/main.c (main_loop_run): added a missing g_main_loop_unref to avoid memory leaks, (main): call msg_syslog_started at the end of initialization to force messages into the system log * src/messages.c (msg_syslog_started): new function to indicate that initialization is finished, messages will be written to stderr instead of the internal() source if syslog is not yet started to let the administrator see important failure messages, (msg_deinit): free the event log context, only close the error pipe if it was really opened 2004-08-20 Balazs Scheidler * src/messages.c: adapted to the latest changes in the eventlog, now it actually compiles again and shows some signs of operation 2003-01-22 Balazs Scheidler * src/logwriter.c: support per-destination time stamp formatting options (keep_timestamp, tz_convert, ts_format) * src/logreader.c: support LR_STRICT flag (specifies LP_STRICT when parsing messages), new per-source option time_zone which specifies the sender's timezone * src/macros.c: support time_zone when formatting a message * src/templates.c: support time_zone specification for templates * src/logmsg.c: added timezone handling, the possibility to parse RFC3339 timestamps in incoming messages * src/cfg.c, src/cfg-grammar.y: added timestamp & timezone specific options * src/afsocket.c: strict RFC3164 mode does not allow RFC3339 timestamps, kept alive file descriptors are stored in persist offseted by +1, so NULL value is not possible * src/afinet.c: UDP uses strict RFC3164 timestamps * src/affile.c: added warning about template_escape() if the template used is not specified inline 2002-12-31 Balazs Scheidler * src/afsocket.c (afsocket_sd_set_keep_alive, afsocket_sd_set_listener_keep_alive): new functions to set the appropriate flags in self, (afsocket_sd_kill_connection): new function, kills and unrefs the given AFSocketSourceConnection object, (afsocket_sd_init, afsocket_sd_deinit): support persistent connections * src/cfg-grammar.y: the inline template definition stores the inline-ness in a gboolean attribute * src/cfg.c: implemented file/directory uid/gid/perm functions, (persist_config_add, persist_config_fetch): new functions * src/filter.c: store the marked matches in global variables, so macro expansion can reference it * src/macros.c: support variables $1 - $9 * src/misc.c: moved resolve_user & family functions here * src/main.c: use resolve_* functions from misc.c * src/afinet.c (afinet_sd_new): set flags to AFSOCKET_KEEP_ALIVE | AFSOCKET_LISTENER_KEEP_ALIVE * src/affile.c (affile_set_template_escape): modify the inline template object instead of a flag in self 2002-11-15 Balazs Scheidler * src/templates.c: make LogTemplate refcounted * src/logwriter.c (log_writer_format_log): support for file_template & proto_template * src/logreader.c: instead of relying on ourselves to let output buffers flush, we use glib source priority mechanism (the exact change was to return TRUE when a complete line is available in prepare), fixed MARK processing * src/cfg.c: file_template & proto_template support * src/cfg-lex.l: added two new options, file_template and proto_template, they specify the ID of a template which will be used by default for file/protocol outputs * src/gsockaddr.c: changed return values from G_IO_ERROR_* to G_IO_STATUS_* (glib 2 style) * src/afsocket.c: changed to match gsockaddr.c changes, fixed a bug that cause message loss between reconnections (self->log_writer was reinitialized before each reconnect) 2002-09-16 Balazs Scheidler * src/afprog.c (afprogram_dd_exit): new function, called when a child exited, calls deinit & init to restart the program (afprogram_dd_init): call child_manager_register(), so the program() destination supports restarting the program * src/afsocket.c: pass LR_PKTTERM flag for AFSOCKET_DGRAM sockets * src/cfg-grammar.y: new token KW_FOLLOW_FREQ, it is a reader option and specifies that the file should be followed using the given frequence (a'la tail -f ) * src/cfg-lex.l: renamed keyword 'mark' to 'mark_freq' * src/cfg.c: initialize follow_freq to -1 * src/children.c, src/children.h: new files which implement process children handling, it makes it possible to register callbacks for SIGCHLD * src/logmsg.c: added 'log parsing flags', prefixed LP_*, which modifies the way log messages are parsed, removed some specialized log_msg_new_*() functions, (log_msg_new_mark): new function, generates a MARK message * src/logreader.c: added follow file option, added packet terminated log processing (for SOCK_DGRAM sources), self->source_id was changed to a GSource *, and renamed to self->source, changed initialization and deinitialization code accordingly * src/main.c: initialize children.c, and call the necessary entry point upon SIGCHLD 2002-08-03 Balazs Scheidler * src/logreader.c, src/logreader.h: runtime variable log message size support * src/cfg.c, src/cfg.h: template storage support * src/cfg-grammar.y: add support for template keywords, add support for log_msg_size * src/templates.c, src/templates.h: new files for defineable templates 2002-07-28 Balazs Scheidler * src/syslog-ng.h: added LOG_PRIORITY_* defines * src/messages.c: initialize msg_pipe to {-1,-1} to let the internal() driver know that internal message pipe has not been initialized * src/logwriter.h (LogWriterOptions): moved fifo_size to here, added declaration for log_writer_options_* functions * src/logwriter.c (log_writer_watch_new): set priority to LOG_PRIORITY_WRITER (log_writer_queue): use log_fifo_size from options, added some more detail to message reporting queue full (log_writer_new): removed initialization of log_fifo_size, it is used from writer_options instead (log_writer_options_defaults): new function (log_writer_options_init): new function * src/logreader.h (LogReaderOptions): added fetch_limit (LogReader): added prev_addr field (to hold the sockaddr of the previous buffer, added declaration for log_reader_options_defaults, log_reader_options_init * src/logreader.c (log_reader_watch_new): set source priority to LOG_PRIORITY_READER (log_reader_iterate_buf): implemented fetch_limit option, fixed sockaddr handling when something remains in the buffer (log_reader_options_defaults, log_reader_options_init): new functions * src/logmsg.c (log_msg_ack_block_end): fixed memory leak, instead of simply removing the list entry, delete it * src/cfg.h (GlobalConfig): added fields log_iw_size and log_fetch_limit * src/cfg.c (cfg_new): set default options for log_iw_size and log_fetch_limit * src/cfg-lex.l: added keywords for log_iw_size and log_fetch_limit * src/cfg-grammar.y: cleaned up token section, added options log_iw_size, log_fetch_limit, fixed log_fifo_size * src/center.c (log_center_queue): pass a reference of msg further, otherwise msg was freed too early * src/afsocket.c (g_listen_source_new): set priority to LOG_PRIORITY_LISTEN (g_connect_source_new): set priority to LOG_PRIORITY_CONNECT (afsocket_sd_init): call log_reader_options_init (afsocket_sd_init_instance): call log_reader_options_defaults instead of setting reader options directly (afsocket_dd_init): call log_writer_options_init (afsocket_dd_init_instance): call log_writer_options_defaults * src/afprog.c (afprogram_dd_init): call log_writer_options_init (afprogram_dd_new): call log_writer_options_defaults * src/afinter.c (afinter_sd_init): call log_reader_options_init, handle the case when internal messages are written to stderr instead of the log (afinter_sd_new): call log_reader_options_defaults * src/affile.c (affile_sd_init): call log_reader_options_init (affile_dd_new): call log_reader_options_defaults (affile_dw_deinit): fixed memory leak, unref self->writer when deinitialized (affile_dd_init): call log_writer_options_init (affile_dd_queue): handle the case when the dw cannot be initialized (affile_dd_new): call log_writer_options_defaults 2002-07-27 Balazs Scheidler * src/main.c (sig_segv_handler): new function, handles SIGSEGV signals * src/macros.c (result_append): instead of using g_string_sprintfa to append an escaped char, append it using g_string_append_c (supposed to be faster) * src/logmsg.c (log_msg_ref, log_msg_unref): added assert() calls to check whether ref_cnt has reached zero * src/afsocket.c (afsocket_sc_free): bugfix, set self->owner->connections to the value returned by g_list_remove(), this one caused major headache to find * src/affile.c (affile_dd_queue): free filename if dw is already allocated 2002-06-30 Balazs Scheidler * src/main.c: support for memtrace added * src/logwriter.c, src/logwriter.h: use fd_write objects instead of simple fds * src/logreader.c, src/logreader.h: use fd_read objects instead of simple fds * src/logmsg.c (log_msg_ack_block_end): fixed memory leak, free the allocated memory block * src/fdread.c, src/fdread.h:: new files which implement file descriptor reading * src/fdwrite.c, src/fdwrite.h:: new files which implement file descriptor writing * src/cfg-grammar.y: pass AFSOCKET_LOCAL flag to unix domain socket sources * src/afsocket.c: removed finalize function from g_connect & g_listen sources, pass fd_read to log_reader, and fd_write to log_writer instead of plain fds * src/affile.c, src/afinter.c, src/afprog.c: pass fd_read object to log_reader_new, and fd_write to log_writer instead of plain fds * src/memtrace.c, src/memtrace.h: ported from Zorp * src/Makefile.am: added memtrace.c & memtrace.h * configure.in: added --enable-mem-trace switch 2002-06-15 Balazs Scheidler * afsocket.c: ported to glib-2.0 * logreader.c: ported to glib-2.0 * logwriter.c: LogWriterOptions split from the main structure, ported to glib-2.0 * affile.h: moved AFFileSourceDriver and AFFileDestDriver here, so the parser can use reader_options/writer_options fields directly * cfg-grammar.y: make log_reader and log_writer options separate rules, so it is easier to add common rules for all source/destination driver * configure.in: use glib-2.0 and pkgconfig 2002-06-08 Balazs Scheidler * src/messages.c: debug messages are never written to syslog as internal message as it would drain the system (for example every incoming log message is reported as a debug message, they are always written to stderr instead * src/cfg-grammar.y, src/cfg-lex.l: added support for flow controlled message paths * src/center.h: LC_FLOW_CONTROL new flag * src/center.c: sources are also stored in a g_ptr_array in addition to the hash table to make it easier to perform iterative tasks (g_hash_table_foreach requires a function pointer), and source references are also resolved at init time. * src/logreader.c, src/center.c, src/dgroup.c, src/logwriter.c, src/afuser.c: implemented flow control * src/logpipe.h: added path_flags argument to queue() as it specifies whether the sender wants ack or not (used by flow control), * src/logreader.h: separated log reader specific options to another structure (LogReaderOptions), to make it easier to specify reader options from the configuration 2002-05-13 Balazs Scheidler * src/messages.h, src/messages.c: added support for verbose_flag and debug_flag, and implemented internal message handling * src/logreader.c: added new flag LR_NOCLOSE to avoid closing the fd if the logreader is destroyed, added LR_INTERNAL for processing internal messages, and LR_NOPARSE to avoid parsing incoming message * src/afinter.c: implemented internal messages driver 2002-05-09 Balazs Scheidler * src/afprog.c: added the ability to respawn the child program once it exited * src/messages.h: added msg_debug macro * src/main.c: added processing most of the command line options, added the ability to go into background, chroot, setuid, setgid etc. * src/afunix.c: implemented afunix sources and destinations * src/logpipe.h: added NC_WRITE_ERROR, renamed NC_CLOSE_ERROR to NC_READ_ERROR, changed referrences appropriately, (log_pipe_append): new function * src/afinet.c: implemented hostname and service lookup, implemented reconnection after a timeout, implemented EOF detection when the channel is idle * src/logwriter.c, src/logreader.c: added new argument named control where notify messages are sent, log readers have no explicit 'next' argument anymore, pipes are constructed using log_pipe_append instead * src/affile.c: implemented destination file reaping 2002-04-04 Balazs Scheidler * affile, afpipe and afinet fixes * do not leak memory on -HUP syslog-ng-syslog-ng-3.13.2/doc/ChangeLog.1000066400000000000000000001572061321171025300201260ustar00rootroot00000000000000# do not edit -- automatically generated by arch changelog # not-id: automatic-ChangeLog--bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0 # 2006-02-11 07:31:40 GMT Balazs Scheidler patch-86 Summary: fixed possible 64 bit compatibility problem Revision: syslog-ng--mainline--2.0--patch-86 * src/logwriter.c (log_writer_queue, log_writer_flush_log): use GPOINTER_TO_UINT/GUINT_TO_POINTER macros instead of casting the values by hand modified files: ChangeLog src/logwriter.c src/logwriter.h 2006-01-25 17:13:29 GMT Balazs Scheidler patch-85 Summary: added support for hostname resolution (fixes: #8036) Revision: syslog-ng--mainline--2.0--patch-85 2006-01-25 Balazs Scheidler * src/afinet.c: support an optional self->dest_addr * src/afsocket.c (afsocket_dd_init): fail if self->dest_addr is NULL, (afsocket_sd_init): fail if self->bind_addr is NULL * src/gsockaddr.c (g_sockaddr_inet_new_resolve): new function, resolves a hostname and stores the result in a GSockAddr, modified files: ChangeLog src/afinet.c src/afinet.h src/afsocket.c src/gsockaddr.c src/gsockaddr.h 2006-01-20 10:01:44 GMT Balazs Scheidler patch-84 Summary: added stats counter sharing and a way to disable stats counter Revision: syslog-ng--mainline--2.0--patch-84 2006-01-20 Balazs Scheidler * src/stats.c (stats_register_counter): added shared parameter to specify that the given counter can be shared * src/logwriter.h (LogWriterOptions): added flags member and two flags LWOF_NO_STATS, LWOF_SHARED_STATS * src/logwriter.c (log_writer_options_init): converted fixed_stamp parameter to a flag word, the actual value is LWOF_FIXED_STAMP, (log_writer_init): don't register a stats counter if LWOF_NO_STAMP is specified * src/af*.c: changed the call of log_writer_options_init() modified files: ChangeLog src/affile.c src/afprog.c src/afsocket.c src/logwriter.c src/logwriter.h src/stats.c src/stats.h 2006-01-13 13:17:29 GMT Balazs Scheidler patch-83 Summary: added compatibility option for stats Revision: syslog-ng--mainline--2.0--patch-83 2006-01-13 Balazs Scheidler * src/cfg-lex.l: added a "stats" keyword to be compatible with 1.6.x modified files: ChangeLog src/cfg-lex.l 2005-12-31 14:09:13 GMT Balazs Scheidler patch-82 Summary: fixed EOF detected messages for UDP destinations where the target is unreachable Revision: syslog-ng--mainline--2.0--patch-82 2005-12-31 Balazs Scheidler * src/afsocket.c (afsocket_dd_init): don't set LW_DETECT_EOF for UDP destinations * src/logwriter.c (log_writer_fd_dispatch): EOF is detected only if G_IO_IN is detected and not for G_IO_ERR as it might be set for UDP destinations when they are unreachable modified files: ChangeLog src/afsocket.c src/logwriter.c 2005-12-20 20:52:38 GMT Balazs Scheidler patch-81 Summary: perparations for an 1.9.8 release Revision: syslog-ng--mainline--2.0--patch-81 modified files: ChangeLog NEWS VERSION 2005-12-20 20:34:51 GMT Balazs Scheidler patch-80 Summary: fixed UDP destination driver initialization Revision: syslog-ng--mainline--2.0--patch-80 2005-12-20 Balazs Scheidler * src/afsocket.c (afsocket_dd_connected): only check socket error state for stream sockets as UDP connections succeed immediately, (afsocket_dd_reconnect): if g_connect returns immediate success (UDP connections) set self->fd to sock modified files: ChangeLog src/afsocket.c 2005-12-05 20:24:45 GMT Balazs Scheidler patch-79 Summary: fix time conversion to the specified timezone Revision: syslog-ng--mainline--2.0--patch-79 2005-12-05 Balazs Scheidler * src/logmsg.c (log_stamp_format): instead of substracting the timezone offset substract it (credit for reporting goes to Andy), * src/macros.c (log_macro_expand): -"- * src/logmsg.c (log_msg_parse): time zone specifies can be more than 12 hours, fixed. modified files: ChangeLog src/logmsg.c src/macros.c 2005-12-03 16:42:19 GMT Balazs Scheidler patch-78 Summary: include VERSION in the dist Revision: syslog-ng--mainline--2.0--patch-78 modified files: ChangeLog Makefile.am 2005-12-03 16:34:15 GMT Balazs Scheidler patch-77 Summary: fixed MARK support Revision: syslog-ng--mainline--2.0--patch-77 2005-12-03 Balazs Scheidler * doc/reference/syslog-ng.xml: added some more words on mark_freq() and stats_freq(), actually fixed the documentation as these options were renamed for consistency * src/afinter.c: move MARK implementation to here instead of logreader, there's no point in creating MARK messages in the name of all of our sources, we need to generate a single MARK message in our name if there's no traffic * src/main.c: removed the use of obsolete GLib functions modified files: ChangeLog NEWS doc/reference/syslog-ng.xml src/afinter.c src/afinter.h src/center.c src/logreader.c src/logreader.h src/main.c 2005-12-03 15:49:30 GMT Balazs Scheidler patch-76 Summary: minor documentation updates, updated NEWS, bumped VERSION to 1.9.7 Revision: syslog-ng--mainline--2.0--patch-76 modified files: ChangeLog NEWS VERSION doc/reference/syslog-ng.xml 2005-12-03 15:29:36 GMT Balazs Scheidler patch-75 Summary: fixed a possible segmentation fault during HUPs Revision: syslog-ng--mainline--2.0--patch-75 2005-12-03 Balazs Scheidler * src/afsocket.c (afsocket_sc_init): fixed DGRAM socket initialization to actually process incoming data in packets (the LR_PKTTERM flag was missed), (afsocket_sd_deinit): don't free the connection list items when iterating the list as connections are removed from the list when they are freed, the loop there only needs to break the circular references modified files: ChangeLog src/afsocket.c 2005-12-03 11:23:55 GMT Balazs Scheidler patch-74 Summary: added VERSION file Revision: syslog-ng--mainline--2.0--patch-74 new files: .arch-ids/VERSION.id VERSION modified files: ChangeLog 2005-12-03 11:23:46 GMT Balazs Scheidler patch-73 Summary: added debianization files, misc build fixes Revision: syslog-ng--mainline--2.0--patch-73 2005-12-03 Balazs Scheidler * debian/*: added debianization files * configure.in: added VERSION file instead of having the actual VERSION inline, added CURRDATE to make it possible to generate debian/changelog automatically new files: debian/.arch-ids/=id debian/.arch-ids/README.Debian.id debian/.arch-ids/changelog.in.id debian/.arch-ids/control.id debian/.arch-ids/copyright.id debian/.arch-ids/rules.id debian/.arch-ids/syslog-ng.conf.example.id debian/.arch-ids/syslog-ng.conf.id debian/.arch-ids/syslog-ng.default.id debian/.arch-ids/syslog-ng.docs.id debian/.arch-ids/syslog-ng.files.id debian/.arch-ids/syslog-ng.init.id debian/.arch-ids/syslog-ng.logcheck.ignore.id debian/.arch-ids/syslog-ng.logrotate.example.id debian/.arch-ids/syslog-ng.logrotate.id debian/.arch-ids/syslog-ng.postinst.id debian/.arch-ids/syslog-ng.postrm.id debian/.arch-ids/syslog-ng.preinst.id debian/README.Debian debian/changelog.in debian/control debian/copyright debian/rules debian/syslog-ng.conf debian/syslog-ng.conf.example debian/syslog-ng.default debian/syslog-ng.docs debian/syslog-ng.files debian/syslog-ng.init debian/syslog-ng.logcheck.ignore debian/syslog-ng.logrotate debian/syslog-ng.logrotate.example debian/syslog-ng.postinst debian/syslog-ng.postrm debian/syslog-ng.preinst modified files: ChangeLog Makefile.am configure.in new directories: debian debian/.arch-ids 2005-11-25 15:25:19 GMT Balazs Scheidler patch-72 Summary: fixed Solaris STREAMS based log device support Revision: syslog-ng--mainline--2.0--patch-72 2005-11-25 Balazs Scheidler * src/afsocket.c (afsocket_dd_format_stats_name): fix compiler warning about uninitialized driver_name, the switch statement covers every possible case * src/afstreams.c: fix compilation issues, it now actually compiles and works on Solaris (tested on Solaris 9) modified files: ChangeLog configure.in src/afsocket.c src/afstreams.c 2005-11-23 16:31:48 GMT Balazs Scheidler patch-71 Summary: fixed timezone calculation Revision: syslog-ng--mainline--2.0--patch-71 2005-11-23 Balazs Scheidler * src/misc (get_local_timezone_ofs): fixed timezone calculation again, * tests/unit/test_zone.c: added some missing testcases for timezones over 12 hours (New Zealand) * tests/unit/test_filters.c: fixed facility testing as the code was changed modified files: ChangeLog src/misc.c tests/unit/test_filters.c tests/unit/test_zone.c 2005-11-15 15:35:15 GMT Balazs Scheidler patch-70 Summary: fixed the detetion of Solaris STREAMS support, fixed segfault when it was not compiled in Revision: syslog-ng--mainline--2.0--patch-70 modified files: ChangeLog configure.in src/afstreams.c 2005-11-03 17:03:26 GMT Balazs Scheidler patch-69 Summary: fixed log message concatenation in certain cases Revision: syslog-ng--mainline--2.0--patch-69 2005-11-03 Balazs Scheidler * src/templates.c (log_template_format): truncate the string before formatting a log message modified files: ChangeLog src/templates.c 2005-10-24 08:40:59 GMT Balazs Scheidler patch-68 Summary: readded syslog-ng.h as it was missed from the distribution Revision: syslog-ng--mainline--2.0--patch-68 modified files: ChangeLog src/Makefile.am 2005-10-22 21:29:23 GMT Balazs Scheidler patch-67 Summary: stats.c & stats.h were not commited in the previous patch Revision: syslog-ng--mainline--2.0--patch-67 new files: src/.arch-ids/stats.c.id src/.arch-ids/stats.h.id src/stats.c src/stats.h modified files: ChangeLog 2005-10-22 21:28:46 GMT Balazs Scheidler patch-66 Summary: added per-destination dropped counters and some bugfixes Revision: syslog-ng--mainline--2.0--patch-66 2005-10-22 Balazs Scheidler * src/stats.{c,h}: new files, a simple framework for named statistical counters, currently only used for per-destination dropped counters * src/message.c, src/messages.h (msg_event): the function was split to msg_event_create and msg_event_send functions and macros were changed accordingly, the reason is that the STATS message uses dynamic message tags * src/main.c (stats_timer): new function to issue statistics message using the stats framework * src/logwriter.h (LogWriterOptions): added stats_name member which is used when registering the dropped counters, (LogWriter): added dropped_messages member to point to our private dropped counter * src/logwriter.c (log_writer_init): register dropped counter, (log_writer_free): deregister dropped counter, (log_writer_options_init): store the name of the dropped counter, added a warning message for the flush_lines > fifo_size case as this will not work, (log_writer_flush_log): call log_writer_broken when an error occurs, (log_writer_broken): changed argument list to be usable from log_writer_flush_log, log message moved out of the function as it might be called from different places, (log_writer_queue): increment dropped counter, (log_writer_fd_prepare, log_writer_fd_check): fixed flush_timeout handling * src/Makefile.am: moved headers to SOURCES from EXTRA_DIST (I like it better this way (tm)) * src/logpipe.h, src/logmsg.h: don't include glib.h directly, use syslog-ng.h instead * src/misc.c (format_zone_info): readded ':' to zone offset formatting, which was missed in the previous patch, fixed the sign for zone offsets * src/logmsg.c (log_stamp_format): the buffer for the zone offset was not large enough to hold the readded ':' * src/cfg-grammar.y, src/cfg-lex.l: added global stats_freq option * src/afprog.c, src/affile.c, src/afprog.c: added dropped stats support * src/afsocket.c: added dropped stats support, (afsocket_dd_connected): do not reinit the writer, (afsocket_dd_init): do not create a new LogWriter instance every time, but reuse the previous one instead, (afsocket_dd_free): fix memory leak by freeing self->writer removed files: src/.arch-ids/sdriver.c.id src/sdriver.c modified files: ChangeLog src/Makefile.am src/affile.c src/afprog.c src/afsocket.c src/cfg-grammar.y src/cfg-lex.l src/logmsg.c src/logmsg.h src/logpipe.h src/logwriter.c src/logwriter.h src/main.c src/messages.c src/messages.h src/misc.c 2005-10-22 17:20:32 GMT Balazs Scheidler patch-65 Summary: do not use the LOG_FAC macro as it is not portable Revision: syslog-ng--mainline--2.0--patch-65 2005-10-22 Balazs Scheidler * src/filter.c: do not use the LOG_FAC macro, it is not available on Solaris * doc/reference/syslog-ng.xml: added documentation on the alternate syntax of the facility() filter modified files: ChangeLog doc/reference/syslog-ng.xml src/filter.c 2005-10-21 16:07:47 GMT Balazs Scheidler patch-64 Summary: test commit for syslog-ng-commit message Revision: syslog-ng--mainline--2.0--patch-64 modified files: ChangeLog src/logmsg.c 2005-10-18 15:40:14 GMT Balazs Scheidler patch-63 Summary: added a note on empty source/destination statements Revision: syslog-ng--mainline--2.0--patch-63 modified files: ChangeLog doc/reference/syslog-ng.xml 2005-10-15 16:36:43 GMT Balazs Scheidler patch-62 Summary: fixed non-null terminated utmp username handling Revision: syslog-ng--mainline--2.0--patch-62 2005-10-15 Balazs Scheidler * src/afuser.c: instead of assuming that names in utmp are NUL terminated (which turned out not to be true), limit the length of comparison to sizeof(ut->ut_name) modified files: ChangeLog src/afuser.c 2005-10-15 16:15:57 GMT Balazs Scheidler patch-61 Summary: preparation for the 1.9.6 release Revision: syslog-ng--mainline--2.0--patch-61 modified files: ChangeLog NEWS configure.in 2005-10-15 16:04:45 GMT Balazs Scheidler patch-60 Summary: fixed problems in syslog priority filter, added unit test for most built-in filters Revision: syslog-ng--mainline--2.0--patch-60 2005-10-15 Balazs Scheidler * src/filter.c (filter_facility_eval): added facility value -> bitmap position cache for improved performance, (filter_level_eval): fixed filter evaluation (the function erroneously used the same values for the internal valid bitmap and the syslog header priority value), a similar search through sl_levels is required as was already present for facility filtering, also the same cache mechanism was added for improved performance * tests/unit/test_filter.c: new unit test file, tests most easily testable filters, AND/OR operations and negation new files: tests/unit/.arch-ids/test_filters.c.id tests/unit/test_filters.c modified files: ChangeLog configure.in src/filter.c tests/unit/Makefile.am tests/unit/test_msgparse.c 2005-10-15 14:25:22 GMT Balazs Scheidler patch-59 Summary: timezone DST fixes Revision: syslog-ng--mainline--2.0--patch-59 2005-10-15 Balazs Scheidler * configure.in: removed check for the global timezone variable * src/misc.c (get_local_timezone_ofs): use tm->tm_gmtoff if available and the difference between the results of gmtime and localtime if not, this should be a portable way to determine the correct timezone offset, (format_zone_info): new function to format a timezone offset in a way similar to strftime %z * src/logmsg.c (log_stamp_format): use the new format_zone_info function * src/macros.c (log_macro_expand): always use the new format_zone_info function instead of strftime * doc/reference/syslog-ng.xml: TZ is now equivalent to TZOFFSET new files: tests/unit/.arch-ids/test_zone.c.id tests/unit/test_zone.c modified files: ChangeLog configure.in doc/reference/syslog-ng.xml src/logmsg.c src/macros.c src/misc.c src/misc.h tests/unit/Makefile.am tests/unit/test_msgparse.c 2005-10-07 16:16:35 GMT Balazs Scheidler patch-58 Summary: added a missing "return" Revision: syslog-ng--mainline--2.0--patch-58 2005-10-07 Balazs Scheidler * src/misc.c (get_local_timezone_ofs): added a missing return modified files: ChangeLog src/misc.c 2005-10-05 13:48:34 GMT Balazs Scheidler patch-57 Summary: check for gmt_off in struct tm and detect timezone accordingly Revision: syslog-ng--mainline--2.0--patch-57 2005-10-05 Balazs Scheidler * configure.in: added a test for tm_gmtoff in struct tm as it is not present on Solaris * src/misc.c: use the old global timezone based timezone detection code if tm_gmtoff is not present in "struct tm" modified files: ChangeLog configure.in src/misc.c 2005-10-01 21:39:51 GMT Balazs Scheidler patch-56 Summary: fixed facility/priority filters Revision: syslog-ng--mainline--2.0--patch-56 modified files: ChangeLog src/filter.c 2005-09-26 09:16:38 GMT Balazs Scheidler patch-55 Summary: contrib subdirectory and its contents copied from syslog-ng 1.6.x Revision: syslog-ng--mainline--2.0--patch-55 new files: contrib/.arch-ids/=id contrib/.arch-ids/Makefile.am.id contrib/.arch-ids/README.id contrib/.arch-ids/init.d.HP-UX.id contrib/.arch-ids/init.d.RedHat-7.3.id contrib/.arch-ids/init.d.RedHat.id contrib/.arch-ids/init.d.SuSE.id contrib/.arch-ids/init.d.SunOS.id contrib/.arch-ids/init.d.solaris.id contrib/.arch-ids/relogger.pl.id contrib/.arch-ids/syslog-ng.conf.HP-UX.id contrib/.arch-ids/syslog-ng.conf.RedHat.id contrib/.arch-ids/syslog-ng.conf.SunOS.id contrib/.arch-ids/syslog-ng.conf.doc.id contrib/.arch-ids/syslog-ng.vim.id contrib/.arch-ids/syslog2ng.id contrib/Makefile.am contrib/README contrib/fedora-packaging/.arch-ids/=id contrib/fedora-packaging/.arch-ids/syslog-ng.conf.id contrib/fedora-packaging/.arch-ids/syslog-ng.init.id contrib/fedora-packaging/.arch-ids/syslog-ng.logrotate.id contrib/fedora-packaging/.arch-ids/syslog-ng.sysconfig.id contrib/fedora-packaging/syslog-ng.conf contrib/fedora-packaging/syslog-ng.init contrib/fedora-packaging/syslog-ng.logrotate contrib/fedora-packaging/syslog-ng.sysconfig contrib/init.d.HP-UX contrib/init.d.RedHat contrib/init.d.RedHat-7.3 contrib/init.d.SuSE contrib/init.d.SunOS contrib/init.d.solaris contrib/relogger.pl contrib/rhel-packaging/.arch-ids/=id contrib/rhel-packaging/.arch-ids/syslog-ng.conf.id contrib/rhel-packaging/.arch-ids/syslog-ng.init.id contrib/rhel-packaging/.arch-ids/syslog-ng.logrotate.id contrib/rhel-packaging/syslog-ng.conf contrib/rhel-packaging/syslog-ng.init contrib/rhel-packaging/syslog-ng.logrotate contrib/syslog-ng.conf.HP-UX contrib/syslog-ng.conf.RedHat contrib/syslog-ng.conf.SunOS contrib/syslog-ng.conf.doc contrib/syslog-ng.vim contrib/syslog2ng modified files: ChangeLog Makefile.am configure.in new directories: contrib contrib/.arch-ids contrib/fedora-packaging contrib/fedora-packaging/.arch-ids contrib/rhel-packaging contrib/rhel-packaging/.arch-ids 2005-08-30 07:35:56 GMT Balazs Scheidler patch-54 Summary: fixed template-escape processing for inline templates Revision: syslog-ng--mainline--2.0--patch-54 2005-08-30 Balazs Scheidler * src/affile.c (affile_dd_set_file_template, affile_dd_set_template_escape, affile_dd_set_fsync): removed as templates are logwriter specific options, (affile_dd_new): do not allocate 'templates' variable, (affile_dd_free): do not free 'templates' * src/affile.h (AFFileDestDriver): removed template variable as it was not used * src/cfg-grammar.y (dest_writer_option): template_escape and fsync were erroneously calling affile specific functions, fixed that * src/logwriter.c (log_writer_options_set_template_escape): new function, basically transformed from affile_dd_set_template_escape modified files: ChangeLog src/affile.c src/affile.h src/cfg-grammar.y src/logwriter.c 2005-08-29 07:56:11 GMT Balazs Scheidler patch-53 Summary: added configure test for regexec() function Revision: syslog-ng--mainline--2.0--patch-53 modified files: ChangeLog configure.in 2005-08-08 07:37:15 GMT Balazs Scheidler patch-52 Summary: fixed test_msgparse program to work on BSDs Revision: syslog-ng--mainline--2.0--patch-52 2005-08-08 Balazs Scheidler * tests/unit/test_msgparse.c (main): do not use "timezone" as a global variable as it is a function on BSD derived platforms modified files: ChangeLog tests/unit/test_msgparse.c 2005-08-07 17:31:23 GMT Balazs Scheidler patch-51 Summary: fixed file uid/gid setting and some gcc4 problems Revision: syslog-ng--mainline--2.0--patch-51 2005-08-07 Balazs Scheidler * src/affile.c: fixed affile_dd_set_{file,dir}_{uid,gid} * src/*.h: added complete prototypes for all functions modified files: ChangeLog src/affile.c src/affile.h src/afinter.h src/cfg.h src/memtrace.h src/messages.h src/misc.c src/misc.h 2005-08-04 12:28:36 GMT Balazs Scheidler patch-50 Summary: fixed mark_freq problem Revision: syslog-ng--mainline--2.0--patch-50 2005-08-04 Balazs Scheidler * src/logreader.c (log_reader_fd_prepare): make sure make_target is initialized before going to the poll loop first modified files: ChangeLog src/logreader.c 2005-08-04 11:11:39 GMT Balazs Scheidler patch-49 Summary: deprecated sync_freq, introduced flush_lines instead, fixed a faction of seconds formatting problem Revision: syslog-ng--mainline--2.0--patch-49 2005-08-04 Balazs Scheidler * doc/reference/syslog-ng.xml: added documentation on the new flush_lines and flush_timeout options * src/affile.c (affile_dd_set_sync_freq): removed sync_freq support, did not work anyway, introduced flush_lines & flush_timeout instead * src/afinet.c (afinet_dd_set_sync_freq): removed * src/cfg-grammar.y: added flush options * src/cfg.c: -"- * src/logwriter.c: added flush_lines and flush_timeout support * src/logmsg.c: fixed time fraction formatting NEWS * NEWS.hu * modified files: ChangeLog doc/reference/syslog-ng.xml src/affile.c src/affile.h src/afinet.c src/cfg-grammar.y src/cfg-lex.l src/cfg.c src/cfg.h src/logmsg.c src/logwriter.c src/logwriter.h 2005-07-30 20:48:37 GMT Balazs Scheidler patch-48 Summary: further fixes to the previous patch to unify tcp/udp codepaths in afsocket, test program fixes Revision: syslog-ng--mainline--2.0--patch-48 2005-07-30 Balazs Scheidler * src/afinter.c (afinter_source_dispatch): do not dispatch message if it is NULL (might happen if several internal sources are defined) * src/afsocket.c (afsocket_sc_queue): removed bogus internal error message, (afsocket_sd_init): added error handling around listen() * tests/functional/func_test.py: added AF_INET testing (udp & tcp) NEWS * NEWS.hu * modified files: ChangeLog src/afinter.c src/afsocket.c tests/functional/func_test.py 2005-07-30 20:20:50 GMT Balazs Scheidler patch-47 Summary: fixed stupid UDP initialization problem and updated a unit test program Revision: syslog-ng--mainline--2.0--patch-47 2005-07-30 Balazs Scheidler * src/afsocket.c (afsocket_sd_init): fixed stupid mistake in UDP initialization code * tests/unit/test_msgparse.c: adapted to the new timezone parsing code (msg has the local timezone by default instead of -1) NEWS * NEWS.hu * modified files: ChangeLog src/afsocket.c tests/unit/test_msgparse.c 2005-07-28 13:39:43 GMT Balazs Scheidler patch-46 Summary: added cfg-lex.c and cfg-grammar.c to the distribution Revision: syslog-ng--mainline--2.0--patch-46 modified files: ChangeLog src/Makefile.am 2005-07-28 13:37:23 GMT Balazs Scheidler patch-45 Summary: small Makefile fixes and a flex compatibility fix Revision: syslog-ng--mainline--2.0--patch-45 2005-07-28 Balazs Scheidler * src/Makefile.am: added cfg-lex.c and cfg-grammar.c to MAINTAINER_CLEAN_FILES * src/cfg-lex.l: removed YY_NO_UNPUT as it was not standard (reported by Roberto Nibali) modified files: ChangeLog src/Makefile.am src/cfg-lex.l 2005-07-26 09:23:24 GMT Balazs Scheidler patch-44 Summary: use the same code path for SOCK_STREAM and SOCK_DGRAM sockets Revision: syslog-ng--mainline--2.0--patch-44 2005-07-26 Balazs Scheidler * src/afsocket.c (afsocket_sd_init, afsocket_sd_deinit): unified SOCK_STREAM and SOCK_DGRAM code-paths, do not use a separate reader for SOCK_DGRAM, use AFSocketSourceConnection instead for both types, (afsocket_sd_format_persist_name): new function, to format a persistent config name, instead of doing it inline every time modified files: ChangeLog src/afsocket.c src/afsocket.h 2005-07-26 09:21:15 GMT Balazs Scheidler patch-43 Summary: timezone portability fixes for BSDs Revision: syslog-ng--mainline--2.0--patch-43 2005-07-26 Balazs Scheidler * src/misc.c (get_local_timezone_ofs): added a time_t when argument, the timezone will be returned for that given time in UTC, the algorithm to return a timezone does not rely on the timezone and daytime global variables as those are Linux specific * src/macros.c (log_macro_expand): pass the appropriate time for get_local_timezone_ofs() * src/logmsg.c (log_msg_parse, log_msg_init): -"- * src/affile.c (affile_dd_queue): -"- NEWS * NEWS.hu * modified files: ChangeLog src/affile.c src/logmsg.c src/macros.c src/misc.c src/misc.h 2005-07-07 09:43:49 GMT Balazs Scheidler patch-42 Summary: updated NEWS file and version number in configure.in Revision: syslog-ng--mainline--2.0--patch-42 modified files: ChangeLog NEWS configure.in 2005-07-07 09:33:10 GMT Balazs Scheidler patch-41 Summary: fix match references Revision: syslog-ng--mainline--2.0--patch-41 2005-07-07 Balazs Scheidler * src/templates.c (log_template_compile): fix match references not to include the reference number itself modified files: ChangeLog src/templates.c 2005-07-07 09:15:47 GMT Balazs Scheidler patch-40 Summary: fixed possible memory/fd leak when a filename contains macros Revision: syslog-ng--mainline--2.0--patch-40 2005-07-07 Balazs Scheidler * src/logwriter.c (log_writer_deinit): fixed memory/fd leak, unref self->source as well as destroy it modified files: ChangeLog src/logwriter.c 2005-06-30 08:58:24 GMT Balazs Scheidler patch-39 Summary: fixed use_time_recvd() option handling, documentation updates Revision: syslog-ng--mainline--2.0--patch-39 2005-06-30 Balazs Scheidler * doc/reference/syslog-ng.xml: updated documentation, removed non-existing template timezone option, separate Macros section, added a table on common destination options, added prefixed time related macros without documentation, added DEPRECATED notice to use_time_recvd(), added documentation on ts_format * src/affile.c: use the value for the global use_time_recvd() option when expanding a filename * src/logwriter.c: use the value for the global use_time_recvd() option when expanding the log message modified files: ChangeLog doc/reference/syslog-ng.xml src/affile.c src/affile.h src/logwriter.c src/logwriter.h 2005-06-27 09:27:36 GMT Balazs Scheidler patch-38 Summary: fix file/directory permission handling Revision: syslog-ng--mainline--2.0--patch-38 2005-06-27 Balazs Scheidler * src/affile.c (affile_dw_init): use the file/dir permissions set by the user modified files: ChangeLog src/affile.c 2005-06-27 09:13:38 GMT Balazs Scheidler patch-37 Summary: removed a nested function from affile.c Revision: syslog-ng--mainline--2.0--patch-37 2005-06-27 Balazs Scheidler * src/affile.c (affile_dd_reap_writers): gcc4 does not like nested functions, do not use that modified files: ChangeLog src/affile.c 2005-06-24 07:57:18 GMT Balazs Scheidler patch-36 Summary: added sync() alias for sync_freq() to maintain 1.6.x compatibility Revision: syslog-ng--mainline--2.0--patch-36 2005-06-24 Balazs Scheidler * src/cfg-lex.l: added sync() alias for sync_freq() to maintain compatibility with 1.6.x modified files: ChangeLog src/cfg-lex.l 2005-06-23 08:50:45 GMT Balazs Scheidler patch-35 Summary: added WEEK macro to macro expansion Revision: syslog-ng--mainline--2.0--patch-35 2005-06-23 Balazs Scheidler * src/macros.c, src/macros.h: added support for WEEK, R_WEEK and S_WEEK macros * doc/reference/syslog-ng.xml: added documentation on the WEEK macro NEWS * NEWS.hu * modified files: ChangeLog doc/reference/syslog-ng.xml src/macros.c src/macros.h 2005-06-05 00:00:28 GMT Balazs Scheidler patch-34 Summary: timezone cleanup and fixes, fixed name resolving for socket sources Revision: syslog-ng--mainline--2.0--patch-34 2005-06-05 Balazs Scheidler * doc/reference/syslog-ng.xml: added a section on timezones * src/cfg-grammar.y, src/cfg-lex.l: removed timezone options from templates, removed zone_offset_set variables, a timezone value of -1 indicates unset state instead, (tz_convert) use explicit timezone specification instead, (recv-time-zone, send-time-zone): new keywords to specify default incoming/outgoing timezones * src/affile.c: adapted to the latest log_template_format() changes * src/cfg.c (cfg_tz_convert_value): removed, (cfg_new): initialize sent/recv timezones * src/fdread.c: fixed a bug in recvfrom, the length for the sockaddr structure was incorrectly specified * src/logmsg.c (log_stamp_format): instead of tz_convert use zone_offset, fixed a problem in zone formatting, (log_msg_parse): a value of -1 indicates "unspecified" zone for incoming messages, use get_local_time_zone_ofs() function instead of referencing the timezone variable directly, (log_msg_init): use get_local_time_zone_ofs() * src/logreader.c (log_reader_handle_line): use only set the timezone associated with the incoming message if it has no timezone setting, (log_reader_options_defaults, log_reader_options_init): inherit default value for zone_offset from recv_zone_offset in the global configuration * src/logwriter.c: adapted to log_template_format changes, inherit zone_offset from send_zone_offset * src/macros.c: added STAMP, R_STAMP and S_STAMP macros to represent the message timestamp formatted as specified by the ts_format() global option, (log_macro_expand): added ts_format argument, and the implementation of the STAMP macro * src/misc.c (get_local_timezone_ofs): new function, calculates and returns the current timezone offset in seconds * src/templates.c (log_template_format): added ts_format and zone_offset arguments NEWS * NEWS.hu * modified files: ChangeLog doc/reference/syslog-ng.xml src/affile.c src/cfg-grammar.y src/cfg-lex.l src/cfg.c src/cfg.h src/fdread.c src/logmsg.c src/logmsg.h src/logreader.c src/logreader.h src/logwriter.c src/logwriter.h src/macros.c src/macros.h src/misc.c src/misc.h src/templates.c src/templates.h tests/unit/test_msgparse.c tests/unit/test_template.c 2005-06-04 18:23:57 GMT Balazs Scheidler patch-33 Summary: added static linking option to configure, small fixes Revision: syslog-ng--mainline--2.0--patch-33 2005-06-04 Balazs Scheidler * configure.in: added --enable-static-linking option * src/cfg-lex.l: fixed problem that caused keyword recognition problems, words that began with a reserved word were erroneously recognized as the reserved word (user vs usertty) * src/cfg.c: added error checking for file_template and proto_template options * src/logmsg.c (log_msg_init): always set frac_present to TRUE, (log_msg_parse): frac_present is set to FALSE if there was a timestamp which did not contain fractions removed files: .arch-ids/aclocal.m4.id aclocal.m4 modified files: .arch-inventory ChangeLog configure.in src/cfg-grammar.y src/cfg-lex.l src/cfg.c src/logmsg.c src/syslog-ng.h 2005-05-19 06:44:44 GMT Balazs Scheidler patch-32 Summary: configure.in and some warning fixes Revision: syslog-ng--mainline--2.0--patch-32 2005-05-19 Balazs Scheidler * configure.in: removed no-define from AM_INIT_AUTOMAKE as this made PACKAGE and VERSION preprocessor symbols undefined * src/macros.c: fixed uninitialized variable for MSGONLY processing * src/cfg.c: fixed two type-punned pointer references modified files: ChangeLog configure.in src/cfg.c src/macros.c 2005-05-19 06:41:45 GMT Balazs Scheidler patch-31 Summary: treat use_fqdn correctly when getting local hostname Revision: syslog-ng--mainline--2.0--patch-31 2005-05-19 Balazs Scheidler * src/misc.c (getlonghostname): new function, returns the fully qualified domain name for localhost, (resolve_hostname): use the new getlonghostname, if use_fqdn was TRUE NEWS * NEWS.hu * modified files: ChangeLog src/misc.c src/misc.h 2005-04-27 08:09:44 GMT Balazs Scheidler patch-30 Summary: cleaned up tla inventory files Revision: syslog-ng--mainline--2.0--patch-30 new files: .arch-ids/.arch-inventory.id .arch-inventory src/.arch-ids/.arch-inventory.id src/.arch-inventory modified files: ChangeLog {arch}/=tagging-method 2005-04-27 08:06:42 GMT Balazs Scheidler patch-29 Summary: Solaris portability fixes Revision: syslog-ng--mainline--2.0--patch-29 2005-04-27 Balazs Scheidler * configure.in: added ld detection code to discover static linking arguments * tests/unit/test_msgparse.c: added * tests/unit/Makefile.am: instead of noinst, use check prefix to avoid building the testprograms during regular builds modified files: ChangeLog configure.in tests/unit/Makefile.am tests/unit/test_msgparse.c 2005-04-21 08:51:33 GMT Balazs Scheidler patch-28 Summary: fixed a docbug in doc/reference/syslog-ng.xml Revision: syslog-ng--mainline--2.0--patch-28 modified files: ChangeLog doc/reference/syslog-ng.xml 2005-04-16 11:12:27 GMT Balazs Scheidler patch-27 Summary: added dist.conf and added automatic substitution of some dynamic variables in the documentation Revision: syslog-ng--mainline--2.0--patch-27 new files: .arch-ids/dist.conf.in.id dist.conf.in doc/.arch-ids/docvars.xml.in.id doc/docvars.xml.in modified files: ChangeLog configure.in doc/Makefile.am doc/reference/syslog-ng.xml 2005-04-16 10:11:49 GMT Balazs Scheidler patch-26 Summary: removed "reference/" the root path for the reference syslog-ng.html.tar.gz Revision: syslog-ng--mainline--2.0--patch-26 modified files: ChangeLog doc/Makefile.am 2005-04-15 08:10:10 GMT Balazs Scheidler patch-25 Summary: Configure fix to --enable-dynamic-linking Revision: syslog-ng--mainline--2.0--patch-25 2005-04-15 Balazs Scheidler * configure.in: do not enforce static glib if --enable-dynamic-linking was specified modified files: ChangeLog configure.in 2005-04-03 11:24:28 GMT Balazs Scheidler patch-24 Summary: fixed release numbers in NEWS Revision: syslog-ng--mainline--2.0--patch-24 modified files: ChangeLog NEWS 2005-04-03 11:22:50 GMT Balazs Scheidler patch-23 Summary: updated NEWS file, bumped version to 1.9.4 Revision: syslog-ng--mainline--2.0--patch-23 modified files: ChangeLog NEWS configure.in 2005-04-03 11:21:55 GMT Balazs Scheidler patch-22 Summary: improved configure tests Revision: syslog-ng--mainline--2.0--patch-22 2005-04-03 Balazs Scheidler * configure.in: improved configure tests modified files: ChangeLog configure.in 2005-03-04 15:53:33 GMT Balazs Scheidler patch-21 Summary: added template unit tests Revision: syslog-ng--mainline--2.0--patch-21 new files: tests/unit/.arch-ids/test_template.c.id tests/unit/test_template.c modified files: ChangeLog 2005-03-04 15:53:16 GMT Balazs Scheidler patch-20 Summary: fixed reference generation Revision: syslog-ng--mainline--2.0--patch-20 modified files: ChangeLog doc/Makefile.am 2005-02-28 16:45:16 GMT Balazs Scheidler patch-19 Summary: Fixed (filename, logoutput) template compilation Revision: syslog-ng--mainline--2.0--patch-19 2005-02-28 Balazs Scheidler * src/templates.c (log_template_compile, log_template_format): fixed a problem in template comilation as it messed up the formatted string modified files: ChangeLog configure.in src/Makefile.am src/syslog-ng.conf src/templates.c tests/unit/Makefile.am 2005-02-28 08:57:20 GMT Balazs Scheidler patch-18 Summary: Changed g_queue_get_length to g_queue_is_empty as it makes syslog-ng compatible with glib 2.2 Revision: syslog-ng--mainline--2.0--patch-18 2005-02-28 Balazs Scheidler * src/afinter.c: instead of using "!!g_queue_get_length()" use "!g_queue_is_empty()" modified files: ChangeLog src/afinter.c 2005-02-12 23:05:09 GMT Balazs Scheidler patch-17 Summary: Updated documentation (manpages) Revision: syslog-ng--mainline--2.0--patch-17 modified files: ChangeLog configure.in doc/man/syslog-ng.8 doc/man/syslog-ng.conf.5 src/main.c 2005-01-22 00:50:50 GMT Balazs Scheidler patch-16 Summary: removed doc/reference/make.sh from dist as it is not needed Revision: syslog-ng--mainline--2.0--patch-16 modified files: ChangeLog doc/Makefile.am 2005-01-22 00:48:47 GMT Balazs Scheidler patch-15 Summary: added some missing files to tla Revision: syslog-ng--mainline--2.0--patch-15 new files: doc/.arch-ids/Makefile.am.id doc/Makefile.am doc/examples/.arch-ids/=id doc/examples/.arch-ids/syslog-ng.conf.sample.id doc/examples/.arch-ids/syslog-ng.conf.solaris.id doc/examples/syslog-ng.conf.sample doc/examples/syslog-ng.conf.solaris doc/man/.arch-ids/=id doc/man/.arch-ids/syslog-ng.8.id doc/man/.arch-ids/syslog-ng.conf.5.id doc/man/syslog-ng.8 doc/man/syslog-ng.conf.5 doc/reference/.arch-ids/=id doc/reference/.arch-ids/syslog-ng.xml.id doc/reference/.arch-ids/syslog-ng.xsl.id doc/reference/syslog-ng.xml doc/reference/syslog-ng.xsl modified files: ChangeLog new directories: doc/examples doc/examples/.arch-ids doc/man doc/man/.arch-ids doc/reference doc/reference/.arch-ids 2005-01-22 00:47:35 GMT Balazs Scheidler patch-14 Summary: Updated NEWS file, released syslog-ng 1.9.3 Revision: syslog-ng--mainline--2.0--patch-14 2005-01-22 Balazs Scheidler * NEWS: updated with 1.9.3 release information * configure.in: bumped version to 1.9.3 modified files: ChangeLog NEWS configure.in 2005-01-22 00:32:06 GMT Balazs Scheidler patch-13 Summary: added automatic regeneration of the ChangeLog file Revision: syslog-ng--mainline--2.0--patch-13 new files: .arch-ids/ChangeLog.id ChangeLog 2005-01-22 00:27:18 GMT Balazs Scheidler patch-12 Summary: Readded and updated documentation from 1.6 Revision: syslog-ng--mainline--2.0--patch-12 2005-01-22 Balazs Scheidler * src/cfg-lex.l: renamed padding to pad_size to make it compatible with 1.6.x, the '-' character in keywords is taken equivalent to '_', fixed C code indentation to match GNU coding style new files: doc/.arch-ids/=id doc/security/.arch-ids/=id doc/security/.arch-ids/bof-2002-09-27.txt.id doc/security/.arch-ids/dos-2000-11-22.txt.id doc/security/bof-2002-09-27.txt doc/security/dos-2000-11-22.txt modified files: ChangeLog.0 Makefile.am configure.in src/cfg-grammar.y src/cfg-lex.l tests/functional/Makefile.am renamed files: .arch-ids/ChangeLog.id ==> .arch-ids/ChangeLog.0.id ChangeLog ==> ChangeLog.0 new directories: doc doc/.arch-ids doc/security doc/security/.arch-ids 2005-01-16 17:48:51 GMT Balazs Scheidler patch-11 Summary: added some missing files to tla Revision: syslog-ng--mainline--2.0--patch-11 new files: tests/functional/.arch-ids/=id tests/functional/.arch-ids/Makefile.am.id tests/functional/.arch-ids/func_test.py.id tests/functional/Makefile.am tests/functional/func_test.py tests/unit/.arch-ids/Makefile.am.id tests/unit/.arch-ids/test_msgparse.c.id tests/unit/Makefile.am tests/unit/test_msgparse.c new directories: tests/functional tests/functional/.arch-ids 2005-01-16 17:47:43 GMT Balazs Scheidler patch-10 Summary: added copyright info, beginnings of a testsuite, fixed some configure problems Revision: syslog-ng--mainline--2.0--patch-10 2005-01-16 Balazs Scheidler * configure.in: take CFLAGS environment variable into consideration when running configure, link eventlog and glib statically * src/fdread.c, src/fdwrite.c: handle EINTR by repeating the read system call * src/logreader, src/logwriter.c: handle EAGAIN correctly new files: .arch-ids/COPYING.id COPYING tests/.arch-ids/Makefile.am.id tests/Makefile.am removed files: tests/.arch-ids/test_msgparse.c.id tests/Makefile.am tests/test_msgparse.c modified files: README configure.in src/Makefile.am src/fdread.c src/fdwrite.c src/logreader.c src/logwriter.c renamed files: tests/.arch-ids/Makefile.am.id ==> tests/unit/.arch-ids/=id new directories: tests/unit tests/unit/.arch-ids 2005-01-15 19:19:05 GMT Balazs Scheidler patch-9 Summary: Set nonblocking mode for g_accepted sockets Revision: syslog-ng--mainline--2.0--patch-9 2005-01-15 Balazs Scheidler * src/afsocket.c (afsocket_sd_accept): added g_fd_set_nonblock for new sockets modified files: src/afsocket.c 2005-01-09 14:34:31 GMT Balazs Scheidler patch-8 Summary: fixed possible deadlocking on the internal message pipe Revision: syslog-ng--mainline--2.0--patch-8 2005-01-09 Balazs Scheidler * src/logsource.c: new file, separated flow control related functions from logreader * src/logreader.c: LogReader is derived from LogSource * src/afinter.c: substituted the pipe used for internal messages with a GQueue new files: src/.arch-ids/logsource.c.id src/.arch-ids/logsource.h.id src/logsource.c src/logsource.h modified files: src/Makefile.am src/afinter.c src/cfg-grammar.y src/logmsg.c src/logmsg.h src/logreader.c src/logreader.h src/messages.c src/messages.h 2005-01-05 12:02:01 GMT Balazs Scheidler patch-7 Summary: Fixed a couple of Solaris portability problems Revision: syslog-ng--mainline--2.0--patch-7 2005-01-05 Balazs Scheidler * configure.in: added checks for -ldoor, -lsocket, -lnsl and getopt.h * other files: fixed a couple of Solaris specific warnings modified files: configure.in src/cfg.c src/filter.c src/gsockaddr.c src/logmsg.c src/macros.c src/main.c 2005-01-03 21:12:30 GMT Balazs Scheidler patch-6 Summary: Updated NEWS file and released 1.9.2 Revision: syslog-ng--mainline--2.0--patch-6 modified files: NEWS 2004-12-31 14:38:06 GMT Balazs Scheidler patch-5 Summary: added missing macros and brace support in macro expansion Revision: syslog-ng--mainline--2.0--patch-5 2004-12-31 Balazs Scheidler * src/macros.c: added PRI and MSGONLY macros * src/templates.c: added support for braces around macros for $example: "{MSG}" modified files: ChangeLog src/macros.c src/macros.h src/syslog-ng.conf src/templates.c 2004-12-28 23:23:29 GMT Balazs Scheidler patch-4 Summary: fixed couple of bugs Revision: syslog-ng--mainline--2.0--patch-4 2004-12-29 Balazs Scheidler * src/afprog.c (afprogram_dd_init): call setsid before launching child, (afprogram_dd_deinit): deinit & unref self->writer here instead of in afprogram_dd_free, * src/center.c (log_center_queue): do not supply self as user_data pointer to the ack_block callback as that would require adding a reference to self * src/dgroup.c (log_dest_group_queue): do not supply self as user_data pointer to the ack_block callback as that would require adding a reference to self * src/logreader.c: instead of using self->window_size use self->options->window_size so that the window is shared between all LogReaders using the same options, (log_reader_handle_line): add reference to self before supplying it as an argument to the ack_block callback function, (log_reader_msg_ack): unref the supplied logreader argument modified files: ChangeLog src/afprog.c src/center.c src/cfg-lex.l src/dgroup.c src/logreader.c src/logreader.h src/logwriter.c 2004-12-27 23:27:07 GMT Balazs Scheidler patch-3 Summary: Added a lot of copyright header, docstrings, and some fixes Revision: syslog-ng--mainline--2.0--patch-3 2004-12-27 Balazs Scheidler * src/afsocket.c (afsocket_sd_deinit): break circular reference between self->reader and self, (afsocket_sd_notify): do not destroy/unref sender in NC_CLOSE, as afsocket_sd_close_connection already does that, (afsocket_sd_init, afsocket_sd_deinit): removed static, (afsocket_sd_free_instance): renamed from afsocket_sd_free, removed static, created a new afsocket_sd_free function at the same time which is set as the free_fn of AFSocketSourceDriver * src/afunix.c: implemented user/group/perm settings * src/cfg-grammar.y: added support for log-prefix * src/cfg.c: changed default timestamp format to BSD for compatibility * src/filter.c: fixed AND and OR operator evaluation, the operands were not correctly saved at initialization time, thus NULL was referenced at evaluation time * src/logreader.c: added log_prefix support for all log readers * src/logwriter.c: use log_msg_drop instead of a simple log_msg_unref * src/main.c: fixed SIGCHLD handling, loop while waitpid returns > 0, added tzset() call removed files: src/.arch-ids/cfg-grammar.c.id src/.arch-ids/cfg-grammar.h.id src/.arch-ids/cfg-lex.c.id src/cfg-grammar.c src/cfg-grammar.h src/cfg-lex.c modified files: ChangeLog configure.in src/affile.c src/affile.h src/afinet.c src/afinet.h src/afinter.c src/afinter.h src/afprog.c src/afprog.h src/afsocket.c src/afsocket.h src/afstreams.c src/afstreams.h src/afunix.c src/afunix.h src/afuser.c src/afuser.h src/center.c src/center.h src/cfg-grammar.y src/cfg-lex.l src/cfg.c src/cfg.h src/children.c src/children.h src/dgroup.c src/dgroup.h src/driver.c src/driver.h src/fdread.c src/fdread.h src/fdwrite.c src/fdwrite.h src/filter.c src/filter.h src/gsockaddr.c src/gsockaddr.h src/logmsg.c src/logmsg.h src/logpipe.c src/logpipe.h src/logreader.c src/logreader.h src/logwriter.c src/logwriter.h src/macros.c src/macros.h src/main.c src/memtrace.h src/messages.c src/messages.h src/misc.c src/misc.h src/sdriver.c src/sgroup.c src/sgroup.h src/syslog-names.c src/syslog-names.h src/syslog-ng.h src/templates.c src/templates.h src/utils.c src/utils.h 2004-12-26 23:24:29 GMT Balazs Scheidler patch-2 Summary: Fixed a lot of memory leaks Revision: syslog-ng--mainline--2.0--patch-2 2004-12-27 Balazs Scheidler * src/affile.c (affile_sd_deinit): make sure to break circular reference between self->reader and self, fixes possible memory leak, (affile_sd_free): call log_drv_free_instance * src/afinter.c (afinter_sd_deinit): break circular reference between self->reader and self * src/afprog.c (afprog_sd_free): added log_drv_free_instance * src/afsocket.c (afsocket_sd_deinit): break circular reference between self->reader and self, (afsocket_sd_free): added log_drv_free_instance, (afsocket_dd_free): -"- * src/afuser.c (afuser_dd_queue): free queued message, (afuser_dd_free): added log_drv_free_instance * src/cfg-grammar.y: unref log driver after appending to avoid memory leaks * src/cfg.c (cfg_reload_config): fixed possible memory leak when cfg_init fails (free persist), (persist_config_free): added missing free for hashtable * src/dgroup.c (log_dest_group_queue): make sure each driver gets its own reference to msg as each will free it on its own, also added an explicit unref at the end of the function (log_dest_group_new): added missing call to log_pipe_init_instance * src/gsockaddr.c: removed all low-level g_message invocation, errors should be reported by the caller * src/logpipe.c: added assertions to _ref and _unref * src/main.c (main_loop_run): added a missing g_main_loop_unref to avoid memory leaks, (main): call msg_syslog_started at the end of initialization to force messages into the system log * src/messages.c (msg_syslog_started): new function to indicate that initialization is finished, messages will be written to stderr instead of the internal() source if syslog is not yet started to let the administrator see important failure messages, (msg_deinit): free the event log context, only close the error pipe if it was really opened modified files: src/affile.c src/afinter.c src/afprog.c src/afsocket.c src/afstreams.c src/afuser.c src/cfg-grammar.c src/cfg-grammar.h src/cfg-grammar.y src/cfg.c src/dgroup.c src/gsockaddr.c src/logpipe.c src/main.c src/messages.c src/messages.h tests/Makefile.am 2004-12-26 20:38:30 GMT Balazs Scheidler patch-1 Summary: Removed CVS files Revision: syslog-ng--mainline--2.0--patch-1 2004-12-26 20:38:05 GMT Balazs Scheidler base-0 Summary: initial import Revision: syslog-ng--mainline--2.0--base-0 (automatically generated log message) new files: AUTHORS ChangeLog Makefile.am NEWS README aclocal.m4 autogen.sh configure.in src/Makefile.am src/affile.c src/affile.h src/afinet.c src/afinet.h src/afinter.c src/afinter.h src/afprog.c src/afprog.h src/afsocket.c src/afsocket.h src/afstreams.c src/afstreams.h src/afunix.c src/afunix.h src/afuser.c src/afuser.h src/center.c src/center.h src/cfg-grammar.c src/cfg-grammar.h src/cfg-grammar.y src/cfg-lex.c src/cfg-lex.l src/cfg.c src/cfg.h src/children.c src/children.h src/dgroup.c src/dgroup.h src/driver.c src/driver.h src/fdread.c src/fdread.h src/fdwrite.c src/fdwrite.h src/filter.c src/filter.h src/gsockaddr.c src/gsockaddr.h src/logmsg.c src/logmsg.h src/logpipe.c src/logpipe.h src/logreader.c src/logreader.h src/logwriter.c src/logwriter.h src/macros.c src/macros.h src/main.c src/memtrace.c src/memtrace.h src/messages.c src/messages.h src/misc.c src/misc.h src/sdriver.c src/sgroup.c src/sgroup.h src/syslog-names.c src/syslog-names.h src/syslog-ng.conf src/syslog-ng.h src/templates.c src/templates.h src/todo src/utils.c src/utils.h tests/Makefile.am tests/test_msgparse.c syslog-ng-syslog-ng-3.13.2/doc/ChangeLog.2000066400000000000000000002517311321171025300201250ustar00rootroot00000000000000# do not edit -- automatically generated by arch changelog # arch-tag: automatic-ChangeLog--devel@balabit.hu--other-1/syslog-ng--mainline--2.0 # 2007-04-06 09:59:15 GMT Balazs Scheidler patch-149 Summary: use stat instead of seek to determine file size Revision: syslog-ng--mainline--2.0--patch-149 * src/logreader.c (log_reader_fd_check): remove lseek based file size determination and use lseek instead, it is not glibc that is buggy, and although gdb reports invalid contents of the stat results, the program sees them correctly modified files: ChangeLog src/logreader.c 2007-04-06 09:08:49 GMT Balazs Scheidler patch-148 Summary: added support for logrotation in file sources Revision: syslog-ng--mainline--2.0--patch-148 2007-04-06 Balazs Scheidler * src/affile.c (affile_sd_open_file): new function, contains the file open code for the source driver, (affile_sd_notify): new function, registered as the notification handler for an affile source, for NC_FILE_MOVED notifications construct a new the log reader and drop the old one, (affile_sd_init): use affile_sd_open_file, (affile_sd_new): register notification handler, tell our LogReader the filename that we are following modified files: ChangeLog src/affile.c src/afsocket.c src/logpipe.h src/logreader.c src/logreader.h src/messages.h 2007-04-05 11:27:02 GMT Balazs Scheidler patch-147 Summary: fixed expansion of utf-8 characters in templates Revision: syslog-ng--mainline--2.0--patch-147 * src/macros.c (result_append): use guchar as the type of the argument instead of gchar * tests/unit/test_templates.c: use utf8 sequences in the message string to ensure that syslog-ng handles them properly modified files: ChangeLog src/macros.c tests/unit/test_template.c 2007-04-04 14:44:29 GMT Balazs Scheidler patch-146 Summary: fixed numeric localport/destport specification Revision: syslog-ng--mainline--2.0--patch-146 * src/afinet.c (afinet_set_port, afinet_sd_set_localport, afinet_dd_set_localport, afinet_dd_set_destport): removed port argument, always use 'service' and check if it's numeric * src/cfg-grammar.y: follow afinet changes modified files: ChangeLog src/afinet.c src/afinet.h src/cfg-grammar.y 2007-04-02 06:53:54 GMT Balazs Scheidler patch-145 Summary: grammar fixes for localport/port/destport parsing options Revision: syslog-ng--mainline--2.0--patch-145 * src/cfg-grammar.y: fixed grammar to parse port related options correctly modified files: ChangeLog src/cfg-grammar.y 2007-03-26 12:28:53 GMT Balazs Scheidler patch-144 Summary: preparations for 2.0.3 release Revision: syslog-ng--mainline--2.0--patch-144 modified files: ChangeLog NEWS VERSION 2007-03-26 12:28:31 GMT Balazs Scheidler patch-143 Summary: increased the minimum value for log_fifo_size to 1000 Revision: syslog-ng--mainline--2.0--patch-143 modified files: ChangeLog src/cfg.c src/logsource.h src/logwriter.c 2007-03-21 16:36:01 GMT Balazs Scheidler patch-142 Summary: fixed dns_cache_hosts() typo in documentation Revision: syslog-ng--mainline--2.0--patch-142 modified files: ChangeLog doc/reference/syslog-ng.xml 2007-03-19 17:41:46 GMT Balazs Scheidler patch-141 Summary: some more message clarification Revision: syslog-ng--mainline--2.0--patch-141 modified files: ChangeLog src/main.c 2007-03-19 17:35:37 GMT Balazs Scheidler patch-140 Summary: clarified internal message severities Revision: syslog-ng--mainline--2.0--patch-140 * src/*.c: clarified the severity value of some log messages generated by syslog-ng modified files: ChangeLog src/affile.c src/cfg-lex.l src/macros.c src/messages.h 2007-03-05 11:33:09 GMT Balazs Scheidler patch-139 Summary: clarified message priorities Revision: syslog-ng--mainline--2.0--patch-139 modified files: ChangeLog src/affile.c src/afinet.c src/cfg.c src/logwriter.c src/stats.c 2007-03-04 11:03:22 GMT Balazs Scheidler patch-138 Summary: added support for remembering input file positions Revision: syslog-ng--mainline--2.0--patch-138 * configure.in: added LARGEFILE_SOURCE & FILE_OFFSET_BITS to CPPFLAGS, export localstatedir to syslog-ng, * src/affile.c (affile_sd_format_persist_name): new function, formats the persistent name associated with the file source, (affile_sd_init): check if the current file position is available and set it if it is, (affile_sd_deinit): save the current file position, * src/afsocket.c (afsocket_sd_kill_connection_list): new function, frees a connection list, (afsocket_sd_deinit): fixed a possible SIGSEGV, a GList was freed as an AFSocketSourceDriver, I wonder how this got unnoticed so far, * src/cfg.c (persist_config_add_entry): new function, (persist_config_add): use the new add_entry function, (persist_config_add_survivor): new function, adds a surviving entry, (PersistentConfig): added saving/loading persistent config entries, * src/logreader.c (log_reader_watch_new): don't seek the file to the end-of-file now as proper file position is recovered, (log_reader_set_pos, log_reader_get_pos): new functions * src/main.c (main): added --ignore-persistent option, use a persistent configuration object around stop/start to save/restore file position information modified files: ChangeLog configure.in src/affile.c src/afsocket.c src/cfg.c src/cfg.h src/logreader.c src/logreader.h src/main.c src/syslog-ng.h 2007-03-03 14:01:24 GMT Balazs Scheidler patch-137 Summary: tightened LogMessage struct, added support for more than 9 match groups Revision: syslog-ng--mainline--2.0--patch-137 * src/logmsg.h (LogMessage): structure tightened a bit, avoid double-referencing various message-parts by inlining GString declarations, instead of allocating them at runtime to be more cache friendly, use 8 bit values for ref_cnt, flags, pri; re_matches is allocated at runtime to allow more matches * src/filter.c (filter_re_eval): dynamically allocate the msg->re_matches array, follow LogMessage changes * src/templates.c (log_template_compile): support ${} syntax for regex match replacements to allow more than 9 matches * src/afuser.c, src/logreader.c, src/logwriter.c, src/sgroup.c, src/test_msgparse.c, src/test_template.c: follow LogMessage changes modified files: ChangeLog src/afuser.c src/filter.c src/logmsg.c src/logmsg.h src/logreader.c src/logwriter.c src/macros.c src/sgroup.c src/templates.c tests/unit/test_msgparse.c tests/unit/test_template.c 2007-02-28 09:21:01 GMT Balazs Scheidler patch-136 Summary: clarified SIGTERM message Revision: syslog-ng--mainline--2.0--patch-136 * src/main.c (main_loop_run): clarified message about the reception of a SIGTERM or SIGINT signal modified files: ChangeLog src/main.c 2007-02-28 09:19:28 GMT Balazs Scheidler patch-135 Summary: updated copyright strings Revision: syslog-ng--mainline--2.0--patch-135 modified files: ChangeLog src/affile.c src/affile.h src/afinet.c src/afinet.h src/afinter.c src/afinter.h src/afprog.c src/afprog.h src/afsocket.c src/afsocket.h src/afstreams.c src/afstreams.h src/afunix.c src/afunix.h src/afuser.c src/afuser.h src/center.c src/center.h src/cfg-lex.l src/cfg.c src/cfg.h src/children.c src/children.h src/dgroup.c src/dgroup.h src/dnscache.c src/dnscache.h src/driver.c src/driver.h src/fdread.c src/fdread.h src/fdwrite.c src/fdwrite.h src/filter.c src/filter.h src/gsockaddr.c src/gsockaddr.h src/logmsg.c src/logmsg.h src/logpipe.c src/logpipe.h src/logreader.c src/logreader.h src/logsource.c src/logsource.h src/logwriter.c src/logwriter.h src/macros.c src/macros.h src/main.c src/memtrace.c src/memtrace.h src/messages.c src/messages.h src/misc.c src/misc.h src/sgroup.c src/sgroup.h src/stats.c src/stats.h src/syslog-names.c src/syslog-names.h src/syslog-ng.h src/templates.c src/templates.h src/utils.c src/utils.h 2007-02-28 09:19:00 GMT Balazs Scheidler patch-134 Summary: implemented TCP wrapper support Revision: syslog-ng--mainline--2.0--patch-134 * configure.in: added tests for libwrap * src/afsocket.c: added support for libwrap access control modified files: ChangeLog configure.in src/afsocket.c 2007-02-12 09:09:08 GMT Balazs Scheidler patch-133 Summary: added endutent() to usertty destination Revision: syslog-ng--mainline--2.0--patch-133 * src/afuser.c (afuser_dd_queue): added missing endutent call() modified files: ChangeLog src/afuser.c 2007-02-12 09:02:37 GMT Balazs Scheidler patch-132 Summary: removed 1024 byte limitation on internal messages Revision: syslog-ng--mainline--2.0--patch-132 * src/messages.c (msg_send_internal_message): use a dynamically allocated buffer instead of a buffer with a fixed size on the stack modified files: ChangeLog src/messages.c 2007-02-12 09:01:43 GMT Balazs Scheidler patch-131 Summary: added testcases for 2007 DST changes Revision: syslog-ng--mainline--2.0--patch-131 * tests/unit/test_zone.c (main): added testcases for 2007 DST changes in the USA modified files: ChangeLog tests/unit/test_zone.c 2007-02-03 17:24:40 GMT Balazs Scheidler patch-130 Summary: added dist.conf to dist Revision: syslog-ng--mainline--2.0--patch-130 modified files: ChangeLog Makefile.am configure.in 2007-02-03 17:21:21 GMT Balazs Scheidler patch-129 Summary: further portability fixes Revision: syslog-ng--mainline--2.0--patch-129 * configure.in: added check for -lresolv modified files: ChangeLog configure.in 2007-02-03 17:16:17 GMT Balazs Scheidler patch-128 Summary: portability fixes for platforms without IPv6 support Revision: syslog-ng--mainline--2.0--patch-128 * configure.in: added checks for struct sockaddr_storage * src/cfg-grammar.y: make sure it compiles even if AF_INET6 is not defined * src/cfg-lex.l: don't define udp6/tcp6 keywords if ENABLE_IPV6 is not defined * src/dnscache.c: added conditional blocks for IPv6 related code * src/misc.c (resolve_hostname): -"- * src/fdread.c (fd_do_read): use plain "struct sockaddr" if struct sockaddr_storage is not defined modified files: ChangeLog configure.in src/cfg-grammar.y src/cfg-lex.l src/dnscache.c src/fdread.c src/misc.c 2007-02-03 16:39:08 GMT Balazs Scheidler patch-127 Summary: implemented spoof-source support for both ipv4/ipv6 Revision: syslog-ng--mainline--2.0--patch-127 * configure.in: added --with-libnet and --enable-spoof-source options * src/afinet.c (afinet_dd_set_spoof_source): new function, called from the parser to enable spoof-source, (afinet_dd_init): new function, (afinet_dd_construct_ipv4_packet): -"-, (afinet_dd_construct_ipv6_packet): -"-, (afinet_dd_queue): -"-, (affile_dd_new): register new init/queue methods, * src/sgroup.h, src/dgroup.h: renamed ref/unref functions for consistency * src/cfg-lex.l, src/cfg-grammar.y: added spoof-source option * src/logwriter.c (log_writer_format_log): removed static as it is directly used by spoof-source to format messages modified files: ChangeLog README configure.in src/afinet.c src/afinet.h src/afsocket.h src/center.c src/cfg-grammar.y src/cfg-lex.l src/dgroup.h src/logwriter.c src/logwriter.h src/sgroup.h 2007-01-30 13:08:22 GMT Balazs Scheidler patch-126 Summary: added netinet/in.h to afinet.c Revision: syslog-ng--mainline--2.0--patch-126 * src/afinet.c: added inclusion of as it caused problems on HP-UX modified files: ChangeLog src/afinet.c 2007-01-29 08:56:55 GMT Balazs Scheidler patch-125 Summary: added check for getutent in configure Revision: syslog-ng--mainline--2.0--patch-125 * configure.in: added getutent() check modified files: ChangeLog configure.in src/afuser.c 2007-01-29 08:49:55 GMT Balazs Scheidler patch-124 Summary: integrated AIX packaging fixes from dev-folti Revision: syslog-ng--mainline--2.0--patch-124 Patches applied: * devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-2 Fixed: AIX5.2 packaging support. (fixes: #10375) * devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-3 Fixes: added libevtlog-dev build dependency. (fixes: #10375) * devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-5 Fixed: RPM packaging for 2.0. (fixes: #nobug) * devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-7 Refresh: Fixed: AIX5.2 packaging support. (fixes: #10375) * devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-8 Refresh: Fixes: added libevtlog-dev build dependency. (fixes: #10375) * devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-9 Refresh: Fixed: RPM packaging for 2.0. (fixes: #nobug) * devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-10 Fixed: removed duplicated install commanands from spec file. (fixes #nobug) new files: contrib/aix-packaging/.arch-ids/=id contrib/aix-packaging/.arch-ids/syslog-ng.conf.id contrib/aix-packaging/syslog-ng.conf modified files: ChangeLog contrib/Makefile.am syslog-ng.spec.bb.in new directories: contrib/aix-packaging contrib/aix-packaging/.arch-ids new patches: devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-2 devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-3 devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-5 devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-7 devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-8 devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-9 devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-10 2007-01-29 08:48:19 GMT Balazs Scheidler patch-123 Summary: fixed possible crash in usertty() driver Revision: syslog-ng--mainline--2.0--patch-123 * src/afuser.c (afuser_dd_queue): don't ack the message if flow control was off (fixes possible crash reported by Bryan Henderson) modified files: ChangeLog src/afuser.c 2007-01-26 09:23:49 GMT Pal Tamas patch-122 Summary: Synced to test Revision: syslog-ng--mainline--2.0--patch-122 modified files: ChangeLog 2007-01-26 07:59:36 GMT Balazs Scheidler patch-121 Summary: missed version change Revision: syslog-ng--mainline--2.0--patch-121 modified files: ChangeLog VERSION 2007-01-26 07:58:21 GMT Balazs Scheidler patch-120 Summary: preparations for 2.0.2 Revision: syslog-ng--mainline--2.0--patch-120 modified files: ChangeLog NEWS 2007-01-23 13:44:15 GMT Balazs Scheidler patch-119 Summary: fixed handling utmp entries where a full path is included as tty name Revision: syslog-ng--mainline--2.0--patch-119 * src/afuser.c (afuser_dd_queue): check if ut->ut_line starts with a '/' and use it directly if it does, otherwise prepend '/dev/' as before. modified files: ChangeLog src/afuser.c 2007-01-19 21:00:06 GMT Balazs Scheidler patch-118 Summary: fixed trailing \0 and \n characters in messages received on dgram transport Revision: syslog-ng--mainline--2.0--patch-118 * src/logmsg.c (log_msg_parse): remove trailing \n and \0 characters which are often added to the end of incoming datagrams modified files: ChangeLog src/logmsg.c 2007-01-07 16:51:40 GMT Balazs Scheidler patch-117 Summary: fixed parsing group information when not enclosed in quotes Revision: syslog-ng--mainline--2.0--patch-117 * src/cfg-grammar.y (string_or_number): use non-terminal string instead of STRING to support non-quoted group specification modified files: ChangeLog src/cfg-grammar.y 2007-01-07 16:46:34 GMT Balazs Scheidler patch-116 Summary: fixed IPv6 related portability problem in DNS cache Revision: syslog-ng--mainline--2.0--patch-116 * src/dnscache.c (dns_cache_key_hash): don't use the unportable s6_addr32 member in struct in6_addr, use an explicit cast instead modified files: ChangeLog src/dnscache.c 2006-12-22 10:07:57 GMT Balazs Scheidler patch-115 Summary: added tcp-keep-alive keyword for compatibility Revision: syslog-ng--mainline--2.0--patch-115 modified files: ChangeLog doc/reference/syslog-ng.xml src/cfg-lex.l 2006-12-22 10:06:01 GMT Balazs Scheidler patch-114 Summary: updated documentation with so_keepalive option Revision: syslog-ng--mainline--2.0--patch-114 modified files: ChangeLog doc/reference/syslog-ng.xml 2006-12-22 10:01:22 GMT Balazs Scheidler patch-113 Summary: added so_keepalive support Revision: syslog-ng--mainline--2.0--patch-113 * src/cfg-grammar.y: added KW_SO_KEEPALIVE keyword, (socket_option): added KW_SO_KEEPALIVE rule * src/afsocket.h (SocketOptions): added keepalive member, * src/afsocket.c (afsocket_setup_socket): set SO_KEEPALIVE socket option based on the keepalive parameter modified files: ChangeLog src/afsocket.c src/afsocket.h src/cfg-grammar.y src/cfg-lex.l 2006-12-21 08:48:42 GMT Balazs Scheidler patch-112 Summary: fixed XML syntax error in refguide Revision: syslog-ng--mainline--2.0--patch-112 modified files: ChangeLog doc/reference/syslog-ng.xml 2006-12-21 08:46:42 GMT Balazs Scheidler patch-111 Summary: bumped version to 2.0.1 Revision: syslog-ng--mainline--2.0--patch-111 modified files: ChangeLog VERSION 2006-12-21 08:45:35 GMT Balazs Scheidler patch-110 Summary: updated documentation with new dns cache options Revision: syslog-ng--mainline--2.0--patch-110 modified files: ChangeLog doc/reference/syslog-ng.xml 2006-12-21 08:39:23 GMT Balazs Scheidler patch-109 Summary: NEWS preparations for syslog-ng 2.0.1 Revision: syslog-ng--mainline--2.0--patch-109 modified files: ChangeLog NEWS 2006-12-21 08:31:08 GMT Balazs Scheidler patch-108 Summary: obsoleted remove_if_older option in favour of overwrite_if_older Revision: syslog-ng--mainline--2.0--patch-108 * src/affile.{c,h}: renamed remove_if_older references to overwrite_if_older * src/cfg-lex.l, src/cfg-grammar.y: -"- * doc/reference/syslog-ng.xml: added overwrite_if_older documentation, added note about obsoleted remove_if_older() modified files: ChangeLog doc/reference/syslog-ng.xml src/affile.c src/affile.h src/cfg-grammar.y src/cfg-lex.l 2006-12-21 08:21:49 GMT Balazs Scheidler patch-107 Summary: documentation updates on remove_if_older() Revision: syslog-ng--mainline--2.0--patch-107 modified files: ChangeLog doc/reference/syslog-ng.xml 2006-12-18 09:01:46 GMT Balazs Scheidler patch-106 Summary: added include misc.h to afstreams.c Revision: syslog-ng--mainline--2.0--patch-106 * src/afstreams.c: added #include "misc.h" modified files: ChangeLog src/afstreams.c 2006-12-11 09:42:40 GMT Balazs Scheidler patch-105 Summary: removed bogus timezone error message for correct timezone values Revision: syslog-ng--mainline--2.0--patch-105 * src/cfg.c (cfg_timezone_value): readded erroneously removed return statement which caused an error message for all timezone values modified files: ChangeLog src/cfg.c 2006-12-08 08:40:35 GMT Balazs Scheidler patch-104 Summary: removed 12 hour limitation from timezone offsets Revision: syslog-ng--mainline--2.0--patch-104 * src/cfg.c (cfg_timezone_value): removed 12 hours limitation as offsets may well exceed that value (maximum is 24 hours) * doc/reference/syslog-ng.xml: removed non-existing timezone() option modified files: ChangeLog doc/reference/syslog-ng.xml src/cfg.c 2006-12-02 22:20:39 GMT Balazs Scheidler patch-103 Summary: added minimum version checking for glib/eventlog, also fixed a portability problem with non-gcc compilers in configure Revision: syslog-ng--mainline--2.0--patch-103 modified files: ChangeLog configure.in 2006-11-30 09:49:22 GMT Balazs Scheidler patch-102 Summary: fixed a typo in the documentation, added sys/socket.h to dnscache.c Revision: syslog-ng--mainline--2.0--patch-102 modified files: ChangeLog doc/reference/syslog-ng.xml src/dnscache.c 2006-11-27 10:55:47 GMT Balazs Scheidler patch-101 Summary: fixed the previously messed up commit Revision: syslog-ng--mainline--2.0--patch-101 modified files: ChangeLog src/logmsg.c 2006-11-27 10:52:40 GMT Balazs Scheidler patch-100 Summary: fixed a compilation problem in logmsg.c Revision: syslog-ng--mainline--2.0--patch-100 * src/logmsg.c (log_msg_parse): fixed a bad assignment modified files: ChangeLog src/cfg-grammar.y 2006-11-16 14:15:50 GMT Balazs Scheidler patch-99 Summary: timezone offset calculation fix Revision: syslog-ng--mainline--2.0--patch-99 * src/logmsg.c (log_stamp_format): don't use the absolute value of timezone offset, (log_msg_parse): initialize tm.tm_gmtoff using a call to localtime() instead of using memset(), fixed tv_sec calculation as it was not really UTC which it should've been. * tests/unit/test_msgparse.c: fixed time parsing testcases modified files: ChangeLog src/logmsg.c tests/unit/test_msgparse.c 2006-11-16 13:11:04 GMT Balazs Scheidler patch-98 Summary: fixed GLib static link configure test to work with non-gcc compilers Revision: syslog-ng--mainline--2.0--patch-98 * configure.in: fixed GLib static link configure test to work with non-gcc compilers modified files: ChangeLog configure.in 2006-11-08 14:18:14 GMT Balazs Scheidler patch-97 Summary: fixed up dnscache unit test program Revision: syslog-ng--mainline--2.0--patch-97 modified files: ChangeLog tests/unit/test_dnscache.c 2006-11-08 14:16:23 GMT Balazs Scheidler patch-96 Summary: implemented DNS cache and custom hosts file support Revision: syslog-ng--mainline--2.0--patch-96 * src/cfg-grammar.y: added KW_PERSIST_ONLY, KW_DNS_CACHE_HOSTS keywords, dnsmode rule, removed tripleoption and related options, added * src/cfg-lex.l: added dnscache specific new keywords, * src/cfg.c (cfg_init): added a call to dns_cache_set_params, (cfg_free): free dns_cache_hosts, * src/main.c (main): call dns_cache_init() and dns_cache_destroy() * src/misc.c (resolve_hostname): added DNS cache and persistent-only resolution support * src/sgroup.c (log_source_group_init): save dns cache params, (log_source_group_queue): pass use_dns_cache param to resolve_hostname * src/dnscache.{c,h}: new files new files: src/.arch-ids/dnscache.c.id src/.arch-ids/dnscache.h.id src/dnscache.c src/dnscache.h tests/unit/.arch-ids/test_dnscache.c.id tests/unit/test_dnscache.c modified files: ChangeLog src/Makefile.am src/affile.h src/cfg-grammar.y src/cfg-lex.l src/cfg.c src/cfg.h src/main.c src/misc.c src/misc.h src/sgroup.c src/sgroup.h tests/unit/Makefile.am 2006-11-08 14:11:00 GMT Balazs Scheidler patch-95 Summary: don't fail at startup if network connection is down Revision: syslog-ng--mainline--2.0--patch-95 * src/afsocket.c (afsocket_open_socket): added an error message if socket creation failed, (afsocket_dd_start_reconnect_timer): new function, deregisters and starts a new reconnect timer, (afsocket_dd_connected): use afsocket_dd_start_reconnect_timer, (afsocket_dd_start_connect): renamed from afsocket_dd_reconnect, removed explicit timer registration, (afsocket_dd_reconnect): new function, calls _start_connect and registers the reconnect timer if that fails, (afsocket_dd_init): afsocket_dd_reconnect does not return a value now modified files: ChangeLog src/afsocket.c 2006-11-08 10:10:37 GMT Balazs Scheidler patch-94 Summary: increased listener source priorities Revision: syslog-ng--mainline--2.0--patch-94 * src/syslog-ng.h (LOG_PRIORITY_LISTEN): increased priority to match LOG_PRIORITY_READER as otherwise a continous input flow can starve accept() modified files: ChangeLog src/syslog-ng.h 2006-11-08 09:53:59 GMT Balazs Scheidler patch-93 Summary: set the pipe for program destinations to nonlbocking mode Revision: syslog-ng--mainline--2.0--patch-93 * src/afprog.c (afprogram_dd_init): set the pipe fd to nonblocking mode to avoid a possible hang modified files: ChangeLog src/afprog.c 2006-10-28 16:07:36 GMT Balazs Scheidler patch-92 Summary: implemented the missing remove_if_older option Revision: syslog-ng--mainline--2.0--patch-92 * src/affile.c (affile_dw_init): check if the file exists and is older than the value for remove_if_older, if it is unlink it, (affile_dd_set_remove_if_older): new function to set remove_if_older value, * src/cfg-grammar.y (dest_affile_option): added KW_REMOVE_IF_OLDER rule * src/cfg-lex.l: added keyword for KW_REMOVE_IF_OLDER modified files: ChangeLog src/affile.c src/affile.h src/cfg-grammar.y src/cfg-lex.l 2006-10-28 15:37:15 GMT Balazs Scheidler patch-91 Summary: preparations for 2.0.0 Revision: syslog-ng--mainline--2.0--patch-91 modified files: ChangeLog NEWS VERSION 2006-10-28 07:24:49 GMT Balazs Scheidler patch-90 Summary: fixed process restarting and some other minor fixes Revision: syslog-ng--mainline--2.0--patch-90 * src/afprog.c (afprogram_dd_exit): check that the current pid is equal to the process that was exited, as the EPIPE handling code might have already done our job, (afprogram_dd_init): don't leave the read side of the pipe twice with the process, removed a call to g_fd_set_cloexec() as it's not needed and was too late anyway, should've been before fork, * src/gsockaddr.c (g_sockaddr_unix_format): the kernel sometimes returns only an address family for unix socket names, and we printed a lot of garbage instead of "anonymous" in this case * src/logwriter.c (log_writer_broken): move log_pipe_deinit() before log_pipe_notify(), this was changed in rc3 with a changelog that it should not matter, however it does matter :P as it might have left the writer in an unpolled state modified files: ChangeLog src/afprog.c src/gsockaddr.c src/logwriter.c 2006-10-27 15:15:30 GMT Balazs Scheidler patch-89 Summary: integrated solaris build scripts from dev-folti (fixes: #10358) Revision: syslog-ng--mainline--2.0--patch-89 Patches applied: * devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--base-0 tag of devel@balabit.hu--other-1/syslog-ng--mainline--2.0--patch-87 * devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-1 Added support for solaris 8/9 and rhel 3/4 packaging. (fixes: #10358) new files: .arch-ids/syslog-ng.spec.bb.in.id solbuild/.arch-ids/=id solbuild/.arch-ids/Makefile.am.id solbuild/.arch-ids/admin.id solbuild/.arch-ids/depend.id solbuild/.arch-ids/pkginfo.in.id solbuild/.arch-ids/pkgmaker.sh.id solbuild/.arch-ids/prototype-maker.sh.id solbuild/.arch-ids/rules.conf.id solbuild/.arch-ids/rules.id solbuild/.arch-ids/space.id solbuild/.arch-ids/syslog-ng.init.d.id solbuild/Makefile.am solbuild/admin solbuild/depend solbuild/pkginfo.in solbuild/pkgmaker.sh solbuild/prototype-maker.sh solbuild/rules solbuild/rules.conf solbuild/space solbuild/syslog-ng.init.d syslog-ng.spec.bb.in modified files: ChangeLog Makefile.am configure.in new directories: solbuild solbuild/.arch-ids new patches: devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--base-0 devel@balabit.hu--other-1/syslog-ng--dev-folti--2.0--patch-1 2006-10-27 15:10:36 GMT Balazs Scheidler patch-88 Summary: fixed some compilation warnings under gcc4 Revision: syslog-ng--mainline--2.0--patch-88 * src/affile.c (affile_dd_init): added some casts to suppress some warnings * src/gsockaddr.c (g_accept): use socklen_t instead of int as a second argument to accept modified files: ChangeLog src/affile.c src/gsockaddr.c 2006-10-25 08:36:58 GMT Balazs Scheidler patch-87 Summary: documentation updates merged from the tech-writer team Revision: syslog-ng--mainline--2.0--patch-87 Patches applied: * devel@balabit.hu--other-1/syslog-ng--documentation--2.0--patch-1 Updated reference guide, still needs work, see FIXMEs * devel@balabit.hu--other-1/syslog-ng--documentation--2.0--patch-2 Updates and fixes from Bazsi modified files: ChangeLog doc/reference/syslog-ng.xml new patches: devel@balabit.hu--other-1/syslog-ng--documentation--2.0--patch-1 devel@balabit.hu--other-1/syslog-ng--documentation--2.0--patch-2 2006-10-24 11:37:43 GMT Balazs Scheidler patch-86 Summary: updated VERSION number Revision: syslog-ng--mainline--2.0--patch-86 modified files: ChangeLog VERSION 2006-10-24 11:37:16 GMT Balazs Scheidler patch-85 Summary: preparations for 2.0rc4 Revision: syslog-ng--mainline--2.0--patch-85 modified files: ChangeLog NEWS 2006-10-21 20:41:41 GMT Balazs Scheidler patch-84 Summary: fixed possible NULL deref on destination connection broken, fixed EOF detection Revision: syslog-ng--mainline--2.0--patch-84 2006-10-21 Balazs Scheidler * src/logwriter.c (log_writer_fd_prepare): when EOF detection is enabled specify G_IO_IN and G_IO_HUP in addition to normal flags, (log_writer_fd_dispatch): input on the destination fd is taken as EOF, (log_writer_broken): _deinit is moved after the call to notify, should not matter at all however the reference counting depends on the fact that log_pipe_notify() will not be called after _deinit finishes, in this specific case it would not really matter, (log_writer_deinit): remove unref of self->control, (log_writer_new): self->control is a borrowed reference, don't increase refcount modified files: ChangeLog src/logwriter.c 2006-10-06 11:49:45 GMT Balazs Scheidler patch-83 Summary: added syslog-multicast client to contrib Revision: syslog-ng--mainline--2.0--patch-83 new files: contrib/.arch-ids/syslog-mc.id contrib/syslog-mc modified files: ChangeLog contrib/README 2006-09-14 12:35:49 GMT Balazs Scheidler patch-82 Summary: preparations for 2.0rc3 Revision: syslog-ng--mainline--2.0--patch-82 modified files: ChangeLog NEWS VERSION 2006-09-14 12:34:44 GMT Balazs Scheidler patch-81 Summary: fixed a possible SEGFAULT caused by one of the leak fixes, when output templates() are used Revision: syslog-ng--mainline--2.0--patch-81 2006-09-14 Balazs Scheidler * src/logwriter.c (log_writer_options_init): save options->template before calling log_writer_options_destroy and restore it afterwards as that is never initialized based on the configuration modified files: ChangeLog src/logwriter.c tests/functional/func_test.py 2006-09-11 10:10:09 GMT Balazs Scheidler patch-80 Summary: NEWS update Revision: syslog-ng--mainline--2.0--patch-80 modified files: ChangeLog NEWS 2006-09-11 10:06:07 GMT Balazs Scheidler patch-79 Summary: preparations for 2.0rc2 release Revision: syslog-ng--mainline--2.0--patch-79 modified files: ChangeLog VERSION 2006-09-11 10:05:05 GMT Balazs Scheidler patch-78 Summary: fixed name resolution for unix domain socket peers Revision: syslog-ng--mainline--2.0--patch-78 2006-09-11 Balazs Scheidler * src/misc.c (resolve_hostname): for UNIX domain socket peers don't try to resolve the sender address, fixes a possible abort, introduced by patch-76 modified files: ChangeLog src/misc.c tests/functional/func_test.py 2006-09-11 09:47:54 GMT Balazs Scheidler patch-77 Summary: added stats counter orphaning to fix "duplicate stats counter message" for program destinations Revision: syslog-ng--mainline--2.0--patch-77 2006-09-11 Balazs Scheidler * src/logwriter.c (log_writer_deinit): call stats_orphan_counter, (log_writer_free): removed stats_unregister_counter, fixed a memory leak by freeing all elements in the logwriter queue, (log_writer_options_init): fixed a possible memory leak by freeing the option structure contents before overwriting it with new values, * src/main.c (main_loop_run): added stats_cleanup_orphans() call * src/stats.c (stats_counter_free): new function, (stats_register_counter): added special case for orphaned counters, save "shared" value in the StatsCounter structure, (stats_orphan_counter): new function, orphanes a counter that can thus be reused by a new configuration upon the receiption of a HUP signal, (stats_unregister_counter): use stats_counter_free instead of open-coding it, (stats_cleanup_orphans): free all orphaned counters, to be called after a reload modified files: ChangeLog src/logmsg.c src/logwriter.c src/main.c src/stats.c src/stats.h 2006-09-11 09:41:42 GMT Balazs Scheidler patch-76 Summary: fixed IPv6 name resolution Revision: syslog-ng--mainline--2.0--patch-76 2006-09-11 Balazs Scheidler * src/misc.c (resolve_hostname): added IPv6 specific name resolution modified files: ChangeLog src/misc.c 2006-09-11 09:40:58 GMT Balazs Scheidler patch-75 Summary: fixed NL handling in DGRAM transports Revision: syslog-ng--mainline--2.0--patch-75 2006-09-11 Balazs Scheidler * src/logreader.c (log_reader_iterate_buf): flush input buffer regardless of embedded NLs in the case of DGRAM transports modified files: ChangeLog src/logreader.c 2006-08-09 08:01:16 GMT Balazs Scheidler patch-74 Summary: fixed another memory leak that might happen during exit Revision: syslog-ng--mainline--2.0--patch-74 * src/messages.c (msg_send_internal_message): don't allocate a LogMessage if internal_msg_queue is NULL as that can't be sent anyway modified files: ChangeLog src/messages.c 2006-08-08 19:58:08 GMT Balazs Scheidler patch-73 Summary: various memory leak fixes Revision: syslog-ng--mainline--2.0--patch-73 * src/affile.c (affile_dw_deinit): check if self->writer is NULL, (affile_dd_free): call log_writer_options_destroy as LogWriterOptions might contain dynamically allocated memory, * src/afprog.c (afprogram_dd_exit): removed log_pipe_unref, it is performed by the children handling framework, (afprogram_dd_init): use the new GDestroyNotify argument of children manager, (afprogram_dd_free): added log_writer_options_destroy call * src/afsocket.c (afsocket_dd_free): added log_writer_options_destroy call * src/children.c (ChildEntry): added callback_data_destroy member, (child_manager_child_entry_free): new function, frees a ChildEntry, (child_manager_sigchild): removed g_free, it is done by the GHashTable automatically, (child_manager_init): use g_hash_table_new_full and specify destroy notify callback for the data stored in the hashtable * src/logreader.c (log_reader_iterate_buf): assume that saddr is a borrowed reference and handle it as such, (log_reader_fetch_log): iterate_buf borrows the reference so it is our duty to free sockaddr, do so in all branches, * src/logwriter.c (log_writer_deinit): drop reference to self->control to break a circular reference, (log_writer_free): removed log_pipe_unref self->control, * src/messages.c (msg_send_internal_message): check if internal_msg_queue is null, (msg_deinit): free internal_msg_queue modified files: ChangeLog src/affile.c src/afprog.c src/afsocket.c src/children.c src/children.h src/logreader.c src/logwriter.c src/logwriter.h src/messages.c 2006-08-02 07:22:17 GMT Balazs Scheidler patch-72 Summary: Fixed possible DoS when a 0 sized packet is received via UDP Revision: syslog-ng--mainline--2.0--patch-72 * src/logreader.c (log_reader_fetch_log): don't take 0 sized packets as EOF for packet based transports like UDP * src/afsocket.c (afsocket_sc_notify): don't close the input connection on read errors for non-stream based transports modified files: ChangeLog src/afsocket.c src/logreader.c 2006-07-28 12:54:35 GMT Balazs Scheidler patch-71 Summary: fixed facility filter evaluation problem on platforms with unsigned chars (powerpc) Revision: syslog-ng--mainline--2.0--patch-71 * src/filter.c (filter_facility_eval): Fixed filter evaluation on platforms which have unsigned character type by default (powerpc) modified files: ChangeLog src/filter.c 2006-07-16 19:29:31 GMT Balazs Scheidler patch-70 Summary: added clarification of the output format of program() Revision: syslog-ng--mainline--2.0--patch-70 modified files: ChangeLog doc/reference/syslog-ng.xml 2006-07-08 11:56:10 GMT Balazs Scheidler patch-69 Summary: NEWS update Revision: syslog-ng--mainline--2.0--patch-69 modified files: ChangeLog NEWS 2006-07-08 11:52:25 GMT Balazs Scheidler patch-68 Summary: preparations for 2.0rc1 release Revision: syslog-ng--mainline--2.0--patch-68 modified files: ChangeLog NEWS 2006-06-28 12:09:44 GMT Balazs Scheidler patch-67 Summary: fixed unix domain destination handling Revision: syslog-ng--mainline--2.0--patch-67 * src/afunix.c (afunix_dd_new): initialize bind_addr as the afsocket code assumes that it is not NULL, fixes a possible SIGSEGV modified files: ChangeLog NEWS src/afunix.c 2006-06-23 14:10:53 GMT Balazs Scheidler patch-66 Summary: fixed dir_group processing Revision: syslog-ng--mainline--2.0--patch-66 * src/affile.c (affile_dd_new): dir_gid was not initialized because of a typo, thus dir_group() did not take effect, fixed modified files: ChangeLog src/affile.c 2006-06-20 12:50:32 GMT Balazs Scheidler patch-65 Summary: bumped version to 2.0rc1 Revision: syslog-ng--mainline--2.0--patch-65 modified files: ChangeLog VERSION 2006-06-20 11:44:31 GMT Balazs Scheidler patch-64 Summary: documentation updates, flush_timeout changed to use msecs Revision: syslog-ng--mainline--2.0--patch-64 * doc/reference/syslog-ng.xml: documentation updates * src/logwriter.c (log_writer_fd_prepare): assume that the flush_timeout parameter is in msecs * src/cfg.c (cfg_init): use 10000 as default for flush_timeout() modified files: ChangeLog NEWS doc/reference/syslog-ng.xml src/cfg.c src/logwriter.c 2006-06-12 09:21:24 GMT Balazs Scheidler patch-63 Summary: support optional() for file destinations, optional destinations are only reopened after time_reopen() time has elapsed Revision: syslog-ng--mainline--2.0--patch-63 * src/affile.c (AFFileDestWriter): added time_reopen and last_open_stamp members, (affile_dw_init): store the time_reopen value from cfg, save the current time in last_open_stamp, don't fail the initialization if optional is enabled, (affile_dw_queue): reopen the destination if time_reopen() time has elapsed, drop the message if we are without a destination, * src/cfg-grammar.y (dest_affile_options): added KW_OPTIONAL parsing modified files: ChangeLog src/affile.c src/cfg-grammar.y 2006-06-12 08:47:41 GMT Balazs Scheidler patch-62 Summary: fixed evaluation of priority range filters Revision: syslog-ng--mainline--2.0--patch-62 * src/syslog-names.c (syslog_name_find_name): new inline function used by various lookup functions, (syslog_name_lookup_id_by_name): renamed from syslog_lookup_name, (syslog_name_lookup_name_by_value): renamed from syslog_lookup_value, (syslog_name_lookup_value_by_name): new function, (syslog_make_range): renamed parameters to make the code more readable * src/syslog-names.h (syslog_name_lookup_level_by_name): changed to return the _VALUE_ for syslog message levels, (syslog_name_lookup_facility_by_name): follow name changes * src/cfg-grammar.y: use the new, more readable function names in syslog-names.c * src/filter.c (filter_level_eval): we store a bitmask of the value of priorities instead of our internal ids, thus the function body was simplified a lot (and it works now :) * src/macros.c (log_macro_expand): follow function renames * tests/unit/test_filters.c: added level range tests modified files: ChangeLog src/cfg-grammar.y src/filter.c src/macros.c src/syslog-names.c src/syslog-names.h tests/unit/test_filters.c 2006-06-12 07:53:10 GMT Balazs Scheidler patch-61 Summary: portability fixes Revision: syslog-ng--mainline--2.0--patch-61 * configure.in: detect AIX and HP-UX using uname -s, instead of trying to extract platform information from the linker's version number (proved not to be reliable on HP-UX) * src/misc.c (getlonghostname, getshorthostname): use 256 characters array to store hostnames * src/sgroup.c (log_source_group_queue): -"- modified files: ChangeLog configure.in src/misc.c src/sgroup.c 2006-06-07 09:14:55 GMT Balazs Scheidler patch-60 Summary: fixed pointer conversion macros on 64 bit platforms Revision: syslog-ng--mainline--2.0--patch-60 * src/macros.c (log_macro_lookup): use GINT_TO_POINTER and GPOINTER_TO_INT macros instead of casting values directly to avoid warnings on 64 bit systems modified files: ChangeLog src/macros.c 2006-06-07 09:09:14 GMT Balazs Scheidler patch-59 Summary: do not reconnect to target immediately but wait for time_reopen first Revision: syslog-ng--mainline--2.0--patch-59 * src/afsocket.c (afsocket_dd_notify): instead of immediately scheduling a reconnect, start the reconnect timer to avoid excessive number of reconnection requests in case of a going up-and-down connection modified files: ChangeLog src/afsocket.c 2006-06-07 09:07:40 GMT Balazs Scheidler patch-58 Summary: fixed IPv6 portability problem Revision: syslog-ng--mainline--2.0--patch-58 * src/afinet.c (afinet_setup_socket): use the "official" IPV6_JOIN_GROUP name instead of IPV6_ADD_MEMBERSHIP as the latter is not defined on all platforms modified files: ChangeLog src/afinet.c 2006-06-01 09:10:00 GMT Balazs Scheidler patch-57 Summary: fixed HP-UX portability problem Revision: syslog-ng--mainline--2.0--patch-57 * src/afinet.c (afinet_setup_socket): fixed IN6_IS_ADDR_MULTICAST call as struct in6_addr definition differs on HP-UX (thanks go to Albert Chin) modified files: ChangeLog src/afinet.c 2006-05-26 19:33:31 GMT Balazs Scheidler patch-56 Summary: removed C99ism from stats.c Revision: syslog-ng--mainline--2.0--patch-56 * src/stats.c (stats_generate_log): remove C99 initializers from the initialization of tag_names to make syslog-ng compatible with vendor compilers of various commercial UNIX platforms modified files: ChangeLog src/stats.c 2006-05-26 19:30:30 GMT Balazs Scheidler patch-55 Summary: compatibility fixes for Solaris/AIX Revision: syslog-ng--mainline--2.0--patch-55 2006-05-26 Balazs Scheidler * src/afinet.c: define SOL_IP and SOL_IPV6 on platforms which use IPPROTO_* for this purpose, added the inclusion of for the definition of memset() modified files: ChangeLog src/afinet.c 2006-05-26 19:25:24 GMT Balazs Scheidler patch-54 Summary: added LEVEL_NUM and FACILITY_NUM macros to follow 1.6.x changes Revision: syslog-ng--mainline--2.0--patch-54 * src/macros.c (log_macro_expand): added code for LEVEL_NUM and FACILITY_NUM macros * tests/test_template.c: added testcase for LEVEL_NUM and FACILITY_NUM macros modified files: ChangeLog src/macros.c src/macros.h tests/unit/test_template.c 2006-05-24 08:59:44 GMT Balazs Scheidler patch-53 Summary: guard LOG_CRON with ifdef as it might not exist on some platforms Revision: syslog-ng--mainline--2.0--patch-53 * src/syslog-names.c (sl_facilities): some platforms do not define LOG_CRON modified files: ChangeLog src/syslog-names.c 2006-05-23 18:45:59 GMT Balazs Scheidler patch-52 Summary: preparations for 1.9.11 Revision: syslog-ng--mainline--2.0--patch-52 modified files: ChangeLog NEWS VERSION 2006-05-23 18:45:37 GMT Balazs Scheidler patch-51 Summary: fixed dropping input/output/error fds when going to background Revision: syslog-ng--mainline--2.0--patch-51 2006-05-23 Balazs Scheidler * src/main.c (setup_std_fds): fix inverted check for errors after opening /dev/null, also close stderr when log_to_stderr is not specified * src/afprog.c (afprogram_dd_init): removed setsid call modified files: ChangeLog src/afprog.c src/main.c 2006-05-23 18:33:25 GMT Balazs Scheidler patch-50 Summary: add program exit status information to 'child program exited' log message Revision: syslog-ng--mainline--2.0--patch-50 2006-05-23 Balazs Scheidler * src/afprog.c (afprogram_dd_exit): added program exit status information to 'child program exited' log message modified files: ChangeLog src/afprog.c 2006-05-23 18:31:55 GMT Balazs Scheidler patch-49 Summary: added direction to socket setup code, fixed multicast setup Revision: syslog-ng--mainline--2.0--patch-49 2006-05-23 Balazs Scheidler * src/afsocket.h (AFSocketDirection): new type, specifies the future communication direction on a socket, used to determine which socket options to set on a socket, * src/afsocket.c (afsocket_setup_socket): added direction parameter, (afsocket_sd_setup_socket, afsocket_dd_setup_socket): pass value for 'direction' parameter * src/afinet.c (afinet_setup_socket): added direction parameter, fixed multicast check for IPv4 addresses modified files: ChangeLog src/afinet.c src/afsocket.c src/afsocket.h 2006-05-23 18:28:52 GMT Balazs Scheidler patch-48 Summary: check that the value for time_sleep is less than 500msec Revision: syslog-ng--mainline--2.0--patch-48 2006-05-23 Balazs Scheidler * src/cfg-grammar.y (options_item, KW_TIME_SLEEP): check if the value is more than 500, and maximize its value in this case * src/main.c (main_loop_run): calculate timespec properly if time_sleep is more than 1 sec modified files: ChangeLog src/cfg-grammar.y src/main.c 2006-05-01 14:06:35 GMT Balazs Scheidler patch-47 Summary: added options to control various socket parameters and added multicast support Revision: syslog-ng--mainline--2.0--patch-47 * src/gsockaddr.h (g_sockaddr_inet6_get_address, g_sockaddr_inet6_set_address): use pointers to struct in6_addr instead of passing the structure by value * src/afsocket.c (afsocket_setup_socket): new function, set generic socket options, (afsocket_sd_accept): call setup_socket for new fds, (afsocket_sd_init): -"-, (afsocket_dd_reconnect): -"-, (afsocket_sd_setup_socket): new function, default setup_socket callback, (afsocket_sd_init_instance): added sock_options argument, set default setup_socket callback, (afsocket_dd_init_instance): added sock_options argument, set default setup_socket callback, * src/afsocket.h (AFSocketSourceDriver): added setup_socket callback, (AFSocketDestDriver): added setup_socket callback, * src/afinet.c (afinet_resolve_name): follow g_sockaddr_inet6_set_address change, (afinet_setup_socket): new function to set AF_INET & AF_INET6 specific socket options, (afinet_sd_setup_socket): new function, used as the setup_socket callback, (afinet_dd_setup_socket): new function, used as the setup_socket callback, * src/afunix.c (afunix_sd_new, afunix_dd_new): adapted to afsocket changes, * src/cfg-grammar.y (socket_option, inet_socket_option): added socket option parsing * src/cfg-lex.l: added new keywords for socket options modified files: ChangeLog doc/reference/syslog-ng.xml src/afinet.c src/afinet.h src/afsocket.c src/afsocket.h src/afunix.c src/afunix.h src/cfg-grammar.y src/cfg-lex.l src/gsockaddr.h 2006-05-01 12:38:10 GMT Balazs Scheidler patch-46 Summary: fixed Solaris portability problems, avoid multiread on STREAMS sources Revision: syslog-ng--mainline--2.0--patch-46 * configure.in: check for -lrt for nanosleep * src/afstreams.c (afstreams_sd_init): pass LR_NOMREAD flag to log_reader_new() modified files: ChangeLog configure.in src/afstreams.c 2006-04-30 20:20:44 GMT Balazs Scheidler patch-45 Summary: fixed fetching kernel messages which was broken by the multi-read patches Revision: syslog-ng--mainline--2.0--patch-45 * src/logreader.h (LR_NOMREAD): new flag, indicates that the log reader should not use multiple read() calls in a single poll loop * src/logreader.c (log_reader_fetch_log): break out of the loop if LR_NOMREAD is specified * src/affile.c (affile_sd_init): specify LR_NOMREAD modified files: ChangeLog src/affile.c src/logreader.c src/logreader.h 2006-04-23 10:35:57 GMT Balazs Scheidler patch-44 Summary: fixed endless-loop and CPU spinning if a non-existing filter is referenced in the internal() path Revision: syslog-ng--mainline--2.0--patch-44 * src/filter.c (filter_call_eval): only log the "not-found filter" error message once modified files: ChangeLog src/filter.c 2006-04-23 10:22:21 GMT Balazs Scheidler patch-43 Summary: fixed possible memory leak Revision: syslog-ng--mainline--2.0--patch-43 * src/logreader.c (log_reader_iterate_buf): drop self->prev_addr reference if it exists, previously it might have been overwritten with a new reference without dropping the old, fixes a potential GSockAddr reference leak modified files: ChangeLog src/logreader.c 2006-04-23 09:23:19 GMT Balazs Scheidler patch-42 Summary: added IPv6 support Revision: syslog-ng--mainline--2.0--patch-42 * configure.in: added --enable-ipv6 option, defaults to "yes", added checks for getaddrinfo() * src/afinet.c (afinet_set_port): added ipv6 support, (afinet_resolve_name): renamed from afinet_set_ip, use getaddrinfo() to resolve names where available, (afinet_sd_new): added af argument, use afinet_resolve_name instead of the removed g_sockaddr_inet_new_resolve() function, use a default "bind address" value if the host argument is NULL, (afinet_dd_new): added af argument, use afinet_resolve_name instead of the removed g_sockaddr_inet_new_resolve() function * src/cfg-grammar.y: added KW_UDP6 and KW_TCP6 keywords, (source_afsocket, dest_afsocket): added rules for KW_UDP6 & KW_TCP6, (dest_afinet_udp_params, dest_afinet_tcp_params): added ipv6 support, adapted to the latest changes in afinet (source_afinet_udp_params, source_afinet_tcp_params): -"- * src/cfg-lex.l: added "udp6" and "tcp6" keywords * src/gsockaddr.c (g_sockaddr_inet_new_resolve): removed this function as it is an address family independent operation now implemented in afinet.c, (g_sockaddr_inet6_check): new function to check whether a GSockAddr contains an ipv6 socket name, * src/gsockaddr.h (g_sockaddr_get_sa, g_sockaddr_inet_get_sa, g_sockaddr_inet_get_address, g_sockaddr_inet_set_address, g_sockaddr_inet_get_port, g_sockaddr_inet_set_port): new inline functions, ported from the Zorp sockaddr code, (g_sockaddr_inet6_get_sa, g_sockaddr_inet6_get_address, g_sockaddr_inet6_set_address, g_sockaddr_inet6_get_port, g_sockaddr_inet6_set_port): new functions, similar to IPv6 counterparts modified files: ChangeLog configure.in src/afinet.c src/afinet.h src/cfg-grammar.y src/cfg-lex.l src/gsockaddr.c src/gsockaddr.h 2006-04-20 12:07:17 GMT Balazs Scheidler patch-41 Summary: fixed off-by-one in flush_lines() calculation Revision: syslog-ng--mainline--2.0--patch-41 * src/logwriter.c (log_writer_fd_prepare): flush_lines(1) required two lines to be flushed, modified the condition so that: flush_lines(0) that output buffering is off, flush_lines(1) is basically equivalent, every single individual line is flushed, flush_lines(2) flushes the output buffer if two lines are already available modified files: ChangeLog src/logwriter.c 2006-04-20 11:57:20 GMT Balazs Scheidler patch-40 Summary: added close-on-exec flag to all opened fds to avoid their inheritance to child processes Revision: syslog-ng--mainline--2.0--patch-40 * src/af*.c: call g_fd_set_cloexec for all new fds * src/misc.c (g_fd_set_cloexec): new function, sets FD_CLOEXEC flag for an fd modified files: ChangeLog src/affile.c src/afprog.c src/afsocket.c src/afstreams.c src/misc.c src/misc.h 2006-04-19 18:47:12 GMT Balazs Scheidler patch-39 Summary: change file owner/group independently Revision: syslog-ng--mainline--2.0--patch-39 * src/affile.c (affile_open_file): change owner/group independently modified files: ChangeLog src/affile.c 2006-04-19 18:44:34 GMT Balazs Scheidler patch-38 Summary: don't try to chmod/chown files that do not exist Revision: syslog-ng--mainline--2.0--patch-38 * src/affile.c (affile_open_file): don't call chmod/chown when opening the file failed modified files: ChangeLog src/affile.c 2006-04-10 21:36:12 GMT Balazs Scheidler patch-37 Summary: fixed a compilation warning Revision: syslog-ng--mainline--2.0--patch-37 modified files: ChangeLog src/cfg-grammar.y 2006-04-10 21:33:37 GMT Balazs Scheidler patch-36 Summary: preparations for 1.9.10, this time for real Revision: syslog-ng--mainline--2.0--patch-36 modified files: ChangeLog NEWS 2006-04-10 21:32:30 GMT Balazs Scheidler patch-35 Summary: display an error message instead of a failed assertion when the user specifies conflicting sources Revision: syslog-ng--mainline--2.0--patch-35 * src/cfg.c (persist_config_add): don't store the value if it is NULL, display an error message instead of a failed assertion if the persistent name conflicts modified files: ChangeLog src/cfg.c 2006-04-10 20:59:32 GMT Balazs Scheidler patch-34 Summary: don't treat parse flags as keywords Revision: syslog-ng--mainline--2.0--patch-34 * src/cfg-grammar.y: removed KW_NO_PARSE and KW_KERNEL tokens, (source_reader_option_flags): use IDENTIFIER instead of using separate keywords and call lookup_parse_flag to convert the textual representation of parse flags to flag values, * src/cfg-lex.l (keywords): removed no_parse and kernel keywords, (lookup_parse_flag): new function, returns the flag value associated with the text representation * src/cfg.c (cfg_init): fixed possible segfault when bad_hostname regexp was not specified modified files: ChangeLog src/cfg-grammar.y src/cfg-lex.l src/cfg.c 2006-04-10 20:47:03 GMT Balazs Scheidler patch-33 Summary: implemented bad_hostname and check_hostname options Revision: syslog-ng--mainline--2.0--patch-33 * src/cfg-grammar.y: added KW_BAD_HOSTNAME and KW_CHECK_HOSTNAME tokens * src/cfg-lex.l: added keywords for KW_BAD_HOSTNAME and KW_CHECK_HOSTNAME * src/cfg.c (cfg_bad_hostname_set): new function, set global bad_hostname regexp, (cfg_init): compile bad_hostname_re * src/log.c (log_msg_parse): added bad_hostname regexp param, and an implementation of check_hostname() and bad_hostname(), (log_msg_init): avoid a time(NULL) call, (log_msg_new): added bad_hostname parameter, (log_reader_options_init): set options->options and options->bad_hostname based on the values stored in GlobalConfig * tests/unit/test_msgparse.c: added testcases for check_hostname() and bad_hostname() * src/*.c, src/*.h: followed changes modified files: ChangeLog NEWS src/cfg-grammar.y src/cfg-lex.l src/cfg.c src/cfg.h src/logmsg.c src/logmsg.h src/logreader.c src/logreader.h src/messages.c tests/unit/test_filters.c tests/unit/test_msgparse.c tests/unit/test_template.c 2006-04-09 08:02:44 GMT Balazs Scheidler patch-32 Summary: fixed timestamp calculation on timezone barriers Revision: syslog-ng--mainline--2.0--patch-32 * src/logmsg.c (log_msg_parse): fixed timestamp calculation where a timezone information was specified, see the comment for details, * tests/unit/test_msgparse.c: added some more testcases with timestamps around the DST switch * tests/unit/test_template.c: fixed the timezone offset of the arbitrary timestamp chosen in the testcases modified files: ChangeLog src/logmsg.c src/misc.c tests/unit/test_msgparse.c tests/unit/test_template.c 2006-04-07 14:27:52 GMT Balazs Scheidler patch-31 Summary: accept negative numbers as NUMBER in the lexer Revision: syslog-ng--mainline--2.0--patch-31 2006-04-07 Balazs Scheidler * src/cfg-lex.l: accept negative numbers in the lexer modified files: ChangeLog src/cfg-lex.l 2006-04-06 10:20:41 GMT Balazs Scheidler patch-30 Summary: added a paragraph to the documentation clarifying pipe and /proc/kmsg Revision: syslog-ng--mainline--2.0--patch-30 modified files: ChangeLog doc/reference/syslog-ng.xml 2006-04-02 10:11:57 GMT Balazs Scheidler patch-29 Summary: updated NEWS file, preparations for 1.9.10 Revision: syslog-ng--mainline--2.0--patch-29 * VERSION: bumped version to 1.9.10 modified files: ChangeLog NEWS VERSION 2006-04-01 08:03:10 GMT Balazs Scheidler patch-28 Summary: fixed large file support Revision: syslog-ng--mainline--2.0--patch-28 * configure.in: check for O_LARGEFILE * src/affile.c: use O_LARGEFILE when available modified files: ChangeLog configure.in src/affile.c 2006-03-26 17:38:09 GMT Balazs Scheidler patch-27 Summary: fixed priority level filtering Revision: syslog-ng--mainline--2.0--patch-27 * src/cfg-grammar.y (filter_level): fixed priority level based filtering, spotted and reported by Jakub Bogusz modified files: ChangeLog src/cfg-grammar.y 2006-03-22 15:39:58 GMT Balazs Scheidler patch-26 Summary: fixed a possible segmentation fault on write errors Revision: syslog-ng--mainline--2.0--patch-26 * src/logwriter.c (log_writer_flush_log): return from the function on error instead of looping with line == NULL, this fixes a possible SIGSEGV, when some messages sit in the queue while the destination goes away modified files: ChangeLog src/logwriter.c 2006-03-18 22:08:50 GMT Balazs Scheidler patch-25 Summary: reimplemented netmask() filter which was missing from 1.9.9 Revision: syslog-ng--mainline--2.0--patch-25 * src/cfg-grammar.y, src/cfg-lex.l: added KW_NETMASK * src/filter.c (filter_netmask_new): new function to construct a netmask filter, cidr "address/prefix" and "address/address" formats are accepted * src/logmsg.h: fixed a warning by declaring log_msg_clear_matches function * doc/reference/syslog-ng.xml: added a notice on redefining template() for network destinations * tests/unit/test_filter.c: added unit tests for netmask filter modified files: ChangeLog doc/reference/syslog-ng.xml src/cfg-grammar.y src/cfg-lex.l src/filter.c src/filter.h src/logmsg.h tests/unit/test_filters.c 2006-03-13 23:12:08 GMT Balazs Scheidler patch-24 Summary: fixed regexp match space macro expansion Revision: syslog-ng--mainline--2.0--patch-24 * src/filter.c (filter_re_eval): added msg parameter, instead of using the re_matches array, use a per-message store * src/logmsg.h (LogMessage): added re_matches * src/macros.c (log_macro_expand): use per-message re_matches array modified files: ChangeLog src/filter.c src/filter.h src/logmsg.c src/logmsg.h src/macros.c src/main.c 2006-03-13 17:16:08 GMT Balazs Scheidler patch-23 Summary: fail the testprogram if the pidfile could not be found Revision: syslog-ng--mainline--2.0--patch-23 modified files: ChangeLog tests/functional/func_test.py 2006-03-13 16:37:17 GMT Balazs Scheidler patch-22 Summary: stats_freq is only taken into account if the value is larger than 0 Revision: syslog-ng--mainline--2.0--patch-22 * src/main.c (main_loop_run): take changed stats_freq into account after a SIGHUP, stats_freq == 0 means to disable stats messages altogether modified files: ChangeLog src/main.c 2006-03-13 10:40:55 GMT Balazs Scheidler patch-21 Summary: added %option noyywrap to cfg-lex.l Revision: syslog-ng--mainline--2.0--patch-21 * src/cfg-lex.l: added %option noyywrap to cfg-lex.l modified files: ChangeLog src/cfg-lex.l 2006-02-28 18:47:01 GMT Balazs Scheidler patch-20 Summary: fixed possible abort in program destination Revision: syslog-ng--mainline--2.0--patch-20 * src/afprog.c (afprogram_dd_deinit): don't drop the reference to self->writer, only deinit it, (afprogram_dd_free): drop the reference to self->writer, * src/main.c (main_loop_run): change the loop so that it actually processes exited children modified files: ChangeLog src/afprog.c src/main.c 2006-02-26 09:39:39 GMT Balazs Scheidler patch-19 Summary: really release 1.9.9 Revision: syslog-ng--mainline--2.0--patch-19 modified files: ChangeLog tests/functional/func_test.py 2006-02-26 09:38:42 GMT Balazs Scheidler patch-18 Summary: fixed a possible heap overflow introduced by the patches from 2006-02-24 Revision: syslog-ng--mainline--2.0--patch-18 * src/logreader.c (log_reader_fetch_log): recalculate the available buffer size before calling read() again, this is a possible heap overflow which was introduced by devel@balabit.hu--other-1/syslog-ng--mainline--2.0--patch-14 ChangeLog is in patch-15, this was never released however modified files: ChangeLog src/logreader.c 2006-02-26 08:50:05 GMT Balazs Scheidler patch-17 Summary: preparations for an 1.9.9 release Revision: syslog-ng--mainline--2.0--patch-17 modified files: ChangeLog NEWS VERSION src/logmsg.c 2006-02-26 08:47:15 GMT Balazs Scheidler patch-16 Summary: added time_sleep() option to add a fixed latency to the poll loop Revision: syslog-ng--mainline--2.0--patch-16 * src/cfg-grammar.y: added KW_TIME_SLEEP processing * src/cfg-lex.l: added keyword for KW_TIME_SLEEP * src/main.c: wait using nanosleep if time_sleep() is set * doc/reference/syslog-ng.xml: added documentation on time_sleep and a section in the tuning part to explain it a little further modified files: ChangeLog doc/reference/syslog-ng.xml src/cfg-grammar.y src/cfg-lex.l src/cfg.h src/main.c 2006-02-24 16:24:14 GMT Balazs Scheidler patch-15 Summary: added missing ChangeLog from previous patchset Revision: syslog-ng--mainline--2.0--patch-15 * src/fdread.c (fd_do_read): added retrying on EINTR * src/logreader.c (log_reader_iterate_buf): added msg_count argument instead of the local variable as log_reader_iterate_buf might be called multiple times and we do not want to fetch more than fetch_limit() messages in total, (log_reader_fetch_log): added loop to iterate over up to fetch_limit messages without going back to the mainloop modified files: ChangeLog 2006-02-24 16:19:33 GMT Balazs Scheidler patch-14 Summary: added reference/syslog-ng.txt to EXTRA_DIST Revision: syslog-ng--mainline--2.0--patch-14 modified files: ChangeLog doc/Makefile.am src/fdread.c src/logreader.c 2006-02-24 16:13:38 GMT Balazs Scheidler patch-13 Summary: added syslog-ng.txt generation to Makefile Revision: syslog-ng--mainline--2.0--patch-13 modified files: ChangeLog doc/Makefile.am 2006-02-12 13:37:21 GMT Balazs Scheidler patch-12 Summary: fixed second fraction processing so that it actually shows up in output Revision: syslog-ng--mainline--2.0--patch-12 * src/afsocket.h: removed AFSOCKET_PROTO_RFC3164, it might be readded later when multiple protocols will be added, but for now it only clutters the code * src/cfg-grammar.y (KW_TIMESTAMP): moved keep_timestamp processing to the readers, logwriters always reformat the timestamp based on the parsed value, keep_timestamp(no) overwrites the timestamp in the message with the received time, (KW_FRAC_DIGITS): added a way to specify second fraction precision, it now defaults to zero, e.g. no fraction information is added, * src/logmsg.c (log_stamp_format): added support for unix and full timestamps, added frac_digits argument (LogStamp): removed frac_present member, if the user requests second fragments one is always generated, if this information is not available 0 is assumed * src/cfg.c (cfg_ts_format_value): added support for unix and full timestamps, (cfg_new): frac_digits is initialized to 0, keep_timestamp to TRUE * src/logreader.c (log_reader_handle_line): overwrite the message timestamp if keep_timestamp if FALSE, (log_reader_options_init): use the global keep_timestamp setting is one is not specified * src/logwriter.c (log_writer_format_log): always regenerate the timestamp if no template was specified, as there's no point in using the original date in the message as it clutters logs and might confuse receivers, (LWOF_FIXED_STAMP): removed, this is the default behaviour which can be overridden by using templates * src/macros.c (log_macro_expand): use log_stamp_format for all date/time formatting instead of open-coding them, DATE uses the BSD timestamp, regardless of the value of ts_format * src/test_template.c: fixed testprogram modified files: ChangeLog NEWS doc/reference/syslog-ng.xml src/affile.c src/afinet.c src/afsocket.c src/afsocket.h src/cfg-grammar.y src/cfg-lex.l src/cfg.c src/cfg.h src/logmsg.c src/logmsg.h src/logreader.c src/logreader.h src/logwriter.c src/logwriter.h src/macros.c src/macros.h src/templates.c src/templates.h tests/unit/test_template.c 2006-02-11 19:29:56 GMT Balazs Scheidler patch-11 Summary: readded HOST_FROM, FULLHOST_FROM, SOURCEIP macros, extended unit test program Revision: syslog-ng--mainline--2.0--patch-11 * src/gsockaddr.c (g_sockaddr_inet_check): new function, returns TRUE if the specified address is GSockAddrInet * src/logmsg.c (log_msg_parse): fixed timezone parsing in ISODATE timestamps, (log_msg_init): added host_from member, (log_msg_free): free host_from * src/macros.c (log_macro_expand): added FULLHOST_FROM, HOST_FROM, SOURCEIP implementation, fixed DATE macros * src/misc.c (resolve_hostname): instead of returning a newly allocated GString, store the result in the one passed as parameter * src/sgroup.c (log_source_group_queue): set host_from member in log message * tests/unit/test_msgparse.c: fixed offset/timestamp value * tests/unit/test_template.c: greatly extended to cover all possible macros, resulting fixes are above :) modified files: ChangeLog NEWS src/gsockaddr.c src/gsockaddr.h src/logmsg.c src/logmsg.h src/macros.c src/macros.h src/misc.c src/misc.h src/sgroup.c tests/unit/test_msgparse.c tests/unit/test_template.c 2006-02-11 17:31:08 GMT Balazs Scheidler patch-10 Summary: fixed possible segmentation fault on SIGHUP Revision: syslog-ng--mainline--2.0--patch-10 * src/afsocket.c (afsocket_sc_set_owner): new function, changes all references to a new AFSocketSourceDriver (this happens accross SIGHUPs), (afsocket_sd_set_listener_keep_alive): removed, there's no separate LISTENER_KEEP_ALIVE setting, (afsocket_sd_init): instead of simply changing the next-hop log-pipe of connections call afsocket_sc_set_owner which changes less explicit references * src/cfg-grammar.y (yyparser_reset): new function, resets all 'last_' variables as they are not referenced and might contain pointers to stale data * src/logpipe.c (log_pipe_free_instance): function body moved to log_pipe_unref to clear some clutter in backtraces and both functions are only a couple of lines anyway * src/logreader.c (log_reader_set_options): new function, allows the caller to change the pointer to the options structure modified files: ChangeLog NEWS src/afinet.c src/afsocket.c src/afsocket.h src/afunix.c src/cfg-grammar.y src/cfg.c src/logpipe.c src/logreader.c src/logreader.h src/logsource.c src/logsource.h src/main.c 2006-02-11 17:22:06 GMT Balazs Scheidler patch-9 Summary: memtrace improvements Revision: syslog-ng--mainline--2.0--patch-9 * src/memtrace.c: added backtrace to add/delblock messages modified files: ChangeLog src/memtrace.c 2006-02-11 13:41:36 GMT Balazs Scheidler patch-8 Summary: added some more unit testcases for filter testing Revision: syslog-ng--mainline--2.0--patch-8 modified files: ChangeLog tests/unit/test_filters.c 2006-02-11 13:07:54 GMT Balazs Scheidler patch-7 Summary: added "kernel" flag to log reader flags Revision: syslog-ng--mainline--2.0--patch-7 2006-02-11 Balazs Scheidler * src/cfg-lex.l, src/cfg-grammar.y: added "kernel" keyword * src/logmsg.c (log_msg_parse): default to kern.crit for kernel messages * src/macros.c: fixed PRI macro as it included the hostname as well modified files: ChangeLog NEWS doc/reference/syslog-ng.xml src/cfg-grammar.y src/cfg-lex.l src/logmsg.c src/logmsg.h src/logreader.c src/logreader.h src/macros.c 2006-02-11 12:44:37 GMT Balazs Scheidler patch-6 Summary: added PID macro and its documentation Revision: syslog-ng--mainline--2.0--patch-6 * src/macros.c (log_expand_macro): added support for PID modified files: ChangeLog NEWS doc/reference/syslog-ng.xml src/macros.c src/macros.h 2006-02-11 12:00:14 GMT Balazs Scheidler patch-5 Summary: added normalize_hostnames() option (fixes: #6294) Revision: syslog-ng--mainline--2.0--patch-5 2006-02-11 Balazs Scheidler * src/cfg-lex.l, src/cfg-grammar.y: added normalize_hostnames option * src/sgroup.c: implement normalize_hostnames * src/logmsg.c (log_msg_parse): removed STRICT check from RFC3339 timestamp parsing * doc/reference/syslog-ng.xml: updated modified files: ChangeLog NEWS doc/reference/syslog-ng.xml src/cfg-grammar.y src/cfg-lex.l src/cfg.h src/logmsg.c src/misc.c src/misc.h src/sgroup.c src/sgroup.h 2006-02-11 10:57:43 GMT Balazs Scheidler patch-4 Summary: Added processed counters for source/destination groups and the log center (fixes: #5368) Revision: syslog-ng--mainline--2.0--patch-4 * src/affile.c (affile_dd_format_stats_name): readded this function to generate a unique stats ID for the specific destination driver instance, (affile_dd_init): use NO_STATS for files only, * src/center.c (log_center_init): added received/queued counters, (log_center_queue): increment counters * src/sgroup.c, src/dgroup.c: added processed counters * src/stats.c, src/stats.h: added SC_TYPE_PROCESSED, make sure that counters are interpreted in their proper namespace, (stats_unregister_counter): added missing "type" argument modified files: ChangeLog NEWS src/affile.c src/center.c src/center.h src/dgroup.c src/dgroup.h src/driver.c src/logwriter.c src/sgroup.c src/sgroup.h src/stats.c src/stats.h 2006-02-11 08:43:32 GMT Balazs Scheidler patch-3 Summary: added optional() parameter to pipe/unix drivers (fixes: #4999) Revision: syslog-ng--mainline--2.0--patch-3 * src/driver.h: added optional member (fixes: #4999) * src/cfg-lex.l: added optional keyword (fixes: #4999) * src/cfg-grammar.y: added optional keyword to pipe and unix domain socket based source drivers (fixes: #4999) * src/afsocket.c (afsocket_sd_init): do not fail if binding failed and optional is TRUE (fixes: #4999) * src/affile.c (affile_sd_init): do not fail if opening failed and optional is TRUE (fixes: #4999) modified files: ChangeLog doc/reference/syslog-ng.xml src/affile.c src/afsocket.c src/cfg-grammar.y src/cfg-lex.l src/driver.h 2006-02-11 08:16:00 GMT Balazs Scheidler patch-2 Summary: implemented filter debugging (fixes: #3988) Revision: syslog-ng--mainline--2.0--patch-2 * src/filter.c (log_filter_rule_eval): new function, previously rule->root was manipulated directly which was not nice, filter rule debugging messages are put here (fixes: #3988), (filter_expr_eval): uninlined, added debugging messages (fixes: #3988), (filter_expr_free): uninlined (*_new): set self->type to be used in log messages properly (fixes: #3988) modified files: ChangeLog src/center.c src/filter.c src/filter.h 2006-02-11 07:53:02 GMT Balazs Scheidler patch-1 Summary: integrated last pending patch from bazsi's archive, started new ChangeLog Revision: syslog-ng--mainline--2.0--patch-1 * tla archives were switched, syslog-ng now uses devel@balabit.hu--other-1, the old ChangeLog file was archived as ChangeLog.1 * integrated a last pending patch from the old archive to fix a possible 64bit compatibility issue new files: .arch-ids/ChangeLog.1.id .arch-ids/ChangeLog.id ChangeLog ChangeLog.1 removed files: .arch-ids/ChangeLog.id ChangeLog modified files: src/logwriter.c src/logwriter.h new patches: bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-86 2006-01-27 09:17:47 GMT Attila SZALAY base-0 Summary: tag of bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-85 Revision: syslog-ng--mainline--2.0--base-0 (automatically generated log message) new patches: bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--base-0 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-1 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-2 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-3 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-4 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-5 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-6 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-7 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-8 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-9 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-10 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-11 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-12 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-13 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-14 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-15 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-16 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-17 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-18 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-19 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-20 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-21 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-22 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-23 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-24 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-25 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-26 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-27 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-28 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-29 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-30 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-31 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-32 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-33 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-34 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-35 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-36 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-37 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-38 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-39 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-40 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-41 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-42 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-43 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-44 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-45 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-46 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-47 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-48 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-49 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-50 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-51 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-52 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-53 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-54 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-55 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-56 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-57 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-58 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-59 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-60 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-61 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-62 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-63 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-64 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-65 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-66 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-67 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-68 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-69 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-70 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-71 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-72 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-73 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-74 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-75 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-76 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-77 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-78 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-79 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-80 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-81 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-82 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-83 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-84 bazsi@balabit.hu--bazsi-1/syslog-ng--mainline--2.0--patch-85 syslog-ng-syslog-ng-3.13.2/doc/Makefile.am000066400000000000000000000027141321171025300202420ustar00rootroot00000000000000xsd_DATA = \ doc/xsd/patterndb-1.xsd \ doc/xsd/patterndb-2.xsd \ doc/xsd/patterndb-3.xsd \ doc/xsd/patterndb-4.xsd \ doc/xsd/patterndb-5.xsd EXTRA_DIST += \ doc/man/dqtool.1.xml \ doc/man/loggen.1.xml \ doc/man/pdbtool.1.xml \ doc/man/syslog-ng-debun.1.xml \ doc/man/syslog-ng-ctl.1.xml \ doc/man/syslog-ng.8.xml \ doc/man/syslog-ng.conf.5.xml \ doc/security/bof-2002-09-27.txt \ doc/security/dos-2000-11-22.txt \ $(xsd_DATA) if ENABLE_MANPAGES man_MANS += \ doc/man/dqtool.1 \ doc/man/loggen.1 \ doc/man/pdbtool.1 \ doc/man/syslog-ng-debun.1 \ doc/man/syslog-ng-ctl.1 \ doc/man/syslog-ng.8 \ doc/man/syslog-ng.conf.5 EXTRA_DIST += $(man_MANS) # NOTE: this uses a hard-coded path for the XSL stylesheets, but the # end-result is also included in the tarball. If so need be, this can # be overridden from the make command line or via the environment. sysconfdir_e = $(shell echo "${sysconfdir}" | sed -e "s,-,\\\\\\\\-,g") prefix_e = $(shell echo "${prefix}" | sed -e "s,-,\\\\\\\\-,g") doc/man/%: doc/man/%.xml $(AM_V_at) $(NOOP) # Removing all XML whitespaces, workaround for the bug in $(AM_V_at) $(NOOP) # docbook-xsl v1.79.1. See https://sourceforge.net/p/docbook/bugs/1381/ $(AM_V_GEN)sed -e '1h;2,$$H;$$!d;g' -e "s/>\s\+$@.tmp && mv $@.tmp $@ endif syslog-ng-syslog-ng-3.13.2/doc/man/000077500000000000000000000000001321171025300167555ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/doc/man/.gitignore000066400000000000000000000000261321171025300207430ustar00rootroot00000000000000/syslog-ng-ose-guides syslog-ng-syslog-ng-3.13.2/doc/man/dqtool.1.xml000066400000000000000000000132771321171025300211520ustar00rootroot00000000000000 The dqtool tool manual page dqtool 1 3.13 dqtool Display the contents of a disk-buffer file created with dqtool command options Description NOTE: The dqtool application is distributed with the system logging application, and is usually part of the syslog-ng package. The latest version of the syslog-ng application is available at the official syslog-ng website. This manual page is only an abstract, for the complete documentation of syslog-ng, see The Administrator Guide. The dqtool application is a utility that can be used to display and format the messages stored in a disk-buffer file. The cat command cat options file Use the cat command to display the log messages stored in the disk-buffer (also called disk-queue) file, and also information from the header of the disk queue file. The messages are printed to the standard output (stdout), so it is possible to use grep and other tools to find particular log messages, e.g., dqtool cat /var/log/messages.lgs |grep 192.168.1.1. The cat command has the following options: --debug or -d Print diagnostic and debugging messages to stderr. --help or -h Display a brief help message. --template=<template> or -t Format the messages using the specified template. --verbose or -v Print verbose messages to stderr. --version or -V Display version information. Example:./dqtool cat ../var/syslog-ng-00000.qf The output looks like: Disk-buffer state loaded; filename='../var/syslog-ng-00000.qf', qout_length='65', qbacklog_length='0', qoverflow_length='9205', qdisk_length='0' Mar 3 10:52:05 tristram localprg[1234]: seq: 0000011630, runid: 1267609923, stamp: 2010-03-03T10:52:05 PADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADD Mar 3 10:52:05 tristram localprg[1234]: seq: 0000011631, runid: 1267609923, stamp: 2010-03-03T10:52:05 PADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADD Files /opt/syslog-ng/bin/dqtool See also syslog-ng.conf(5) syslog-ng(8) For the detailed documentation of see The 3.13 Administrator Guide If you experience any problems or need help with syslog-ng, visit the syslog-ng mailing list. For news and notifications about of syslog-ng, visit the syslog-ng blogs. Author This manual page was written by the Balabit Documentation Team <documentation@balabit.com>. Copyright syslog-ng-syslog-ng-3.13.2/doc/man/loggen.1.xml000066400000000000000000000366641321171025300211300ustar00rootroot00000000000000 The loggen manual page loggen 1 3.13 loggen Generate syslog messages at a specified rate loggen options target port Description NOTE: The loggen application is distributed with the syslog-ng system logging application, and is usually part of the syslog-ng package. The latest version of the syslog-ng application is available at the official syslog-ng website. This manual page is only an abstract, for the complete documentation of syslog-ng, see The syslog-ng Administrator Guide. The loggen application is tool to test and stress-test your syslog server and the connection to the server. It can send syslog messages to the server at a specified rate, using a number of connection types and protocols, including TCP, UDP, and unix domain sockets. The messages can be generated automatically (repeating the PADDstring over and over), or read from a file or the standard input. When loggen finishes sending the messages, it displays the following statistics: average rate: Average rate the messages were sent in messages/second. count: The total number of messages sent. time: The time required to send the messages in seconds. average message size: The average size of the sent messages in bytes. bandwidth: The average bandwidth used for sending the messages in kilobytes/second. Options --active-connections <number-of-connections> Number of connections loggen will use to send messages to the destination. This option is usable only when using TCP or TLS connections to the destination. Default value: 1 The loggen utility waits until every connection is established before starting to send messages. See also the --idle-connections option. --csv or -C Send the statistics of the sent messages to stdout as CSV. This can be used for plotting the message rate. --dgram or -D Use datagram socket (UDP or unix-dgram) to send the messages to the target. Requires the --inet option as well. --dont-parse or -d Do not parse the lines read from the input files, send them as received. --help or -h Display a brief help message. --idle-connections <number-of-connections> Number of idle connections loggen will establish to the destination. Note that loggen will not send any messages on idle connections, but the connection is kept open using keep-alive messages. This option is usable only when using TCP or TLS connections to the destination. See also the --active-connections option. Default value: 0 --inet or -i Use the TCP (by default) or UDP (when used together with the --dgram option) protocol to send the messages to the target. --interval <seconds> or -I <seconds> The number of seconds loggen will run. Default value: 10 Note that when the --interval and --number are used together, loggen will send messages until the period set in --interval expires or the amount of messages set in --number is reached, whichever happens first. --ipv6 or -6 Specify the destination using its IPv6 address. Note that the destination must have a real IPv6 address. --loop-reading or -l Read the file specified in --read-file option in loop: loggen will start reading from the beginning of the file when it reaches the end of the file. --number <number-of-messages> or -n <number-of-messages> Number of messages to generate. Note that when the --interval and --number are used together, loggen will send messages until the period set in --interval expires or the amount of messages set in --number is reached, whichever happens first. --no-framing or -F Do not use the framing of the IETF-syslog protocol style, even if the syslog-proto option is set. --quiet or -Q Output statistics only when the execution of loggen is finished. If not set, the statistics are displayed every second. --permanent or -T Keep sending logs indefinitely, without time limit. --rate <message/second> or -r <message/second> The number of messages generated per second for every active connection. Default value: 1000 --read-file <filename> or -R <filename> Read the messages from a file and send them to the target. See also the --skip-tokens option. Specify - as the input file to read messages from the standard input (stdio). Note that when reading messages from the standard input, loggen can only use a single thread. The -R - parameters must be placed at end of command, like: loggen 127.0.0.1 1061 --read-file - --sdata <data-to-send> or -p <data-to-send> Send the argument of the --sdata option as the SDATA part of IETF-syslog (RFC5424 formatted) messages. Use it together with the --syslog-proto option. For example: --sdata "[test name=\"value\"] --size <message-size> or -s <message-size> The size of a syslog message in bytes. Default value: 256. Minimum value: 127 bytes, maximum value: 8192 bytes. --skip-tokens <number> Skip the specified number of space-separated tokens (words) at the beginning of every line. For example, if the messages in the file look like foo bar message, --skip-tokens 2 skips the foo bar part of the line, and sends only the message part. Works only when used together with the --read-file parameter. Default value: 3 --stream or -S Use a stream socket (TCP or unix-stream) to send the messages to the target. --syslog-proto or -P Use the new IETF-syslog message format as specified in RFC5424. By default, loggen uses the legacy BSD-syslog message format (as described in RFC3164). See also the --no-framing option. --unix </path/to/socket> or -x </path/to/socket> Use a UNIX domain socket to send the messages to the target. --use-ssl or -U Use an SSL-encrypted channel to send the messages to the target. Note that it is not possible to check the certificate of the target, or to perform mutual authentication. --version or -V Display version number of syslog-ng. Examples The following command generates 100 messages per second for ten minutes, and sends them to port 2010 of the localhost via TCP. Each message is 300 bytes long. loggen --size 300 --rate 100 --interval 600 127.0.0.1 2010 The following command is similar to the one above, but uses the UDP protocol. loggen --inet --dgram --size 300 --rate 100 --interval 600 127.0.0.1 2010 Send a single message on TCP6 to the ::1 IPv6 address, port 1061: loggen --ipv6 --number 1 ::1 1061 Send a single message on UDP6 to the ::1 IPv6 address, port 1061: loggen --ipv6 --dgram --number 1 ::1 1061 Send a single message using a unix domain-socket: loggen --unix --stream --number 1 </path/to/socket> Read messages from the standard input (stdio) and send them to the localhost: loggen 127.0.0.1 1061 --read-file - Files /opt/syslog-ng/bin/loggen See also syslog-ng.conf(5) For the detailed documentation of see The 3.13 Administrator Guide If you experience any problems or need help with syslog-ng, visit the syslog-ng mailing list. For news and notifications about of syslog-ng, visit the syslog-ng blogs. Author This manual page was written by the Balabit Documentation Team <documentation@balabit.com>. Copyright syslog-ng-syslog-ng-3.13.2/doc/man/pdbtool.1.xml000066400000000000000000000553161321171025300213130ustar00rootroot00000000000000 The pdbtool manual page pdbtool 1 3.13 pdbtool An application to test and convert syslog-ng pattern database rules pdbtool command options Description This manual page is only an abstract, for the complete documentation of syslog-ng and pdbtool, see The syslog-ng Administrator Guide. The syslog-ng application can match the contents of the log messages to a database of predefined message patterns (also called patterndb). By comparing the messages to the known patterns, syslog-ng is able to identify the exact type of the messages, tag the messages, and sort them into message classes. The message classes can be used to classify the type of the event described in the log message. The functionality of the pattern database is similar to that of the logcheck project, but the syslog-ng approach is faster, scales better, and is much easier to maintain compared to the regular expressions of logcheck. The pdbtool application is a utility that can be used to: test messages, or specific rules convert an older pattern database to the latest database format merge pattern databases into a single file automatically create pattern databases from a large amount of log messages dump the RADIX tree built from the pattern database (or a part of it) to explore how the pattern matching works. The dictionary command dictionary options Lists every name-value pair that can be set by the rules of the pattern database. --dump-tags or -T List the tags instead of the names of the name-value pairs. --pdb <path-to-file> or -p <path-to-file> Name of the pattern database file to use. --program <programname> or -P <programname> List only the name-value pairs that can be set for the messages of the specified $PROGRAM application. The dump command dump options Display the RADIX tree built from the patterns. This shows how are the patterns represented in syslog-ng and it might also help to track down pattern-matching problems. The dump utility can dump the tree used for matching the PROGRAM or the MESSAGE parts. --debug or -d Enable debug/diagnostic messages on stderr. --pdb or -p Name of the pattern database file to use. --program or -P Displays the RADIX tree built from the patterns belonging to the ${PROGRAM} application. --program-tree or -T Display the ${PROGRAM} tree. --verbose or -v Enable verbose messages on stderr. Example and sample output:pdbtool dump -p patterndb.xml -P 'sshd''p' 'assword for' @QSTRING:@ 'from' @QSTRING:@ 'port ' @NUMBER:@ rule_id='fc49054e-75fd-11dd-9bba-001e6806451b' ' ssh' rule_id='fc55cf86-75fd-11dd-9bba-001e6806451b' '2' rule_id='fc4b7982-75fd-11dd-9bba-001e6806451b' 'ublickey for' @QSTRING:@ 'from' @QSTRING:@ 'port ' @NUMBER:@ rule_id='fc4d377c-75fd-11dd-9bba-001e6806451b' ' ssh' rule_id='fc5441ac-75fd-11dd-9bba-001e6806451b' '2' rule_id='fc44a9fe-75fd-11dd-9bba-001e6806451b' The match command match options Use the match command to test the rules in a pattern database. The command tries to match the specified message against the patterns of the database, evaluates the parsers of the pattern, and also displays which part of the message was parsed successfully. The command returns with a 0 (success) or 1 (no match) return code and displays the following information: the class assigned to the message (that is, system, violation, and so on), the ID of the rule that matched the message, and the values of the parsers (if there were parsers in the matching pattern). The match command has the following options: --color-out or -c Color the terminal output to highlight the part of the message that was successfully parsed. --debug or -d Enable debug/diagnostic messages on stderr. --debug-csv or -C Print the debugging information returned by the --debug-pattern option as comma-separated values. --debug-pattern or -D Print debugging information about the pattern matching. See also the --debug-csv option. --file=<filename-with-path> or -f Process the messages of the specified log file with the pattern database. This option allows to classify messages offline, and to apply the pattern database to already existing logfiles. To read the messages from the standard input (stdin), specify a hyphen (-) character instead of a filename. --filter=<filter-expression> or -F Print only messages matching the specified syslog-ng filter expression. --message or -M The text of the log message to match (only the ${MESSAGE} part without the syslog headers). --pdb or -p Name of the pattern database file to use. --program or -P Name of the program to use, as contained in the ${PROGRAM} part of the syslog message. --template=<template-expression> or -T A syslog-ng template expression that is used to format the output messages. --verbose or -v Enable verbose messages on stderr. Example: The following command checks if the patterndb.xml file recognizes the Accepted publickey for myuser from 127.0.0.1 port 59357 ssh2 message: pdbtool match -p patterndb.xml -P sshd -M "Accepted publickey for myuser from 127.0.0.1 port 59357 ssh2" The following example applies the sshd.pdb pattern database file to the log messages stored in the /var/log/messages file, and displays only the messages that received a useracct tag. pdbtool match -p sshd.pdb \ –file /var/log/messages \ –filter ‘tags(“usracct”);’ The merge command merge options Use the merge command to combine separate pattern database files into a single file (pattern databases are usually stored in separate files per applications to simplify maintenance). If a file uses an older database format, it is automatically updated to the latest format (V3). See the The syslog-ng Administrator Guide for details on the different pattern database versions. --debug or -d Enable debug/diagnostic messages on stderr. --directory or -D The directory that contains the pattern database XML files to be merged. --glob or -G Specify filenames to be merged using a glob pattern, for example, using wildcards. For details on glob patterns, see man glob. This pattern is applied only to the filenames, and not on directory names. --pdb or -p Name of the output pattern database file. --recursive or -r Merge files from subdirectories as well. --verbose or -v Enable verbose messages on stderr. Example:pdbtool merge --recursive --directory /home/me/mypatterns/ --pdb /var/lib/syslog-ng/patterndb.xmlCurrently it is not possible to convert a file without merging, so if you only want to convert an older pattern database file to the latest format, you have to copy it into an empty directory. The patternize command patternize options Automatically create a pattern database from a log file containing a large number of log messages. The resulting pattern database is printed to the standard output (stdout). The pdbtool patternize command uses a data clustering technique to find similar log messages and replacing the differing parts with @ESTRING:: @ parsers. For details on pattern databases and message parsers, see the The syslog-ng Administrator Guide. The patternize command is available only in version 3.2 and later. --debug or -d Enable debug/diagnostic messages on stderr. --file=<path> or -f The logfile containing the log messages to create patterns from. To receive the log messages from the standard input (stdin), use -. --iterate-outliers or -o Recursively iterate on the log lines to cover as many log messages with patterns as possible. --named-parsers or -n The number of example log messages to include in the pattern database for every pattern. Default value: 1 --no-parse or -p Do not parse the input file, treat every line as the message part of a log message. --samples=<number-of-samples> Include a generated name in the parsers, for example, .dict.string1, .dict.string2, and so on. --support=<number> or -S A pattern is added to the output pattern database if at least the specified percentage of log messages from the input logfile match the pattern. For example, if the input logfile contains 1000 log messages and the --support=3.0 option is used, a pattern is created only if the pattern matches at least 3 percent of the log messages (that is, 30 log messages). If patternize does not create enough patterns, try to decrease the support value. Default value: 4.0 --verbose or -v Enable verbose messages on stderr. Example:pdbtool patternize --support=2.5 --file=/var/log/messages The test command test options Use the test command to validate a pattern database XML file. Note that you must have the xmllint application installed. The test command is available only in version 3.2 and later. --color-out or -c Enable coloring in terminal output. --debug or -d Enable debug/diagnostic messages on stderr. --debug or -D Print debugging information on non-matching patterns. --rule-id or -r Test only the patterndb rule (specified by its rule id) against its example. --validate Validate a pattern database XML file. --verbose or -v Enable verbose messages on stderr. Example:pdbtool test --validate /home/me/mypatterndb.pdb Files /opt/syslog-ng/ /opt/syslog-ng/etc/syslog-ng.conf See also The syslog-ng Administrator Guide syslog-ng.conf(5) syslog-ng(8) For the detailed documentation of see The 3.13 Administrator Guide If you experience any problems or need help with syslog-ng, visit the syslog-ng mailing list. For news and notifications about of syslog-ng, visit the syslog-ng blogs. Author This manual page was written by the Balabit Documentation Team <documentation@balabit.com>. Copyright syslog-ng-syslog-ng-3.13.2/doc/man/syslog-ng-ctl.1.xml000066400000000000000000000216421321171025300223450ustar00rootroot00000000000000 The syslog-ng control tool manual page syslog-ng-ctl 1 3.13 syslog-ng-ctl Display message statistics and enable verbose, debug and trace modes in syslog-ng-ctl command options Description NOTE: The syslog-ng-ctl application is distributed with the system logging application, and is usually part of the syslog-ng package. The latest version of the syslog-ng application is available at the official syslog-ng website. This manual page is only an abstract, for the complete documentation of syslog-ng, see The Administrator Guide. The syslog-ng-ctl application is a utility that can be used to: enable/disable various syslog-ng messages for troubleshooting display statistics about the processed messages reload the configuration of . Enabling troubleshooting messages command options Use the syslog-ng-ctl <command> --set=on command to display verbose, trace, or debug messages. If you are trying to solve configuration problems, the verbose (and occasionally trace) messages are usually sufficient. Debug messages are needed mostly for finding software errors. After solving the problem, do not forget to turn these messages off using the syslog-ng-ctl <command> --set=off. Note that enabling debug messages does not enable verbose and trace messages. Use syslog-ng-ctl <command> without any parameters to display whether the particular type of messages are enabled or not. If you need to use a non-standard control socket to access syslog-ng, use the syslog-ng-ctl <command> --set=on --control=<socket> command to specify the socket to use. verbose Print verbose messages. If syslog-ng was started with the --stderr or -e option, the messages will be sent to stderr. If not specified, syslog-ng will log such messages to its internal source. trace Print trace messages of how messages are processed. If syslog-ng was started with the --stderr or -e option, the messages will be sent to stderr. If not specified, syslog-ng will log such messages to its internal source. debug Print debug messages. If syslog-ng was started with the --stderr or -e option, the messages will be sent to stderr. If not specified, syslog-ng will log such messages to its internal source. Example:syslog-ng-ctl verbose --set=on The stats command stats options Use the stats command to display statistics about the processed messages. The stats command has the following options: --control=<socket> or -c Specify the socket to use to access syslog-ng. Only needed when using a non-standard socket. --reset or -r Reset all statistics to zero, except for the stored counters. (The stored counters show the number of messages stored in the message queue of the destination driver, waiting to be sent to the destination.) Example:syslog-ng-ctl stats An example output: src.internal;s_all#0;;a;processed;6445 src.internal;s_all#0;;a;stamp;1268989330 destination;df_auth;;a;processed;404 destination;df_news_dot_notice;;a;processed;0 destination;df_news_dot_err;;a;processed;0 destination;d_ssb;;a;processed;7128 destination;df_uucp;;a;processed;0 source;s_all;;a;processed;7128 destination;df_mail;;a;processed;0 destination;df_user;;a;processed;1 destination;df_daemon;;a;processed;1 destination;df_debug;;a;processed;15 destination;df_messages;;a;processed;54 destination;dp_xconsole;;a;processed;671 dst.tcp;d_network#0;10.50.0.111:514;a;dropped;5080 dst.tcp;d_network#0;10.50.0.111:514;a;processed;7128 dst.tcp;d_network#0;10.50.0.111:514;a;stored;2048 destination;df_syslog;;a;processed;6724 destination;df_facility_dot_warn;;a;processed;0 destination;df_news_dot_crit;;a;processed;0 destination;df_lpr;;a;processed;0 destination;du_all;;a;processed;0 destination;df_facility_dot_info;;a;processed;0 center;;received;a;processed;0 destination;df_kern;;a;processed;70 center;;queued;a;processed;0 destination;df_facility_dot_err;;a;processed;0 Reloading the configuration command options Use the syslog-ng-ctl reload command to reload the configuration file of without having to restart the application. The syslog-ng-ctl reload works like a SIGHUP. Files /opt/syslog-ng/sbin/syslog-ng-ctl See also The syslog-ng Administrator Guide syslog-ng.conf(5) syslog-ng(8) For the detailed documentation of see The 3.13 Administrator Guide If you experience any problems or need help with syslog-ng, visit the syslog-ng mailing list. For news and notifications about of syslog-ng, visit the syslog-ng blogs. Author This manual page was written by the Balabit Documentation Team <documentation@balabit.com>. Copyright syslog-ng-syslog-ng-3.13.2/doc/man/syslog-ng-debun.1.xml000066400000000000000000000265341321171025300226650ustar00rootroot00000000000000 The syslog-ng-debun manual page syslog-ng-debun 1 3.13 syslog-ng-debun syslog-ng DEBUg buNdle generator syslog-ng-debun options Description NOTE: The syslog-ng-debun application is distributed with the system logging application, and is usually part of the package. The latest version of the application is available at . This manual page is only an abstract, for the complete documentation of syslog-ng, see The syslog-ng Administrator Guide. The syslog-ng-debun tool collects and saves information about your installation, making troubleshooting easier, especially if you ask help about your related problem. General Options -r Run syslog-ng-debun. Using this option is required to actually execute the data collection with syslog-ng-debun. It is needed to prevent accidentally running syslog-ng-debun. -h Display the help page. -l Do not collect privacy-sensitive data, for example, process tree, fstab, and so on. If you use with -d, then the following parameters will be used for debug mode:-Fev -R <directory> The directory where is installed instead of /opt/syslog-ng. -W <directory> Set the working directory, where the debug bundle will be saved. Default value: /tmp. The name of the created file is syslog.debun.${host}.${date}.${3-random-characters-or-pid}.tgz Debug mode options -d Start in debug mode, using the -Fedv --enable-core options. Warning! Using this option under high message load may increase disk I/O during the debug, and the resulting debug bundle can be huge. To exit debug mode, press Enter. -D <options> Start in debug mode, using the specified command-line options. To exit debug mode, press Enter. For details on the available options, see . -t <seconds> Run in noninteractive debug mode for <seconds>, and automatically exit debug mode after the specified number of seconds. -w <seconds> Wait <seconds> seconds before starting debug mode. System call tracing -s Enable syscall tracing (strace -f or truss -f). Note that using -s itself does not enable debug mode, only traces the system calls of an already running process. To trace system calls in debug mode, use both the -s and -d options. Packet capture options Capturing packets requires a packet capture tool on the host. The syslog-ng-debun tool attempts to use tcpdump on most platforms, except for Solaris, where it uses snoop. -i <interface> Capture packets only on the specified interface, for example, eth0. -p Capture incoming packets using the following filter: port 514 or port 601 or port 53 -P <options> Capture incoming packets using the specified filter. -t <seconds> Run in noninteractive debug mode for <seconds>, and automatically exit debug mode after the specified number of seconds. Examples syslog-ng-debun -r Create a simple debug bundle, collecting information about your environment, for example, list packages containing the word: syslog, ldd of your syslog-binary, and so on. syslog-ng-debun -r -l Similar to syslog-ng-debun -r, but without privacy-sensitive information. For example, the following is NOT collected: fstab, df output, mount info, ip / network interface configuration, DNS resolv info, and process tree. syslog-ng-debun -r -d Similar to syslog-ng-debun -r, but it also stops syslog-ng, then restarts it in debug mode (-Fedv --enable-core). To stop debug mode, press Enter. The output of the debug mode collected into a separate file, and also added to the debug bundle. syslog-ng-debun -r -s Trace the system calls (using strace or truss) of an already running process. syslog-ng-debun -r -d -s Restart in debug mode, and also trace the system calls (using strace or truss) of the process. syslog-ng-debun -r -p Run packet capture (pcap) with the filter: port 514 or port 601 or port 53 Also waits for pressing Enter, like debug mode. syslog-ng-debun -r -p -t 10 Noninteractive debug mode: Similar to syslog-ng-debun -r -p, but automatically exit after 10 seconds. syslog-ng-debun -r -P "host 1.2.3.4" -D "-Fev --enable-core" Change the packet-capturing filter from the default to host 1.2.3.4. Also change debugging parameters from the default to -Fev --enable-core. Since a timeout (-t) is not given, waits for pressing Enter. syslog-ng-debun -r -p -d -w 5 -t 10 Collect pcap and debug mode output following this scenario: Start packet capture with default parameters (-p) Wait 5 seconds (-w 5) Stop syslog-ng Start syslog-ng in debug mode with default parameters (-d) Wait 10 seconds (-t 10) Stop syslog-ng debuging Start syslog-ng Stop packet capturing Files /opt/syslog-ng/bin/loggen See also syslog-ng.conf(5) For the detailed documentation of see The 3.13 Administrator Guide If you experience any problems or need help with syslog-ng, visit the syslog-ng mailing list. For news and notifications about of syslog-ng, visit the syslog-ng blogs. Author This manual page was written by the Balabit Documentation Team <documentation@balabit.com>. Copyright syslog-ng-syslog-ng-3.13.2/doc/man/syslog-ng.8.xml000066400000000000000000000442341321171025300215760ustar00rootroot00000000000000 The syslog-ng manual page syslog-ng 8 3.13 syslog-ng syslog-ng system logger application syslog-ng options Description This manual page is only an abstract, for the complete documentation of syslog-ng, see The Administrator Guide or the official syslog-ng website. The application is a flexible and highly scalable system logging application. Typically, syslog-ng is used to manage log messages and implement centralized logging, where the aim is to collect the log messages of several devices on a single, central log server. The different devices - called syslog-ng clients - all run syslog-ng, and collect the log messages from the various applications, files, and other sources. The clients send all important log messages to the remote syslog-ng server, where the server sorts and stores them. Options --caps --caps caps Run process with the specified POSIX capability flags. If the --no-caps option is not set, and the host supports CAP_SYSLOG, uses the following capabilities: "cap_net_bind_service, cap_net_broadcast, cap_net_raw, cap_dac_read_search, cap_dac_override, cap_chown, cap_fowner=p cap_syslog=ep" If the --no-caps option is not set, and the host does not support CAP_SYSLOG, uses the following capabilities: "cap_net_bind_service, cap_net_broadcast, cap_net_raw,cap_dac_read_search, cap_dac_override, cap_chown, cap_fowner=p cap_sys_admin=ep" For example: /opt/syslog-ng/sbin/syslog-ng -Fv --caps cap_sys_admin,cap_chown,cap_dac_override,cap_net_bind_service,cap_fowner=pi Note that the capabilities are not case sensitive, the following command is also good: /opt/syslog-ng/sbin/syslog-ng -Fv --caps CAP_SYS_ADMIN,CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_NET_BIND_SERVICE,CAP_FOWNER=pi For details on the capability flags, see the following man pages: cap_from_text(3) and capabilities(7) --cfgfile <file> or -f <file> --cfgfile cfgfile Use the specified configuration file. --chroot <dir> or -C <dir> --chroot chroot Change root to the specified directory. The configuration file is read after chrooting so, the configuration file must be available within the chroot. That way it is also possible to reload the syslog-ng configuration after chrooting. However, note that the --user and --group options are resolved before chrooting. --control <file> or -c <file> Set the location of the syslog-ng control socket. Default value: /var/run/syslog-ng.ctl --debug or -d --debug debug Start syslog-ng in debug mode. --default-modules --default-modules default-modules A comma-separated list of the modules that are loaded automatically. Modules not loaded automatically can be loaded by including the @module <modulename> statement in the configuration file. The following modules are loaded by default: . Available only in and later. --enable-core --enable-core enable-core Enable syslog-ng to write core files in case of a crash to help support and debugging. --fd-limit <number> --fd-limit fd-limit Set the minimal number of required file descriptors (fd-s). This sets how many files syslog-ng can keep open simultaneously. Default value: 4096. Note that this does not override the global ulimit setting of the host. --foreground or -F --foreground foreground Do not daemonize, run in the foreground. When running in the foreground, starts from the current directory ($CWD) so it can create core files (normally, starts from $PREFIX/var). --group <group> or -g <group> --group group Switch to the specified group after initializing the configuration file. --help or -h --help help Display a brief help message. --module-registry --module-registry module-registry Display the list and description of the available modules. Note that not all of these modules are loaded automatically, only the ones specified in the --default-modules option. Available only in and later. --no-caps --no-caps no-caps Run syslog-ng as root, without capability-support. This is the default behavior. On Linux, it is possible to run syslog-ng as non-root with capability-support if syslog-ng was compiled with the --enable-linux-caps option enabled. (Execute syslog-ng --version to display the list of enabled build parameters.) To run with specific capabilities, use the --caps option. --persist-file <persist-file> or -R <persist-file> --persist-file persist-file Set the path and name of the syslog-ng.persist file where the persistent options and data are stored. --pidfile <pidfile> or -p <pidfile> --pidfile pidfile Set path to the PID file where the pid of the main process is stored. --preprocess-into <output-file> --preprocess-into preprocess-into After processing the configuration file and resolving included files and variables, write the resulting configuration into the specified output file. Available only in and later. --process-mode <mode> --process-mode process-mode Sets how to run syslog-ng: in the foreground (mainly used for debugging), in the background as a daemon, or in safe-background mode. By default, syslog-ng runs in safe-background mode. This mode creates a supervisor process called supervising syslog-ng , that restarts syslog-ng if it crashes. --stderr or -e --stderr stderr Log internal messages of syslog-ng to stderr. Mainly used for debugging purposes in conjunction with the --foreground option. If not specified, syslog-ng will log such messages to its internal source. --syntax-only or -s --syntax-only syntax-only Verify that the configuration file is syntactically correct and exit. --user <user> or -u <user> --user user Switch to the specified user after initializing the configuration file (and optionally chrooting). Note that it is not possible to reload the syslog-ng configuration if the specified user has no privilege to create the /dev/log file. --verbose or -v --verbose verbose Enable verbose logging used to troubleshoot syslog-ng. --version or -V --version version Display version number and compilation information, and also the list and short description of the available modules. For detailed description of the available modules, see the --module-registry option. Note that not all of these modules are loaded automatically, only the ones specified in the --default-modules option. --worker-threads --worker-threads worker-threads Sets the number of worker threads can use, including the main thread. Note that certain operations in can use threads that are not limited by this option. This setting has effect only when is running in multithreaded mode. Available only in and later. See The 3.13 Administrator Guide for details. Files /opt/syslog-ng/ /opt/syslog-ng/etc/syslog-ng.conf See also syslog-ng.conf(5) For the detailed documentation of see The 3.13 Administrator Guide If you experience any problems or need help with syslog-ng, visit the syslog-ng mailing list. For news and notifications about of syslog-ng, visit the syslog-ng blogs. Author This manual page was written by the Balabit Documentation Team <documentation@balabit.com>. Copyright syslog-ng-syslog-ng-3.13.2/doc/man/syslog-ng.conf.5.xml000066400000000000000000000622121321171025300225130ustar00rootroot00000000000000 The syslog-ng.conf manual page syslog-ng.conf 5 3.13 syslog-ng.conf syslog-ng configuration file syslog-ng.conf Description This manual page is only an abstract, for the complete documentation of syslog-ng, see The Administrator Guide or the official syslog-ng website. The application is a flexible and highly scalable system logging application. Typically, syslog-ng is used to manage log messages and implement centralized logging, where the aim is to collect the log messages of several devices on a single, central log server. The different devices - called syslog-ng clients - all run syslog-ng, and collect the log messages from the various applications, files, and other sources. The clients send all important log messages to the remote syslog-ng server, where the server sorts and stores them. Basic concepts of The syslog-ng application reads incoming messages and forwards them to the selected destinations. The syslog-ng application can receive messages from files, remote hosts, and other sources. destinations Log messages enter syslog-ng in one of the defined sources, and are sent to one or more destinations. log paths log statements log paths Sources and destinations are independent objects, log paths define what syslog-ng does with a message, connecting the sources to the destinations. A log path consists of one or more sources and one or more destinations: messages arriving from a source are sent to every destination listed in the log path. A log path defined in syslog-ng is called a log statement. filters Optionally, log paths can include filters. Filters are rules that select only certain messages, for example, selecting only messages sent by a specific application. If a log path includes filters, syslog-ng sends only the messages satisfying the filter rules to the destinations set in the log path. parsers rewrite rules Other optional elements that can appear in log statements are parsers and rewriting rules. Parsers segment messages into different fields to help processing the messages, while rewrite rules modify the messages by adding, replacing, or removing parts of the messages. Configuring syslog-ng The main body of the configuration file consists of object definitions: sources, destinations, logpaths define which log message are received and where they are sent. All identifiers, option names and attributes, and any other strings used in the syslog-ng configuration file are case sensitive. Object definitions (also called statements) have the following syntax: type-of-the-object identifier-of-the-object {<parameters>}; Type of the object: One of source, destination, log, filter, parser, rewrite rule, or template. Identifier of the object: A unique name identifying the object. When using a reserved word as an identifier, enclose the identifier in quotation marks. All identifiers, attributes, and any other strings used in the syslog-ng configuration file are case sensitive. Use identifiers that refer to the type of the object they identify. For example, prefix source objects with s_, destinations with d_, and so on. Repeating a definition of an object (that is, defining the same object with the same id more than once) is not allowed, unless you use the @define allow-config-dups 1 definition in the configuration file. Parameters: The parameters of the object, enclosed in braces {parameters}. Semicolon: Object definitions end with a semicolon (;). For example, the following line defines a source and calls it s_internal. source s_internal { internal(); }; The object can be later referenced in other statements using its ID, for example, the previous source is used as a parameter of the following log statement: log { source(s_internal); destination(d_file); }; The parameters and options within a statement are similar to function calls of the C programming language: the name of the option followed by a list of its parameters enclosed within brackets and terminated with a semicolon. option(parameter1, parameter2); option2(parameter1, parameter2); For example, the file() driver in the following source statement has three options: the filename (/var/log/apache/access.log), follow-freq(), and flags(). The follow-freq() option also has a parameter, while the flags() option has two parameters. source s_tail { file("/var/log/apache/access.log" follow-freq(1) flags(no-parse, validate-utf8)); }; Objects may have required and optional parameters. Required parameters are positional, meaning that they must be specified in a defined order. Optional parameters can be specified in any order using the option(value) format. If a parameter (optional or required) is not specified, its default value is used. The parameters and their default values are listed in the reference section of the particular object. Using required and optional parameters The unix-stream() source driver has a single required argument: the name of the socket to listen on. Optional parameters follow the socket name in any order, so the following source definitions have the same effect: source s_demo_stream1 { unix-stream("<path-to-socket>" max-connections(10) group(log)); }; source s_demo_stream2 { unix-stream("<path-to-socket>" group(log) max-connections(10)); }; Some options are global options, or can be set globally, for example, whether should use DNS resolution to resolve IP addresses. Global options are detailed in . options { use-dns(no); }; Objects can be used before definition. Objects can be defined inline as well. This is useful if you use the object only once (for example, a filter). For details, see . To add comments to the configuration file, start a line with # and write your comments. These lines are ignored by syslog-ng. # Comment: This is a stream source source s_demo_stream { unix-stream("<path-to-socket>" max-connections(10) group(log)); }; The syntax of log statements is as follows: log { source(s1); source(s2); ... optional_element(filter1|parser1|rewrite1); optional_element(filter2|parser2|rewrite2); ... destination(d1); destination(d2); ... flags(flag1[, flag2...]); }; The following log statement sends all messages arriving to the localhost to a remote server. source s_localhost { network(ip(127.0.0.1) port(1999)); }; destination d_tcp { network("10.1.2.3" port(1999) localport(999)); }; log { source(s_localhost); destination(d_tcp); }; The syslog-ng application has a number of global options governing DNS usage, the timestamp format used, and other general points. Each option may have parameters, similarly to driver specifications. To set global options, add an option statement to the syslog-ng configuration file using the following syntax: options { option1(params); option2(params); ... }; Using global options To disable domain name resolving, add the following line to the syslog-ng configuration file: options { use-dns(no); }; The sources, destinations, and filters available in syslog-ng are listed below. For details, see The syslog-ng Administrator Guide. Source drivers available in syslog-ng source drivers list of Name Description file() Opens the specified file and reads messages. internal() Messages generated internally in syslog-ng. network() Receives messages from remote hosts using the BSD-syslog protocol over IPv4 and IPv6. Supports the TCP, UDP, and TLS network protocols. pipe() Opens the specified named pipe and reads messages. program() Opens the specified application and reads messages from its standard output. sun-stream(), sun-streams() Opens the specified STREAMS device on Solaris systems and reads incoming messages. syslog() Listens for incoming messages using the new IETF-standard syslog protocol. system() Automatically detects which platform is running on, and collects the native log messages of that platform. systemd-journal() Collects messages directly from the journal of platforms that use systemd. systemd-syslog() Collects messages from the journal using a socket on platforms that use systemd. unix-dgram() Opens the specified unix socket in SOCK_DGRAM mode and listens for incoming messages. unix-stream() Opens the specified unix socket in SOCK_STREAM mode and listens for incoming messages.
Destination drivers available in syslog-ng destination drivers list of Name Description elasticsearch and elasticsearch2 Sends messages to an Elasticsearch server. The elasticsearch2 driver supports Elasticsearch version 2 and newer. file() Writes messages to the specified file. hdfs() Sends messages into a file on a Hadoop Distributed File System (HDFS) node. kafka() Publishes log messages to the Apache Kafka message bus, where subscribers can access them. loggly() Sends log messages to the Loggly Logging-as-a-Service provider. logmatic() Sends log messages to the Logmatic.io Logging-as-a-Service provider. mongodb() Sends messages to a MongoDB database. network() Sends messages to a remote host using the BSD-syslog protocol over IPv4 and IPv6. Supports the TCP, UDP, and TLS network protocols. pipe() Writes messages to the specified named pipe. program() Forks and launches the specified program, and sends messages to its standard input. sql() Sends messages into an SQL database. In addition to the standard syslog-ng packages, the sql() destination requires database-specific packages to be installed. Refer to the section appropriate for your platform in . syslog() Sends messages to the specified remote host using the IETF-syslog protocol. The IETF standard supports message transport using the UDP, TCP, and TLS networking protocols. unix-dgram() Sends messages to the specified unix socket in SOCK_DGRAM style (BSD). unix-stream() Sends messages to the specified unix socket in SOCK_STREAM style (Linux). usertty() Sends messages to the terminal of the specified user, if the user is logged in.
Filter functions available in filter functions list of Name Description facility() Filter messages based on the sending facility. filter() Call another filter function. host() Filter messages based on the sending host. inlist() File-based whitelisting and blacklisting. level() or priority() Filter messages based on their priority. match() Use a regular expression to filter messages based on a specified header or content field. message() Use a regular expression to filter messages based on their content. netmask() Filter messages based on the IP address of the sending host. program() Filter messages based on the sending application. source() Select messages of the specified source statement. tags() Select messages having the specified tag.
Files /opt/syslog-ng/ /opt/syslog-ng/etc/syslog-ng.conf See also syslog-ng(8) For the detailed documentation of see The 3.13 Administrator Guide If you experience any problems or need help with syslog-ng, visit the syslog-ng mailing list. For news and notifications about of syslog-ng, visit the syslog-ng blogs. Author This manual page was written by the Balabit Documentation Team <documentation@balabit.com>. Copyright
syslog-ng-syslog-ng-3.13.2/doc/man/update-manpages.sh000077500000000000000000000033111321171025300223650ustar00rootroot00000000000000#!/usr/bin/env bash ############################################################################# # Copyright (c) 2017 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# GUIDE_REPO=syslog-ng-ose-guides PROJECT_DIR=$(dirname $(realpath ${BASH_SOURCE})) set -e echo -e "\e[33;1mDownload admin guide\e[0m" cd $PROJECT_DIR rm -rf $GUIDE_REPO git clone git@github.com:balabit/${GUIDE_REPO}.git cd $GUIDE_REPO/en echo -e "\e[33;1mBuild profiled XML source files\e[0m" make manpages echo -e "\e[33;1mUpdate manpage source files\e[0m" cd $PROJECT_DIR rm *.xml for new_file in $GUIDE_REPO/en/out/tmp/man/*.profiled.xml; do original=$(basename ${new_file/.profiled/}) echo "Updating file '$original'" cp "$new_file" "./$original" done rm -rf $GUIDE_REPO echo -e "\e[33;1mDONE.\e[0m" git status syslog-ng-syslog-ng-3.13.2/doc/security/000077500000000000000000000000001321171025300200515ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/doc/security/bof-2002-09-27.txt000066400000000000000000000042761321171025300224260ustar00rootroot00000000000000 BalaBit security advisory Advisory ID: BB-2002/01 Package: syslog-ng Versions affected: versions prior to and including 1.5.20 Problem type: buffer overflow Exploitable: yes Date: 2002-09-27 1) Background syslog-ng is a portable syslog implementation. Its highlights include regexp based log selection, TCP transport and more. For more information: http://www.balabit.hu/en/downloads/syslog-ng/ 2) Problem description To make it easier to specify message destinations, syslog-ng supports macros in destination filenames as the following log snippet shows: destination d_messages_by_host { file("/var/log/$HOST/messages"); }; The same syntax is used when specifying the contents of destination files: destination d_special_messages { file("/var/log/messages" template("$ISODATE $HOST $MSG\n")); }; The problem lies in the way macro expansion handles constant characters. (ie everything other than macro references). As syslog-ng expands macros it uses a buffer, and a variable called 'left', which contains the number of characters available in the buffer. When a constant character is appended, this variable is not decremented, thus when expanding macros incorrect bounds checking is performed. 3) Impact If templated filenames or templated output is used, it is possible to overflow a buffer. The number of bytes exceeding the allocated buffer depends on the exact template being used. It is believed that this overflow can be exploited, given enough constant characters are present in the template string. 4) Solution Upgrade syslog-ng to 1.5.21 (devel) or 1.4.16 (stable) or apply the following patch: diff -u -r1.52 -r1.53 --- affile.c 21 Aug 2002 14:03:50 -0000 1.52 +++ affile.c 27 Sep 2002 09:11:33 -0000 1.53 @@ -859,7 +859,7 @@ { "SOURCEIP", M_SOURCE_IP } }; char format[cfg->log_msg_size + 1], *format_ptr = format; - int left = sizeof(format); + int left = sizeof(format) - 1; int i, j; i = 0; @@ -888,6 +888,7 @@ *format_ptr = template->data[i]; format_ptr++; i++; + left--; } } *format_ptr = 0; syslog-ng-syslog-ng-3.13.2/doc/security/dos-2000-11-22.txt000066400000000000000000000042351321171025300224220ustar00rootroot00000000000000 BalaBit security advisory Advisory ID: BB-2000/01 Package: syslog-ng Versions affected: versions prior to and including 1.4.8 Problem type: remote DoS attack Date: 2000-11-22 1) Background syslog-ng is a portable syslog implementation. Its highlights include regexp based log selection, TCP transport and more. For more information: http://www.balabit.hu/products/syslog-ng/ 2) Problem description When syslog-ng parses log messages a variable named "left" is used to store the remaining length of the log message. The priority part in the message should look like this: <6> When the line ends without the closing '>' this "left" variable becomes -1 due a to a bug. The remaining part of the message parsing routine checks if there's any characters left using the condition: left != 0, since -1 is not 0, this condition evaluates to true. Syslog-ng versions after 1.4.7 filters out \r and \n characters from log messages and replaces them with spaces to avoid cluttering logfiles. Due to a problem in the parsing of log messages, this character change may access unaccessible memory region. This causes a segmentation fault. So sending a "<6", terminated with a newline to one of the input channels causes a SIGSEGV. Prior to 1.4.7, this character change was not implemented, so mounting a DoS attack is not so trivial, but is still possible. (it's left to the reader as an exercise) It is believed that no other exploitation is possible. 3) Impact Sending a carefully crafted syslog packet may cause syslog-ng to exit with a Segmentation Fault. 4) Solution Upgrade syslog-ng to 1.4.9, which is a security upgrade, and changes nothing compared to 1.4.8 or apply this patch: diff -urN syslog-ng-1.4.8/src/log.c syslog-ng-1.4.9/src/log.c --- syslog-ng-1.4.8/src/log.c Tue Oct 10 15:05:52 2000 +++ syslog-ng-1.4.9/src/log.c Wed Nov 22 16:45:11 2000 @@ -67,8 +67,10 @@ left--; } lm->pri = pri; - src++; - left--; + if (left) { + src++; + left--; + } } else { lm->pri = LOG_USER | LOG_NOTICE; syslog-ng-syslog-ng-3.13.2/doc/xsd/000077500000000000000000000000001321171025300170005ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/doc/xsd/examples/000077500000000000000000000000001321171025300206165ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/doc/xsd/examples/patterndb-1.xml000066400000000000000000000021041321171025300234560ustar00rootroot00000000000000 p-p p-desc p-url p1 p2 url2 d2 p-p2 p-p 3p1 syslog-ng-syslog-ng-3.13.2/doc/xsd/patterndb-1.xsd000066400000000000000000000171511321171025300216460ustar00rootroot00000000000000 A container to group log patterns for an application/program. The schema version of the pattern database. The current version is '1'. The publication date of the XML file. An optional element to attach description to an application/program. An optional element to point to the homepage of the application. The pattern representing the name of the application in the syslog program field. The patterns for the application. A rule describes one log pattern with classifications and details. The name of the application. The globaly unique ID of the application. FIXME: how it is generated? (simple md5 of the @name?) An optional element to describe the log disposition. An optional element to point to some external resource for disposition. The pattern representing the log message. The provider of the rule. To distinguish between who supplied the rule, or if it has been added to the xml by a local user. The globaly unique ID of the rule. FIXME: how it is generated? (simple md5 of the @name?) The class of the rule. This type describes a radix/parser pattern which is used to match a program name or a whole log message. The classification class for a single rule. The log message is a VIOLATION where immediate action must be taken. The log message is related to a SECURITY event. The log message is related to a normal SYSTEM event. The log message is UNKNOWN and as is an anomaly. syslog-ng-syslog-ng-3.13.2/doc/xsd/patterndb-2.xsd000066400000000000000000000231021321171025300216400ustar00rootroot00000000000000 A container to group log patterns for an application/program. The schema version of the pattern database. The current version is '2'. The publication date of the XML file. An optional element to attach description to a ruleset. An optional element to point to a URL related to the ruleset. An optional element with a pattern representing the name of the application related to the ruleset in the syslog program field. The rules in the ruleset. A rule describes one log event with classifications and details. The name of the application. An optional element to describe the log disposition. Optional elements to point to some external resource for disposition. Optional keywords that can be used for a freeform grouping of the rules. Patterns representing the rule. Log messages matching any one of the patterns are classified to this rule. A pattern representing the log message. The provider of the rule. To distinguish between who supplied the rule, or if it has been added to the xml by a local user. The class of the rule. The globaly unique ID of the rule. This type describes a radix/parser pattern which is used to match a program name or a whole log message. The classification class for a single rule. The log message is a VIOLATION where immediate action must be taken. The log message is related to a SECURITY event. The log message is related to a normal SYSTEM event. The log message is UNKNOWN and as is an anomaly. syslog-ng-syslog-ng-3.13.2/doc/xsd/patterndb-3.xsd000066400000000000000000000307361321171025300216540ustar00rootroot00000000000000 A container to group log patterns for an application/program. The schema version of the pattern database. The current version is '3'. The publication date of the XML file. An optional element to attach description to a ruleset. An optional element to point to a URL related to the ruleset. An optional element with a pattern representing the name of the application related to the ruleset in the syslog program field. The rules in the ruleset. A rule describes one log event with classifications and details. The name of the application. An optional element to describe the log disposition. Optional elements to point to some external resource for disposition. Optional values that are added after template evaluation to messages Optional examples to test rule patterns and configuration Optional keywords that can be used for a freeform grouping of the rules. Patterns representing the rule. Log messages matching any one of the patterns are classified to this rule. A pattern representing the log message. The provider of the rule. To distinguish between who supplied the rule, or if it has been added to the xml by a local user. The class of the rule. This describes a UUID syntax. Currently it is not used for the IDing to avoid enforcing the use of UUIDs, which some users complained about. Once the decision on the rule id format happens this may completely be removed. This type describes a radix/parser pattern which is used to match a program name or a whole log message. The classification class for a single rule. The example message to test rule patterns syslog-ng-syslog-ng-3.13.2/doc/xsd/patterndb-4.xsd000066400000000000000000000506371321171025300216570ustar00rootroot00000000000000 A container to group log patterns for an application/program. The schema version of the pattern database. The current version is '4'. The publication date of the XML file. An optional element to attach description to a ruleset. An optional element to point to a URL related to the ruleset. If an application uses multiple values for its program name, then you can list them all in a patterns element containing multiple pattern elements. An optional element with a pattern representing the name of the application related to the ruleset in the syslog program field. An optional element with a pattern representing the name of the application related to the ruleset in the syslog program field. The rules in the ruleset. A rule describes one log event with classifications and details. The name of the application. An optional element to describe the log disposition. Optional elements to point to some external resource for disposition. Optional values that are added after template evaluation to messages Optional examples to test rule patterns and configuration Optional keywords that can be used for a freeform grouping of the rules. Patterns representing the rule. Log messages matching any one of the patterns are classified to this rule. A pattern representing the log message. The provider of the rule. To distinguish between who supplied the rule, or if it has been added to the xml by a local user. The class of the rule. The message to be generated when the action triggers. A filter expression guarding the triggering of this action. If the filter evaluates to TRUE the action is executed, otherwise it is skipped. The maximum rate at which this action is executed. Excess actions are ignored. Specifies when the action is to be executed. Specifies that the action is to be executed when the correllation timeout elapses without matching a further rule. Specifies that the action is to be executed immediately as the rule matches. Name-value pairs that make up the message to be generated. Optional keywords that can be used for a freeform grouping of the rules. If set to TRUE, the original message that triggered the action is cloned, including its name-value pairs and tags. For details, see Section 13.4, Triggering actions for identified messages. This describes a UUID syntax. Currently it is not used for the IDing to avoid enforcing the use of UUIDs, which some users complained about. Once the decision on the rule id format happens this may completely be removed. This type describes a radix/parser pattern which is used to match a program name or a whole log message. The classification class for a single rule. The example message to test rule patterns syslog-ng-syslog-ng-3.13.2/doc/xsd/patterndb-5.xsd000066400000000000000000000600611321171025300216500ustar00rootroot00000000000000 A container to group log patterns for an application/program. The schema version of the pattern database. The current version is '5'. The publication date of the XML file. An optional element to attach description to a ruleset. An optional element to point to a URL related to the ruleset. Optional elements to point to some external resource for disposition. If an application uses multiple values for its program name, then you can list them all in a patterns element containing multiple pattern elements. An optional element with a pattern representing the name of the application related to the ruleset in the syslog program field. An optional element with a pattern representing the name of the application related to the ruleset in the syslog program field. The rules in the ruleset. A rule describes one log event with classifications and details. The name of the application. An optional element to describe the log disposition. Optional elements to point to some external resource for disposition. Optional values that are added after template evaluation to messages Optional examples to test rule patterns and configuration Optional keywords that can be used for a freeform grouping of the rules. Patterns representing the rule. Log messages matching any one of the patterns are classified to this rule. A pattern representing the log message. The provider of the rule. To distinguish between who supplied the rule, or if it has been added to the xml by a local user. The class of the rule. The message to be generated when the action triggers. The context to be created when the action is triggered. A filter expression guarding the triggering of this action. If the filter evaluates to TRUE the action is executed, otherwise it is skipped. The maximum rate at which this action is executed. Excess actions are ignored. Specifies when the action is to be executed. Specifies that the action is to be executed when the correllation timeout elapses without matching a further rule. Specifies that the action is to be executed immediately as the rule matches. Name-value pairs that make up the message to be generated. Optional keywords that can be used for a freeform grouping of the rules. If set to TRUE, the original message that triggered the action is cloned, including its name-value pairs and tags. For details, see Section 13.4, Triggering actions for identified messages. NOTE: This attribute is deprecated in favour of inherit-mode. This attribute is used to control which set of name-value pairs are propagated to the newly generated message. "context" means that the new message is populated with a union of all name-value pairs present in messages in the context. "last-message" means that only name-value pairs of the last message is copied. "none" means that the new message becomes empty initially. For details, see Section 13.4, Triggering actions for identified messages. The message that gets added to the new context to be created. This describes a UUID syntax. Currently it is not used for the IDing to avoid enforcing the use of UUIDs, which some users complained about. Once the decision on the rule id format happens this may completely be removed. This type describes a radix/parser pattern which is used to match a program name or a whole log message. The classification class for a single rule. The example message to test rule patterns syslog-ng-syslog-ng-3.13.2/lib/000077500000000000000000000000001321171025300162035ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/.gitignore000066400000000000000000000000401321171025300201650ustar00rootroot00000000000000m4 .arch-ids .arch-inventory *~ syslog-ng-syslog-ng-3.13.2/lib/CMakeLists.txt000066400000000000000000000174761321171025300207620ustar00rootroot00000000000000flex_target(CfgLexer ${PROJECT_SOURCE_DIR}/lib/cfg-lex.l ${PROJECT_BINARY_DIR}/lib/cfg-lex.c ${PROJECT_BINARY_DIR}/lib/cfg-lex.h) bison_target(CfgGrammar ${PROJECT_SOURCE_DIR}/lib/cfg-grammar.y ${PROJECT_BINARY_DIR}/lib/cfg-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) add_flex_bison_dependency(CfgLexer CfgGrammar) add_subdirectory(compat) add_subdirectory(control) add_subdirectory(debugger) add_subdirectory(filter) add_subdirectory(logmsg) add_subdirectory(logproto) add_subdirectory(parser) add_subdirectory(rewrite) add_subdirectory(stats) add_subdirectory(template) add_subdirectory(transport) add_subdirectory(value-pairs) add_subdirectory(scanner) add_subdirectory(str-repr) set(LIB_SUBDIR_HEADERS ${COMPAT_HEADERS} ${CONTROL_HEADERS} ${DEBUGGER_HEADERS} ${FILTER_HEADERS} ${LOGMSG_HEADERS} ${LOGPROTO_HEADERS} ${PARSER_HEADERS} ${REWRITE_HEADERS} ${STATS_HEADERS} ${TEMPLATE_HEADERS} ${TRANSPORT_HEADERS} ${VALUE_PAIRS_HEADERS} ${CSV_SCANNER_HEADERS} ${LIST_SCANNER_HEADERS} ${KV_SCANNER_HEADERS} ${STR_REPR_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/filter/filter-expr-grammar.h ${CMAKE_CURRENT_BINARY_DIR}/rewrite/rewrite-expr-grammar.h ${CMAKE_CURRENT_BINARY_DIR}/parser/parser-expr-grammar.h ) set (LIB_HEADERS afinter.h alarms.h apphook.h atomic.h block-ref-parser.h cache.h cfg.h cfg-lexer.h cfg-lexer-subst.h cfg-args.h cfg-block.h cfg-block-generator.h cfg-parser.h cfg-tree.h children.h crypto.h dnscache.h driver.h fdhelpers.h file-perms.h find-crlf.h gprocess.h gsockaddr.h gsocket.h hostname.h host-resolve.h logmatcher.h logmpx.h logpipe.h logqueue-fifo.h logqueue.h logreader.h logsource.h logstamp.h logthrdestdrv.h logwriter.h mainloop.h mainloop-call.h mainloop-worker.h mainloop-io-worker.h module-config.h memtrace.h messages.h ml-batched-timer.h msg-format.h parse-number.h pathutils.h persist-state.h persistable-state-header.h persistable-state-presenter.h plugin.h plugin-types.h poll-events.h poll-fd-events.h pragma-parser.h presented-persistable-state.h reloc.h rcptid.h run-id.h scratch-buffers.h serialize.h service-management.h seqnum.h str-format.h str-utils.h syslog-names.h syslog-ng.h string-list.h timeutils.h tls-support.h thread-utils.h tlscontext.h type-hinting.h uuid.h userdb.h utf8utils.h versioning.h bookmark.h ringbuffer.h ack_tracker.h host-id.h resolved-configurable-paths.h ${PROJECT_BINARY_DIR}/lib/cfg-grammar.h ${PROJECT_BINARY_DIR}/lib/block-ref-grammar.h ${PROJECT_BINARY_DIR}/lib/cfg-lex.h ${PROJECT_BINARY_DIR}/lib/pragma-grammar.h ) set(LIB_SOURCES afinter.c alarms.c apphook.c block-ref-parser.c cache.c cfg.c cfg-args.c cfg-block.c cfg-block-generator.c cfg-lexer.c cfg-lexer-subst.c cfg-parser.c cfg-tree.c children.c dnscache.c driver.c fdhelpers.c file-perms.c find-crlf.c globals.c gprocess.c gsockaddr.c gsocket.c hostname.c host-resolve.c logmatcher.c logmpx.c logpipe.c logqueue.c logqueue-fifo.c logreader.c logsource.c logstamp.c logthrdestdrv.c logwriter.c mainloop.c mainloop-call.c mainloop-worker.c mainloop-io-worker.c module-config.c memtrace.c messages.c ml-batched-timer.c msg-format.c parse-number.c pathutils.c persist-state.c plugin.c poll-events.c poll-fd-events.c pragma-parser.c persistable-state-presenter.c rcptid.c reloc.c run-id.c scratch-buffers.c serialize.c service-management.c str-format.c str-utils.c syslog-names.c string-list.c timeutils.c type-hinting.c ringbuffer.c late_ack_tracker.c early_ack_tracker.c crypto.c tlscontext.c uuid.c userdb.c utf8utils.c host-id.c resolved-configurable-paths.c ${COMPAT_SOURCES} ${CONTROL_SOURCES} ${DEBUGGER_SOURCES} ${FILTER_SOURCES} ${LOGMSG_SOURCES} ${LOGPROTO_SOURCES} ${PARSER_SOURCES} ${REWRITE_SOURCES} ${STATS_SOURCES} ${TEMPLATE_SOURCES} ${TRANSPORT_SOURCES} ${VALUE_PAIRS_SOURCES} ${CSV_SCANNER_SOURCES} ${LIST_SCANNER_SOURCES} ${KV_SCANNER_SOURCES} ${STR_REPR_SOURCES} ${PROJECT_BINARY_DIR}/lib/cfg-grammar.c ${PROJECT_BINARY_DIR}/lib/block-ref-grammar.c ${PROJECT_BINARY_DIR}/lib/cfg-lex.c ${PROJECT_BINARY_DIR}/lib/pragma-grammar.c ${CMAKE_CURRENT_BINARY_DIR}/filter/filter-expr-grammar.c ${CMAKE_CURRENT_BINARY_DIR}/rewrite/rewrite-expr-grammar.c ${CMAKE_CURRENT_BINARY_DIR}/parser/parser-expr-grammar.c ) generate_y_from_ym (lib/block-ref-grammar) bison_target(BlockRefGrammar ${PROJECT_BINARY_DIR}/lib/block-ref-grammar.y ${PROJECT_BINARY_DIR}/lib/block-ref-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) add_flex_bison_dependency(CfgLexer BlockRefGrammar) generate_y_from_ym (lib/pragma-grammar) bison_target(PragmaGrammar ${PROJECT_BINARY_DIR}/lib/pragma-grammar.y ${PROJECT_BINARY_DIR}/lib/pragma-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) add_flex_bison_dependency(CfgLexer PragmaGrammar) generate_y_from_ym (lib/filter/filter-expr-grammar) bison_target(FilterExprGrammar ${CMAKE_CURRENT_BINARY_DIR}/filter/filter-expr-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/filter/filter-expr-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) add_flex_bison_dependency(CfgLexer FilterExprGrammar) generate_y_from_ym (lib/rewrite/rewrite-expr-grammar) bison_target(RewriteExprGrammar ${CMAKE_CURRENT_BINARY_DIR}/rewrite/rewrite-expr-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/rewrite/rewrite-expr-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) add_flex_bison_dependency(CfgLexer RewriteExprGrammar) generate_y_from_ym (lib/parser/parser-expr-grammar) bison_target(ParserExprGrammar ${CMAKE_CURRENT_BINARY_DIR}/parser/parser-expr-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/parser/parser-expr-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) add_flex_bison_dependency(CfgLexer ParserExprGrammar) include_directories(SYSTEM ${CORE_INCLUDE_DIRS}) add_library(syslog-ng SHARED ${LIB_SOURCES} ${LIB_HEADERS} ${LIB_SUBDIR_HEADERS}) target_include_directories(syslog-ng SYSTEM INTERFACE ${CORE_INCLUDE_DIRS}) target_link_libraries( syslog-ng LINK_PUBLIC ${CORE_LIBRARIES}) set_target_properties(syslog-ng PROPERTIES VERSION ${SYSLOG_NG_VERSION} SOVERSION ${SYSLOG_NG_VERSION}) install(TARGETS syslog-ng LIBRARY DESTINATION lib) install(FILES ${LIB_HEADERS} DESTINATION include/syslog-ng) install(FILES ${VALUE_PAIRS_HEADERS} DESTINATION include/syslog-ng/value-pairs) install(FILES ${COMPAT_HEADERS} DESTINATION include/syslog-ng/compat) install(FILES ${CONTROL_HEADERS} DESTINATION include/syslog-ng/control) install(FILES ${DEBUGGER_HEADERS} DESTINATION include/syslog-ng/debugger) install(FILES ${FILTER_HEADERS} DESTINATION include/syslog-ng/filter) install(FILES ${LOGMSG_HEADERS} DESTINATION include/syslog-ng/logmsg) install(FILES ${LOGPROTO_HEADERS} DESTINATION include/syslog-ng/logproto) install(FILES ${PARSER_HEADERS} DESTINATION include/syslog-ng/parser) install(FILES ${REWRITE_HEADERS} DESTINATION include/syslog-ng/rewrite) install(FILES ${STATS_HEADERS} DESTINATION include/syslog-ng/stats) install(FILES ${TEMPLATE_HEADERS} DESTINATION include/syslog-ng/template) install(FILES ${TRANSPORT_HEADERS} DESTINATION include/syslog-ng/transport) install(FILES ${CSV_SCANNER_HEADERS} DESTINATION include/syslog-ng/scanner/csv-scanner) set(TOOLS merge-grammar.py cfg-grammar.y ) install(FILES ${TOOLS} DESTINATION share/syslog-ng/tools) syslog-ng-syslog-ng-3.13.2/lib/Makefile.am000066400000000000000000000172371321171025300202510ustar00rootroot00000000000000DIST_SUBDIRS += @IVYKIS_SUBDIRS@ include lib/eventlog/src/Makefile.am include lib/eventlog/tests/Makefile.am include lib/transport/Makefile.am include lib/logproto/Makefile.am include lib/rewrite/Makefile.am include lib/parser/Makefile.am include lib/filter/Makefile.am include lib/template/Makefile.am include lib/value-pairs/Makefile.am include lib/stats/Makefile.am include lib/control/Makefile.am include lib/debugger/Makefile.am include lib/compat/Makefile.am include lib/logmsg/Makefile.am include lib/scanner/csv-scanner/Makefile.am include lib/scanner/list-scanner/Makefile.am include lib/scanner/kv-scanner/Makefile.am include lib/str-repr/Makefile.am LSNG_RELEASE = $(shell echo @PACKAGE_VERSION@ | cut -d. -f1,2) # * Start with version information of ‘0:0:0’ for each libtool # library. # * Update the version information only immediately before a public # release of your software. More frequent updates are unnecessary, # and only guarantee that the current interface number gets larger # faster. # * If the library source code has changed at all since the last # update, then increment revision (‘c:r:a’ becomes ‘c:r+1:a’). # * If any interfaces have been added, removed, or changed since the # last update, increment current, and set revision to 0. # * If any interfaces have been added since the last public release, # then increment age. # * If any interfaces have been removed or changed since the last # public release, then set age to 0. LSNG_CURRENT = 0 LSNG_REVISION = 0 LSNG_AGE = 0 lib_LTLIBRARIES += lib/libsyslog-ng.la lib_libsyslog_ng_la_LIBADD = @CORE_DEPS_LIBS@ $(libsystemd_LIBS) lib_libsyslog_ng_la_LDFLAGS = -no-undefined -release ${LSNG_RELEASE} \ -version-info ${LSNG_CURRENT}:${LSNG_REVISION}:${LSNG_AGE} lib_test_subdirs = lib_filter lib_logproto lib_parser lib_rewrite lib_template lib_stats lib_control lib_libsyslog_ng_la_DEPENDENCIES = lib/eventlog/src/libevtlog.la if IVYKIS_INTERNAL lib_libsyslog_ng_la_DEPENDENCIES += lib/ivykis/src/libivykis.la lib/ivykis/src/libivykis.la: ${MAKE} CFLAGS="${CFLAGS} -Wno-error" -C lib/ivykis CLEAN_SUBDIRS += @IVYKIS_SUBDIRS@ EXTRA_DIST += \ lib/ivykis/configure.gnu install-ivykis: ${MAKE} -C lib/ivykis/src \ install-includeHEADERS \ install-nodist_includeHEADERS \ includedir="${pkgincludedir}/ivykis" uninstall-ivykis: ${MAKE} -C lib/ivykis/src \ uninstall-includeHEADERS \ uninstall-nodist_includeHEADERS \ includedir="${pkgincludedir}/ivykis" INSTALL_EXEC_HOOKS += install-ivykis UNINSTALL_HOOKS += uninstall-ivykis endif if JSON_INTERNAL lib/jsonc/libjson-c.la: ${MAKE} -C lib/jsonc CLEAN_SUBDIRS += @JSON_SUBDIRS@ endif # this is intentionally formatted so conflicts are less likely to arise. one name in every line. pkginclude_HEADERS += \ lib/afinter.h \ lib/alarms.h \ lib/apphook.h \ lib/atomic.h \ lib/block-ref-parser.h \ lib/cache.h \ lib/cfg.h \ lib/cfg-grammar.h \ lib/cfg-lexer.h \ lib/cfg-lexer-subst.h \ lib/cfg-args.h \ lib/cfg-block.h \ lib/cfg-block-generator.h \ lib/cfg-parser.h \ lib/cfg-tree.h \ lib/children.h \ lib/crypto.h \ lib/dnscache.h \ lib/driver.h \ lib/fdhelpers.h \ lib/file-perms.h \ lib/find-crlf.h \ lib/gprocess.h \ lib/gsockaddr.h \ lib/gsocket.h \ lib/hostname.h \ lib/host-resolve.h \ lib/logmatcher.h \ lib/logmpx.h \ lib/logpipe.h \ lib/logqueue-fifo.h \ lib/logqueue.h \ lib/logreader.h \ lib/logsource.h \ lib/logstamp.h \ lib/logthrdestdrv.h \ lib/logwriter.h \ lib/mainloop.h \ lib/mainloop-call.h \ lib/mainloop-worker.h \ lib/mainloop-io-worker.h \ lib/module-config.h \ lib/memtrace.h \ lib/messages.h \ lib/ml-batched-timer.h \ lib/msg-format.h \ lib/parse-number.h \ lib/pathutils.h \ lib/persist-state.h \ lib/persistable-state-header.h \ lib/persistable-state-presenter.h \ lib/plugin.h \ lib/plugin-types.h \ lib/poll-events.h \ lib/poll-fd-events.h \ lib/pragma-parser.h \ lib/presented-persistable-state.h \ lib/reloc.h \ lib/rcptid.h \ lib/run-id.h \ lib/scratch-buffers.h \ lib/serialize.h \ lib/service-management.h \ lib/seqnum.h \ lib/str-format.h \ lib/str-utils.h \ lib/syslog-names.h \ lib/syslog-ng.h \ lib/string-list.h \ lib/timeutils.h \ lib/tls-support.h \ lib/thread-utils.h \ lib/tlscontext.h \ lib/type-hinting.h \ lib/uuid.h \ lib/userdb.h \ lib/utf8utils.h \ lib/versioning.h \ lib/bookmark.h \ lib/ringbuffer.h \ lib/ack_tracker.h \ lib/host-id.h \ lib/resolved-configurable-paths.h \ lib/pe-versioning.h # this is intentionally formatted so conflicts are less likely to arise. one name in every line. lib_libsyslog_ng_la_SOURCES = \ lib/afinter.c \ lib/alarms.c \ lib/apphook.c \ lib/block-ref-parser.c \ lib/cache.c \ lib/cfg.c \ lib/cfg-args.c \ lib/cfg-block.c \ lib/cfg-block-generator.c \ lib/cfg-lexer.c \ lib/cfg-lexer-subst.c \ lib/cfg-parser.c \ lib/cfg-tree.c \ lib/children.c \ lib/dnscache.c \ lib/driver.c \ lib/fdhelpers.c \ lib/file-perms.c \ lib/find-crlf.c \ lib/globals.c \ lib/gprocess.c \ lib/gsockaddr.c \ lib/gsocket.c \ lib/hostname.c \ lib/host-resolve.c \ lib/logmatcher.c \ lib/logmpx.c \ lib/logpipe.c \ lib/logqueue.c \ lib/logqueue-fifo.c \ lib/logreader.c \ lib/logsource.c \ lib/logstamp.c \ lib/logthrdestdrv.c \ lib/logwriter.c \ lib/mainloop.c \ lib/mainloop-call.c \ lib/mainloop-worker.c \ lib/mainloop-io-worker.c \ lib/module-config.c \ lib/memtrace.c \ lib/messages.c \ lib/ml-batched-timer.c \ lib/msg-format.c \ lib/parse-number.c \ lib/pathutils.c \ lib/persist-state.c \ lib/plugin.c \ lib/poll-events.c \ lib/poll-fd-events.c \ lib/pragma-parser.c \ lib/persistable-state-presenter.c \ lib/rcptid.c \ lib/reloc.c \ lib/run-id.c \ lib/scratch-buffers.c \ lib/serialize.c \ lib/service-management.c \ lib/str-format.c \ lib/str-utils.c \ lib/syslog-names.c \ lib/string-list.c \ lib/timeutils.c \ lib/type-hinting.c \ lib/ringbuffer.c \ lib/late_ack_tracker.c \ lib/early_ack_tracker.c \ lib/crypto.c \ lib/tlscontext.c \ lib/uuid.c \ lib/userdb.c \ lib/utf8utils.c \ $(transport_crypto_sources) \ lib/host-id.c \ lib/resolved-configurable-paths.c \ \ lib/cfg-lex.l \ lib/cfg-grammar.y \ lib/block-ref-grammar.y \ lib/pragma-grammar.y \ $(csvscanner_sources) \ $(kvscanner_sources) \ $(listscanner_sources) \ $(transport_sources) \ $(logproto_sources) \ $(filter_sources) \ $(parser_sources) \ $(rewrite_sources) \ $(template_sources) \ $(value_pairs_sources) \ $(stats_sources) \ $(control_sources) \ $(debugger_sources) \ $(compat_sources) \ $(logmsg_sources) \ $(str_repr_sources) lib_libsyslog_ng_la_CFLAGS = \ $(AM_CFLAGS) \ @UUID_CFLAGS@ $(libsystemd_CFLAGS) lib_libsyslog_ng_la_LIBADD += @OPENSSL_LIBS@ @UUID_LIBS@ # each line with closely related files (e.g. the ones generated from the same source) BUILT_SOURCES += lib/cfg-lex.c lib/cfg-lex.h \ lib/cfg-grammar.c lib/cfg-grammar.h \ lib/block-ref-grammar.y lib/block-ref-grammar.c lib/block-ref-grammar.h \ lib/pragma-grammar.y lib/pragma-grammar.h lib/pragma-grammar.c EXTRA_DIST += \ lib/block-ref-grammar.ym \ lib/pragma-grammar.ym \ lib/merge-grammar.py \ lib/hostname-unix.c lib/plugin-types.h: lib/cfg-grammar.h lib/ libsyslog-ng: lib/libsyslog-ng.la if IVYKIS_INTERNAL lib/ivykis/ ivykis: lib/ivykis/src/libivykis.la endif if JSON_INTERNAL lib/jsonc/ jsonc: lib/jsonc/libjson-c.la endif .PHONY: lib/ libsyslog-ng ivykis lib/ivykis/ lib/jsonc/ jsonc include lib/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/ack_tracker.h000066400000000000000000000043271321171025300206330ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 2014 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef ACK_TRACKER_H_INCLUDED #define ACK_TRACKER_H_INCLUDED #include "syslog-ng.h" #include "logsource.h" struct _AckTracker { gboolean late; LogSource *source; Bookmark* (*request_bookmark)(AckTracker *self); void (*track_msg)(AckTracker *self, LogMessage *msg); void (*manage_msg_ack)(AckTracker *self, LogMessage *msg, AckType ack_type); }; struct _AckRecord { AckTracker *tracker; }; AckTracker* late_ack_tracker_new(LogSource *source); AckTracker* early_ack_tracker_new(LogSource *source); void late_ack_tracker_free(AckTracker *self); void early_ack_tracker_free(AckTracker *self); static inline void ack_tracker_free(AckTracker *self) { if (self) { if (self->late) late_ack_tracker_free(self); else early_ack_tracker_free(self); } } static inline gboolean ack_tracker_is_late(AckTracker *self) { return self->late; } static inline Bookmark* ack_tracker_request_bookmark(AckTracker *self) { return self->request_bookmark(self); } static inline void ack_tracker_track_msg(AckTracker *self, LogMessage *msg) { self->track_msg(self, msg); } static inline void ack_tracker_manage_msg_ack(AckTracker *self, LogMessage *msg, AckType ack_type) { self->manage_msg_ack(self, msg, ack_type); } #endif syslog-ng-syslog-ng-3.13.2/lib/afinter.c000066400000000000000000000362011321171025300200010ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afinter.h" #include "logreader.h" #include "stats/stats-registry.h" #include "messages.h" #include "apphook.h" #include "mainloop.h" #include typedef struct _AFInterSource AFInterSource; static GStaticMutex internal_msg_lock = G_STATIC_MUTEX_INIT; static GQueue *internal_msg_queue; static AFInterSource *current_internal_source; static StatsCounterItem *internal_queue_length; /* the expiration timer of the next MARK message */ static struct timespec next_mark_target = { -1, 0 }; /* as different sources from different threads can call afinter_postpone_mark, and we use the value in the init thread, we need to syncronize the value references */ static GStaticMutex internal_mark_target_lock = G_STATIC_MUTEX_INIT; /* * This class is parallel to LogReader, e.g. it hangs on the * AFInterSourceDriver on the left (e.g. feeds messages to * AFInterSourceDriver). * * Threading: * ========== * * syslog-ng can generate internal() messages in any of its threads, thus * some care must be taken to make the internal() source multithreaded. * This is how it works: * * Whenever a thread decides to send a message using the msg_() API, it puts * an entry into the internal_msg_queue under the protection of * "internal_msg_lock". * * The receiving side of this queue is in the main thread, where the * internal() source is operating. This object will publish a pointer to * itself into current_internal_source. This pointer will be set under the * protection of the internal_msg_lock. The internal source will define an * ivykis event, a post is submitted to this event whenever a new message is * added to the queue. * * Once the event arrives to the main loop, it wakes up and feeds all * internal messages into the log path. * * If the window is depleted (e.g. flow control is enabled and the * destination is unable to process any more messages), * current_internal_source will be set to NULL, which means that messages * will be added to the queue, but the wakeup will not be done. * * When the window becomes free, log_source_wakeup() is called, which * restores the current_internal_source pointer (e.g. further messages will * wake up the source) and also starts emptying the messages accumulated in the queue. * * Possible races: * =============== * * The biggest offenders are when a client thread submits a message and * we're in the process of getting asleep (no window), or waking up. There * are notes in the code how we handle these cases (search for "Possible race"). * */ struct _AFInterSource { LogSource super; gint mark_freq; struct iv_event post; struct iv_event schedule_wakeup; struct iv_timer mark_timer; struct iv_task restart_task; gboolean watches_running:1, free_to_send:1; }; static void afinter_source_update_watches(AFInterSource *self); static void afinter_source_post(gpointer s) { AFInterSource *self = (AFInterSource *) s; LogMessage *msg; while (log_source_free_to_send(&self->super)) { g_static_mutex_lock(&internal_msg_lock); msg = g_queue_pop_head(internal_msg_queue); g_static_mutex_unlock(&internal_msg_lock); if (!msg) break; stats_counter_dec(internal_queue_length); log_source_post(&self->super, msg); } afinter_source_update_watches(self); } static void afinter_source_mark(gpointer s) { AFInterSource *self = (AFInterSource *) s; LogMessage *msg; LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; struct timespec nmt; main_loop_assert_main_thread(); g_static_mutex_lock(&internal_mark_target_lock); nmt = next_mark_target; g_static_mutex_unlock(&internal_mark_target_lock); if (log_source_free_to_send(&self->super) && nmt.tv_sec <= self->mark_timer.expires.tv_sec) { /* the internal_mark_target has not been overwritten by an incoming message in afinter_postpone_mark (there was no msg in the meantime) -> the mark msg can be sent */ msg = log_msg_new_mark(); path_options.ack_needed = FALSE; log_pipe_queue(&self->super.super, msg, &path_options); /* the next_mark_target will be increased in afinter_postpone_mark */ } afinter_source_update_watches(self); } static void afinter_source_wakeup(LogSource *s) { AFInterSource *self = (AFInterSource *) s; /* * We might get called even after this AFInterSource has been * deinitialized, in which case we must not do anything (since the * iv_event triggered here is not registered). * * This happens when log_writer_deinit() flushes its output queue * after the internal source which produced the message has already been * deinited. Since init/deinit calls are made in the main thread, no * locking is needed. * */ if (self->super.super.flags & PIF_INITIALIZED) iv_event_post(&self->schedule_wakeup); } static void afinter_source_init_watches(AFInterSource *self) { IV_EVENT_INIT(&self->post); self->post.cookie = self; self->post.handler = afinter_source_post; IV_TIMER_INIT(&self->mark_timer); self->mark_timer.cookie = self; self->mark_timer.handler = afinter_source_mark; IV_EVENT_INIT(&self->schedule_wakeup); self->schedule_wakeup.cookie = self; self->schedule_wakeup.handler = (void (*)(void *)) afinter_source_update_watches; IV_TASK_INIT(&self->restart_task); self->restart_task.cookie = self; self->restart_task.handler = afinter_source_post; } static void afinter_source_start_watches(AFInterSource *self) { if (!self->watches_running) { if (self->mark_timer.expires.tv_sec >= 0) iv_timer_register(&self->mark_timer); self->watches_running = TRUE; } } static void afinter_source_stop_watches(AFInterSource *self) { if (self->watches_running) { if (iv_task_registered(&self->restart_task)) iv_task_unregister(&self->restart_task); if (iv_timer_registered(&self->mark_timer)) iv_timer_unregister(&self->mark_timer); self->watches_running = FALSE; } } static void afinter_source_update_watches(AFInterSource *self) { if (!log_source_free_to_send(&self->super)) { /* ok, we go to sleep now. let's disable the post event by setting * current_internal_source to NULL. Messages get accumulated into * internal_msg_queue. */ g_static_mutex_lock(&internal_msg_lock); self->free_to_send = FALSE; g_static_mutex_unlock(&internal_msg_lock); /* Possible race: * * After the check log_source_free_to_send() above, the destination * may actually write out a message, thus by the time we get here, the * window may have space again. This is taken care of by the fact * that the wakeup is running in the main thread, which we do too. So * the wakeup is either completely performed before we entered this * function, or after we return. * * In case it happened earlier, the check above will find that we have * window space, in case it's going to be happening afterwards, we * will be woken up by the schedule_wakeup event (which calls * update_watches again). */ /* MARK events also get disabled */ afinter_source_stop_watches(self); } else { /* ok we can send our stuff. make sure we wake up */ afinter_source_stop_watches(self); self->mark_timer.expires = next_mark_target; afinter_source_start_watches(self); /* Possible race: * * Our current_internal_source pointer is set to NULL here (in case * we're just waking up). In case the sender submits a message, it'll * not trigger the self->post (since the pointer is NULL). This is * taken care of by the queue-length check in the locked region below. * If the queue has elements, we need to wake up, because we may have * lost a wakeup call. If it happens after the locked region, that * doesn't matter, in that case we already pointed * current_internal_source to ourselves, thus the post event will also * be triggered. */ g_static_mutex_lock(&internal_msg_lock); if (internal_msg_queue && g_queue_get_length(internal_msg_queue) > 0) iv_task_register(&self->restart_task); self->free_to_send = TRUE; g_static_mutex_unlock(&internal_msg_lock); } } static gboolean afinter_source_init(LogPipe *s) { AFInterSource *self = (AFInterSource *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_source_init(s)) return FALSE; self->mark_freq = cfg->mark_freq; afinter_postpone_mark(self->mark_freq); self->mark_timer.expires = next_mark_target; /* post event is used by other threads and can only be unregistered if * current_afinter_source is set to NULL in a thread safe manner */ iv_event_register(&self->post); iv_event_register(&self->schedule_wakeup); afinter_source_start_watches(self); g_static_mutex_lock(&internal_msg_lock); current_internal_source = self; self->free_to_send = TRUE; g_static_mutex_unlock(&internal_msg_lock); return TRUE; } static gboolean afinter_source_deinit(LogPipe *s) { AFInterSource *self = (AFInterSource *) s; g_static_mutex_lock(&internal_msg_lock); current_internal_source = NULL; g_static_mutex_unlock(&internal_msg_lock); /* the post handler can now be unregistered as current_internal_source is * set to NULL. Locks are only used as a memory barrier. */ iv_event_unregister(&self->post); iv_event_unregister(&self->schedule_wakeup); afinter_source_stop_watches(self); return log_source_deinit(s); } static LogSource * afinter_source_new(AFInterSourceDriver *owner, LogSourceOptions *options) { AFInterSource *self = g_new0(AFInterSource, 1); log_source_init_instance(&self->super, owner->super.super.super.cfg); log_source_set_options(&self->super, options, owner->super.super.id, NULL, FALSE, FALSE, owner->super.super.super.expr_node); afinter_source_init_watches(self); self->super.super.init = afinter_source_init; self->super.super.deinit = afinter_source_deinit; self->super.wakeup = afinter_source_wakeup; return &self->super; } static gboolean afinter_sd_init(LogPipe *s) { AFInterSourceDriver *self = (AFInterSourceDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_src_driver_init_method(s)) return FALSE; if (current_internal_source != NULL) { msg_error("Multiple internal() sources were detected, this is not possible"); return FALSE; } log_source_options_init(&self->source_options, cfg, self->super.super.group); self->source_options.stats_level = STATS_LEVEL0; self->source_options.stats_source = SCS_INTERNAL; self->source = afinter_source_new(self, &self->source_options); log_pipe_append(&self->source->super, s); if (!log_pipe_init(&self->source->super)) { log_pipe_unref(&self->source->super); self->source = NULL; return FALSE; } return TRUE; } static gboolean afinter_sd_deinit(LogPipe *s) { AFInterSourceDriver *self = (AFInterSourceDriver *) s; if (self->source) { log_pipe_deinit(&self->source->super); /* break circular reference created during _init */ log_pipe_unref(&self->source->super); self->source = NULL; } if (!log_src_driver_deinit_method(s)) return FALSE; return TRUE; } static void afinter_sd_free(LogPipe *s) { AFInterSourceDriver *self = (AFInterSourceDriver *) s; g_assert(!self->source); log_src_driver_free(s); } LogDriver * afinter_sd_new(GlobalConfig *cfg) { AFInterSourceDriver *self = g_new0(AFInterSourceDriver, 1); log_src_driver_init_instance((LogSrcDriver *)&self->super, cfg); self->super.super.super.init = afinter_sd_init; self->super.super.super.deinit = afinter_sd_deinit; self->super.super.super.free_fn = afinter_sd_free; log_source_options_defaults(&self->source_options); return (LogDriver *)&self->super.super; } /**************************************************************************** * Global entry points, without an AFInterSourceDriver instance. ****************************************************************************/ void afinter_postpone_mark(gint mark_freq) { if (mark_freq > 0) { iv_validate_now(); g_static_mutex_lock(&internal_mark_target_lock); next_mark_target = iv_now; next_mark_target.tv_sec += mark_freq; g_static_mutex_unlock(&internal_mark_target_lock); } else { next_mark_target.tv_sec = -1; } } static void _release_internal_msg_queue(void) { LogMessage *internal_message = g_queue_pop_head(internal_msg_queue); while (internal_message) { log_msg_unref(internal_message); internal_message = g_queue_pop_head(internal_msg_queue); } g_queue_free(internal_msg_queue); internal_msg_queue = NULL; } void afinter_message_posted(LogMessage *msg) { g_static_mutex_lock(&internal_msg_lock); if (!current_internal_source) { if (internal_msg_queue) { _release_internal_msg_queue(); } log_msg_unref(msg); goto exit; } if (!internal_msg_queue) { internal_msg_queue = g_queue_new(); stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_GLOBAL, "internal_queue_length", NULL ); stats_register_counter(0, &sc_key, SC_TYPE_PROCESSED, &internal_queue_length); stats_unlock(); } g_queue_push_tail(internal_msg_queue, msg); stats_counter_inc(internal_queue_length); if (current_internal_source->free_to_send) iv_event_post(¤t_internal_source->post); exit: g_static_mutex_unlock(&internal_msg_lock); } static void afinter_register_posted_hook(gint hook_type, gpointer user_data) { msg_set_post_func(afinter_message_posted); } void afinter_global_init(void) { register_application_hook(AH_POST_CONFIG_LOADED, afinter_register_posted_hook, NULL); } void afinter_global_deinit(void) { if (internal_msg_queue) { stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_GLOBAL, "internal_queue_length", NULL ); stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &internal_queue_length); stats_unlock(); g_queue_free_full(internal_msg_queue, (GDestroyNotify)log_msg_unref); internal_msg_queue = NULL; } current_internal_source = NULL; } syslog-ng-syslog-ng-3.13.2/lib/afinter.h000066400000000000000000000027221321171025300200070ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef SDINTER_H_INCLUDED #define SDINTER_H_INCLUDED #include "driver.h" #include "logsource.h" /* * This is the actual source driver, linked into the configuration tree. */ typedef struct _AFInterSourceDriver { LogSrcDriver super; LogSource *source; LogSourceOptions source_options; } AFInterSourceDriver; void afinter_postpone_mark(gint mark_freq); LogDriver *afinter_sd_new(GlobalConfig *cfg); void afinter_global_init(void); void afinter_global_deinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/alarms.c000066400000000000000000000034351321171025300176330ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "alarms.h" #include "messages.h" #include #include #include static gboolean sig_alarm_received = FALSE; static gboolean alarm_pending = FALSE; static void sig_alarm_handler(int signo) { sig_alarm_received = TRUE; } void alarm_set(int timeout) { if (G_UNLIKELY(alarm_pending)) { msg_error("Internal error, alarm_set() called while an alarm is still active"); return; } alarm(timeout); alarm_pending = TRUE; } void alarm_cancel(void) { alarm(0); sig_alarm_received = FALSE; alarm_pending = FALSE; } gboolean alarm_has_fired(void) { gboolean res = sig_alarm_received; return res; } void alarm_init(void) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_alarm_handler; sigaction(SIGALRM, &sa, NULL); } syslog-ng-syslog-ng-3.13.2/lib/alarms.h000066400000000000000000000022621321171025300176350ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef ALARMS_H_INCLUDED #define ALARMS_H_INCLUDED #include "syslog-ng.h" void alarm_set(int timeout); void alarm_cancel(void); gboolean alarm_has_fired(void); void alarm_init(void); #endif syslog-ng-syslog-ng-3.13.2/lib/apphook.c000066400000000000000000000124571321171025300200210ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "apphook.h" #include "messages.h" #include "children.h" #include "dnscache.h" #include "alarms.h" #include "stats/stats-registry.h" #include "logmsg/logmsg.h" #include "timeutils.h" #include "logsource.h" #include "logwriter.h" #include "afinter.h" #include "template/templates.h" #include "hostname.h" #include "mainloop-call.h" #include "service-management.h" #include "crypto.h" #include "value-pairs/value-pairs.h" #include "scratch-buffers.h" #include #include #include typedef struct _ApplicationHookEntry { gint type; ApplicationHookFunc func; gpointer user_data; } ApplicationHookEntry; static GList *application_hooks = NULL; static gint current_state = AH_STARTUP; void register_application_hook(gint type, ApplicationHookFunc func, gpointer user_data) { if (current_state < type) { ApplicationHookEntry *entry = g_new0(ApplicationHookEntry, 1); entry->type = type; entry->func = func; entry->user_data = user_data; application_hooks = g_list_append(application_hooks, entry); } else { /* the requested hook has already passed, call the requested function immediately */ msg_debug("Application hook registered after the given point passed", evt_tag_int("current", current_state), evt_tag_int("hook", type)); func(type, user_data); } } static void run_application_hook(gint type, gboolean remove_hook) { GList *l, *l_next; if (remove_hook) { g_assert(current_state <= type); current_state = type; } msg_debug("Running application hooks", evt_tag_int("hook", type)); for (l = application_hooks; l; l = l_next) { ApplicationHookEntry *e = l->data; if (e->type == type) { l_next = l->next; e->func(type, e->user_data); if (remove_hook) { application_hooks = g_list_remove_link(application_hooks, l); g_free(e); g_list_free_1(l); } } else { l_next = l->next; } } } static void app_fatal(const char *msg) { fprintf(stderr, "%s\n", msg); } void app_startup(void) { msg_init(FALSE); iv_set_fatal_msg_handler(app_fatal); iv_init(); g_thread_init(NULL); crypto_init(); hostname_global_init(); dns_caching_global_init(); dns_caching_thread_init(); afinter_global_init(); child_manager_init(); alarm_init(); stats_init(); tzset(); log_msg_global_init(); log_tags_global_init(); log_source_global_init(); log_template_global_init(); value_pairs_global_init(); service_management_init(); scratch_buffers_allocator_init(); } void app_finish_app_startup_after_cfg_init(void) { log_tags_reinit_stats(); log_msg_stats_global_init(); scratch_buffers_global_init(); } void app_post_daemonized(void) { run_application_hook(AH_POST_DAEMONIZED, TRUE); } void app_pre_config_loaded(void) { current_state = AH_PRE_CONFIG_LOADED; } void app_post_config_loaded(void) { run_application_hook(AH_POST_CONFIG_LOADED, TRUE); res_init(); } void app_shutdown(void) { run_application_hook(AH_SHUTDOWN, TRUE); scratch_buffers_allocator_deinit(); scratch_buffers_global_deinit(); value_pairs_global_deinit(); log_template_global_deinit(); log_tags_global_deinit(); log_msg_global_deinit(); afinter_global_deinit(); stats_destroy(); child_manager_deinit(); g_list_foreach(application_hooks, (GFunc) g_free, NULL); g_list_free(application_hooks); dns_caching_thread_deinit(); dns_caching_global_deinit(); hostname_global_deinit(); crypto_deinit(); msg_deinit(); /* NOTE: the iv_deinit() call should come here, but there's some exit * synchronization issue in libivykis that causes use-after-free with the * thread-local-state for the main thread and iv_work_pool worker threads. * I've dropped a mail to Lennert about the issue, but I'm commenting this * out for now to avoid it biting someone. Bazsi, 2013/12/23. * * iv_deinit(); */ } void app_reopen(void) { run_application_hook(AH_REOPEN, FALSE); } void app_thread_start(void) { scratch_buffers_allocator_init(); dns_caching_thread_init(); main_loop_call_thread_init(); } void app_thread_stop(void) { main_loop_call_thread_deinit(); dns_caching_thread_deinit(); scratch_buffers_allocator_deinit(); } syslog-ng-syslog-ng-3.13.2/lib/apphook.h000066400000000000000000000033061321171025300200170ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef APPHOOK_H_INCLUDED #define APPHOOK_H_INCLUDED #include "syslog-ng.h" /* this enum must be in the order the given events actually happen in time */ enum { AH_STARTUP, AH_POST_DAEMONIZED, AH_PRE_CONFIG_LOADED, AH_POST_CONFIG_LOADED, AH_SHUTDOWN, AH_REOPEN, }; typedef void (*ApplicationHookFunc)(gint type, gpointer user_data); void register_application_hook(gint type, ApplicationHookFunc func, gpointer user_data); void app_startup(void); void app_finish_app_startup_after_cfg_init(void); void app_post_daemonized(void); void app_pre_config_loaded(void); void app_post_config_loaded(void); void app_thread_start(void); void app_thread_stop(void); void app_shutdown(void); void app_reopen(void); #endif syslog-ng-syslog-ng-3.13.2/lib/atomic.h000066400000000000000000000041341321171025300176320ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef ATOMIC_H_INCLUDED #define ATOMIC_H_INCLUDED typedef struct { gint counter; } GAtomicCounter; static inline void g_atomic_counter_inc(GAtomicCounter *c) { g_atomic_int_inc(&c->counter); } static inline gboolean g_atomic_counter_dec_and_test(GAtomicCounter *c) { return g_atomic_int_dec_and_test(&c->counter); } static inline gint g_atomic_counter_get(GAtomicCounter *c) { return g_atomic_int_get(&c->counter); } static inline gint g_atomic_counter_exchange_and_add(GAtomicCounter *c, gint val) { #if GLIB_CHECK_VERSION(2, 30, 0) return g_atomic_int_add(&c->counter, val); #else return g_atomic_int_exchange_and_add(&c->counter, val); #endif } static inline gint g_atomic_counter_racy_get(GAtomicCounter *c) { return c->counter; } static inline void g_atomic_counter_set(GAtomicCounter *c, gint value) { /* FIXME: we should use g_atomic_int_set, but that's available starting * with GLib 2.10 only, and we only use this function for initialization, * thus atomic write is not strictly needed as there's no concurrency * while initializing a refcounter. */ c->counter = value; } #endif syslog-ng-syslog-ng-3.13.2/lib/block-ref-grammar.ym000066400000000000000000000034021321171025300220410ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code requires { #include "block-ref-parser.h" #include } %name-prefix "block_ref_" %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {CfgArgs **result} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %% start : { *result = cfg_args_new(); } '(' block_args ')' { YYACCEPT; } ; block_args : block_arg block_args | ; block_arg : LL_IDENTIFIER { cfg_lexer_push_context(lexer, LL_CONTEXT_BLOCK_ARG, NULL, "block argument"); } LL_BLOCK { cfg_lexer_pop_context(lexer); cfg_args_set(*result, $1, $3); free($1); free($3); } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/lib/block-ref-parser.c000066400000000000000000000031441321171025300215070ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "block-ref-parser.h" #include "block-ref-grammar.h" extern int block_ref_debug; int block_ref_parse(CfgLexer *lexer, CfgArgs **node, gpointer arg); static CfgLexerKeyword block_ref_keywords[] = { { CFG_KEYWORD_STOP }, }; CfgLexerKeyword *block_def_keywords = block_ref_keywords; CfgParser block_ref_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &block_ref_debug, #endif .name = "block reference", .context = LL_CONTEXT_BLOCK_REF, .keywords = block_ref_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer arg)) block_ref_parse, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(block_ref_, CfgArgs **) syslog-ng-syslog-ng-3.13.2/lib/block-ref-parser.h000066400000000000000000000023401321171025300215110ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef BLOCK_REF_PARSER_H_INCLUDED #define BLOCK_REF_PARSER_H_INCLUDED #include "cfg-parser.h" extern CfgParser block_ref_parser; extern CfgLexerKeyword *block_def_keywords; CFG_PARSER_DECLARE_LEXER_BINDING(block_ref_, CfgArgs **) #endif syslog-ng-syslog-ng-3.13.2/lib/bookmark.h000066400000000000000000000031221321171025300201570ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 2014 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef BOOKMARK_H_INCLUDED #define BOOKMARK_H_INCLUDED #include "syslog-ng.h" #include "persist-state.h" #define MAX_BOOKMARK_DATA_LENGTH (128) typedef struct _BookmarkContainer { /* Bookmark structure should be aligned (ie. HPUX-11v2 ia64) */ gint64 other_state[MAX_BOOKMARK_DATA_LENGTH/sizeof(gint64)]; } BookmarkContainer; struct _Bookmark { PersistState *persist_state; void (*save)(Bookmark *self); void (*destroy)(Bookmark *self); BookmarkContainer container; }; static inline void bookmark_init(Bookmark *self) { self->persist_state = NULL; self->save = NULL; self->destroy = NULL; } #endif syslog-ng-syslog-ng-3.13.2/lib/cache.c000066400000000000000000000033161321171025300174150ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cache.h" struct _Cache { GHashTable *hash_table; CacheResolver *resolver; }; Cache * cache_new(CacheResolver *resolver) { Cache *self = g_new0(Cache, 1); self->resolver = resolver; self->hash_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, resolver->free_elem); return self; } void cache_free(Cache *self) { cache_resolver_free(self->resolver); g_hash_table_unref(self->hash_table); g_free(self); } void * cache_lookup(Cache *self, const gchar *key) { void *result = g_hash_table_lookup(self->hash_table, key); if (!result) { result = cache_resolver_resolve_elem(self->resolver, key); if (result) { g_hash_table_insert(self->hash_table, g_strdup(key), result); } } return result; } syslog-ng-syslog-ng-3.13.2/lib/cache.h000066400000000000000000000036471321171025300174310ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CACHE_H_INCLUDED #define CACHE_H_INCLUDED #include "syslog-ng.h" typedef struct _CacheResolver CacheResolver; typedef struct _Cache Cache; struct _CacheResolver { void *(*resolve_elem)(CacheResolver *self, const gchar *key); /* NOTE: free_elem lacks a self argument as we are using it as a * GDestroyNotify callback for hashtables. Lacking a better solution * (e.g. curried functions) this means that we can't pass self here. */ void (*free_elem)(gpointer value); void (*free_fn)(CacheResolver *self); }; static inline void * cache_resolver_resolve_elem(CacheResolver *self, const gchar *key) { if (self->resolve_elem) { return self->resolve_elem(self, key); } return NULL; } static inline void cache_resolver_free(CacheResolver *self) { if (self->free_fn) { self->free_fn(self); } g_free(self); } Cache *cache_new(CacheResolver *resolver); void *cache_lookup(Cache *self, const gchar *key); void cache_free(Cache *self); #endif syslog-ng-syslog-ng-3.13.2/lib/cfg-args.c000066400000000000000000000073251321171025300200470ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-args.h" #include "messages.h" #include "str-utils.h" #include "str-repr/encode.h" struct _CfgArgs { gint ref_cnt; GHashTable *args; }; /* token block args */ static void cfg_args_validate_callback(gpointer k, gpointer v, gpointer user_data) { CfgArgs *defs = ((gpointer *) user_data)[0]; gchar **bad_key = (gchar **) &((gpointer *) user_data)[1]; gchar **bad_value = (gchar **) &((gpointer *) user_data)[2]; if ((*bad_key == NULL) && (!defs || cfg_args_get(defs, k) == NULL)) { *bad_key = k; *bad_value = v; } } void cfg_args_foreach(CfgArgs *self, GHFunc func, gpointer user_data) { g_hash_table_foreach(self->args, func, user_data); } gboolean cfg_args_validate(CfgArgs *self, CfgArgs *defs, const gchar *context) { gpointer validate_params[] = { defs, NULL, NULL }; cfg_args_foreach(self, cfg_args_validate_callback, validate_params); if (validate_params[1]) { msg_error("Unknown argument", evt_tag_str("context", context), evt_tag_str("arg", validate_params[1]), evt_tag_str("value", validate_params[2])); return FALSE; } return TRUE; } static void _resolve_unknown_blockargs_as_varargs(gpointer key, gpointer value, gpointer user_data) { CfgArgs *defaults = ((gpointer *) user_data)[0]; GString *varargs = ((gpointer *) user_data)[1]; if (!defaults || cfg_args_get(defaults, key) == NULL) { g_string_append(varargs, key); g_string_append_c(varargs, '('); str_repr_encode_append(varargs, value, -1, NULL); g_string_append(varargs, ") "); } } gchar * cfg_args_format_varargs(CfgArgs *self, CfgArgs *defaults) { GString *varargs = g_string_new(""); gpointer user_data[] = { defaults, varargs }; cfg_args_foreach(self, _resolve_unknown_blockargs_as_varargs, user_data); return g_string_free(varargs, FALSE); } void cfg_args_set(CfgArgs *self, const gchar *name, const gchar *value) { g_hash_table_insert(self->args, __normalize_key(name), g_strdup(value)); } const gchar * cfg_args_get(CfgArgs *self, const gchar *name) { const gchar *value = g_hash_table_lookup(self->args, name); if (!value) { gchar *normalized_name = __normalize_key(name); value = g_hash_table_lookup(self->args, normalized_name); g_free(normalized_name); } return value; } CfgArgs * cfg_args_new(void) { CfgArgs *self = g_new0(CfgArgs, 1); self->args = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); self->ref_cnt = 1; return self; } CfgArgs * cfg_args_ref(CfgArgs *self) { if (self) self->ref_cnt++; return self; } void cfg_args_unref(CfgArgs *self) { if (self && --self->ref_cnt == 0) { g_hash_table_destroy(self->args); g_free(self); } } syslog-ng-syslog-ng-3.13.2/lib/cfg-args.h000066400000000000000000000031331321171025300200450ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CFG_ARGS_H_INCLUDED #define CFG_ARGS_H_INCLUDED 1 #include "syslog-ng.h" typedef struct _CfgArgs CfgArgs; /* argument list for a block generator */ gboolean cfg_args_validate(CfgArgs *self, CfgArgs *defs, const gchar *context); gchar *cfg_args_format_varargs(CfgArgs *self, CfgArgs *defaults); void cfg_args_set(CfgArgs *self, const gchar *name, const gchar *value); const gchar *cfg_args_get(CfgArgs *self, const gchar *name); void cfg_args_foreach(CfgArgs *self, GHFunc func, gpointer user_data); CfgArgs *cfg_args_new(void); CfgArgs *cfg_args_ref(CfgArgs *self); void cfg_args_unref(CfgArgs *self); #endif syslog-ng-syslog-ng-3.13.2/lib/cfg-block-generator.c000066400000000000000000000031411321171025300221610ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-block-generator.h" gboolean cfg_block_generator_generate(CfgBlockGenerator *self, GlobalConfig *cfg, CfgArgs *args, GString *result) { return self->generate(self, cfg, args, result); } void cfg_block_generator_init_instance(CfgBlockGenerator *self, gint context, const gchar *name) { self->context = context; self->name = g_strdup(name); self->free_fn = cfg_block_generator_free_instance; } void cfg_block_generator_free_instance(CfgBlockGenerator *self) { g_free(self->name); } void cfg_block_generator_free(CfgBlockGenerator *self) { if (self->free_fn) self->free_fn(self); g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/cfg-block-generator.h000066400000000000000000000041551321171025300221740ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CFG_BLOCK_GENERATOR_H_INCLUDED #define CFG_BLOCK_GENERATOR_H_INCLUDED 1 #include "syslog-ng.h" #include "cfg-args.h" /** * CfgBlockGenerator: * * This class describes a block generator, e.g. a function callback * that returns a configuration snippet in a given context. Each * user-defined "block" results in a generator to be registered, but * theoretically this mechanism can be used to write plugins that * generate syslog-ng configuration on the fly, based on system * settings for example. **/ typedef struct _CfgBlockGenerator CfgBlockGenerator; struct _CfgBlockGenerator { gint context; gchar *name; gboolean suppress_backticks; gboolean (*generate)(CfgBlockGenerator *self, GlobalConfig *cfg, CfgArgs *args, GString *result); void (*free_fn)(CfgBlockGenerator *self); }; gboolean cfg_block_generator_generate(CfgBlockGenerator *self, GlobalConfig *cfg, CfgArgs *args, GString *result); void cfg_block_generator_init_instance(CfgBlockGenerator *self, gint context, const gchar *name); void cfg_block_generator_free_instance(CfgBlockGenerator *self); void cfg_block_generator_free(CfgBlockGenerator *self); #endif syslog-ng-syslog-ng-3.13.2/lib/cfg-block.c000066400000000000000000000066101321171025300202010ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-block.h" #include "cfg-lexer-subst.h" #include "cfg.h" #include "str-utils.h" /* * This class encapsulates a configuration block that the user defined * via the configuration file. It behaves like a macro, e.g. when * referenced the content of the block is expanded. * * Each block is identified by its name and the context (source, * destination, etc.) where it is meant to be used. * * A block has a set of name-value pairs to allow expansion to be * parameterized. The set of allowed NV pairs is defined at block * definition time */ typedef struct _CfgBlock CfgBlock; struct _CfgBlock { CfgBlockGenerator super; gchar *content; CfgArgs *arg_defs; }; /* * cfg_block_generate: * * This is a CfgBlockGeneratorFunc, which takes a CfgBlock defined by * the user, substitutes backtick values and generates input tokens * for the lexer. */ gboolean cfg_block_generate(CfgBlockGenerator *s, GlobalConfig *cfg, CfgArgs *args, GString *result) { CfgBlock *self = (CfgBlock *) s; gchar *value; gsize length; GError *error = NULL; cfg_args_set(args, "__VARARGS__", cfg_args_format_varargs(args, self->arg_defs)); value = cfg_lexer_subst_args_in_input(cfg->globals, self->arg_defs, args, self->content, -1, &length, &error); if (!value) { msg_warning("Syntax error while resolving backtick references in block", evt_tag_str("context", cfg_lexer_lookup_context_name_by_type(self->super.context)), evt_tag_str("block", self->super.name), evt_tag_str("error", error->message), NULL); g_clear_error(&error); return FALSE; } g_string_assign_len(result, value, length); g_free(value); return TRUE; } /* * Free a user defined block. */ void cfg_block_free_instance(CfgBlockGenerator *s) { CfgBlock *self = (CfgBlock *) s; g_free(self->content); cfg_args_unref(self->arg_defs); cfg_block_generator_free_instance(s); } /* * Construct a user defined block. */ CfgBlockGenerator * cfg_block_new(gint context, const gchar *name, const gchar *content, CfgArgs *arg_defs) { CfgBlock *self = g_new0(CfgBlock, 1); cfg_block_generator_init_instance(&self->super, context, name); self->super.free_fn = cfg_block_free_instance; self->super.generate = cfg_block_generate; self->super.suppress_backticks = TRUE; self->content = g_strdup(content); self->arg_defs = arg_defs; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/cfg-block.h000066400000000000000000000023501321171025300202030ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CFG_BLOCK_H_INCLUDED #define CFG_BLOCK_H_INCLUDED 1 #include "cfg-block-generator.h" /* user defined configuration block */ CfgBlockGenerator *cfg_block_new(gint context, const gchar *name, const gchar *content, CfgArgs *arg_defs); #endif syslog-ng-syslog-ng-3.13.2/lib/cfg-grammar.y000066400000000000000000001313041321171025300205620ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code requires { /* this block is inserted into cfg-grammar.h, so it is included practically all of the syslog-ng code. Please add headers here with care. If you need additional headers, please look for a massive list of includes further below. */ /* YYSTYPE and YYLTYPE is defined by the lexer */ #include "cfg-lexer.h" #include "afinter.h" #include "type-hinting.h" #include "filter/filter-expr-parser.h" #include "filter/filter-pipe.h" #include "parser/parser-expr-parser.h" #include "rewrite/rewrite-expr-parser.h" #include "logmatcher.h" #include "logthrdestdrv.h" /* uses struct declarations instead of the typedefs to avoid having to * include logreader/logwriter/driver.h, which defines the typedefs. This * is to avoid including unnecessary dependencies into grammars that are not * themselves reader/writer based */ extern struct _LogSourceOptions *last_source_options; extern struct _LogReaderOptions *last_reader_options; extern struct _LogProtoServerOptions *last_proto_server_options; extern struct _LogWriterOptions *last_writer_options; extern struct _FilePermOptions *last_file_perm_options; extern struct _MsgFormatOptions *last_msg_format_options; extern struct _LogDriver *last_driver; extern struct _LogParser *last_parser; extern struct _LogTemplateOptions *last_template_options; extern struct _LogTemplate *last_template; extern struct _ValuePairs *last_value_pairs; extern struct _ValuePairsTransformSet *last_vp_transset; extern struct _LogMatcherOptions *last_matcher_options; extern struct _HostResolveOptions *last_host_resolve_options; extern struct _StatsOptions *last_stats_options; } %name-prefix "main_" %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {gpointer *dummy} %parse-param {gpointer arg} /* START_DECLS */ %require "2.4.1" %locations %define api.pure %pure-parser %error-verbose %code { # define YYLLOC_DEFAULT(Current, Rhs, N) \ do { \ if (N) \ { \ (Current).level = YYRHSLOC(Rhs, 1).level; \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).level = YYRHSLOC(Rhs, 0).level; \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ } while (0) #define CHECK_ERROR_WITHOUT_MESSAGE(val, token) do { \ if (!(val)) \ { \ YYERROR; \ } \ } while (0) #define CHECK_ERROR(val, token, errorfmt, ...) do { \ if (!(val)) \ { \ if (errorfmt) \ { \ gchar __buf[256]; \ g_snprintf(__buf, sizeof(__buf), errorfmt, ## __VA_ARGS__); \ yyerror(& (token), lexer, NULL, NULL, __buf); \ } \ YYERROR; \ } \ } while (0) #define CHECK_ERROR_GERROR(val, token, error, errorfmt, ...) do { \ if (!(val)) \ { \ if (errorfmt) \ { \ gchar __buf[256]; \ g_snprintf(__buf, sizeof(__buf), errorfmt ", error=%s", ## __VA_ARGS__, error->message); \ yyerror(& (token), lexer, NULL, NULL, __buf); \ } \ g_clear_error(&error); \ YYERROR; \ } \ } while (0) #define YYMAXDEPTH 20000 } /* plugin types, must be equal to the numerical values of the plugin type in plugin.h */ %token LL_CONTEXT_ROOT 1 %token LL_CONTEXT_DESTINATION 2 %token LL_CONTEXT_SOURCE 3 %token LL_CONTEXT_PARSER 4 %token LL_CONTEXT_REWRITE 5 %token LL_CONTEXT_FILTER 6 %token LL_CONTEXT_LOG 7 %token LL_CONTEXT_BLOCK_DEF 8 %token LL_CONTEXT_BLOCK_REF 9 %token LL_CONTEXT_BLOCK_CONTENT 10 %token LL_CONTEXT_BLOCK_ARG 11 %token LL_CONTEXT_PRAGMA 12 %token LL_CONTEXT_FORMAT 13 %token LL_CONTEXT_TEMPLATE_FUNC 14 %token LL_CONTEXT_INNER_DEST 15 %token LL_CONTEXT_INNER_SRC 16 %token LL_CONTEXT_CLIENT_PROTO 17 %token LL_CONTEXT_SERVER_PROTO 18 %token LL_CONTEXT_SELECTOR 19 /* statements */ %token KW_SOURCE 10000 %token KW_FILTER 10001 %token KW_PARSER 10002 %token KW_DESTINATION 10003 %token KW_LOG 10004 %token KW_OPTIONS 10005 %token KW_INCLUDE 10006 %token KW_BLOCK 10007 %token KW_JUNCTION 10008 %token KW_CHANNEL 10009 /* source & destination items */ %token KW_INTERNAL 10010 %token KW_FILE 10011 %token KW_SYSLOG 10060 /* option items */ %token KW_MARK_FREQ 10071 %token KW_STATS_FREQ 10072 %token KW_STATS_LEVEL 10073 %token KW_STATS_LIFETIME 10074 %token KW_FLUSH_LINES 10075 %token KW_SUPPRESS 10076 %token KW_FLUSH_TIMEOUT 10077 %token KW_LOG_MSG_SIZE 10078 %token KW_FILE_TEMPLATE 10079 %token KW_PROTO_TEMPLATE 10080 %token KW_MARK_MODE 10081 %token KW_ENCODING 10082 %token KW_TYPE 10083 %token KW_STATS_MAX_DYNAMIC 10084 %token KW_CHAIN_HOSTNAMES 10090 %token KW_NORMALIZE_HOSTNAMES 10091 %token KW_KEEP_HOSTNAME 10092 %token KW_CHECK_HOSTNAME 10093 %token KW_BAD_HOSTNAME 10094 %token KW_KEEP_TIMESTAMP 10100 %token KW_USE_DNS 10110 %token KW_USE_FQDN 10111 %token KW_CUSTOM_DOMAIN 10112 %token KW_DNS_CACHE 10120 %token KW_DNS_CACHE_SIZE 10121 %token KW_DNS_CACHE_EXPIRE 10130 %token KW_DNS_CACHE_EXPIRE_FAILED 10131 %token KW_DNS_CACHE_HOSTS 10132 %token KW_PERSIST_ONLY 10140 %token KW_USE_RCPTID 10141 %token KW_USE_UNIQID 10142 %token KW_TZ_CONVERT 10150 %token KW_TS_FORMAT 10151 %token KW_FRAC_DIGITS 10152 %token KW_LOG_FIFO_SIZE 10160 %token KW_LOG_FETCH_LIMIT 10162 %token KW_LOG_IW_SIZE 10163 %token KW_LOG_PREFIX 10164 %token KW_PROGRAM_OVERRIDE 10165 %token KW_HOST_OVERRIDE 10166 %token KW_THROTTLE 10170 %token KW_THREADED 10171 %token KW_PASS_UNIX_CREDENTIALS 10231 %token KW_PERSIST_NAME 10302 %token KW_JVM_OPTIONS 10303 %token KW_READ_OLD_RECORDS 10304 /* log statement options */ %token KW_FLAGS 10190 /* reader options */ %token KW_PAD_SIZE 10200 %token KW_TIME_ZONE 10201 %token KW_RECV_TIME_ZONE 10202 %token KW_SEND_TIME_ZONE 10203 %token KW_LOCAL_TIME_ZONE 10204 %token KW_FORMAT 10205 /* timers */ %token KW_TIME_REOPEN 10210 %token KW_TIME_REAP 10211 %token KW_TIME_SLEEP 10212 /* destination options */ %token KW_TMPL_ESCAPE 10220 /* driver specific options */ %token KW_OPTIONAL 10230 /* file related options */ %token KW_CREATE_DIRS 10240 %token KW_OWNER 10250 %token KW_GROUP 10251 %token KW_PERM 10252 %token KW_DIR_OWNER 10260 %token KW_DIR_GROUP 10261 %token KW_DIR_PERM 10262 %token KW_TEMPLATE 10270 %token KW_TEMPLATE_ESCAPE 10271 %token KW_TEMPLATE_FUNCTION 10272 %token KW_DEFAULT_FACILITY 10300 %token KW_DEFAULT_LEVEL 10301 %token KW_PORT 10323 /* misc options */ %token KW_USE_TIME_RECVD 10340 /* filter items*/ %token KW_FACILITY 10350 %token KW_LEVEL 10351 %token KW_HOST 10352 %token KW_MATCH 10353 %token KW_MESSAGE 10354 %token KW_NETMASK 10355 %token KW_TAGS 10356 %token KW_NETMASK6 10357 /* parser items */ /* rewrite items */ %token KW_REWRITE 10370 /* yes/no switches */ %token KW_YES 10380 %token KW_NO 10381 %token KW_IFDEF 10410 %token KW_ENDIF 10411 %token LL_DOTDOT 10420 %token LL_IDENTIFIER 10421 %token LL_NUMBER 10422 %token LL_FLOAT 10423 %token LL_STRING 10424 %token LL_TOKEN 10425 %token LL_BLOCK 10426 %token LL_PRAGMA 10427 %token LL_EOL 10428 %token LL_ERROR 10429 %destructor { free($$); } /* value pairs */ %token KW_VALUE_PAIRS 10500 %token KW_EXCLUDE 10502 %token KW_PAIR 10503 %token KW_KEY 10504 %token KW_SCOPE 10505 %token KW_SHIFT 10506 %token KW_REKEY 10507 %token KW_ADD_PREFIX 10508 %token KW_REPLACE_PREFIX 10509 %token KW_ON_ERROR 10510 %token KW_RETRIES 10511 /* END_DECLS */ %code { #include "cfg-parser.h" #include "cfg.h" #include "cfg-tree.h" #include "cfg-block.h" #include "template/templates.h" #include "template/user-function.h" #include "logreader.h" #include "logpipe.h" #include "parser/parser-expr.h" #include "rewrite/rewrite-expr.h" #include "rewrite/rewrite-expr-parser.h" #include "filter/filter-expr-parser.h" #include "value-pairs/value-pairs.h" #include "file-perms.h" #include "block-ref-parser.h" #include "plugin.h" #include "logwriter.h" #include "messages.h" #include "syslog-names.h" #include #include #include #include #include "cfg-grammar.h" LogDriver *last_driver; LogParser *last_parser; LogSourceOptions *last_source_options; LogProtoServerOptions *last_proto_server_options; LogReaderOptions *last_reader_options; LogWriterOptions *last_writer_options; MsgFormatOptions *last_msg_format_options; FilePermOptions *last_file_perm_options; LogTemplateOptions *last_template_options; LogTemplate *last_template; CfgArgs *last_block_args; ValuePairs *last_value_pairs; ValuePairsTransformSet *last_vp_transset; LogMatcherOptions *last_matcher_options; HostResolveOptions *last_host_resolve_options; StatsOptions *last_stats_options; DNSCacheOptions *last_dns_cache_options; } %type expr_stmt %type source_stmt %type dest_stmt %type filter_stmt %type parser_stmt %type rewrite_stmt %type log_stmt %type plugin_stmt /* START_DECLS */ %type source_content %type source_items %type source_item %type source_afinter %type source_plugin %type source_afinter_params %type dest_content %type dest_items %type dest_item %type dest_plugin %type template_content %type filter_content %type parser_content %type rewrite_content %type log_items %type log_item %type log_last_junction %type log_junction %type log_content %type log_forks %type log_fork %type log_flags %type log_flags_items %type value_pair_option %type yesno %type dnsmode %type dest_writer_options_flags %type string %type string_or_number %type string_list %type string_list_build %type facility_string %type level_string %type positive_integer %type nonnegative_integer /* END_DECLS */ %type template_def %type template_block %type template_simple %type template_fn %% start : stmts ; stmts : stmt ';' stmts | ; stmt : expr_stmt { CHECK_ERROR(cfg_tree_add_object(&configuration->tree, $1) || cfg_allow_config_dups(configuration), @1, "duplicate %s definition", log_expr_node_get_content_name(((LogExprNode *) $1)->content)); } | template_stmt | options_stmt | block_stmt | plugin_stmt ; expr_stmt : source_stmt | dest_stmt | filter_stmt | parser_stmt | rewrite_stmt | log_stmt ; source_stmt : KW_SOURCE string '{' source_content '}' { $$ = log_expr_node_new_source($2, $4, &@1); free($2); } ; dest_stmt : KW_DESTINATION string '{' dest_content '}' { $$ = log_expr_node_new_destination($2, $4, &@1); free($2); } ; filter_stmt : KW_FILTER string '{' filter_content '}' { /* NOTE: the filter() subexpression (e.g. the one that invokes * one filter expression from another) depends on the layout * parsed into the cfg-tree when looking up the referenced * filter expression. So when changing how a filter statement * is transformed into the cfg-tree, make sure you check * filter-call.c, especially filter_call_init() function as * well. */ $$ = log_expr_node_new_filter($2, $4, &@1); free($2); } ; parser_stmt : KW_PARSER string '{' parser_content '}' { $$ = log_expr_node_new_parser($2, $4, &@1); free($2); } ; rewrite_stmt : KW_REWRITE string '{' rewrite_content '}' { $$ = log_expr_node_new_rewrite($2, $4, &@1); free($2); } log_stmt : KW_LOG { cfg_lexer_push_context(lexer, LL_CONTEXT_LOG, NULL, "log"); } '{' log_content '}' { cfg_lexer_pop_context(lexer); } { $$ = $4; } ; plugin_stmt : LL_IDENTIFIER { Plugin *p; gint context = LL_CONTEXT_ROOT; gpointer result; p = cfg_find_plugin(configuration, context, $1); CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); result = cfg_parse_plugin(configuration, p, &@1, NULL); free($1); if (!result) YYERROR; $$ = NULL; } /* START_RULES */ source_content : { cfg_lexer_push_context(lexer, LL_CONTEXT_SOURCE, NULL, "source"); } source_items { cfg_lexer_pop_context(lexer); } { $$ = log_expr_node_new_junction($2, &@$); } ; source_items : source_item semicolons source_items { $$ = log_expr_node_append_tail(log_expr_node_new_pipe($1, &@1), $3); } | log_fork semicolons source_items { $$ = log_expr_node_append_tail($1, $3); } | { $$ = NULL; } ; source_item : source_afinter { $$ = $1; } | source_plugin { $$ = $1; } ; source_plugin : LL_IDENTIFIER { Plugin *p; gint context = LL_CONTEXT_SOURCE; p = cfg_find_plugin(configuration, context, $1); CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); last_driver = (LogDriver *) cfg_parse_plugin(configuration, p, &@1, NULL); free($1); if (!last_driver) { YYERROR; } $$ = last_driver; } ; source_afinter : KW_INTERNAL '(' source_afinter_params ')' { $$ = $3; } ; source_afinter_params : { last_driver = afinter_sd_new(configuration); last_source_options = &((AFInterSourceDriver *) last_driver)->source_options; } source_afinter_options { $$ = last_driver; } ; source_afinter_options : source_afinter_option source_afinter_options | ; source_afinter_option : source_option ; filter_content : { FilterExprNode *last_filter_expr = NULL; CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&filter_expr_parser, lexer, (gpointer *) &last_filter_expr, NULL), @$); $$ = log_expr_node_new_pipe(log_filter_pipe_new(last_filter_expr, configuration), &@$); } ; parser_content : { LogExprNode *last_parser_expr = NULL; CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&parser_expr_parser, lexer, (gpointer *) &last_parser_expr, NULL), @$); $$ = last_parser_expr; } ; rewrite_content : { LogExprNode *last_rewrite_expr = NULL; CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&rewrite_expr_parser, lexer, (gpointer *) &last_rewrite_expr, NULL), @$); $$ = last_rewrite_expr; } ; dest_content : { cfg_lexer_push_context(lexer, LL_CONTEXT_DESTINATION, NULL, "destination"); } dest_items { cfg_lexer_pop_context(lexer); } { $$ = log_expr_node_new_junction($2, &@$); } ; dest_items /* all destination drivers are added as an independent branch in a junction*/ : dest_item semicolons dest_items { $$ = log_expr_node_append_tail(log_expr_node_new_pipe($1, &@1), $3); } | log_fork semicolons dest_items { $$ = log_expr_node_append_tail($1, $3); } | { $$ = NULL; } ; dest_item : dest_plugin { $$ = $1; } ; dest_plugin : LL_IDENTIFIER { Plugin *p; gint context = LL_CONTEXT_DESTINATION; p = cfg_find_plugin(configuration, context, $1); CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); last_driver = (LogDriver *) cfg_parse_plugin(configuration, p, &@1, NULL); free($1); if (!last_driver) { YYERROR; } $$ = last_driver; } ; log_items : log_item semicolons log_items { log_expr_node_append_tail($1, $3); $$ = $1; } | { $$ = NULL; } ; log_item : KW_SOURCE '(' string ')' { $$ = log_expr_node_new_source_reference($3, &@$); free($3); } | KW_SOURCE '{' source_content '}' { $$ = log_expr_node_new_source(NULL, $3, &@$); } | KW_FILTER '(' string ')' { $$ = log_expr_node_new_filter_reference($3, &@$); free($3); } | KW_FILTER '{' filter_content '}' { $$ = log_expr_node_new_filter(NULL, $3, &@$); } | KW_PARSER '(' string ')' { $$ = log_expr_node_new_parser_reference($3, &@$); free($3); } | KW_PARSER '{' parser_content '}' { $$ = log_expr_node_new_parser(NULL, $3, &@$); } | KW_REWRITE '(' string ')' { $$ = log_expr_node_new_rewrite_reference($3, &@$); free($3); } | KW_REWRITE '{' rewrite_content '}' { $$ = log_expr_node_new_rewrite(NULL, $3, &@$); } | KW_DESTINATION '(' string ')' { $$ = log_expr_node_new_destination_reference($3, &@$); free($3); } | KW_DESTINATION '{' dest_content '}' { $$ = log_expr_node_new_destination(NULL, $3, &@$); } | log_junction { $$ = $1; } ; log_junction : KW_JUNCTION '{' log_forks '}' { $$ = log_expr_node_new_junction($3, &@$); } ; log_last_junction /* this rule matches the last set of embedded log {} * statements at the end of the log {} block. * It is the final junction and was the only form of creating * a processing tree before syslog-ng 3.4. * * We emulate if the user was writing junction {} explicitly. */ : log_forks { $$ = $1 ? log_expr_node_new_junction($1, &@1) : NULL; } ; log_forks : log_fork semicolons log_forks { log_expr_node_append_tail($1, $3); $$ = $1; } | { $$ = NULL; } ; log_fork : KW_LOG '{' log_content '}' { $$ = $3; } | KW_CHANNEL '{' log_content '}' { $$ = $3; } ; log_content : log_items log_last_junction log_flags { $$ = log_expr_node_new_log(log_expr_node_append_tail($1, $2), $3, &@$); } ; log_flags : KW_FLAGS '(' log_flags_items ')' semicolons { $$ = $3; } | { $$ = 0; } ; log_flags_items : string log_flags_items { $$ = log_expr_node_lookup_flag($1) | $2; free($1); } | { $$ = 0; } ; /* END_RULES */ options_stmt : KW_OPTIONS '{' options_items '}' ; template_stmt : template_def { CHECK_ERROR(cfg_tree_add_template(&configuration->tree, $1) || cfg_allow_config_dups(configuration), @1, "duplicate template"); } | template_fn { user_template_function_register(configuration, last_template->name, last_template); log_template_unref(last_template); last_template = NULL; } ; template_def : template_block | template_simple ; template_block : KW_TEMPLATE string { last_template = log_template_new(configuration, $2); } '{' template_items '}' { $$ = last_template; free($2); } ; template_simple : KW_TEMPLATE string { last_template = log_template_new(configuration, $2); } template_content_inner { $$ = last_template; free($2); } ; template_fn : KW_TEMPLATE_FUNCTION string { last_template = log_template_new(configuration, $2); } template_content_inner { $$ = last_template; free($2); } ; template_items : template_item ';' template_items | ; /* START_RULES */ template_content_inner : string { GError *error = NULL; CHECK_ERROR(log_template_compile(last_template, $1, &error), @1, "Error compiling template (%s)", error->message); free($1); } | LL_IDENTIFIER '(' string ')' { GError *error = NULL; CHECK_ERROR(log_template_compile(last_template, $3, &error), @3, "Error compiling template (%s)", error->message); free($3); CHECK_ERROR(log_template_set_type_hint(last_template, $1, &error), @1, "Error setting the template type-hint (%s)", error->message); free($1); } ; template_content : { last_template = log_template_new(configuration, NULL); } template_content_inner { $$ = last_template; } ; /* END_RULES */ template_item : KW_TEMPLATE '(' template_content_inner ')' | KW_TEMPLATE_ESCAPE '(' yesno ')' { log_template_set_escape(last_template, $3); } ; block_stmt : KW_BLOCK { cfg_lexer_push_context(lexer, LL_CONTEXT_BLOCK_DEF, block_def_keywords, "block definition"); } LL_IDENTIFIER LL_IDENTIFIER '(' { last_block_args = cfg_args_new(); } block_args ')' { cfg_lexer_push_context(lexer, LL_CONTEXT_BLOCK_CONTENT, NULL, "block content"); } LL_BLOCK { CfgBlockGenerator *block; /* block content */ cfg_lexer_pop_context(lexer); /* block definition */ cfg_lexer_pop_context(lexer); block = cfg_block_new(cfg_lexer_lookup_context_type_by_name($3), $4, $10, last_block_args); cfg_lexer_register_generator_plugin(&configuration->plugin_context, block); free($3); free($4); free($10); last_block_args = NULL; } ; block_args : block_arg block_args | ; block_arg : LL_IDENTIFIER { cfg_lexer_push_context(lexer, LL_CONTEXT_BLOCK_ARG, NULL, "block argument"); } LL_BLOCK { cfg_lexer_pop_context(lexer); cfg_args_set(last_block_args, $1, $3); free($1); free($3); } ; options_items : options_item ';' options_items | ; options_item : KW_MARK_FREQ '(' nonnegative_integer ')' { configuration->mark_freq = $3; } | KW_FLUSH_LINES '(' nonnegative_integer ')' { configuration->flush_lines = $3; } | KW_MARK_MODE '(' KW_INTERNAL ')' { cfg_set_mark_mode(configuration, "internal"); } | KW_MARK_MODE '(' string ')' { CHECK_ERROR(cfg_lookup_mark_mode($3) > 0 && cfg_lookup_mark_mode($3) != MM_GLOBAL, @3, "illegal global mark-mode"); cfg_set_mark_mode(configuration, $3); free($3); } | KW_FLUSH_TIMEOUT '(' positive_integer ')' { configuration->flush_timeout = $3; } | KW_CHAIN_HOSTNAMES '(' yesno ')' { configuration->chain_hostnames = $3; } | KW_KEEP_HOSTNAME '(' yesno ')' { configuration->keep_hostname = $3; } | KW_CHECK_HOSTNAME '(' yesno ')' { configuration->check_hostname = $3; } | KW_BAD_HOSTNAME '(' string ')' { cfg_bad_hostname_set(configuration, $3); free($3); } | KW_TIME_REOPEN '(' positive_integer ')' { configuration->time_reopen = $3; } | KW_TIME_REAP '(' positive_integer ')' { configuration->time_reap = $3; } | KW_TIME_SLEEP '(' nonnegative_integer ')' {} | KW_SUPPRESS '(' nonnegative_integer ')' { configuration->suppress = $3; } | KW_THREADED '(' yesno ')' { configuration->threaded = $3; } | KW_PASS_UNIX_CREDENTIALS '(' yesno ')' { configuration->pass_unix_credentials = $3; } | KW_USE_RCPTID '(' yesno ')' { cfg_set_use_uniqid($3); } | KW_USE_UNIQID '(' yesno ')' { cfg_set_use_uniqid($3); } | KW_LOG_FIFO_SIZE '(' positive_integer ')' { configuration->log_fifo_size = $3; } | KW_LOG_IW_SIZE '(' positive_integer ')' { msg_warning("WARNING: Support for the global log-iw-size() option was removed, please use a per-source log-iw-size()", cfg_lexer_format_location_tag(lexer, &@1)); } | KW_LOG_FETCH_LIMIT '(' positive_integer ')' { msg_warning("WARNING: Support for the global log-fetch-limit() option was removed, please use a per-source log-fetch-limit()", cfg_lexer_format_location_tag(lexer, &@1)); } | KW_LOG_MSG_SIZE '(' positive_integer ')' { configuration->log_msg_size = $3; } | KW_KEEP_TIMESTAMP '(' yesno ')' { configuration->keep_timestamp = $3; } | KW_CREATE_DIRS '(' yesno ')' { configuration->create_dirs = $3; } | KW_CUSTOM_DOMAIN '(' string ')' { configuration->custom_domain = g_strdup($3); free($3); } | KW_FILE_TEMPLATE '(' string ')' { configuration->file_template_name = g_strdup($3); free($3); } | KW_PROTO_TEMPLATE '(' string ')' { configuration->proto_template_name = g_strdup($3); free($3); } | KW_RECV_TIME_ZONE '(' string ')' { configuration->recv_time_zone = g_strdup($3); free($3); } | KW_JVM_OPTIONS '(' string ')' {configuration->jvm_options = g_strdup($3); free($3);} | { last_template_options = &configuration->template_options; } template_option | { last_host_resolve_options = &configuration->host_resolve_options; } host_resolve_option | { last_stats_options = &configuration->stats_options; } stat_option | { last_dns_cache_options = &configuration->dns_cache_options; } dns_cache_option | { last_file_perm_options = &configuration->file_perm_options; } file_perm_option ; stat_option : KW_STATS_FREQ '(' nonnegative_integer ')' { last_stats_options->log_freq = $3; } | KW_STATS_LEVEL '(' nonnegative_integer ')' { last_stats_options->level = $3; } | KW_STATS_LIFETIME '(' positive_integer ')' { last_stats_options->lifetime = $3; } | KW_STATS_MAX_DYNAMIC '(' nonnegative_integer ')' { last_stats_options->max_dynamic = $3; } ; dns_cache_option : KW_DNS_CACHE_SIZE '(' positive_integer ')' { last_dns_cache_options->cache_size = $3; } | KW_DNS_CACHE_EXPIRE '(' positive_integer ')' { last_dns_cache_options->expire = $3; } | KW_DNS_CACHE_EXPIRE_FAILED '(' positive_integer ')' { last_dns_cache_options->expire_failed = $3; } | KW_DNS_CACHE_HOSTS '(' string ')' { last_dns_cache_options->hosts = g_strdup($3); free($3); } ; /* START_RULES */ string : LL_IDENTIFIER | LL_STRING ; yesno : KW_YES { $$ = 1; } | KW_NO { $$ = 0; } | LL_NUMBER { $$ = $1; } ; dnsmode : yesno { $$ = $1; } | KW_PERSIST_ONLY { $$ = 2; } ; nonnegative_integer : LL_NUMBER { CHECK_ERROR(($1 >= 0), @1, "It cannot be negative"); } ; positive_integer : LL_NUMBER { CHECK_ERROR(($1 > 0), @1, "Must be positive"); } ; string_or_number : string { $$ = $1; } | LL_NUMBER { $$ = strdup(lexer->token_text->str); } | LL_FLOAT { $$ = strdup(lexer->token_text->str); } ; string_list : string_list_build { $$ = $1; } ; string_list_build : string string_list_build { $$ = g_list_prepend($2, g_strdup($1)); free($1); } | { $$ = NULL; } ; semicolons : ';' | ';' semicolons ; level_string : string { /* return the numeric value of the "level" */ int n = syslog_name_lookup_level_by_name($1); CHECK_ERROR((n != -1), @1, "Unknown priority level\"%s\"", $1); free($1); $$ = n; } ; facility_string : string { /* return the numeric value of facility */ int n = syslog_name_lookup_facility_by_name($1); CHECK_ERROR((n != -1), @1, "Unknown facility \"%s\"", $1); free($1); $$ = n; } | KW_SYSLOG { $$ = LOG_SYSLOG; } ; parser_opt : KW_TEMPLATE '(' string ')' { LogTemplate *template; GError *error = NULL; template = cfg_tree_check_inline_template(&configuration->tree, $3, &error); CHECK_ERROR_GERROR(template != NULL, @3, error, "Error compiling template"); log_parser_set_template(last_parser, template); free($3); } ; /* LogSource related options */ source_option /* NOTE: plugins need to set "last_source_options" in order to incorporate this rule in their grammar */ : KW_LOG_IW_SIZE '(' positive_integer ')' { last_source_options->init_window_size = $3; } | KW_CHAIN_HOSTNAMES '(' yesno ')' { last_source_options->chain_hostnames = $3; } | KW_KEEP_HOSTNAME '(' yesno ')' { last_source_options->keep_hostname = $3; } | KW_PROGRAM_OVERRIDE '(' string ')' { last_source_options->program_override = g_strdup($3); free($3); } | KW_HOST_OVERRIDE '(' string ')' { last_source_options->host_override = g_strdup($3); free($3); } | KW_LOG_PREFIX '(' string ')' { gchar *p = strrchr($3, ':'); if (p) *p = 0; last_source_options->program_override = g_strdup($3); free($3); } | KW_KEEP_TIMESTAMP '(' yesno ')' { last_source_options->keep_timestamp = $3; } | KW_READ_OLD_RECORDS '(' yesno ')' { last_source_options->read_old_records = $3; } | KW_TAGS '(' string_list ')' { log_source_options_set_tags(last_source_options, $3); } | { last_host_resolve_options = &last_source_options->host_resolve_options; } host_resolve_option | driver_option ; source_proto_option : KW_ENCODING '(' string ')' { CHECK_ERROR(log_proto_server_options_set_encoding(last_proto_server_options, $3), @3, "unknown encoding %s", $3); free($3); } | KW_LOG_MSG_SIZE '(' positive_integer ')' { last_proto_server_options->max_msg_size = $3; } ; source_reader_options : source_reader_option source_reader_options ; host_resolve_option : KW_USE_FQDN '(' yesno ')' { last_host_resolve_options->use_fqdn = $3; } | KW_USE_DNS '(' dnsmode ')' { last_host_resolve_options->use_dns = $3; } | KW_DNS_CACHE '(' yesno ')' { last_host_resolve_options->use_dns_cache = $3; } | KW_NORMALIZE_HOSTNAMES '(' yesno ')' { last_host_resolve_options->normalize_hostnames = $3; } ; msg_format_option : KW_TIME_ZONE '(' string ')' { last_msg_format_options->recv_time_zone = g_strdup($3); free($3); } | KW_DEFAULT_LEVEL '(' level_string ')' { if (last_msg_format_options->default_pri == 0xFFFF) last_msg_format_options->default_pri = LOG_USER; last_msg_format_options->default_pri = (last_msg_format_options->default_pri & ~7) | $3; } | KW_DEFAULT_FACILITY '(' facility_string ')' { if (last_msg_format_options->default_pri == 0xFFFF) last_msg_format_options->default_pri = LOG_NOTICE; last_msg_format_options->default_pri = (last_msg_format_options->default_pri & 7) | $3; } ; /* LogReader related options, inherits from LogSource */ source_reader_option /* NOTE: plugins need to set "last_reader_options" in order to incorporate this rule in their grammar */ : KW_CHECK_HOSTNAME '(' yesno ')' { last_reader_options->check_hostname = $3; } | KW_FLAGS '(' source_reader_option_flags ')' | KW_LOG_FETCH_LIMIT '(' positive_integer ')' { last_reader_options->fetch_limit = $3; } | KW_FORMAT '(' string ')' { last_reader_options->parse_options.format = g_strdup($3); free($3); } | { last_source_options = &last_reader_options->super; } source_option | { last_proto_server_options = &last_reader_options->proto_options.super; } source_proto_option | { last_msg_format_options = &last_reader_options->parse_options; } msg_format_option ; source_reader_option_flags : string source_reader_option_flags { CHECK_ERROR(log_reader_options_process_flag(last_reader_options, $1), @1, "Unknown flag %s", $1); free($1); } | KW_CHECK_HOSTNAME source_reader_option_flags { log_reader_options_process_flag(last_reader_options, "check-hostname"); } | ; driver_option : KW_PERSIST_NAME '(' string ')' { log_pipe_set_persist_name(&last_driver->super, g_strdup($3)); free($3); } ; threaded_dest_driver_option : KW_RETRIES '(' positive_integer ')' { log_threaded_dest_driver_set_max_retries(last_driver, $3); } dest_driver_option /* NOTE: plugins need to set "last_driver" in order to incorporate this rule in their grammar */ : KW_LOG_FIFO_SIZE '(' positive_integer ')' { ((LogDestDriver *) last_driver)->log_fifo_size = $3; } | KW_THROTTLE '(' nonnegative_integer ')' { ((LogDestDriver *) last_driver)->throttle = $3; } | LL_IDENTIFIER { Plugin *p; gint context = LL_CONTEXT_INNER_DEST; gpointer value; p = cfg_find_plugin(configuration, context, $1); CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); value = cfg_parse_plugin(configuration, p, &@1, last_driver); free($1); if (!value) { YYERROR; } log_driver_add_plugin(last_driver, (LogDriverPlugin *) value); } | driver_option ; dest_writer_options : dest_writer_option dest_writer_options | ; dest_writer_option /* NOTE: plugins need to set "last_writer_options" in order to incorporate this rule in their grammar */ : KW_FLAGS '(' dest_writer_options_flags ')' { last_writer_options->options = $3; } | KW_FLUSH_LINES '(' nonnegative_integer ')' { last_writer_options->flush_lines = $3; } | KW_FLUSH_TIMEOUT '(' positive_integer ')' { last_writer_options->flush_timeout = $3; } | KW_SUPPRESS '(' nonnegative_integer ')' { last_writer_options->suppress = $3; } | KW_TEMPLATE '(' string ')' { GError *error = NULL; last_writer_options->template = cfg_tree_check_inline_template(&configuration->tree, $3, &error); CHECK_ERROR_GERROR(last_writer_options->template != NULL, @3, error, "Error compiling template"); free($3); } | KW_TEMPLATE_ESCAPE '(' yesno ')' { log_writer_options_set_template_escape(last_writer_options, $3); } | KW_PAD_SIZE '(' nonnegative_integer ')' { last_writer_options->padding = $3; } | KW_MARK_FREQ '(' nonnegative_integer ')' { last_writer_options->mark_freq = $3; } | KW_MARK_MODE '(' KW_INTERNAL ')' { log_writer_options_set_mark_mode(last_writer_options, "internal"); } | KW_MARK_MODE '(' string ')' { CHECK_ERROR(cfg_lookup_mark_mode($3) != -1, @3, "illegal mark mode: %s", $3); log_writer_options_set_mark_mode(last_writer_options, $3); free($3); } | { last_template_options = &last_writer_options->template_options; } template_option ; dest_writer_options_flags : string dest_writer_options_flags { $$ = log_writer_options_lookup_flag($1) | $2; free($1); } | { $$ = 0; } ; file_perm_option : KW_OWNER '(' string_or_number ')' { file_perm_options_set_file_uid(last_file_perm_options, $3); free($3); } | KW_OWNER '(' ')' { file_perm_options_dont_change_file_uid(last_file_perm_options); } | KW_GROUP '(' string_or_number ')' { file_perm_options_set_file_gid(last_file_perm_options, $3); free($3); } | KW_GROUP '(' ')' { file_perm_options_dont_change_file_gid(last_file_perm_options); } | KW_PERM '(' LL_NUMBER ')' { file_perm_options_set_file_perm(last_file_perm_options, $3); } | KW_PERM '(' ')' { file_perm_options_dont_change_file_perm(last_file_perm_options); } | KW_DIR_OWNER '(' string_or_number ')' { file_perm_options_set_dir_uid(last_file_perm_options, $3); free($3); } | KW_DIR_OWNER '(' ')' { file_perm_options_dont_change_dir_uid(last_file_perm_options); } | KW_DIR_GROUP '(' string_or_number ')' { file_perm_options_set_dir_gid(last_file_perm_options, $3); free($3); } | KW_DIR_GROUP '(' ')' { file_perm_options_dont_change_dir_gid(last_file_perm_options); } | KW_DIR_PERM '(' LL_NUMBER ')' { file_perm_options_set_dir_perm(last_file_perm_options, $3); } | KW_DIR_PERM '(' ')' { file_perm_options_dont_change_dir_perm(last_file_perm_options); } ; template_option : KW_TS_FORMAT '(' string ')' { last_template_options->ts_format = cfg_ts_format_value($3); free($3); } | KW_FRAC_DIGITS '(' nonnegative_integer ')' { last_template_options->frac_digits = $3; } | KW_TIME_ZONE '(' string ')' { last_template_options->time_zone[LTZ_SEND] = g_strdup($3); free($3); } | KW_SEND_TIME_ZONE '(' string ')' { last_template_options->time_zone[LTZ_SEND] = g_strdup($3); free($3); } | KW_LOCAL_TIME_ZONE '(' string ')' { last_template_options->time_zone[LTZ_LOCAL] = g_strdup($3); free($3); } | KW_ON_ERROR '(' string ')' { gint on_error; CHECK_ERROR(log_template_on_error_parse($3, &on_error), @3, "Invalid on-error() setting"); free($3); log_template_options_set_on_error(last_template_options, on_error); } ; matcher_option : KW_TYPE '(' string ')' { CHECK_ERROR(log_matcher_options_set_type(last_matcher_options, $3), @3, "unknown matcher type"); free($3); } | KW_FLAGS '(' matcher_flags ')' ; matcher_flags : string matcher_flags { CHECK_ERROR(log_matcher_options_process_flag(last_matcher_options, $1), @1, "unknown matcher flag"); free($1); } | ; value_pair_option : KW_VALUE_PAIRS { last_value_pairs = value_pairs_new(); } '(' vp_options ')' { $$ = last_value_pairs; } ; vp_options : vp_option vp_options | ; vp_option : KW_PAIR '(' string ':' template_content ')' { value_pairs_add_pair(last_value_pairs, $3, $5); free($3); } | KW_PAIR '(' string template_content ')' { value_pairs_add_pair(last_value_pairs, $3, $4); free($3); } | KW_KEY '(' string KW_REKEY '(' { last_vp_transset = value_pairs_transform_set_new($3); value_pairs_add_glob_pattern(last_value_pairs, $3, TRUE); free($3); } vp_rekey_options ')' { value_pairs_add_transforms(last_value_pairs, last_vp_transset); } ')' | KW_KEY '(' string_list ')' { value_pairs_add_glob_patterns(last_value_pairs, $3, TRUE); } | KW_REKEY '(' string { last_vp_transset = value_pairs_transform_set_new($3); free($3); } vp_rekey_options ')' { value_pairs_add_transforms(last_value_pairs, last_vp_transset); } | KW_EXCLUDE '(' string_list ')' { value_pairs_add_glob_patterns(last_value_pairs, $3, FALSE); } | KW_SCOPE '(' vp_scope_list ')' ; vp_scope_list : string vp_scope_list { value_pairs_add_scope(last_value_pairs, $1); free($1); } | ; vp_rekey_options : vp_rekey_option vp_rekey_options | ; vp_rekey_option : KW_SHIFT '(' LL_NUMBER ')' { value_pairs_transform_set_add_func(last_vp_transset, value_pairs_new_transform_shift($3)); } | KW_ADD_PREFIX '(' string ')' { value_pairs_transform_set_add_func(last_vp_transset, value_pairs_new_transform_add_prefix($3)); free($3); } | KW_REPLACE_PREFIX '(' string string ')' { value_pairs_transform_set_add_func(last_vp_transset, value_pairs_new_transform_replace_prefix($3, $4)); free($3); free($4); } ; /* END_RULES */ %% syslog-ng-syslog-ng-3.13.2/lib/cfg-lex.l000066400000000000000000000331021321171025300177040ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %{ #include "syslog-ng.h" #include "cfg-lexer.h" #include "cfg-lexer-subst.h" #include "cfg-grammar.h" #include "messages.h" #include "parse-number.h" #include #include static gint yy_input_run_backtick_substitution(CfgLexer *self, gchar *buf, gsize buf_size) { gchar *res; gsize len; GError *error = NULL; YYLTYPE *cur_lloc = &self->include_stack[self->include_depth].lloc; res = cfg_lexer_subst_args_in_input(self->cfg->globals, NULL, NULL, buf, -1, &len, &error); if (!res) { msg_error("Error performing backtick substitution in configuration file", evt_tag_str("error", error->message), evt_tag_str("filename", cur_lloc->level->name), evt_tag_printf("line", "%d:%d", cur_lloc->first_line, cur_lloc->first_column)); g_clear_error(&error); goto error; } else { if (len > buf_size) { msg_error("Error performing backtick substitution in configuration file", evt_tag_str("error", "lexer buffer is too small to hold substituted result"), evt_tag_str("filename", cur_lloc->level->name), evt_tag_printf("line", "%d:%d", cur_lloc->first_line, cur_lloc->first_column)); goto error; } else { memcpy(buf, res, len); } g_free(res); return len; } error: return -1; } #define YY_INPUT(buf, result, max_size) \ do \ { \ if (!fgets(buf, max_size, yyin)) \ result = YY_NULL; \ else if (YY_START >= block) \ result = strlen(buf); \ else \ { \ gint rc; \ rc = yy_input_run_backtick_substitution(yyextra, buf, max_size); \ if (rc < 0) \ { \ YY_FATAL_ERROR("backtick substitution failure"); \ result = YY_NULL; \ } \ else \ { \ result = rc; \ } \ } \ } while(0) #define YY_USER_ACTION \ do { \ YYLTYPE *cur_lloc = &yyextra->include_stack[yyextra->include_depth].lloc; \ if (YY_START == INITIAL) \ { \ cur_lloc->first_column = cur_lloc->last_column; \ } \ cur_lloc->last_column = cur_lloc->last_column + yyleng; \ if (yyextra->token_text) \ g_string_append_len(yyextra->token_text, yytext, yyleng); \ *yylloc = *cur_lloc; \ } while(0); #define YY_BREAK \ do { \ if (yyextra->token_text && YY_START == INITIAL) \ { \ g_string_append_len(yyextra->token_pretext, yyextra->token_text->str, yyextra->token_text->len); \ g_string_truncate(yyextra->token_text, 0); \ } \ } while (0); \ break; #define YY_FATAL_ERROR(msg) \ do { \ struct yyguts_t * __yyg = (struct yyguts_t*) yyscanner; \ \ msg_error("Fatal error in configuration lexer, giving up", \ evt_tag_str("error", msg), \ NULL); \ longjmp(__yyg->yyextra_r->fatal_error, 1); \ } while(0) static void _cfg_lex_new_line(CfgLexer *lexer) { lexer->include_stack[lexer->include_depth].lloc.first_line++; lexer->include_stack[lexer->include_depth].lloc.last_line++; lexer->include_stack[lexer->include_depth].lloc.first_column = 1; lexer->include_stack[lexer->include_depth].lloc.last_column = 1; } %} %option bison-bridge bison-locations reentrant %option prefix="_cfg_lexer_" %option header-file="lex.yy.h" %option outfile="lex.yy.c" %option extra-type="CfgLexer *" %option noyywrap %option stack white [ \t] digit [0-9] xdigit [0-9a-fA-F] odigit [0-7] alpha [a-zA-Z] alphanum [a-zA-Z0-9] word [^ \#'"\(\)\{\}\[\]\\;\r\n\t,|\.@:] /* block related states must be last, as we use this fact in YY_INPUT */ %x string %x qstring %x block %x block_content %x block_string %x block_qstring %% \# { int ch; ch = input(yyscanner); while (ch != '\n' && ch != EOF && ch != 0) { if (yyextra->token_text) g_string_append_c(yyextra->token_text, ch); ch = input(yyscanner); } if (ch == '\n') { unput(ch); } } ^@ { return LL_PRAGMA; } <*>\r?\n { *yylloc = yyextra->include_stack[yyextra->include_depth].lloc; _cfg_lex_new_line(yyextra); if (yyextra->tokenize_eol) return LL_EOL; else g_string_append(yyextra->string_buffer, yytext); } {white}+ ; \.\. { return LL_DOTDOT; } (-|\+)?{digit}+\.{digit}+ { yylval->fnum = strtod(yytext, NULL); return LL_FLOAT; } 0x{xdigit}+ { yylval->num = strtoll(yytext + 2, NULL, 16); return LL_NUMBER; } 0{odigit}+ { yylval->num = strtoll(yytext + 1, NULL, 8); return LL_NUMBER; } (-|\+)?{digit}+(M|m|G|g|k|K)?(i|I)?(b|B)? { if (!parse_number_with_suffix(yytext, &yylval->num)) { return LL_ERROR; } return LL_NUMBER; } ({word}+(\.)?)*{word}+ { return cfg_lexer_lookup_keyword(yyextra, yylval, yylloc, yytext); } \( | \) | \; | \{ | \} | \[ | \] | \: | \| { return yytext[0]; } \, ; \" { g_string_truncate(yyextra->string_buffer, 0); yy_push_state(string, yyscanner); } \' { g_string_truncate(yyextra->string_buffer, 0); yy_push_state(qstring, yyscanner); } \\a { g_string_append_c(yyextra->string_buffer, 7); } \\n { g_string_append_c(yyextra->string_buffer, 10); } \\r { g_string_append_c(yyextra->string_buffer, 13); } \\t { g_string_append_c(yyextra->string_buffer, 9); } \\v { g_string_append_c(yyextra->string_buffer, 11); } \\x{xdigit}{1,2} { g_string_append_c(yyextra->string_buffer, strtol(yytext+2, NULL, 16)); } \\o{odigit}{1,3} { g_string_append_c(yyextra->string_buffer, strtol(yytext+2, NULL, 8)); } \\[^anrtv] { g_string_append_c(yyextra->string_buffer, yytext[1]); } \" { yy_pop_state(yyscanner); yylval->cptr = strdup(yyextra->string_buffer->str); return LL_STRING; } [^"\\]+ { g_string_append(yyextra->string_buffer, yytext); } [^']+ { g_string_append(yyextra->string_buffer, yytext); } \' { yy_pop_state(yyscanner); yylval->cptr = strdup(yyextra->string_buffer->str); return LL_STRING; } /* rules to parse a block as a LL_BLOCK token */ {white}+ ; [^{( \t]+ { return LL_ERROR; } [{(] { if (yytext[0] != yyextra->block_boundary[0]) REJECT; g_string_truncate(yyextra->string_buffer, 0); yyextra->brace_count = 1; yy_push_state(block_content, yyscanner); } \" { g_string_append_c(yyextra->string_buffer, yytext[0]); yy_push_state(block_string, yyscanner); } \' { g_string_append_c(yyextra->string_buffer, yytext[0]); yy_push_state(block_qstring, yyscanner); } [^"]+ { g_string_append(yyextra->string_buffer, yytext); } \\\" { g_string_append(yyextra->string_buffer, yytext); } \" { g_string_append_c(yyextra->string_buffer, yytext[0]); yy_pop_state(yyscanner); } \' { g_string_append_c(yyextra->string_buffer, yytext[0]); yy_pop_state(yyscanner); } [^']+ { g_string_append(yyextra->string_buffer, yytext); } [{(] { g_string_append_c(yyextra->string_buffer, yytext[0]); if (yytext[0] == yyextra->block_boundary[0]) yyextra->brace_count++; } [})] { if (yytext[0] == yyextra->block_boundary[1]) yyextra->brace_count--; if (yyextra->brace_count == 0) { yy_pop_state(yyscanner); yy_pop_state(yyscanner); yylval->cptr = strdup(yyextra->string_buffer->str); return LL_BLOCK; } else { g_string_append_c(yyextra->string_buffer, yytext[0]); } } [^{}()\"\'\n\r]+ { g_string_append(yyextra->string_buffer, yytext); } <> { if (!cfg_lexer_start_next_include(yyextra)) { if (yyextra->include_depth == 0) { *yylloc = yyextra->include_stack[0].lloc; yyterminate(); } else return LL_ERROR; } } %% void cfg_lexer_unput_string(CfgLexer *self, const char *str) { int len = strlen(str); int i; for (i = len - 1; i >= 0; i--) { yyunput(str[i], _cfg_lexer_get_text(self->state), self->state); self->include_stack[self->include_depth].lloc.first_column--; self->include_stack[self->include_depth].lloc.last_column--; } } void cfg_lexer_start_block_state(CfgLexer *self, gchar block_boundary[2]) { memcpy(&self->block_boundary, block_boundary, sizeof(self->block_boundary)); yy_push_state(block, self->state); } /* avoid warnings of unused symbols */ gpointer __dummy[] = { yy_top_state, yy_fatal_error }; syslog-ng-syslog-ng-3.13.2/lib/cfg-lexer-subst.c000066400000000000000000000203331321171025300213620ustar00rootroot00000000000000/* * Copyright (c) 2010-2013 Balabit * Copyright (c) 2010-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-lexer-subst.h" #include "cfg-args.h" #include "cfg-grammar.h" #include #include typedef enum _CfgLexerStringTrackState { CLS_NOT_STRING, CLS_WITHIN_STRING, CLS_WITHIN_STRING_QUOTE, CLS_WITHIN_STRING_QUOTED_CHARACTER, CLS_WITHIN_QSTRING, } CfgLexerStringTrackState; /* substitute backtick references into lexer input */ struct _CfgLexerSubst { CfgArgs *globals; CfgArgs *defs; CfgArgs *args; CfgLexerStringTrackState string_state; GString *result_buffer; }; static const gchar * _lookup_value(CfgLexerSubst *self, const gchar *name) { const gchar *arg; if (self->args && (arg = cfg_args_get(self->args, name))) ; else if (self->defs && (arg = cfg_args_get(self->defs, name))) ; else if (self->globals && (arg = cfg_args_get(self->globals, name))) ; else if ((arg = g_getenv(name))) ; else arg = NULL; return arg; } static CfgLexerStringTrackState _track_string_state(CfgLexerSubst *self, CfgLexerStringTrackState last_state, const gchar *p) { switch (last_state) { case CLS_NOT_STRING: if (*p == '"') return CLS_WITHIN_STRING; else if (*p == '\'') return CLS_WITHIN_QSTRING; return CLS_NOT_STRING; case CLS_WITHIN_STRING: if (*p == '\\') return CLS_WITHIN_STRING_QUOTE; else if (*p == '"') return CLS_NOT_STRING; return CLS_WITHIN_STRING; case CLS_WITHIN_STRING_QUOTE: return CLS_WITHIN_STRING_QUOTED_CHARACTER; case CLS_WITHIN_STRING_QUOTED_CHARACTER: return CLS_WITHIN_STRING; case CLS_WITHIN_QSTRING: if (*p == '\'') return CLS_NOT_STRING; return CLS_WITHIN_QSTRING; } g_assert_not_reached(); } static gchar * _extract_string_literal(const gchar *value) { CfgLexer *lexer; gint token, look_ahead_token; YYSTYPE yylval, look_ahead_yylval; YYLTYPE yylloc, look_ahead_yylloc; gchar *result = NULL; lexer = cfg_lexer_new_buffer(configuration, value, strlen(value)); token = cfg_lexer_lex(lexer, &yylval, &yylloc); if (token == LL_STRING) { look_ahead_token = cfg_lexer_lex(lexer, &look_ahead_yylval, &look_ahead_yylloc); if (!look_ahead_token) result = g_strdup(yylval.cptr); cfg_lexer_free_token(&look_ahead_yylval); } cfg_lexer_free_token(&yylval); cfg_lexer_free(lexer); return result; } static gboolean _encode_as_string(CfgLexerSubst *self, const gchar *value, GError **error) { gint i; g_return_val_if_fail(error == NULL || (*error) == NULL, FALSE); for (i = 0; value[i]; i++) { gchar p = value[i]; if (p == '"') g_string_append(self->result_buffer, "\\\""); else if (p == '\n') g_string_append(self->result_buffer, "\\n"); else if (p == '\r') g_string_append(self->result_buffer, "\\r"); else if (p == '\\') g_string_append(self->result_buffer, "\\\\"); else g_string_append_c(self->result_buffer, p); } return TRUE; } static gboolean _encode_as_qstring(CfgLexerSubst *self, const gchar *value, GError **error) { gint i; g_return_val_if_fail(error == NULL || (*error) == NULL, FALSE); for (i = 0; value[i]; i++) { gchar p = value[i]; if (p == '\'') { g_set_error(error, CFG_LEXER_ERROR, CFG_LEXER_CANNOT_REPRESENT_APOSTROPHES_IN_QSTRINGS, "cannot represent apostrophes within apostroph-enclosed string"); return FALSE; } g_string_append_c(self->result_buffer, p); } return TRUE; } static gboolean _append_value(CfgLexerSubst *self, const gchar *value, GError **error) { g_return_val_if_fail(error == NULL || (*error) == NULL, FALSE); gboolean result = TRUE; if (self->string_state == CLS_NOT_STRING) { g_string_append(self->result_buffer, value); } else { gchar *string_literal; string_literal = _extract_string_literal(value); if (string_literal) { switch (self->string_state) { case CLS_WITHIN_STRING: result = _encode_as_string(self, string_literal, error); break; case CLS_WITHIN_QSTRING: result = _encode_as_qstring(self, string_literal, error); break; default: g_assert_not_reached(); break; } g_free(string_literal); } else g_string_append(self->result_buffer, value); } return result; } gchar * cfg_lexer_subst_invoke(CfgLexerSubst *self, const gchar *input, gssize input_len, gsize *output_length, GError **error) { gboolean backtick = FALSE; const gchar *p, *ref_start = input; GString *result; g_return_val_if_fail(error == NULL || (*error) == NULL, FALSE); if (input_len < 0) input_len = strlen(input); result = g_string_sized_new(32); self->result_buffer = result; p = input; while (p - input < input_len) { self->string_state = _track_string_state(self, self->string_state, p); if (!backtick && (*p) == '`') { if (self->string_state == CLS_WITHIN_STRING_QUOTED_CHARACTER) { g_set_error(error, CFG_LEXER_ERROR, CFG_LEXER_BACKTICKS_CANT_BE_SUBSTITUTED_AFTER_BACKSLASH, "cannot subsitute backticked values right after a string quote character"); goto error; } /* start of reference */ backtick = TRUE; ref_start = p + 1; } else if (backtick && (*p) == '`') { /* end of reference */ backtick = FALSE; if (ref_start == p) { /* empty ref, just include a ` character */ g_string_append_c(result, '`'); } else { const gchar *value; gchar *name; name = g_strndup(ref_start, p - ref_start); value = _lookup_value(self, name); g_free(name); if (!_append_value(self, value ? : "", error)) goto error; } } else if (!backtick) g_string_append_c(result, *p); p++; } self->result_buffer = NULL; if (backtick) { g_set_error(error, CFG_LEXER_ERROR, CFG_LEXER_MISSING_BACKTICK_PAIR, "missing closing backtick (`) character"); goto error; } *output_length = result->len; return g_string_free(result, FALSE); error: g_string_free(result, TRUE); return NULL; } CfgLexerSubst * cfg_lexer_subst_new(CfgArgs *globals, CfgArgs *defs, CfgArgs *args) { CfgLexerSubst *self = g_new0(CfgLexerSubst, 1); self->globals = globals; self->defs = defs; self->args = args; return self; } void cfg_lexer_subst_free(CfgLexerSubst *self) { cfg_args_unref(self->globals); cfg_args_unref(self->defs); cfg_args_unref(self->args); g_free(self); } gchar * cfg_lexer_subst_args_in_input(CfgArgs *globals, CfgArgs *defs, CfgArgs *args, const gchar *input, gssize input_length, gsize *output_length, GError **error) { CfgLexerSubst *subst = cfg_lexer_subst_new(cfg_args_ref(globals), cfg_args_ref(defs), cfg_args_ref(args)); gchar *result; result = cfg_lexer_subst_invoke(subst, input, input_length, output_length, error); cfg_lexer_subst_free(subst); return result; } syslog-ng-syslog-ng-3.13.2/lib/cfg-lexer-subst.h000066400000000000000000000031061321171025300213660ustar00rootroot00000000000000/* * Copyright (c) 2010-2013 Balabit * Copyright (c) 2010-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CFG_LEXER_SUBST_H_INCLUDED #define CFG_LEXER_SUBST_H_INCLUDED 1 #include "syslog-ng.h" #include "cfg-args.h" typedef struct _CfgLexerSubst CfgLexerSubst; gchar *cfg_lexer_subst_invoke(CfgLexerSubst *self, const gchar *input, gssize input_len, gsize *output_length, GError **error); CfgLexerSubst *cfg_lexer_subst_new(CfgArgs *globals, CfgArgs *defs, CfgArgs *args); void cfg_lexer_subst_free(CfgLexerSubst *self); gchar * cfg_lexer_subst_args_in_input(CfgArgs *globals, CfgArgs *defs, CfgArgs *args, const gchar *input, gssize input_length, gsize *output_length, GError **error); #endif syslog-ng-syslog-ng-3.13.2/lib/cfg-lexer.c000066400000000000000000001011511321171025300202220ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-lexer.h" #include "cfg-lexer-subst.h" #include "cfg-block-generator.h" #include "cfg-lex.h" #include "cfg-grammar.h" #include "block-ref-parser.h" #include "pragma-parser.h" #include "messages.h" #include "pathutils.h" #include "plugin.h" #include "plugin-types.h" #include #include #include /* * A token block is a series of tokens to be injected into the tokens * fetched by the lexer. It is assumed to be filled and then depleted, the * two operations cannot be intermixed. */ struct _CfgTokenBlock { gint pos; GArray *tokens; }; /** * CfgLexerContext: * * This object tells the lexer in which context it is operating right * now. The context influences the way the lexer works, for example in * LL_CONTEXT_BLOCK_DEF/REF all keyword resolutions are disabled. * * A textual description is also associated with the current context * in order to give better error messages. **/ typedef struct _CfgLexerContext { gint type; CfgLexerKeyword *keywords; gchar desc[0]; } CfgLexerContext; /* * cfg_lexer_push_context: * * This function can be used to push a lexer context to the stack. The top * of the stack determines how an error is reported and can also influence * the lexer. */ void cfg_lexer_push_context(CfgLexer *self, gint type, CfgLexerKeyword *keywords, const gchar *desc) { CfgLexerContext *context; context = g_malloc(sizeof(CfgLexerContext) + strlen(desc) + 1); context->type = type ? type : cfg_lexer_get_context_type(self); context->keywords = keywords; memcpy(&context->desc, desc, strlen(desc) + 1); self->context_stack = g_list_prepend(self->context_stack, context); } /* * cfg_lexer_pop_context: * * Pop the topmost item off the stack. */ void cfg_lexer_pop_context(CfgLexer *self) { if (self->context_stack) { g_free((gchar *) self->context_stack->data); self->context_stack = g_list_delete_link(self->context_stack, self->context_stack); } } /* * cfg_lexer_get_context_type: * * Get the current context type (one of LL_CONTEXT_* values). */ gint cfg_lexer_get_context_type(CfgLexer *self) { GList *l; l = self->context_stack; if (l) return ((CfgLexerContext *) l->data)->type; return 0; } /* * cfg_lexer_get_context_description: * * Get the description of the current context. */ const gchar * cfg_lexer_get_context_description(CfgLexer *self) { GList *l; l = self->context_stack; if (l) return ((CfgLexerContext *) l->data)->desc; return "configuration"; } /* this can only be called from the grammar */ static CfgIncludeLevel * _find_closest_file_inclusion(CfgLexer *self, YYLTYPE *yylloc) { for (gint level_ndx = self->include_depth; level_ndx >= 0; level_ndx--) { CfgIncludeLevel *level = &self->include_stack[level_ndx]; if (level->include_type == CFGI_FILE) return level; } return NULL; } EVTTAG * cfg_lexer_format_location_tag(CfgLexer *self, YYLTYPE *yylloc) { gchar buf[256]; CfgIncludeLevel *level; level = _find_closest_file_inclusion(self, yylloc); if (level) g_snprintf(buf, sizeof(buf), "%s:%d:%d", level->name, level->lloc.first_line, level->lloc.first_column); else g_snprintf(buf, sizeof(buf), "%s:%d:%d", "#buffer", yylloc->first_line, yylloc->first_column); return evt_tag_str("location", buf); } int cfg_lexer_lookup_keyword(CfgLexer *self, YYSTYPE *yylval, YYLTYPE *yylloc, const char *token) { GList *l; l = self->context_stack; while (l) { CfgLexerContext *context = ((CfgLexerContext *) l->data); CfgLexerKeyword *keywords = context->keywords; if (keywords) { int i, j; for (i = 0; keywords[i].kw_name; i++) { if (strcmp(keywords[i].kw_name, CFG_KEYWORD_STOP) == 0) { yylval->type = LL_IDENTIFIER; yylval->cptr = strdup(token); return LL_IDENTIFIER; } for (j = 0; token[j] && keywords[i].kw_name[j]; j++) { if (token[j] == '-' || token[j] == '_') { if (keywords[i].kw_name[j] != '_') break; } else if (token[j] != keywords[i].kw_name[j]) break; } if (token[j] == 0 && keywords[i].kw_name[j] == 0) { /* match */ switch (keywords[i].kw_status) { case KWS_OBSOLETE: msg_warning("WARNING: Your configuration file uses an obsoleted keyword, please update your configuration", evt_tag_str("keyword", keywords[i].kw_name), evt_tag_str("change", keywords[i].kw_explain), cfg_lexer_format_location_tag(self, yylloc)); break; default: break; } keywords[i].kw_status = KWS_NORMAL; yylval->type = LL_TOKEN; yylval->token = keywords[i].kw_token; return keywords[i].kw_token; } } } l = l->next; } yylval->type = LL_IDENTIFIER; yylval->cptr = strdup(token); return LL_IDENTIFIER; } gboolean cfg_lexer_start_next_include(CfgLexer *self) { CfgIncludeLevel *level = &self->include_stack[self->include_depth]; gchar *filename; gboolean buffer_processed = FALSE; if (self->include_depth == 0) { return FALSE; } if (level->yybuf) { msg_debug("Finishing include", evt_tag_str((level->include_type == CFGI_FILE ? "filename" : "content"), level->name), evt_tag_int("depth", self->include_depth)); buffer_processed = TRUE; } /* reset the include state, should also handle initial invocations, in which case everything is NULL */ if (level->yybuf) { _cfg_lexer__delete_buffer(level->yybuf, self->state); level->yybuf = NULL; } if (level->include_type == CFGI_FILE) { if (level->file.include_file) { fclose(level->file.include_file); level->file.include_file = NULL; } } if ((level->include_type == CFGI_BUFFER && buffer_processed) || (level->include_type == CFGI_FILE && !level->file.files)) { /* we finished with an include statement that included a series of * files (e.g. directory include). */ g_free(level->name); if (level->include_type == CFGI_BUFFER) g_free(level->buffer.content); memset(level, 0, sizeof(*level)); self->include_depth--; _cfg_lexer__switch_to_buffer(self->include_stack[self->include_depth].yybuf, self->state); return TRUE; } /* now populate "level" with the new include information */ if (level->include_type == CFGI_BUFFER) { level->yybuf = _cfg_lexer__scan_buffer(level->buffer.content, level->buffer.content_length, self->state); } else if (level->include_type == CFGI_FILE) { FILE *include_file; filename = (gchar *) level->file.files->data; level->file.files = g_slist_delete_link(level->file.files, level->file.files); include_file = fopen(filename, "r"); if (!include_file) { msg_error("Error opening include file", evt_tag_str("filename", filename), evt_tag_int("depth", self->include_depth)); g_free(filename); return FALSE; } msg_debug("Starting to read include file", evt_tag_str("filename", filename), evt_tag_int("depth", self->include_depth)); g_free(level->name); level->name = filename; level->file.include_file = include_file; level->yybuf = _cfg_lexer__create_buffer(level->file.include_file, YY_BUF_SIZE, self->state); } else { g_assert_not_reached(); } level->lloc.first_line = level->lloc.last_line = 1; level->lloc.first_column = level->lloc.last_column = 1; level->lloc.level = level; _cfg_lexer__switch_to_buffer(level->yybuf, self->state); return TRUE; } static gboolean cfg_lexer_include_file_simple(CfgLexer *self, const gchar *filename) { CfgIncludeLevel *level; struct stat st; if (stat(filename, &st) < 0) { return FALSE; } self->include_depth++; level = &self->include_stack[self->include_depth]; level->include_type = CFGI_FILE; if (S_ISDIR(st.st_mode)) { GDir *dir; GError *error = NULL; const gchar *entry; dir = g_dir_open(filename, 0, &error); if (!dir) { msg_error("Error opening directory for reading", evt_tag_str("filename", filename), evt_tag_str("error", error->message)); goto drop_level; } while ((entry = g_dir_read_name(dir))) { const gchar *p; if (entry[0] == '.') { msg_debug("Skipping include file, it cannot begin with .", evt_tag_str("filename", entry)); continue; } for (p = entry; *p; p++) { if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || (*p == '_') || (*p == '-') || (*p == '.'))) { msg_debug("Skipping include file, does not match pattern [\\-_a-zA-Z0-9]+", evt_tag_str("filename", entry)); p = NULL; break; } } if (p) { gchar *full_filename = g_build_filename(filename, entry, NULL); if (stat(full_filename, &st) < 0 || S_ISDIR(st.st_mode)) { msg_debug("Skipping include file as it is a directory", evt_tag_str("filename", entry)); g_free(full_filename); continue; } level->file.files = g_slist_insert_sorted(level->file.files, full_filename, (GCompareFunc) strcmp); msg_debug("Adding include file", evt_tag_str("filename", entry), evt_tag_int("depth", self->include_depth)); } } g_dir_close(dir); if (!level->file.files) { /* no include files in the specified directory */ msg_debug("No files in this include directory", evt_tag_str("dir", filename)); self->include_depth--; return TRUE; } } else { g_assert(level->file.files == NULL); level->file.files = g_slist_prepend(level->file.files, g_strdup(filename)); } return cfg_lexer_start_next_include(self); drop_level: g_slist_foreach(level->file.files, (GFunc) g_free, NULL); g_slist_free(level->file.files); level->file.files = NULL; return FALSE; } static int _cfg_lexer_glob_err (const char *p, gint e) { if (e != ENOENT) { msg_debug ("Error processing path for inclusion", evt_tag_str("path", p), evt_tag_errno("errno", e)); return -1; } return 0; } #ifndef GLOB_NOMAGIC #define GLOB_NOMAGIC 0 int __glob_pattern_p (const char *pattern) { register const char *p; int open = 0; for (p = pattern; *p != '\0'; ++p) switch (*p) { case '?': case '*': return 1; case '\\': if (p[1] != '\0') ++p; break; case '[': open = 1; break; case ']': if (open) return 1; break; } return 0; } #else #define SYSLOG_NG_HAVE_GLOB_NOMAGIC 1 #endif static gboolean cfg_lexer_include_file_add(CfgLexer *self, const gchar *fn) { CfgIncludeLevel *level; level = &self->include_stack[self->include_depth]; level->include_type = CFGI_FILE; level->file.files = g_slist_insert_sorted(level->file.files, strdup(fn), (GCompareFunc) strcmp); msg_debug("Adding include file", evt_tag_str("filename", fn), evt_tag_int("depth", self->include_depth)); return TRUE; } static gboolean cfg_lexer_include_file_glob_at(CfgLexer *self, const gchar *pattern) { glob_t globbuf; size_t i; int r; r = glob(pattern, GLOB_NOMAGIC, _cfg_lexer_glob_err, &globbuf); if (r != 0) { globfree(&globbuf); if (r == GLOB_NOMATCH) { #ifndef SYSLOG_NG_HAVE_GLOB_NOMAGIC if (!__glob_pattern_p (pattern)) { return cfg_lexer_include_file_add(self, pattern); } #endif return FALSE; } return TRUE; } for (i = 0; i < globbuf.gl_pathc; i++) { cfg_lexer_include_file_add(self, globbuf.gl_pathv[i]); } globfree(&globbuf); return TRUE; } static const gchar * _get_include_path(CfgLexer *self) { return self->cfg ? cfg_args_get(self->cfg->globals, "include-path") : NULL; } static gboolean cfg_lexer_include_file_glob(CfgLexer *self, const gchar *filename_) { const gchar *path = _get_include_path(self); gboolean process = FALSE; self->include_depth++; if (filename_[0] == '/' || !path) process = cfg_lexer_include_file_glob_at(self, filename_); else { gchar **dirs; gchar *cf; gint i = 0; dirs = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 0); while (dirs && dirs[i]) { cf = g_build_filename(dirs[i], filename_, NULL); process |= cfg_lexer_include_file_glob_at(self, cf); g_free(cf); i++; } g_strfreev(dirs); } if (process) { return cfg_lexer_start_next_include(self); } else { self->include_depth--; return TRUE; } } gboolean cfg_lexer_include_file(CfgLexer *self, const gchar *filename_) { struct stat st; gchar *filename; if (self->include_depth >= MAX_INCLUDE_DEPTH - 1) { msg_error("Include file depth is too deep, increase MAX_INCLUDE_DEPTH and recompile", evt_tag_str("filename", filename_), evt_tag_int("depth", self->include_depth)); return FALSE; } filename = find_file_in_path(_get_include_path(self), filename_, G_FILE_TEST_EXISTS); if (!filename || stat(filename, &st) < 0) { if (cfg_lexer_include_file_glob(self, filename_)) return TRUE; msg_error("Include file/directory not found", evt_tag_str("filename", filename_), evt_tag_str("include-path", _get_include_path(self)), evt_tag_errno("error", errno)); return FALSE; } else { gboolean result; result = cfg_lexer_include_file_simple(self, filename); g_free(filename); return result; } } gboolean cfg_lexer_include_buffer_without_backtick_substitution(CfgLexer *self, const gchar *name, const gchar *buffer, gsize length) { CfgIncludeLevel *level; gchar *lexer_buffer; gsize lexer_buffer_len; g_assert(length >= 0); if (self->include_depth >= MAX_INCLUDE_DEPTH - 1) { msg_error("Include file depth is too deep, increase MAX_INCLUDE_DEPTH and recompile", evt_tag_str("buffer", name), evt_tag_int("depth", self->include_depth)); return FALSE; } /* lex requires two NUL characters at the end of the input */ lexer_buffer_len = length + 2; lexer_buffer = g_malloc(lexer_buffer_len); memcpy(lexer_buffer, buffer, length); lexer_buffer[length] = 0; lexer_buffer[length + 1] = 0; self->include_depth++; level = &self->include_stack[self->include_depth]; level->include_type = CFGI_BUFFER; level->buffer.content = lexer_buffer; level->buffer.content_length = lexer_buffer_len; level->name = g_strdup(name); return cfg_lexer_start_next_include(self); } /* NOTE: if length is negative, it indicates zero-terminated buffer and * length should be determined based on that */ gboolean cfg_lexer_include_buffer(CfgLexer *self, const gchar *name, const gchar *buffer, gssize length) { gchar *substituted_buffer; gsize substituted_length = 0; GError *error = NULL; gboolean result = FALSE; substituted_buffer = cfg_lexer_subst_args_in_input(self->cfg ? self->cfg->globals : NULL, NULL, NULL, buffer, length, &substituted_length, &error); if (!substituted_buffer) { msg_error("Error resolving backtick references in block or buffer", evt_tag_str("buffer", name), evt_tag_str("error", error->message)); g_clear_error(&error); return FALSE; } result = cfg_lexer_include_buffer_without_backtick_substitution(self, name, substituted_buffer, substituted_length); g_free(substituted_buffer); return result; } void cfg_lexer_inject_token_block(CfgLexer *self, CfgTokenBlock *block) { self->token_blocks = g_list_append(self->token_blocks, block); } typedef struct _GeneratorPlugin { Plugin super; CfgBlockGenerator *gen; } GeneratorPlugin; static gpointer _generator_plugin_construct(Plugin *s) { GeneratorPlugin *self = (GeneratorPlugin *) s; return self->gen; } static void _generator_plugin_free(Plugin *s) { GeneratorPlugin *self = (GeneratorPlugin *) s; cfg_block_generator_free(self->gen); g_free((gchar *) self->super.name); g_free(s); } void cfg_lexer_register_generator_plugin(PluginContext *context, CfgBlockGenerator *gen) { GeneratorPlugin *plugin = g_new0(GeneratorPlugin, 1); plugin->super.type = gen->context | LL_CONTEXT_FLAG_GENERATOR; plugin->super.name = g_strdup(gen->name); plugin->super.free_fn = _generator_plugin_free; plugin->super.construct = _generator_plugin_construct; plugin->gen = gen; plugin_register(context, &plugin->super, 1); } static gboolean _is_generator_plugin(Plugin *p) { return p->type & LL_CONTEXT_FLAG_GENERATOR; } static CfgBlockGenerator * cfg_lexer_find_generator(CfgLexer *self, GlobalConfig *cfg, gint context, const gchar *name) { Plugin *p; CfgBlockGenerator *gen; p = plugin_find(&cfg->plugin_context, context | LL_CONTEXT_FLAG_GENERATOR, name); if (!p || !_is_generator_plugin(p)) return NULL; gen = plugin_construct(p); return gen; } static YYSTYPE cfg_lexer_copy_token(const YYSTYPE *original) { YYSTYPE dest; int type = original->type; dest.type = type; if (type == LL_TOKEN) { dest.token = original->token; } else if (type == LL_IDENTIFIER || type == LL_STRING || type == LL_BLOCK) { dest.cptr = strdup(original->cptr); } else if (type == LL_NUMBER) { dest.num = original->num; } else if (type == LL_FLOAT) { dest.fnum = original->fnum; } return dest; } void cfg_lexer_unput_token(CfgLexer *self, YYSTYPE *yylval) { CfgTokenBlock *block; block = cfg_token_block_new(); cfg_token_block_add_token(block, yylval); cfg_lexer_inject_token_block(self, block); } /* * NOTE: the caller is expected to manage the YYSTYPE instance itself (as * this is the way it is defined by the lexer), this function only frees its * contents. */ void cfg_lexer_free_token(YYSTYPE *token) { if (token->type == LL_STRING || token->type == LL_IDENTIFIER || token->type == LL_BLOCK) free(token->cptr); } static int _invoke__cfg_lexer_lex(CfgLexer *self, YYSTYPE *yylval, YYLTYPE *yylloc) { if (setjmp(self->fatal_error)) { YYLTYPE *cur_lloc = &self->include_stack[self->include_depth].lloc; *yylloc = *cur_lloc; return LL_ERROR; } return _cfg_lexer_lex(yylval, yylloc, self->state); } static gboolean cfg_lexer_consume_next_injected_token(CfgLexer *self, gint *tok, YYSTYPE *yylval, YYLTYPE *yylloc) { CfgTokenBlock *block; YYSTYPE *token; while (self->token_blocks) { block = self->token_blocks->data; token = cfg_token_block_get_token(block); if (token) { *yylval = *token; *yylloc = self->include_stack[self->include_depth].lloc; if (token->type == LL_TOKEN) *tok = token->token; else *tok = token->type; return TRUE; } else { self->token_blocks = g_list_delete_link(self->token_blocks, self->token_blocks); cfg_token_block_free(block); } } return FALSE; } int cfg_lexer_lex(CfgLexer *self, YYSTYPE *yylval, YYLTYPE *yylloc) { CfgBlockGenerator *gen; gint tok; gboolean injected; relex: injected = cfg_lexer_consume_next_injected_token(self, &tok, yylval, yylloc); if (!injected) { if (cfg_lexer_get_context_type(self) == LL_CONTEXT_BLOCK_CONTENT) cfg_lexer_start_block_state(self, "{}"); else if (cfg_lexer_get_context_type(self) == LL_CONTEXT_BLOCK_ARG) cfg_lexer_start_block_state(self, "()"); yylval->type = 0; g_string_truncate(self->token_text, 0); g_string_truncate(self->token_pretext, 0); tok = _invoke__cfg_lexer_lex(self, yylval, yylloc); if (yylval->type == 0) yylval->type = tok; if (self->preprocess_output) g_string_append_printf(self->preprocess_output, "%s", self->token_pretext->str); } /* NOTE: most of the code below is a monster, which should be factored out * to tiny little functions. This is not very simple and I am in the * middle of something that I would rather close than doing the * refactoring desperately needed here. I am silencing my conscience with * this note and also take the time to document some of the quirks below. * * 1) This code is deeply coupled with GlobalConfig and most of it does * not make sense to execute if self->cfg is NULL. Thus, some of the * conditionals contain an explicit self->cfg check, in other cases it is * implicitly checked by the first conditional of a series of if-then-else * statements. * * 2) the role of the relex label is to restart the lexing process once * new tokens were injected into the input stream. (e.g. after a * generator was called). This should really be a loop, and quite * possible any refactors should start here by eliminating that * loop-using-goto * * 3) make note that string tokens are allocated by malloc/free and not * g_malloc/g_free, this is significant. The grammar contains the free() * call, so getting rid of that would require a lot of changes to the * grammar. (on Windows glib, malloc/g_malloc are NOT equivalent) * */ if (tok == LL_IDENTIFIER && self->cfg && (gen = cfg_lexer_find_generator(self, self->cfg, cfg_lexer_get_context_type(self), yylval->cptr))) { CfgArgs *args; self->preprocess_suppress_tokens++; if (cfg_parser_parse(&block_ref_parser, self, (gpointer *) &args, NULL)) { gboolean success; gchar buf[256]; GString *result = g_string_sized_new(256); self->preprocess_suppress_tokens--; success = cfg_block_generator_generate(gen, self->cfg, args, result); free(yylval->cptr); cfg_args_unref(args); g_snprintf(buf, sizeof(buf), "%s generator %s", cfg_lexer_lookup_context_name_by_type(gen->context), gen->name); if (gen->suppress_backticks) success = cfg_lexer_include_buffer_without_backtick_substitution(self, buf, result->str, result->len); else success = cfg_lexer_include_buffer(self, buf, result->str, result->len); g_string_free(result, TRUE); if (success) { goto relex; } } else { free(yylval->cptr); self->preprocess_suppress_tokens--; } return LL_ERROR; } if (self->ignore_pragma || self->cfg == NULL) { /* only process @pragma/@include tokens in case pragma allowed is set * and the associated configuration is not NULL */ ; } else if (tok == LL_PRAGMA) { gpointer dummy; if (self->preprocess_output) g_string_append_printf(self->preprocess_output, "@"); if (!cfg_parser_parse(&pragma_parser, self, &dummy, NULL)) { return LL_ERROR; } goto relex; } else if (tok == KW_INCLUDE && cfg_lexer_get_context_type(self) != LL_CONTEXT_PRAGMA) { gchar *include_file; self->preprocess_suppress_tokens++; tok = cfg_lexer_lex(self, yylval, yylloc); if (tok != LL_STRING && tok != LL_IDENTIFIER) { self->preprocess_suppress_tokens--; return LL_ERROR; } include_file = g_strdup(yylval->cptr); free(yylval->cptr); tok = cfg_lexer_lex(self, yylval, yylloc); if (tok != ';') { self->preprocess_suppress_tokens--; g_free(include_file); return LL_ERROR; } if (!cfg_lexer_include_file(self, include_file)) { g_free(include_file); self->preprocess_suppress_tokens--; return LL_ERROR; } self->preprocess_suppress_tokens--; g_free(include_file); goto relex; } else if (self->cfg->user_version == 0 && self->cfg->parsed_version != 0) { if (!cfg_set_version(self->cfg, configuration->parsed_version)) return LL_ERROR; } else if (cfg_lexer_get_context_type(self) != LL_CONTEXT_PRAGMA && !self->non_pragma_seen) { /* first non-pragma token */ if (self->cfg->user_version == 0 && self->cfg->parsed_version == 0) { msg_error("ERROR: configuration files without a version number has become unsupported in " VERSION_3_13 ", please specify a version number using @version and update your configuration accordingly"); return LL_ERROR; } cfg_load_candidate_modules(self->cfg); #if (!SYSLOG_NG_ENABLE_FORCED_SERVER_MODE) if (!cfg_load_module(self->cfg, "license")) { msg_error("Error loading the license module, forcing exit"); exit(1); } #endif self->non_pragma_seen = TRUE; } if (!injected) { if (self->preprocess_suppress_tokens == 0 && self->preprocess_output) { g_string_append_printf(self->preprocess_output, "%s", self->token_text->str); } } return tok; } static void cfg_lexer_init(CfgLexer *self, GlobalConfig *cfg) { CfgIncludeLevel *level; _cfg_lexer_lex_init_extra(self, &self->state); self->string_buffer = g_string_sized_new(32); self->token_text = g_string_sized_new(32); self->token_pretext = g_string_sized_new(32); self->cfg = cfg; level = &self->include_stack[0]; level->lloc.first_line = level->lloc.last_line = 1; level->lloc.first_column = level->lloc.last_column = 1; level->lloc.level = level; } /* NOTE: cfg might be NULL in some call sites, but in those cases the lexer * should remain operational, obviously skipping cases where it would be * using the configuration instance. The lexer and the configuration stuff * should be one-way dependent, right now it is a circular dependency. */ CfgLexer * cfg_lexer_new(GlobalConfig *cfg, FILE *file, const gchar *filename, GString *preprocess_output) { CfgLexer *self; CfgIncludeLevel *level; self = g_new0(CfgLexer, 1); cfg_lexer_init(self, cfg); self->preprocess_output = preprocess_output; level = &self->include_stack[0]; level->include_type = CFGI_FILE; level->name = g_strdup(filename); level->yybuf = _cfg_lexer__create_buffer(file, YY_BUF_SIZE, self->state); _cfg_lexer__switch_to_buffer(level->yybuf, self->state); return self; } CfgLexer * cfg_lexer_new_buffer(GlobalConfig *cfg, const gchar *buffer, gsize length) { CfgLexer *self; CfgIncludeLevel *level; self = g_new0(CfgLexer, 1); cfg_lexer_init(self, cfg); self->ignore_pragma = TRUE; level = &self->include_stack[0]; level->include_type = CFGI_BUFFER; level->buffer.content = g_malloc(length + 2); memcpy(level->buffer.content, buffer, length); level->buffer.content[length] = 0; level->buffer.content[length + 1] = 0; level->buffer.content_length = length + 2; level->name = g_strdup(""); level->yybuf = _cfg_lexer__scan_buffer(level->buffer.content, level->buffer.content_length, self->state); _cfg_lexer__switch_to_buffer(level->yybuf, self->state); return self; } void cfg_lexer_free(CfgLexer *self) { gint i; for (i = 0; i <= self->include_depth; i++) { CfgIncludeLevel *level = &self->include_stack[i]; g_free(level->name); if (level->yybuf) _cfg_lexer__delete_buffer(level->yybuf, self->state); if (level->include_type == CFGI_FILE) { if (level->file.include_file) fclose(level->file.include_file); g_slist_foreach(level->file.files, (GFunc) g_free, NULL); g_slist_free(level->file.files); } else if (level->include_type == CFGI_BUFFER) { g_free(level->buffer.content); } } self->include_depth = 0; _cfg_lexer_lex_destroy(self->state); g_string_free(self->string_buffer, TRUE); if (self->token_text) g_string_free(self->token_text, TRUE); if (self->token_pretext) g_string_free(self->token_pretext, TRUE); while (self->context_stack) cfg_lexer_pop_context(self); g_list_foreach(self->token_blocks, (GFunc) cfg_token_block_free, NULL); g_list_free(self->token_blocks); g_free(self); } static const gchar *lexer_contexts[] = { [LL_CONTEXT_ROOT] = "root", [LL_CONTEXT_DESTINATION] = "destination", [LL_CONTEXT_SOURCE] = "source", [LL_CONTEXT_PARSER] = "parser", [LL_CONTEXT_REWRITE] = "rewrite", [LL_CONTEXT_FILTER] = "filter", [LL_CONTEXT_LOG] = "log", [LL_CONTEXT_BLOCK_DEF] = "block-def", [LL_CONTEXT_BLOCK_REF] = "block-ref", [LL_CONTEXT_BLOCK_CONTENT] = "block-content", [LL_CONTEXT_PRAGMA] = "pragma", [LL_CONTEXT_FORMAT] = "format", [LL_CONTEXT_TEMPLATE_FUNC] = "template-func", [LL_CONTEXT_INNER_DEST] = "inner-dest", [LL_CONTEXT_INNER_SRC] = "inner-src", [LL_CONTEXT_CLIENT_PROTO] = "client-proto", [LL_CONTEXT_SERVER_PROTO] = "server-proto", [LL_CONTEXT_SELECTOR] = "selector", }; gint cfg_lexer_lookup_context_type_by_name(const gchar *name) { gint i; for (i = 0; i < G_N_ELEMENTS(lexer_contexts); i++) { if (lexer_contexts[i] && strcmp(lexer_contexts[i], name) == 0) return i; } return 0; } const gchar * cfg_lexer_lookup_context_name_by_type(gint type) { type &= ~LL_CONTEXT_FLAGS; g_assert(type < G_N_ELEMENTS(lexer_contexts)); return lexer_contexts[type]; } /* token blocks */ void cfg_token_block_add_and_consume_token(CfgTokenBlock *self, YYSTYPE *token) { g_assert(self->pos == 0); g_array_append_val(self->tokens, *token); } void cfg_token_block_add_token(CfgTokenBlock *self, YYSTYPE *token) { YYSTYPE copied_token = cfg_lexer_copy_token(token); cfg_token_block_add_and_consume_token(self, &copied_token); } YYSTYPE * cfg_token_block_get_token(CfgTokenBlock *self) { if (self->pos < self->tokens->len) { YYSTYPE *result; result = &g_array_index(self->tokens, YYSTYPE, self->pos); self->pos++; return result; } return NULL; } CfgTokenBlock * cfg_token_block_new(void) { CfgTokenBlock *self = g_new0(CfgTokenBlock, 1); self->tokens = g_array_new(FALSE, TRUE, sizeof(YYSTYPE)); return self; } void cfg_token_block_free(CfgTokenBlock *self) { if (self->pos < self->tokens->len) { for (gint i = self->pos; i < self->tokens->len; i++) { YYSTYPE *token = &g_array_index(self->tokens, YYSTYPE, i); cfg_lexer_free_token(token); } } g_array_free(self->tokens, TRUE); g_free(self); } GQuark cfg_lexer_error_quark(void) { return g_quark_from_static_string("cfg-lexer-error-quark"); } syslog-ng-syslog-ng-3.13.2/lib/cfg-lexer.h000066400000000000000000000137171321171025300202410ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CFG_LEXER_H_INCLUDED #define CFG_LEXER_H_INCLUDED 1 #include "syslog-ng.h" #include "cfg-args.h" #include "cfg-block-generator.h" #include "messages.h" #include #include /* this module provides a higher level encapsulation for the configuration * file lexer. */ #define MAX_INCLUDE_DEPTH 256 typedef struct _CfgIncludeLevel CfgIncludeLevel; typedef struct _CfgTokenBlock CfgTokenBlock; /* the location type to carry location information from the lexer to the grammar */ #define YYLTYPE YYLTYPE typedef struct YYLTYPE { int first_line; int first_column; int last_line; int last_column; CfgIncludeLevel *level; } YYLTYPE; #define YYLTYPE_IS_TRIVIAL 1 /* symbol type that carries token related information to the grammar */ typedef struct YYSTYPE { /* one of LL_ types that indicates which field is being used */ int type; union { gint token; gint64 num; double fnum; char *cptr; void *ptr; gpointer node; }; } YYSTYPE; #define YYSTYPE_IS_TRIVIAL 1 #define YYSTYPE_IS_DECLARED 1 #define KWS_NORMAL 0 #define KWS_OBSOLETE 1 /* used to describe a syslog-ng keyword */ typedef struct _CfgLexerKeyword { const gchar *kw_name; gint kw_token; gint kw_status; const gchar *kw_explain; } CfgLexerKeyword; #define CFG_KEYWORD_STOP "@!#?" /* structure that describes a given location in the include stack */ struct _CfgIncludeLevel { enum { CFGI_FILE, CFGI_BUFFER, } include_type; /* include file or block name */ gchar *name; union { struct { GSList *files; FILE *include_file; } file; struct { gchar *content; gsize content_length; } buffer; }; YYLTYPE lloc; struct yy_buffer_state *yybuf; }; /* Lexer class that encapsulates a flex generated lexer. This can be * instantiated multiple times in parallel, e.g. doesn't use any global * state as we're using the "reentrant" code by flex */ struct _CfgLexer { /* flex state, not using yyscan_t as it is not defined */ gpointer state; jmp_buf fatal_error; CfgIncludeLevel include_stack[MAX_INCLUDE_DEPTH]; GList *context_stack; gint include_depth; gchar block_boundary[2]; gint brace_count; gint tokenize_eol; GList *token_blocks; GString *string_buffer; GString *preprocess_output; gint preprocess_suppress_tokens; GString *token_pretext; GString *token_text; GlobalConfig *cfg; gboolean non_pragma_seen:1, ignore_pragma:1; }; /* pattern buffer */ void cfg_lexer_unput_token(CfgLexer *self, YYSTYPE *yylval); void cfg_lexer_start_block_state(CfgLexer *self, gchar block_boundary[2]); void cfg_lexer_append_string(CfgLexer *self, int length, char *str); void cfg_lexer_append_char(CfgLexer *self, char c); /* keyword handling */ void cfg_lexer_set_current_keywords(CfgLexer *self, CfgLexerKeyword *keywords); char *cfg_lexer_get_keyword_string(CfgLexer *self, int kw); int cfg_lexer_lookup_keyword(CfgLexer *self, YYSTYPE *yylval, YYLTYPE *yylloc, const char *token); /* include files */ gboolean cfg_lexer_start_next_include(CfgLexer *self); gboolean cfg_lexer_include_file(CfgLexer *self, const gchar *filename); gboolean cfg_lexer_include_buffer(CfgLexer *self, const gchar *name, const gchar *buffer, gssize length); gboolean cfg_lexer_include_buffer_without_backtick_substitution(CfgLexer *self, const gchar *name, const gchar *buffer, gsize length); EVTTAG *cfg_lexer_format_location_tag(CfgLexer *self, YYLTYPE *yylloc); /* context tracking */ void cfg_lexer_push_context(CfgLexer *self, gint context, CfgLexerKeyword *keywords, const gchar *desc); void cfg_lexer_pop_context(CfgLexer *self); const gchar *cfg_lexer_get_context_description(CfgLexer *self); gint cfg_lexer_get_context_type(CfgLexer *self); /* token blocks */ void cfg_lexer_inject_token_block(CfgLexer *self, CfgTokenBlock *block); int cfg_lexer_lex(CfgLexer *self, YYSTYPE *yylval, YYLTYPE *yylloc); void cfg_lexer_free_token(YYSTYPE *token); CfgLexer *cfg_lexer_new(GlobalConfig *cfg, FILE *file, const gchar *filename, GString *preprocess_output); CfgLexer *cfg_lexer_new_buffer(GlobalConfig *cfg, const gchar *buffer, gsize length); void cfg_lexer_free(CfgLexer *self); gint cfg_lexer_lookup_context_type_by_name(const gchar *name); const gchar *cfg_lexer_lookup_context_name_by_type(gint id); /* token block objects */ void cfg_token_block_add_and_consume_token(CfgTokenBlock *self, YYSTYPE *token); void cfg_token_block_add_token(CfgTokenBlock *self, YYSTYPE *token); YYSTYPE *cfg_token_block_get_token(CfgTokenBlock *self); CfgTokenBlock *cfg_token_block_new(void); void cfg_token_block_free(CfgTokenBlock *self); void cfg_lexer_register_generator_plugin(PluginContext *context, CfgBlockGenerator *gen); #define CFG_LEXER_ERROR cfg_lexer_error_quark() GQuark cfg_lexer_error_quark(void); enum CfgLexerError { CFG_LEXER_MISSING_BACKTICK_PAIR, CFG_LEXER_CANNOT_REPRESENT_APOSTROPHES_IN_QSTRINGS, CFG_LEXER_BACKTICKS_CANT_BE_SUBSTITUTED_AFTER_BACKSLASH, }; #endif syslog-ng-syslog-ng-3.13.2/lib/cfg-parser.c000066400000000000000000000271621321171025300204100ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "cfg-grammar.h" #include #include extern int main_debug; /* defined in the parser */ int main_parse(CfgLexer *lexer, gpointer *dummy, gpointer arg); /* * PLEASE: if at all possible avoid adding keywords here, as these * keywords might collide with user-defined identifiers (e.g. source, * destination & block names). * * Add the keyword & the token to the parser of the module in question * instead, even if there are multiple modules using the same * keywords. * * Tokens (e.g. KW_xxx) associated with core keywords (e.g. those * listed here) should be declared only once and only in cfg-grammar.y * and NOT in external modules. */ static CfgLexerKeyword main_keywords[] = { /* statements */ { "source", KW_SOURCE }, { "filter", KW_FILTER }, { "parser", KW_PARSER }, { "rewrite", KW_REWRITE }, { "destination", KW_DESTINATION }, { "log", KW_LOG }, { "junction", KW_JUNCTION }, { "channel", KW_CHANNEL }, { "options", KW_OPTIONS }, { "include", KW_INCLUDE, }, { "block", KW_BLOCK }, /* source or destination items */ { "internal", KW_INTERNAL }, /* value pairs */ { "value_pairs", KW_VALUE_PAIRS }, { "exclude", KW_EXCLUDE }, { "pair", KW_PAIR }, { "key", KW_KEY }, { "scope", KW_SCOPE }, { "rekey", KW_REKEY }, { "shift", KW_SHIFT }, { "add_prefix", KW_ADD_PREFIX }, { "replace", KW_REPLACE_PREFIX, KWS_OBSOLETE, "replace_prefix" }, { "replace_prefix", KW_REPLACE_PREFIX }, /* option items */ { "flags", KW_FLAGS }, { "pad_size", KW_PAD_SIZE }, { "mark_freq", KW_MARK_FREQ }, { "mark", KW_MARK_FREQ, KWS_OBSOLETE, "mark_freq" }, { "mark_mode", KW_MARK_MODE }, { "stats_freq", KW_STATS_FREQ }, { "stats_lifetime", KW_STATS_LIFETIME }, { "stats_level", KW_STATS_LEVEL }, { "stats", KW_STATS_FREQ, KWS_OBSOLETE, "stats_freq" }, { "stats_max_dynamics", KW_STATS_MAX_DYNAMIC }, { "flush_lines", KW_FLUSH_LINES }, { "flush_timeout", KW_FLUSH_TIMEOUT }, { "suppress", KW_SUPPRESS }, { "sync_freq", KW_FLUSH_LINES, KWS_OBSOLETE, "flush_lines" }, { "sync", KW_FLUSH_LINES, KWS_OBSOLETE, "flush_lines" }, { "long_hostnames", KW_CHAIN_HOSTNAMES, KWS_OBSOLETE, "chain_hostnames" }, { "chain_hostnames", KW_CHAIN_HOSTNAMES }, { "normalize_hostnames",KW_NORMALIZE_HOSTNAMES }, { "keep_hostname", KW_KEEP_HOSTNAME }, { "check_hostname", KW_CHECK_HOSTNAME }, { "bad_hostname", KW_BAD_HOSTNAME }, { "custom_domain", KW_CUSTOM_DOMAIN }, { "keep_timestamp", KW_KEEP_TIMESTAMP }, { "encoding", KW_ENCODING }, { "ts_format", KW_TS_FORMAT }, { "frac_digits", KW_FRAC_DIGITS }, { "time_zone", KW_TIME_ZONE }, { "recv_time_zone", KW_RECV_TIME_ZONE }, { "send_time_zone", KW_SEND_TIME_ZONE }, { "local_time_zone", KW_LOCAL_TIME_ZONE }, { "format", KW_FORMAT }, { "use_time_recvd", KW_USE_TIME_RECVD, KWS_OBSOLETE, "Use R_ or S_ prefixed macros in templates or keep_timestamp(no)" }, { "use_fqdn", KW_USE_FQDN }, { "use_dns", KW_USE_DNS }, { "time_reopen", KW_TIME_REOPEN }, { "time_reap", KW_TIME_REAP }, { "time_sleep", KW_TIME_SLEEP, KWS_OBSOLETE, "time_sleep() has been deprecated" }, { "file_template", KW_FILE_TEMPLATE }, { "proto_template", KW_PROTO_TEMPLATE }, { "default_level", KW_DEFAULT_LEVEL }, { "default_priority", KW_DEFAULT_LEVEL }, { "default_facility", KW_DEFAULT_FACILITY }, { "threaded", KW_THREADED }, { "use_rcptid", KW_USE_RCPTID, KWS_OBSOLETE, "This has been deprecated, try use_uniqid() instead" }, { "use_uniqid", KW_USE_UNIQID }, { "log_fifo_size", KW_LOG_FIFO_SIZE }, { "log_fetch_limit", KW_LOG_FETCH_LIMIT }, { "log_iw_size", KW_LOG_IW_SIZE }, { "log_msg_size", KW_LOG_MSG_SIZE }, { "log_prefix", KW_LOG_PREFIX, KWS_OBSOLETE, "program_override" }, { "program_override", KW_PROGRAM_OVERRIDE }, { "host_override", KW_HOST_OVERRIDE }, { "throttle", KW_THROTTLE }, { "jvm_options", KW_JVM_OPTIONS }, { "create_dirs", KW_CREATE_DIRS }, { "optional", KW_OPTIONAL }, { "owner", KW_OWNER }, { "group", KW_GROUP }, { "perm", KW_PERM }, { "dir_owner", KW_DIR_OWNER }, { "dir_group", KW_DIR_GROUP }, { "dir_perm", KW_DIR_PERM }, { "template", KW_TEMPLATE }, { "template_escape", KW_TEMPLATE_ESCAPE }, { "template_function", KW_TEMPLATE_FUNCTION }, { "on_error", KW_ON_ERROR }, { "persist_only", KW_PERSIST_ONLY }, { "dns_cache_hosts", KW_DNS_CACHE_HOSTS }, { "dns_cache", KW_DNS_CACHE }, { "dns_cache_size", KW_DNS_CACHE_SIZE }, { "dns_cache_expire", KW_DNS_CACHE_EXPIRE }, { "dns_cache_expire_failed", KW_DNS_CACHE_EXPIRE_FAILED }, { "pass_unix_credentials", KW_PASS_UNIX_CREDENTIALS }, { "persist_name", KW_PERSIST_NAME, VERSION_VALUE_3_8 }, { "retries", KW_RETRIES }, { "read_old_records", KW_READ_OLD_RECORDS}, /* filter items */ { "type", KW_TYPE }, { "tags", KW_TAGS }, /* on/off switches */ { "yes", KW_YES }, { "on", KW_YES }, { "no", KW_NO }, { "off", KW_NO }, { NULL, 0 } }; CfgParser main_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &main_debug, #endif .name = "config", .context = LL_CONTEXT_ROOT, .keywords = main_keywords, .parse = main_parse, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(main_, gpointer *) static void _underline_source(YYLTYPE *yylloc, gchar *buf) { gint i; if (buf[0]) { fprintf(stderr, "\n%s", buf); if (buf[strlen(buf) - 1] != '\n') fprintf(stderr, "\n"); for (i = 0; buf[i] && i < yylloc->first_column - 1; i++) { fprintf(stderr, "%c", buf[i] == '\t' ? '\t' : ' '); } for (i = yylloc->first_column; (i == yylloc->first_column) || (i < yylloc->last_column); i++) fprintf(stderr, "^"); fprintf(stderr, "\n"); } } static void _report_file_location(const gchar *filename, YYLTYPE *yylloc) { FILE *f; gint lineno = 1; gchar buf[1024]; f = fopen(filename, "r"); if (f) { while (fgets(buf, sizeof(buf), f) && lineno < yylloc->first_line) lineno++; if (lineno != yylloc->first_line) buf[0] = 0; fclose(f); } _underline_source(yylloc, buf); } static void _report_buffer_location(const gchar *buffer_content, YYLTYPE *yylloc) { const gchar *sol, *eol; gchar buf[1024]; gint lineno = 1; sol = buffer_content; eol = strchr(sol, '\n'); while (eol && lineno < yylloc->first_line) { lineno++; sol = eol + 1; eol = strchr(sol, '\n'); } if (lineno == yylloc->first_line) { gsize cs = MIN(eol ? eol - sol - 1 : strlen(sol), sizeof(buf) - 2); memcpy(buf, sol, cs); buf[cs] = 0; } _underline_source(yylloc, buf); } void report_syntax_error(CfgLexer *lexer, YYLTYPE *yylloc, const char *what, const char *msg) { CfgIncludeLevel *level = yylloc->level, *from; gint file_pos; fprintf(stderr, "Error parsing %s, %s in %n%s at line %d, column %d:\n", what, msg, &file_pos, yylloc->level->name, yylloc->first_line, yylloc->first_column); from = level - 1; while (from >= lexer->include_stack) { fprintf(stderr, "%*sincluded from %s line %d, column %d\n", MAX(file_pos - 14, 0), "", from->name, from->lloc.first_line, from->lloc.first_column); from--; } if (level->include_type == CFGI_FILE) { _report_file_location(level->name, yylloc); } else if (level->include_type == CFGI_BUFFER) { _report_buffer_location(level->buffer.content, yylloc); } fprintf(stderr, "\nsyslog-ng documentation: https://www.balabit.com/support/documentation?product=%s\n" "contact: %s\n", PRODUCT_NAME, PRODUCT_CONTACT); } /* the debug flag for the main parser will be used for all parsers */ extern int cfg_parser_debug; gboolean cfg_parser_parse(CfgParser *self, CfgLexer *lexer, gpointer *instance, gpointer arg) { gboolean success; if (cfg_parser_debug) { fprintf(stderr, "\n\nStarting parser %s\n", self->name); } if (self->debug_flag) (*self->debug_flag) = cfg_parser_debug; cfg_lexer_push_context(lexer, self->context, self->keywords, self->name); success = (self->parse(lexer, instance, arg) == 0); cfg_lexer_pop_context(lexer); if (cfg_parser_debug) { fprintf(stderr, "\nStopping parser %s, result: %d\n", self->name, success); } return success; } void cfg_parser_cleanup(CfgParser *self, gpointer instance) { if (instance && self->cleanup) self->cleanup(instance); } /* * This function can be used to parse flags in a flags(...) option. It * makes it quite easy to write a flags parser by specifying the * operations to be performed in a getopt-like array. */ gboolean cfg_process_flag(CfgFlagHandler *handlers, gpointer base, const gchar *flag_) { gint h; gchar flag[32]; for (h = 0; flag_[h] && h < sizeof(flag); h++) { if (flag_[h] == '_') flag[h] = '-'; else flag[h] = flag_[h]; } flag[h] = 0; for (h = 0; handlers[h].name; h++) { CfgFlagHandler *handler = &handlers[h]; if (strcmp(handlers[h].name, flag) == 0) { guint32 *field = ((guint32 *) (((gchar *) base) + handler->ofs)); switch (handler->op) { case CFH_SET: /* this works if handler->mask is unset and handler->param is a single bit only */ if (handler->mask) *field = ((*field) & ~handler->mask) | handler->param; else *field = (*field) | handler->param; return TRUE; case CFH_CLEAR: /* set the bitfield to zero */ if (handler->mask) *field = (*field) & ~handler->mask; else *field = (*field) & ~handler->param; return TRUE; } } } return FALSE; } gboolean cfg_process_yesno(const gchar *yesno) { if (strcasecmp(yesno, "yes") == 0 || atoi(yesno) > 0) return TRUE; return FALSE; } syslog-ng-syslog-ng-3.13.2/lib/cfg-parser.h000066400000000000000000000077551321171025300204230ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CFG_PARSER_H_INCLUDED #define CFG_PARSER_H_INCLUDED #include "syslog-ng.h" #include "cfg-lexer.h" /* high level interface to a configuration file parser, it encapsulates the * grammar/lexer pair. */ typedef struct _CfgParser { /* how to enable bison debug in the parser */ gint *debug_flag; gint context; const gchar *name; /* parser specific keywords to be pushed to the lexer */ CfgLexerKeyword *keywords; /* the parser entry point, returns the parsed object in *instance */ gint (*parse)(CfgLexer *lexer, gpointer *instance, gpointer arg); /* in case of parse failure and instance != NULL, this should free instance */ void (*cleanup)(gpointer instance); } CfgParser; gboolean cfg_parser_parse(CfgParser *self, CfgLexer *lexer, gpointer *instance, gpointer arg); void cfg_parser_cleanup(CfgParser *self, gpointer instance); enum { CFH_SET, CFH_CLEAR, }; typedef struct _CfgFlagHandler { const gchar *name; gint op; gint ofs; guint32 param; guint32 mask; } CfgFlagHandler; gboolean cfg_process_flag(CfgFlagHandler *handlers, gpointer base, const gchar *flag); gboolean cfg_process_yesno(const gchar *yesno); extern CfgParser main_parser; #define CFG_PARSER_DECLARE_LEXER_BINDING(parser_prefix, root_type) \ int \ parser_prefix ## lex(YYSTYPE *yylval, YYLTYPE *yylloc, CfgLexer *lexer); \ \ void \ parser_prefix ## error(YYLTYPE *yylloc, CfgLexer *lexer, root_type instance, gpointer arg, const char *msg); #define CFG_PARSER_IMPLEMENT_LEXER_BINDING(parser_prefix, root_type) \ int \ parser_prefix ## lex(YYSTYPE *yylval, YYLTYPE *yylloc, CfgLexer *lexer) \ { \ int token; \ \ token = cfg_lexer_lex(lexer, yylval, yylloc); \ return token; \ } \ \ void \ parser_prefix ## error(YYLTYPE *yylloc, CfgLexer *lexer, root_type instance, gpointer arg, const char *msg) \ { \ report_syntax_error(lexer, yylloc, cfg_lexer_get_context_description(lexer), msg); \ } void report_syntax_error(CfgLexer *lexer, YYLTYPE *yylloc, const char *what, const char *msg); CFG_PARSER_DECLARE_LEXER_BINDING(main_, gpointer *) #endif syslog-ng-syslog-ng-3.13.2/lib/cfg-tree.c000066400000000000000000001020221321171025300200400ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-tree.h" #include "logmpx.h" #include "logpipe.h" #include /* * Return the textual representation of a node content type. */ const gchar * log_expr_node_get_content_name(gint content) { switch (content) { case ENC_PIPE: return "log"; case ENC_SOURCE: return "source"; case ENC_FILTER: return "filter"; case ENC_PARSER: return "parser"; case ENC_REWRITE: return "rewrite"; case ENC_DESTINATION: return "destination"; default: g_assert_not_reached(); break; } } /* * Return the textual representation of a node layout. */ const gchar * log_expr_node_get_layout_name(gint layout) { switch (layout) { case ENL_SINGLE: return "single"; case ENL_REFERENCE: return "reference"; case ENL_SEQUENCE: return "sequence"; case ENL_JUNCTION: return "junction"; default: g_assert_not_reached(); break; } } /* return the top-most rule that matches content. This is used to * query the enclosing rule for a given LogExprNode. It is looking up * the top-most node, so that we use the name of the enclosing block * that the user specified. In-line defined, and thus anonymous * expressions are automatically named. In that case this function * will return a node matching @content but without an actual name. */ LogExprNode * log_expr_node_get_container_rule(LogExprNode *self, gint content) { LogExprNode *node, *result = NULL; node = self->parent; while (node) { if (node->content == content) { result = node; } node = node->parent; } return result; } /** * log_expr_node_append: * @a: first LogExprNode * @b: second LogExprNode * * This function appends @b to @a in a linked list using the ep_next field * in LogExprNode. **/ void log_expr_node_append(LogExprNode *a, LogExprNode *b) { a->next = b; } LogExprNode * log_expr_node_append_tail(LogExprNode *a, LogExprNode *b) { if (a) { LogExprNode *p = a; while (p->next) p = p->next; log_expr_node_append(p, b); return a; } return b; } /* * Format the location information for a LogExprNode. For nodes that * have no location information, the parent is considered, this way * always returning something close to the location that defined the * node. */ const gchar * log_expr_node_format_location(LogExprNode *self, gchar *buf, gsize buf_len) { LogExprNode *node = self; while (node) { if (node->line || node->column) { g_snprintf(buf, buf_len, "%s:%d:%d", self->filename ? : "#buffer", node->line, node->column); break; } node = node->parent; } if (!node) strncpy(buf, "#unknown", buf_len); return buf; } EVTTAG * log_expr_node_location_tag(LogExprNode *self) { gchar buf[128]; return evt_tag_str("location", log_expr_node_format_location(self, buf, sizeof(buf))); } /* * Set the list of children of a LogExprNode. It automatically updates * the children's "parent" pointers so that the tree can be traversed * upwards too. */ void log_expr_node_set_children(LogExprNode *self, LogExprNode *children) { LogExprNode *ep; /* we don't currently support setting the children list multiple * times. no inherent reason, just the proper free function would * need to be written, until then this assert would reveal the case * quite fast. */ g_assert(self->children == NULL); for (ep = children; ep; ep = ep->next) ep->parent = self; self->children = children; } /* * Set the object associated with a node. The "object" member is used * to store the LogPipe instance associated with ENL_SINGLE/ENC_PIPE * nodes. */ void log_expr_node_set_object(LogExprNode *self, gpointer object, GDestroyNotify destroy) { self->object = object; self->object_destroy = destroy; } /* * The aux object is the secondary object associated with a node, it * is mostly unused, except for nodes storing source and destination * statements, in which case this contains a reference to the last * item of the compiled sequence (for sources) or the first item of * the compiled sequence (destinations). * * This mechanism is used to avoid having to clone source/destination * pipes, which operation they don't support. */ void log_expr_node_set_aux(LogExprNode *self, gpointer aux, GDestroyNotify destroy) { self->aux = aux; self->aux_destroy = destroy; } /** * log_expr_node_new: * @layout: layout of the children (ENL_*) * @content: what kind of expression this node stores (ENC_*) * @name: name of this rule (optional) * @children: child nodes * @flags: a combination of LC_* flags as specified by the administrator * @yylloc: the lexer location in the configuration file. * * This function constructs a LogExprNode object which encapsulates a * log expression in the configuration. See the note in cfg-tree.h for * more information about LogExprNode objects and log expressions. **/ LogExprNode * log_expr_node_new(gint layout, gint content, const gchar *name, LogExprNode *children, guint32 flags, YYLTYPE *yylloc) { LogExprNode *self = g_new0(LogExprNode, 1); self->layout = layout; self->content = content; self->name = g_strdup(name); log_expr_node_set_children(self, children); self->flags = flags; if (yylloc) { self->filename = g_strdup(yylloc->level->name); self->line = yylloc->first_line; self->column = yylloc->first_column; } return self; } /** * log_expr_node_free: * @self: LogExprNode instance * * This function frees the LogExprNode object encapsulating a log * expression node pointed to by @self. **/ void log_expr_node_free(LogExprNode *self) { LogExprNode *next, *p; for (p = self->children ; p; p = next) { next = p->next; log_expr_node_free(p); } if (self->object && self->object_destroy) self->object_destroy(self->object); if (self->aux && self->aux_destroy) self->aux_destroy(self->aux); g_free(self->name); g_free(self->filename); g_free(self); } LogExprNode * log_expr_node_new_pipe(LogPipe *pipe, YYLTYPE *yylloc) { LogExprNode *node = log_expr_node_new(ENL_SINGLE, ENC_PIPE, NULL, NULL, 0, yylloc); log_expr_node_set_object(node, pipe, (GDestroyNotify) log_pipe_unref); return node; } LogExprNode * log_expr_node_new_source(const gchar *name, LogExprNode *children, YYLTYPE *yylloc) { return log_expr_node_new(ENL_SEQUENCE, ENC_SOURCE, name, children, 0, yylloc); } LogExprNode * log_expr_node_new_source_reference(const gchar *name, YYLTYPE *yylloc) { return log_expr_node_new(ENL_REFERENCE, ENC_SOURCE, name, NULL, 0, yylloc); } LogExprNode * log_expr_node_new_destination(const gchar *name, LogExprNode *children, YYLTYPE *yylloc) { return log_expr_node_new(ENL_SEQUENCE, ENC_DESTINATION, name, children, 0, yylloc); } LogExprNode * log_expr_node_new_destination_reference(const gchar *name, YYLTYPE *yylloc) { return log_expr_node_new(ENL_REFERENCE, ENC_DESTINATION, name, NULL, 0, yylloc); } LogExprNode * log_expr_node_new_filter(const gchar *name, LogExprNode *child, YYLTYPE *yylloc) { return log_expr_node_new(ENL_SEQUENCE, ENC_FILTER, name, child, 0, yylloc); } LogExprNode * log_expr_node_new_filter_reference(const gchar *name, YYLTYPE *yylloc) { return log_expr_node_new(ENL_REFERENCE, ENC_FILTER, name, NULL, 0, yylloc); } LogExprNode * log_expr_node_new_parser(const gchar *name, LogExprNode *children, YYLTYPE *yylloc) { return log_expr_node_new(ENL_SEQUENCE, ENC_PARSER, name, children, 0, yylloc); } LogExprNode * log_expr_node_new_parser_reference(const gchar *name, YYLTYPE *yylloc) { return log_expr_node_new(ENL_REFERENCE, ENC_PARSER, name, NULL, 0, yylloc); } LogExprNode * log_expr_node_new_rewrite(const gchar *name, LogExprNode *children, YYLTYPE *yylloc) { return log_expr_node_new(ENL_SEQUENCE, ENC_REWRITE, name, children, 0, yylloc); } LogExprNode * log_expr_node_new_rewrite_reference(const gchar *name, YYLTYPE *yylloc) { return log_expr_node_new(ENL_REFERENCE, ENC_REWRITE, name, NULL, 0, yylloc); } LogExprNode * log_expr_node_new_log(LogExprNode *children, guint32 flags, YYLTYPE *yylloc) { return log_expr_node_new(ENL_SEQUENCE, ENC_PIPE, NULL, children, flags, yylloc); } LogExprNode * log_expr_node_new_sequence(LogExprNode *children, YYLTYPE *yylloc) { return log_expr_node_new(ENL_SEQUENCE, ENC_PIPE, NULL, children, 0, yylloc); } LogExprNode * log_expr_node_new_junction(LogExprNode *children, YYLTYPE *yylloc) { return log_expr_node_new(ENL_JUNCTION, ENC_PIPE, NULL, children, 0, yylloc); } gint log_expr_node_lookup_flag(const gchar *flag) { if (strcmp(flag, "catch-all") == 0 || strcmp(flag, "catchall") == 0 || strcmp(flag, "catch_all") == 0) return LC_CATCHALL; else if (strcmp(flag, "fallback") == 0) return LC_FALLBACK; else if (strcmp(flag, "final") == 0) return LC_FINAL; else if (strcmp(flag, "flow_control") == 0 || strcmp(flag, "flow-control") == 0) return LC_FLOW_CONTROL; msg_error("Unknown log statement flag", evt_tag_str("flag", flag)); return 0; } LogPipe * cfg_tree_new_pipe(CfgTree *self, LogExprNode *related_expr) { LogPipe *pipe = log_pipe_new(self->cfg); pipe->expr_node = related_expr; g_ptr_array_add(self->initialized_pipes, pipe); return pipe; } LogMultiplexer * cfg_tree_new_mpx(CfgTree *self, LogExprNode *related_expr) { LogMultiplexer *pipe = log_multiplexer_new(self->cfg); pipe->super.expr_node = related_expr; g_ptr_array_add(self->initialized_pipes, pipe); return pipe; } /* * Return the name of the rule that contains a LogExprNode. Generates * one automatically for anonymous log expressions. * * NOTE: this returns an allocated string, the caller must free that. */ gchar * cfg_tree_get_rule_name(CfgTree *self, gint content, LogExprNode *node) { LogExprNode *rule = log_expr_node_get_container_rule(node, content); if (!rule->name) rule->name = g_strdup_printf("#anon-%s%d", log_expr_node_get_content_name(content), self->anon_counters[content]++); return g_strdup(rule->name); } /* * Return a unique the name associated with a LogExprNode. It is of * the format #. * * NOTE: this returns an allocated string, the caller must free that. */ gchar * cfg_tree_get_child_id(CfgTree *self, gint content, LogExprNode *node) { LogExprNode *rule = log_expr_node_get_container_rule(node, content); gchar *rule_name = cfg_tree_get_rule_name(self, content, node); gchar *res; res = g_strdup_printf("%s#%d", rule_name, rule->child_id++); g_free(rule_name); return res; } /* hash foreach function to add all source objects to catch-all rules */ static void cfg_tree_add_all_sources(gpointer key, gpointer value, gpointer user_data) { gpointer *args = (gpointer *) user_data; LogExprNode *referring_rule = args[1]; LogExprNode *rule = (LogExprNode *) value; if (rule->content != ENC_SOURCE) return; /* prepend a source reference */ referring_rule->children = log_expr_node_append_tail(log_expr_node_new_source_reference(rule->name, NULL), referring_rule->children); } static gboolean cfg_tree_compile_node(CfgTree *self, LogExprNode *node, LogPipe **outer_pipe_head, LogPipe **outer_pipe_tail); static gboolean cfg_tree_compile_single(CfgTree *self, LogExprNode *node, LogPipe **outer_pipe_head, LogPipe **outer_pipe_tail) { LogPipe *pipe; g_assert(node->content == ENC_PIPE); /* LC_XXX flags are currently only implemented for sequences, ensure that the grammar enforces this. */ g_assert(node->flags == 0); pipe = node->object; if ((pipe->flags & PIF_INLINED) == 0) { /* first reference to the pipe uses the same instance, further ones will get cloned */ pipe->flags |= PIF_INLINED; /* The pipe object is borrowed, so the reference counter must be increased. */ log_pipe_ref(pipe); } else { /* ok, we are using this pipe again, it needs to be cloned */ pipe = log_pipe_clone(pipe); if (!pipe) { msg_error("Error cloning pipe into its reference point, probably the element in question is not meant to be used in this situation", log_expr_node_location_tag(node)); goto error; } pipe->flags |= PIF_INLINED; } g_ptr_array_add(self->initialized_pipes, pipe); pipe->expr_node = node; if ((pipe->flags & PIF_SOURCE) == 0) *outer_pipe_head = pipe; *outer_pipe_tail = pipe; return TRUE; error: return FALSE; } static gboolean cfg_tree_compile_reference(CfgTree *self, LogExprNode *node, LogPipe **outer_pipe_head, LogPipe **outer_pipe_tail) { LogExprNode *referenced_node; /* LC_XXX flags are currently only implemented for sequences, ensure that the grammar enforces this. */ g_assert(node->flags == 0); if (!node->object) { referenced_node = cfg_tree_get_object(self, node->content, node->name); } else referenced_node = node->object; if (!referenced_node) { msg_error("Error resolving reference", evt_tag_str("content", log_expr_node_get_content_name(node->content)), evt_tag_str("name", node->name), log_expr_node_location_tag(node)); goto error; } switch (referenced_node->content) { case ENC_SOURCE: { LogMultiplexer *mpx; LogPipe *sub_pipe_head = NULL, *sub_pipe_tail = NULL; LogPipe *attach_pipe = NULL; if (!referenced_node->aux) { if (!cfg_tree_compile_node(self, referenced_node, &sub_pipe_head, &sub_pipe_tail)) goto error; log_expr_node_set_aux(referenced_node, log_pipe_ref(sub_pipe_tail), (GDestroyNotify) log_pipe_unref); } else { sub_pipe_tail = referenced_node->aux; } attach_pipe = cfg_tree_new_pipe(self, node); if (sub_pipe_tail) { /* when the source is empty, we'll get a NULL tail in * sub_pipe_tail. We handle that by simply not connecting * anything to the attachment point */ if (!sub_pipe_tail->pipe_next) { mpx = cfg_tree_new_mpx(self, referenced_node); log_pipe_append(sub_pipe_tail, &mpx->super); } else { mpx = (LogMultiplexer *) sub_pipe_tail->pipe_next; } log_multiplexer_add_next_hop(mpx, attach_pipe); } *outer_pipe_head = NULL; *outer_pipe_tail = attach_pipe; break; } case ENC_DESTINATION: { LogMultiplexer *mpx; LogPipe *sub_pipe_head = NULL, *sub_pipe_tail = NULL; if (!referenced_node->aux) { if (!cfg_tree_compile_node(self, referenced_node, &sub_pipe_head, &sub_pipe_tail)) goto error; log_expr_node_set_aux(referenced_node, log_pipe_ref(sub_pipe_head), (GDestroyNotify) log_pipe_unref); } else { sub_pipe_head = referenced_node->aux; } /* We need a new LogMultiplexer instance for two reasons: 1) we need to link something into the sequence, all reference based destination invocations need a separate LogPipe 2) we have to fork downwards to the destination, it may change the message but we need the original one towards our next chain */ mpx = cfg_tree_new_mpx(self, node); if (sub_pipe_head) { /* when the destination is empty */ log_multiplexer_add_next_hop(mpx, sub_pipe_head); } *outer_pipe_head = &mpx->super; *outer_pipe_tail = NULL; break; } default: return cfg_tree_compile_node(self, referenced_node, outer_pipe_head, outer_pipe_tail); } return TRUE; error: return FALSE; } static void cfg_tree_propagate_expr_node_properties_to_pipe(LogExprNode *node, LogPipe *pipe) { if (node->flags & LC_FALLBACK) pipe->flags |= PIF_BRANCH_FALLBACK; if (node->flags & LC_FINAL) pipe->flags |= PIF_BRANCH_FINAL; if (node->flags & LC_FLOW_CONTROL) pipe->flags |= PIF_HARD_FLOW_CONTROL; if (!pipe->expr_node) pipe->expr_node = node; } /** * cfg_tree_compile_sequence: * * Construct the sequential part of LogPipe pipeline as specified by * the user. The sequential part is where no branches exist, pipes are * merely linked to each other. This is in contrast with a "junction" * where the processing is forked into different branches. Junctions * are built using cfg_tree_compile_junction() above. * * The configuration is parsed into a series of LogExprNode * elements, each giving a reference to a source, filter, parser, * rewrite and destination. This function connects these so that their * log_pipe_queue() method will dispatch the message correctly (which * in turn boils down to setting the LogPipe->next member). * * The tree like structure is created using LogMultiplexer instances, * pipes are connected back with a simple LogPipe instance that only * forwards messages. * * The next member pointer is not holding a reference, but can be * assumed to be kept alive as long as the configuration is running. * * Parameters: * @self: the CfgTree instance * @rule: the series of LogExprNode instances encapsulates as a LogExprNode * @outer_pipe_tail: the last LogPipe to be used to chain further elements to this sequence * @cfg: GlobalConfig instance * @toplevel: whether this rule is a top-level one. **/ static gboolean cfg_tree_compile_sequence(CfgTree *self, LogExprNode *node, LogPipe **outer_pipe_head, LogPipe **outer_pipe_tail) { LogExprNode *ep; LogPipe *first_pipe, /* the head of the constructed pipeline */ *last_pipe; /* the current tail of the constructed pipeline */ LogPipe *source_join_pipe = NULL; gboolean node_properties_propagated = FALSE; if ((node->flags & LC_CATCHALL) != 0) { /* the catch-all resolution code clears this flag */ msg_error("Error in configuration, catch-all flag can only be specified for top-level log statements"); goto error; } /* the loop below creates a sequence of LogPipe instances which * essentially execute the user configuration once it is * started. * * The input of this is a log expression, denoted by a tree of * LogExprNode structures, built by the parser. We are storing the * sequence as a linked list, pipes are linked with their "next" * field. * * The head of this list is pointed to by @first_pipe, the current * end is known as @last_pipe. * * In case the sequence starts with a source LogPipe (PIF_SOURCE * flag), the head of the list is _not_ tracked, in that case * first_pipe is NULL. * */ first_pipe = last_pipe = NULL; for (ep = node->children; ep; ep = ep->next) { LogPipe *sub_pipe_head = NULL, *sub_pipe_tail = NULL; if (!cfg_tree_compile_node(self, ep, &sub_pipe_head, &sub_pipe_tail)) goto error; /* add pipe to the current pipe_line, e.g. after last_pipe, update last_pipe & first_pipe */ if (sub_pipe_head) { if (!node_properties_propagated) { cfg_tree_propagate_expr_node_properties_to_pipe(node, sub_pipe_head); node_properties_propagated = TRUE; } if (!first_pipe && !last_pipe) { /* we only remember the first pipe in case we're not in * source mode. In source mode, only last_pipe is set */ first_pipe = sub_pipe_head; } if (last_pipe) { g_assert(last_pipe->pipe_next == NULL); log_pipe_append(last_pipe, sub_pipe_head); } if (sub_pipe_tail) { last_pipe = sub_pipe_tail; } else { last_pipe = sub_pipe_head; /* look for the final pipe */ while (last_pipe->pipe_next) { last_pipe = last_pipe->pipe_next; } } sub_pipe_head = NULL; } else if (sub_pipe_tail) { /* source pipe */ if (first_pipe) { msg_error("Error compiling sequence, source-pipe follows a non-source one, please list source references/definitions first", log_expr_node_location_tag(ep)); goto error; } if (!source_join_pipe) { source_join_pipe = last_pipe = cfg_tree_new_pipe(self, node); } log_pipe_append(sub_pipe_tail, source_join_pipe); } } /* NOTE: if flow control is enabled, then we either need to have an * embedded log statement (in which case first_pipe is set, as we're not * starting with sources), OR we created a source_join_pipe already. * */ g_assert(((node->flags & LC_FLOW_CONTROL) && (first_pipe || source_join_pipe)) || !(node->flags & LC_FLOW_CONTROL)); if (!first_pipe && !last_pipe) { /* this is an empty sequence, insert a do-nothing LogPipe */ first_pipe = last_pipe = cfg_tree_new_pipe(self, node); } if (!node_properties_propagated) { /* we never encountered anything that would produce a head_pipe, e.g. * this sequence only contains a source and nothing else. In that * case, apply node flags to the last pipe. It should be picked up * when LogMultiplexer iterates over the branch in * log_multiplexer_init() as long as last_pipe is linked into the * pipe_next list and is not forked off at a LogMultiplexer. * */ cfg_tree_propagate_expr_node_properties_to_pipe(node, last_pipe); node_properties_propagated = TRUE; } *outer_pipe_tail = last_pipe; *outer_pipe_head = first_pipe; return TRUE; error: /* we don't need to free anything, everything we allocated is recorded in * @self, thus will be freed whenever cfg_tree_free is called */ return FALSE; } /** * cfg_tree_compile_junction(): * * This function builds a junction within the configuration. A * junction is where processing is forked into several branches, each * doing its own business, and then the end of each branch is * collected at the end so that further processing can be done on the * combined output of each log branch. * * /-- branch --\ * / \ * ---+---- branch ----+--- * \ / * \-- branch --/ **/ static gboolean cfg_tree_compile_junction(CfgTree *self, LogExprNode *node, LogPipe **outer_pipe_head, LogPipe **outer_pipe_tail) { LogExprNode *ep; LogPipe *join_pipe = NULL; /* the pipe where parallel branches are joined in a junction */ LogMultiplexer *fork_mpx = NULL; /* LC_XXX flags are currently only implemented for sequences, ensure that the grammar enforces this. */ g_assert(node->flags == 0); for (ep = node->children; ep; ep = ep->next) { LogPipe *sub_pipe_head = NULL, *sub_pipe_tail = NULL; gboolean is_first_branch = (ep == node->children); if (!cfg_tree_compile_node(self, ep, &sub_pipe_head, &sub_pipe_tail)) goto error; if (sub_pipe_head) { /* ep is an intermediate LogPipe or a destination, we have to fork */ if (!is_first_branch && !fork_mpx) { msg_error("Error compiling junction, source and non-source branches are mixed", log_expr_node_location_tag(ep)); goto error; } if (!fork_mpx) { fork_mpx = cfg_tree_new_mpx(self, node); } log_multiplexer_add_next_hop(fork_mpx, sub_pipe_head); } else { /* ep is a "source" LogPipe (cause no sub_pipe_head returned by compile_node). */ if (fork_mpx) { msg_error("Error compiling junction, source and non-source branches are mixed", log_expr_node_location_tag(ep)); goto error; } } if (sub_pipe_tail && outer_pipe_tail) { if (!join_pipe) { join_pipe = cfg_tree_new_pipe(self, node); } log_pipe_append(sub_pipe_tail, join_pipe); } } *outer_pipe_head = &fork_mpx->super; if (outer_pipe_tail) *outer_pipe_tail = join_pipe; return TRUE; error: /* we don't need to free anything, everything we allocated is recorded in * @self, thus will be freed whenever cfg_tree_free is called */ return FALSE; } /* * cfg_tree_compile_node: * * This function takes care of compiling a LogExprNode. * */ gboolean cfg_tree_compile_node(CfgTree *self, LogExprNode *node, LogPipe **outer_pipe_head, LogPipe **outer_pipe_tail) { gboolean result = FALSE; static gint indent = -1; if (debug_flag) { gchar buf[128]; gchar compile_message[256]; indent++; g_snprintf(compile_message, sizeof(compile_message), "%-*sCompiling %s %s [%s] at [%s]", indent * 2, "", node->name ? : "#unnamed", log_expr_node_get_layout_name(node->layout), log_expr_node_get_content_name(node->content), log_expr_node_format_location(node, buf, sizeof(buf))); msg_send_formatted_message(EVT_PRI_DEBUG, compile_message); } switch (node->layout) { case ENL_SINGLE: result = cfg_tree_compile_single(self, node, outer_pipe_head, outer_pipe_tail); break; case ENL_REFERENCE: result = cfg_tree_compile_reference(self, node, outer_pipe_head, outer_pipe_tail); break; case ENL_SEQUENCE: result = cfg_tree_compile_sequence(self, node, outer_pipe_head, outer_pipe_tail); break; case ENL_JUNCTION: result = cfg_tree_compile_junction(self, node, outer_pipe_head, outer_pipe_tail); break; default: g_assert_not_reached(); } indent--; return result; } gboolean cfg_tree_compile_rule(CfgTree *self, LogExprNode *rule) { LogPipe *sub_pipe_head = NULL, *sub_pipe_tail = NULL; return cfg_tree_compile_node(self, rule, &sub_pipe_head, &sub_pipe_tail); } static gboolean cfg_tree_objects_equal(gconstpointer v1, gconstpointer v2) { LogExprNode *r1 = (LogExprNode *) v1; LogExprNode *r2 = (LogExprNode *) v2; if (r1->content != r2->content) return FALSE; /* we assume that only rules with a name are hashed */ return strcmp(r1->name, r2->name) == 0; } static guint cfg_tree_objects_hash(gconstpointer v) { LogExprNode *r = (LogExprNode *) v; /* we assume that only rules with a name are hashed */ return r->content + g_str_hash(r->name); } gboolean cfg_tree_add_object(CfgTree *self, LogExprNode *rule) { gboolean res = TRUE; if (rule->name) { /* only named rules can be stored as objects to be referenced later */ /* check if already present */ res = (g_hash_table_lookup(self->objects, rule) == NULL); /* key is the same as the object */ g_hash_table_replace(self->objects, rule, rule); } else { /* unnamed rules are simply put in the rules array */ g_ptr_array_add(self->rules, rule); } return res; } LogExprNode * cfg_tree_get_object(CfgTree *self, gint content, const gchar *name) { LogExprNode lookup_node; memset(&lookup_node, 0, sizeof(lookup_node)); lookup_node.content = content; lookup_node.name = (gchar *) name; return g_hash_table_lookup(self->objects, &lookup_node); } GList * cfg_tree_get_objects(CfgTree *self) { return g_hash_table_get_values(self->objects); } gboolean cfg_tree_add_template(CfgTree *self, LogTemplate *template) { gboolean res = TRUE; res = (g_hash_table_lookup(self->templates, template->name) == NULL); g_hash_table_replace(self->templates, template->name, template); return res; } LogTemplate * cfg_tree_lookup_template(CfgTree *self, const gchar *name) { if (name) return log_template_ref(g_hash_table_lookup(self->templates, name)); return NULL; } LogTemplate * cfg_tree_check_inline_template(CfgTree *self, const gchar *template_or_name, GError **error) { LogTemplate *template = cfg_tree_lookup_template(self, template_or_name); if (template == NULL) { template = log_template_new(self->cfg, NULL); if (!log_template_compile(template, template_or_name, error)) { log_template_unref(template); return NULL; } template->def_inline = TRUE; } return template; } gboolean cfg_tree_compile(CfgTree *self) { gint i; /* resolve references within the configuration */ if (self->compiled) return TRUE; for (i = 0; i < self->rules->len; i++) { LogExprNode *rule = (LogExprNode *) g_ptr_array_index(self->rules, i); if ((rule->flags & LC_CATCHALL)) { gpointer args[] = { self, rule }; g_hash_table_foreach(self->objects, cfg_tree_add_all_sources, args); rule->flags &= ~LC_CATCHALL; } if (!cfg_tree_compile_rule(self, rule)) { return FALSE; } } self->compiled = TRUE; return TRUE; } static gboolean _verify_unique_persist_names_among_pipes(const GPtrArray *initialized_pipes) { GHashTable *pipe_persist_names = g_hash_table_new(g_str_hash, g_str_equal); gboolean result = TRUE; for (gint i = 0; i < initialized_pipes->len; ++i) { LogPipe *current_pipe = g_ptr_array_index(initialized_pipes, i); const gchar *current_pipe_name = log_pipe_get_persist_name(current_pipe); if (current_pipe_name != NULL) { if (g_hash_table_lookup_extended(pipe_persist_names, current_pipe_name, NULL, NULL)) { msg_error("Error checking the uniqueness of the persist names, please override it " "with persist-name option. Shutting down.", evt_tag_str("persist_name", current_pipe_name), log_pipe_location_tag(current_pipe), NULL); result = FALSE; } else { g_hash_table_replace(pipe_persist_names, (gpointer)current_pipe_name, (gpointer)current_pipe_name); } } } g_hash_table_destroy(pipe_persist_names); return result; } gboolean cfg_tree_start(CfgTree *self) { gint i; if (!cfg_tree_compile(self)) return FALSE; /* * As there are pipes that are dynamically created during init, these * pipes must be deinited before destroying the configuration, otherwise * circular references will inhibit the free of the configuration * structure. */ for (i = 0; i < self->initialized_pipes->len; i++) { LogPipe *pipe = g_ptr_array_index(self->initialized_pipes, i); if (!log_pipe_init(pipe)) { msg_error("Error initializing message pipeline", evt_tag_str("plugin name", pipe->plugin_name ? pipe->plugin_name : "not a plugin"), log_pipe_location_tag(pipe)); return FALSE; } } return _verify_unique_persist_names_among_pipes(self->initialized_pipes); } gboolean cfg_tree_stop(CfgTree *self) { gboolean success = TRUE; gint i; for (i = 0; i < self->initialized_pipes->len; i++) { if (!log_pipe_deinit(g_ptr_array_index(self->initialized_pipes, i))) success = FALSE; } return success; } void cfg_tree_init_instance(CfgTree *self, GlobalConfig *cfg) { memset(self, 0, sizeof(*self)); self->initialized_pipes = g_ptr_array_new(); self->objects = g_hash_table_new_full(cfg_tree_objects_hash, cfg_tree_objects_equal, NULL, (GDestroyNotify) log_expr_node_free); self->templates = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify) log_template_unref); self->rules = g_ptr_array_new(); self->cfg = cfg; } void cfg_tree_free_instance(CfgTree *self) { g_ptr_array_foreach(self->initialized_pipes, (GFunc) log_pipe_unref, NULL); g_ptr_array_free(self->initialized_pipes, TRUE); g_ptr_array_foreach(self->rules, (GFunc) log_expr_node_free, NULL); g_ptr_array_free(self->rules, TRUE); g_hash_table_destroy(self->objects); g_hash_table_destroy(self->templates); self->cfg = NULL; } syslog-ng-syslog-ng-3.13.2/lib/cfg-tree.h000066400000000000000000000147771321171025300200700ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CFGTREE_H_INCLUDED #define CFGTREE_H_INCLUDED #include "syslog-ng.h" #include "template/templates.h" #include "cfg-lexer.h" #include "messages.h" const gchar *log_expr_node_get_content_name(gint content); #define LC_CATCHALL 1 #define LC_FALLBACK 2 #define LC_FINAL 4 #define LC_FLOW_CONTROL 8 enum { /* expr node content type */ ENC_SOURCE, ENC_DESTINATION, ENC_FILTER, ENC_PARSER, ENC_REWRITE, ENC_MAX, /* */ ENC_PIPE, /* expr node layouts type */ ENL_SINGLE, ENL_REFERENCE, ENL_SEQUENCE, ENL_JUNCTION, }; typedef struct _LogExprNode LogExprNode; /** * Log Expressions * =============== * * Everything except a few things are parsed from the configuration as * a log expression. The few exceptions are: templates, global options and blocks. * * Sources, destinations, filters, parsers, rewrite rules and global * log statements are log expressions. * * Log expressions describe a graph, which is then traversed by * messages received by syslog-ng. The graph used to be a tree * (e.g. no cycles), but this limitation was lifted in syslog-ng 3.4, * when the concept of log expression was introduced. * * Log expression is a part of the graph, the larger graph is created * by connecting these parts as dictated by the configuration. * * Each log expression is represented using a tree of LogExprNode * elements. Each node in this tree defines the layout how its children * are to be connected: * - simple element: holds a single LogPipe, no children * - reference: used to reference log expressions defined elsewhere, no children * - sequence: holds a sequence of LogExprNodes * - junction: holds a junction * * Sometimes syslog-ng needs to know what kind of object the user * originally defined, this is stored in the "content" member. * * ENC_PIPE: content is a single LogPipe instance (in the "object" member) * ENC_SOURCE: content is a source log expression node (source statement or one defined inline) * ENC_DESTINATION: content is a destination node * ENC_FILTER: content is a filter node * ENC_PARSER: content is a parser node * ENC_REWRITE: content is a rewrite node */ struct _LogExprNode { gint16 layout; gint16 content; guint32 flags; /* name of the rule for named rules and name of the named rule for references */ gchar *name; /* parent node */ LogExprNode *parent; /* list of children */ LogExprNode *children; /* next sibling */ LogExprNode *next; gpointer object; GDestroyNotify object_destroy; /* used during construction in case a rule specific object needs to be created. */ gpointer aux; GDestroyNotify aux_destroy; gchar *filename; gint line, column; gint child_id; }; gint log_expr_node_lookup_flag(const gchar *flag); LogExprNode *log_expr_node_append_tail(LogExprNode *a, LogExprNode *b); void log_expr_node_set_object(LogExprNode *self, gpointer object, GDestroyNotify destroy); const gchar *log_expr_node_format_location(LogExprNode *self, gchar *buf, gsize buf_len); EVTTAG *log_expr_node_location_tag(LogExprNode *self); LogExprNode *log_expr_node_new(gint layout, gint content, const gchar *name, LogExprNode *children, guint32 flags, YYLTYPE *yylloc); void log_expr_node_free(LogExprNode *self); LogExprNode *log_expr_node_new_pipe(LogPipe *pipe, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_source(const gchar *name, LogExprNode *children, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_source_reference(const gchar *name, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_destination(const gchar *name, LogExprNode *children, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_destination_reference(const gchar *name, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_filter(const gchar *name, LogExprNode *node, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_filter_reference(const gchar *name, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_parser(const gchar *name, LogExprNode *children, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_parser_reference(const gchar *name, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_rewrite(const gchar *name, LogExprNode *children, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_rewrite_reference(const gchar *name, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_log(LogExprNode *children, guint32 flags, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_sequence(LogExprNode *children, YYLTYPE *yylloc); LogExprNode *log_expr_node_new_junction(LogExprNode *children, YYLTYPE *yylloc); typedef struct _CfgTree { GlobalConfig *cfg; GPtrArray *initialized_pipes; gint anon_counters[ENC_MAX]; /* hash of predefined source/filter/rewrite/parser/destination objects */ GHashTable *objects; /* list of top-level rules */ GPtrArray *rules; GHashTable *templates; gboolean compiled; } CfgTree; gboolean cfg_tree_add_object(CfgTree *self, LogExprNode *rule); LogExprNode *cfg_tree_get_object(CfgTree *self, gint type, const gchar *name); GList *cfg_tree_get_objects(CfgTree *self); gboolean cfg_tree_add_template(CfgTree *self, LogTemplate *template); LogTemplate *cfg_tree_lookup_template(CfgTree *self, const gchar *name); LogTemplate *cfg_tree_check_inline_template(CfgTree *self, const gchar *template_or_name, GError **error); gchar *cfg_tree_get_rule_name(CfgTree *self, gint content, LogExprNode *node); gchar *cfg_tree_get_child_id(CfgTree *self, gint content, LogExprNode *node); gboolean cfg_tree_start(CfgTree *self); gboolean cfg_tree_stop(CfgTree *self); void cfg_tree_init_instance(CfgTree *self, GlobalConfig *cfg); void cfg_tree_free_instance(CfgTree *self); #endif syslog-ng-syslog-ng-3.13.2/lib/cfg.c000066400000000000000000000451751321171025300171220ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg.h" #include "cfg-grammar.h" #include "module-config.h" #include "cfg-tree.h" #include "messages.h" #include "template/templates.h" #include "userdb.h" #include "logmsg/logmsg.h" #include "dnscache.h" #include "serialize.h" #include "plugin.h" #include "cfg-parser.h" #include "stats/stats-registry.h" #include "logproto/logproto-builtins.h" #include "reloc.h" #include "hostname.h" #include "rcptid.h" #include "resolved-configurable-paths.h" #include "mainloop.h" #include #include #include #include #include #include /* PersistConfig */ struct _PersistConfig { GHashTable *keys; }; typedef struct _PersistConfigEntry { gpointer value; GDestroyNotify destroy; } PersistConfigEntry; static void persist_config_entry_free(PersistConfigEntry *self) { if (self->destroy) { self->destroy(self->value); } g_free(self); } PersistConfig * persist_config_new(void) { PersistConfig *self = g_new0(PersistConfig, 1); self->keys = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify) g_free, (GDestroyNotify) persist_config_entry_free); return self; } void persist_config_free(PersistConfig *self) { g_hash_table_destroy(self->keys); g_free(self); } gint cfg_ts_format_value(gchar *format) { if (strcmp(format, "rfc3164") == 0 || strcmp(format, "bsd") == 0) return TS_FMT_BSD; else if (strcmp(format, "rfc3339") == 0 || strcmp(format, "iso") == 0) return TS_FMT_ISO; else if (strcmp(format, "full") == 0) return TS_FMT_FULL; else if (strcmp(format, "unix") == 0 || strcmp(format, "utc") == 0) return TS_FMT_UNIX; else { msg_error("Invalid ts_format() value", evt_tag_str("value", format)); return TS_FMT_BSD; } } void cfg_bad_hostname_set(GlobalConfig *self, gchar *bad_hostname_re) { if (self->bad_hostname_re) g_free(self->bad_hostname_re); self->bad_hostname_re = g_strdup(bad_hostname_re); } gint cfg_lookup_mark_mode(gchar *mark_mode) { if (!strcmp(mark_mode, "internal")) return MM_INTERNAL; if (!strcmp(mark_mode, "dst_idle") || !strcmp(mark_mode, "dst-idle")) return MM_DST_IDLE; if (!strcmp(mark_mode, "host_idle") || !strcmp(mark_mode, "host-idle")) return MM_HOST_IDLE; if (!strcmp(mark_mode, "periodical")) return MM_PERIODICAL; if (!strcmp(mark_mode, "none")) return MM_NONE; if (!strcmp(mark_mode, "global")) return MM_GLOBAL; return -1; } void cfg_set_mark_mode(GlobalConfig *self, gchar *mark_mode) { self->mark_mode = cfg_lookup_mark_mode(mark_mode); } static void _invoke_module_init(gchar *key, ModuleConfig *mc, gpointer *args) { GlobalConfig *cfg = (GlobalConfig *) args[0]; gboolean *result = (gboolean *) args[1]; if (!module_config_init(mc, cfg)) *result = FALSE; } static void _invoke_module_deinit(gchar *key, ModuleConfig *mc, gpointer user_data) { GlobalConfig *cfg = (GlobalConfig *) user_data; module_config_deinit(mc, cfg); } static void _sync_plugin_module_path_with_global_define(GlobalConfig *self) { const gchar *module_path; /* Sync the @define module-path with the actual module search path as implemented by plugin. * * if @define module-path is not defined, we use whatever there's in * PluginContext by default */ if (self->lexer) { module_path = cfg_args_get(self->globals, "module-path"); if (module_path) { plugin_context_set_module_path(&self->plugin_context, module_path); } } } gboolean cfg_load_module(GlobalConfig *cfg, const gchar *module_name) { _sync_plugin_module_path_with_global_define(cfg); return plugin_load_module(&cfg->plugin_context, module_name, NULL); } void cfg_load_candidate_modules(GlobalConfig *self) { gboolean autoload_enabled = atoi(cfg_args_get(self->globals, "autoload-compiled-modules") ? : "1"); if (self->use_plugin_discovery && autoload_enabled) { _sync_plugin_module_path_with_global_define(self); plugin_load_candidate_modules(&self->plugin_context); } } Plugin * cfg_find_plugin(GlobalConfig *cfg, gint plugin_type, const gchar *plugin_name) { return plugin_find(&cfg->plugin_context, plugin_type, plugin_name); } /* construct a plugin instance by parsing its relevant portion from the * configuration file */ gpointer cfg_parse_plugin(GlobalConfig *cfg, Plugin *plugin, YYLTYPE *yylloc, gpointer arg) { CfgTokenBlock *block; YYSTYPE token; /* we add two tokens to an inserted token-block: * 1) the plugin type (in order to make it possible to support different * plugins from the same grammar) * * 2) the keyword equivalent of the plugin name */ block = cfg_token_block_new(); /* add plugin->type as a token */ memset(&token, 0, sizeof(token)); token.type = LL_TOKEN; token.token = plugin->type; cfg_token_block_add_and_consume_token(block, &token); /* start a new lexer context, so plugin specific keywords are recognized, * we only do this to lookup the parser name. */ cfg_lexer_push_context(cfg->lexer, plugin->parser->context, plugin->parser->keywords, plugin->parser->name); cfg_lexer_lookup_keyword(cfg->lexer, &token, yylloc, plugin->name); cfg_lexer_pop_context(cfg->lexer); /* add plugin name token */ cfg_token_block_add_and_consume_token(block, &token); cfg_lexer_inject_token_block(cfg->lexer, block); return plugin_construct_from_config(plugin, cfg->lexer, arg); } static gboolean cfg_init_modules(GlobalConfig *cfg) { gboolean result = TRUE; gpointer args[] = { cfg, &result }; g_hash_table_foreach(cfg->module_config, (GHFunc) _invoke_module_init, args); return result; } static void cfg_deinit_modules(GlobalConfig *cfg) { g_hash_table_foreach(cfg->module_config, (GHFunc) _invoke_module_deinit, cfg); } /* Request that this configuration shuts down and terminates. Right now, as * there's only one configuration executed in a syslog-ng process, it will * cause the mainloop to exit. Should there be multiple configs running in * the same process at a future point, this would only terminate one and * continue with the rest. */ void cfg_shutdown(GlobalConfig *cfg) { MainLoop *main_loop = main_loop_get_instance(); main_loop_exit(main_loop); } gboolean cfg_init(GlobalConfig *cfg) { gint regerr; if (cfg->file_template_name && !(cfg->file_template = cfg_tree_lookup_template(&cfg->tree, cfg->file_template_name))) msg_error("Error resolving file template", evt_tag_str("name", cfg->file_template_name)); if (cfg->proto_template_name && !(cfg->proto_template = cfg_tree_lookup_template(&cfg->tree, cfg->proto_template_name))) msg_error("Error resolving protocol template", evt_tag_str("name", cfg->proto_template_name)); if (cfg->bad_hostname_re) { if ((regerr = regcomp(&cfg->bad_hostname, cfg->bad_hostname_re, REG_NOSUB | REG_EXTENDED)) != 0) { gchar buf[256]; regerror(regerr, &cfg->bad_hostname, buf, sizeof(buf)); msg_error("Error compiling bad_hostname regexp", evt_tag_str("error", buf)); } else { cfg->bad_hostname_compiled = TRUE; } } if (!rcptid_init(cfg->state, cfg->use_uniqid)) return FALSE; stats_reinit(&cfg->stats_options); dns_caching_update_options(&cfg->dns_cache_options); hostname_reinit(cfg->custom_domain); host_resolve_options_init_globals(&cfg->host_resolve_options); log_template_options_init(&cfg->template_options, cfg); if (!cfg_init_modules(cfg)) return FALSE; return cfg_tree_start(&cfg->tree); } gboolean cfg_deinit(GlobalConfig *cfg) { cfg_deinit_modules(cfg); rcptid_deinit(); return cfg_tree_stop(&cfg->tree); } gboolean cfg_set_version(GlobalConfig *self, gint version) { self->user_version = version; if (cfg_is_config_version_older(self, 0x0300)) { msg_error("ERROR: compatibility with configurations below 3.0 was dropped in " VERSION_3_13 ", please update your configuration accordingly"); return FALSE; } if (cfg_is_config_version_older(self, VERSION_VALUE)) { msg_warning("WARNING: Configuration file format is too old, syslog-ng is running in compatibility mode. " "Please update it to use the " VERSION_CURRENT " format at your time of convenience. " "To upgrade the configuration, please review the warnings about incompatible changes printed " "by syslog-ng, and once completed change the @version header at the top of the configuration " "file."); } else if (version_convert_from_user(self->user_version) > VERSION_VALUE) { msg_warning("WARNING: Configuration file format is newer than the current version, please specify the " "current version number (" VERSION_CURRENT_VER_ONLY ") in the @version directive. " "syslog-ng will operate at its highest supported version in this mode"); self->user_version = VERSION_VALUE; } if (cfg_is_config_version_older(self, 0x0303)) { msg_warning("WARNING: global: the default value of log_fifo_size() has changed to 10000 in " VERSION_3_3 " to reflect log_iw_size() changes for tcp()/udp() window size changes"); } return TRUE; } gboolean cfg_allow_config_dups(GlobalConfig *self) { const gchar *s; if (cfg_is_config_version_older(self, 0x0303)) return TRUE; s = cfg_args_get(self->globals, "allow-config-dups"); if (s && atoi(s)) { return TRUE; } else { /* duplicate found, but allow-config-dups is not enabled, hint the user that he might want to use allow-config-dups */ msg_warning_once("WARNING: Duplicate configuration objects (sources, destinations, ...) are not allowed by default starting with syslog-ng 3.3, add \"@define allow-config-dups 1\" to your configuration to re-enable"); return FALSE; } } static void cfg_register_builtin_plugins(GlobalConfig *self) { log_proto_register_builtin_plugins(&self->plugin_context); } GlobalConfig * cfg_new(gint version) { GlobalConfig *self = g_new0(GlobalConfig, 1); self->module_config = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) module_config_free); self->globals = cfg_args_new(); self->user_version = version; self->flush_lines = 100; self->flush_timeout = 10000; /* 10 seconds */ self->mark_freq = 1200; /* 20 minutes */ self->mark_mode = MM_HOST_IDLE; self->chain_hostnames = 0; self->time_reopen = 60; self->time_reap = 60; self->log_fifo_size = 10000; self->log_msg_size = 65536; file_perm_options_global_defaults(&self->file_perm_options); dns_cache_options_defaults(&self->dns_cache_options); self->threaded = TRUE; self->pass_unix_credentials = TRUE; log_template_options_defaults(&self->template_options); self->template_options.ts_format = TS_FMT_BSD; self->template_options.frac_digits = 0; self->template_options.on_error = ON_ERROR_DROP_MESSAGE; host_resolve_options_global_defaults(&self->host_resolve_options); self->recv_time_zone = NULL; self->keep_timestamp = TRUE; self->use_uniqid = FALSE; self->jvm_options = NULL; stats_options_defaults(&self->stats_options); cfg_tree_init_instance(&self->tree, self); plugin_context_init_instance(&self->plugin_context); self->use_plugin_discovery = TRUE; cfg_register_builtin_plugins(self); return self; } GlobalConfig * cfg_new_snippet(void) { GlobalConfig *self = cfg_new(VERSION_VALUE); self->use_plugin_discovery = FALSE; return self; } void cfg_set_global_paths(GlobalConfig *self) { gchar *include_path; cfg_args_set(self->globals, "syslog-ng-root", get_installation_path_for(SYSLOG_NG_PATH_PREFIX)); cfg_args_set(self->globals, "syslog-ng-data", get_installation_path_for(SYSLOG_NG_PATH_DATADIR)); cfg_args_set(self->globals, "syslog-ng-include", get_installation_path_for(SYSLOG_NG_PATH_CONFIG_INCLUDEDIR)); cfg_args_set(self->globals, "scl-root", get_installation_path_for(SYSLOG_NG_PATH_SCLDIR)); cfg_args_set(self->globals, "module-path", resolvedConfigurablePaths.initial_module_path); cfg_args_set(self->globals, "module-install-dir", resolvedConfigurablePaths.initial_module_path); include_path = g_strdup_printf("%s:%s", get_installation_path_for(SYSLOG_NG_PATH_SYSCONFDIR), get_installation_path_for(SYSLOG_NG_PATH_CONFIG_INCLUDEDIR)); cfg_args_set(self->globals, "include-path", include_path); g_free(include_path); } gboolean cfg_run_parser(GlobalConfig *self, CfgLexer *lexer, CfgParser *parser, gpointer *result, gpointer arg) { gboolean res; GlobalConfig *old_cfg; CfgLexer *old_lexer; old_cfg = configuration; configuration = self; old_lexer = self->lexer; self->lexer = lexer; cfg_set_global_paths(self); res = cfg_parser_parse(parser, lexer, result, arg); cfg_lexer_free(lexer); self->lexer = NULL; self->lexer = old_lexer; configuration = old_cfg; return res; } static void cfg_dump_processed_config(GString *preprocess_output, gchar *output_filename) { FILE *output_file; output_file = fopen(output_filename,"w+"); if (output_file) { fprintf(output_file, "%s", preprocess_output->str); fclose(output_file); } } gboolean cfg_load_config(GlobalConfig *self, gchar *config_string, gboolean syntax_only, gchar *preprocess_into) { gint res; CfgLexer *lexer; GString *preprocess_output = g_string_sized_new(8192); lexer = cfg_lexer_new_buffer(self, config_string, strlen(config_string)); lexer->preprocess_output = preprocess_output; res = cfg_run_parser(self, lexer, &main_parser, (gpointer *) &self, NULL); if (preprocess_into) { cfg_dump_processed_config(preprocess_output, preprocess_into); } g_string_free(preprocess_output, TRUE); if (res) { return TRUE; } return FALSE; } gboolean cfg_read_config(GlobalConfig *self, const gchar *fname, gboolean syntax_only, gchar *preprocess_into) { FILE *cfg_file; gint res; self->filename = fname; if ((cfg_file = fopen(fname, "r")) != NULL) { CfgLexer *lexer; GString *preprocess_output = g_string_sized_new(8192); lexer = cfg_lexer_new(self, cfg_file, fname, preprocess_output); res = cfg_run_parser(self, lexer, &main_parser, (gpointer *) &self, NULL); fclose(cfg_file); if (preprocess_into) { cfg_dump_processed_config(preprocess_output, preprocess_into); } g_string_free(preprocess_output, TRUE); if (res) { /* successfully parsed */ return TRUE; } } else { msg_error("Error opening configuration file", evt_tag_str(EVT_TAG_FILENAME, fname), evt_tag_errno(EVT_TAG_OSERROR, errno)); } return FALSE; } void cfg_free(GlobalConfig *self) { g_assert(self->persist == NULL); if (self->state) persist_state_free(self->state); g_free(self->file_template_name); g_free(self->proto_template_name); log_template_unref(self->file_template); log_template_unref(self->proto_template); log_template_options_destroy(&self->template_options); host_resolve_options_destroy(&self->host_resolve_options); if (self->bad_hostname_compiled) regfree(&self->bad_hostname); if (self->source_mangle_callback_list) g_list_free(self->source_mangle_callback_list); g_free(self->bad_hostname_re); dns_cache_options_destroy(&self->dns_cache_options); g_free(self->custom_domain); plugin_context_deinit_instance(&self->plugin_context); cfg_tree_free_instance(&self->tree); g_hash_table_unref(self->module_config); cfg_args_unref(self->globals); g_free(self); } void cfg_persist_config_move(GlobalConfig *src, GlobalConfig *dest) { if (dest->persist != NULL) persist_config_free(dest->persist); dest->persist = src->persist; dest->state = src->state; src->persist = NULL; src->state = NULL; } void cfg_persist_config_add(GlobalConfig *cfg, const gchar *name, gpointer value, GDestroyNotify destroy, gboolean force) { PersistConfigEntry *p; if (cfg->persist && value) { if (g_hash_table_lookup(cfg->persist->keys, name)) { if (!force) { msg_error("Internal error, duplicate configuration elements refer to the same persistent config", evt_tag_str("name", name)); if (destroy) destroy(value); return; } } p = g_new0(PersistConfigEntry, 1); p->value = value; p->destroy = destroy; g_hash_table_insert(cfg->persist->keys, g_strdup(name), p); return; } else if (destroy && value) { destroy(value); } return; } gpointer cfg_persist_config_fetch(GlobalConfig *cfg, const gchar *name) { gpointer res = NULL; gchar *orig_key; PersistConfigEntry *p; gpointer tmp1, tmp2; if (cfg->persist && g_hash_table_lookup_extended(cfg->persist->keys, name, &tmp1, &tmp2)) { orig_key = (gchar *) tmp1; p = (PersistConfigEntry *) tmp2; res = p->value; g_hash_table_steal(cfg->persist->keys, name); g_free(orig_key); g_free(p); } return res; } gint cfg_get_user_version(const GlobalConfig *cfg) { return cfg->user_version; } gint cfg_get_parsed_version(const GlobalConfig *cfg) { return cfg->parsed_version; } void register_source_mangle_callback(GlobalConfig *src,mangle_callback cb) { src->source_mangle_callback_list = g_list_append(src->source_mangle_callback_list,cb); } void uregister_source_mangle_callback(GlobalConfig *src,mangle_callback cb) { src->source_mangle_callback_list = g_list_remove(src->source_mangle_callback_list,cb); } const gchar * cfg_get_filename(const GlobalConfig *cfg) { return cfg->filename; } syslog-ng-syslog-ng-3.13.2/lib/cfg.h000066400000000000000000000127201321171025300171150ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CFG_H_INCLUDED #define CFG_H_INCLUDED #include "syslog-ng.h" #include "cfg-tree.h" #include "cfg-lexer.h" #include "cfg-parser.h" #include "plugin.h" #include "persist-state.h" #include "template/templates.h" #include "host-resolve.h" #include "type-hinting.h" #include "stats/stats.h" #include "dnscache.h" #include "file-perms.h" #include #include /* destination mark modes */ enum { MM_INTERNAL = 1, MM_DST_IDLE, MM_HOST_IDLE, MM_PERIODICAL, MM_NONE, MM_GLOBAL, }; /* configuration data kept between configuration reloads */ typedef struct _PersistConfig PersistConfig; /* configuration data as loaded from the config file */ struct _GlobalConfig { /* version number specified by the user, set _after_ parsing is complete */ /* hex-encoded syslog-ng major/minor, e.g. 0x0201 is syslog-ng 2.1 format */ gint user_version; /* version number as parsed from the configuration file, it can be set * multiple times if the user uses @version multiple times */ gint parsed_version; const gchar *filename; PluginContext plugin_context; gboolean use_plugin_discovery; CfgLexer *lexer; CfgArgs *globals; StatsOptions stats_options; gint mark_freq; gint flush_lines; gint mark_mode; gint flush_timeout; gboolean threaded; gboolean pass_unix_credentials; gboolean chain_hostnames; gboolean keep_hostname; gboolean check_hostname; gboolean bad_hostname_compiled; regex_t bad_hostname; gchar *bad_hostname_re; gchar *custom_domain; DNSCacheOptions dns_cache_options; gint time_reopen; gint time_reap; gint suppress; gint type_cast_strictness; gint log_fifo_size; gint log_msg_size; gboolean create_dirs; FilePermOptions file_perm_options; GList *source_mangle_callback_list; gboolean use_uniqid; gboolean keep_timestamp; gchar *recv_time_zone; LogTemplateOptions template_options; HostResolveOptions host_resolve_options; gchar *file_template_name; gchar *proto_template_name; gchar *jvm_options; LogTemplate *file_template; LogTemplate *proto_template; PersistConfig *persist; PersistState *state; GHashTable *module_config; CfgTree tree; }; gboolean cfg_load_module(GlobalConfig *cfg, const gchar *module_name); Plugin *cfg_find_plugin(GlobalConfig *cfg, gint plugin_type, const gchar *plugin_name); gpointer cfg_parse_plugin(GlobalConfig *cfg, Plugin *plugin, YYLTYPE *yylloc, gpointer arg); gboolean cfg_allow_config_dups(GlobalConfig *self); void cfg_bad_hostname_set(GlobalConfig *self, gchar *bad_hostname_re); gint cfg_lookup_mark_mode(gchar *mark_mode); void cfg_set_mark_mode(GlobalConfig *self, gchar *mark_mode); gint cfg_tz_convert_value(gchar *convert); gint cfg_ts_format_value(gchar *format); gboolean cfg_set_version(GlobalConfig *self, gint version); void cfg_load_candidate_modules(GlobalConfig *self); void cfg_set_global_paths(GlobalConfig *self); GlobalConfig *cfg_new(gint version); GlobalConfig *cfg_new_snippet(void); gboolean cfg_run_parser(GlobalConfig *self, CfgLexer *lexer, CfgParser *parser, gpointer *result, gpointer arg); gboolean cfg_read_config(GlobalConfig *cfg, const gchar *fname, gboolean syntax_only, gchar *preprocess_into); gboolean cfg_load_config(GlobalConfig *self, gchar *config_string, gboolean syntax_only, gchar *preprocess_into); void cfg_shutdown(GlobalConfig *self); void cfg_free(GlobalConfig *self); gboolean cfg_init(GlobalConfig *cfg); gboolean cfg_deinit(GlobalConfig *cfg); PersistConfig *persist_config_new(void); void persist_config_free(PersistConfig *self); void cfg_persist_config_move(GlobalConfig *src, GlobalConfig *dest); void cfg_persist_config_add(GlobalConfig *cfg, const gchar *name, gpointer value, GDestroyNotify destroy, gboolean force); gpointer cfg_persist_config_fetch(GlobalConfig *cfg, const gchar *name); typedef gboolean(* mangle_callback)(GlobalConfig *cfg, LogMessage *msg, gpointer user_data); void register_source_mangle_callback(GlobalConfig *src,mangle_callback cb); void uregister_source_mangle_callback(GlobalConfig *src,mangle_callback cb); static inline gboolean cfg_is_config_version_older(GlobalConfig *cfg, gint req) { if (!cfg) return FALSE; if (version_convert_from_user(cfg->user_version) >= req) return FALSE; return TRUE; } static inline void cfg_set_use_uniqid(gboolean flag) { configuration->use_uniqid = !!flag; } gint cfg_get_user_version(const GlobalConfig *cfg); gint cfg_get_parsed_version(const GlobalConfig *cfg); const gchar* cfg_get_filename(const GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/lib/children.c000066400000000000000000000045601321171025300201440ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "children.h" typedef struct _ChildEntry { pid_t pid; gpointer callback_data; GDestroyNotify callback_data_destroy; void (*exit_callback)(pid_t pid, int status, gpointer user_data); } ChildEntry; GHashTable *child_hash; static void child_manager_child_entry_free(ChildEntry *ce) { if (ce->callback_data_destroy) ce->callback_data_destroy(ce->callback_data); g_free(ce); } void child_manager_register(pid_t pid, void (*callback)(pid_t, int, gpointer), gpointer user_data, GDestroyNotify callback_data_destroy) { ChildEntry *ce = g_new0(ChildEntry, 1); ce->pid = pid; ce->exit_callback = callback; ce->callback_data = user_data; ce->callback_data_destroy = callback_data_destroy; g_hash_table_insert(child_hash, &ce->pid, ce); } void child_manager_unregister(pid_t pid) { if (g_hash_table_lookup(child_hash, &pid)) { g_hash_table_remove(child_hash, &pid); } } void child_manager_sigchild(pid_t pid, int status) { ChildEntry *ce; ce = g_hash_table_lookup(child_hash, &pid); if (ce) { ce->exit_callback(pid, status, ce->callback_data); g_hash_table_remove(child_hash, &pid); } } void child_manager_init(void) { child_hash = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, (GDestroyNotify) child_manager_child_entry_free); } void child_manager_deinit(void) { g_hash_table_destroy(child_hash); } syslog-ng-syslog-ng-3.13.2/lib/children.h000066400000000000000000000026041321171025300201460ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CHILDREN_H_INCLUDED #define CHILDREN_H_INCLUDED #include "syslog-ng.h" #include void child_manager_register(pid_t pid, void (*callback)(pid_t, int, gpointer), gpointer user_data, GDestroyNotify user_data_destroy); void child_manager_unregister(pid_t pid); void child_manager_sigchild(pid_t pid, int status); void child_manager_init(void); void child_manager_deinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/compat/000077500000000000000000000000001321171025300174665ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/compat/CMakeLists.txt000066400000000000000000000010231321171025300222220ustar00rootroot00000000000000set(COMPAT_HEADERS compat/compat.h compat/getutent.h compat/glib.h compat/lfs.h compat/pio.h compat/socket.h compat/string.h compat/time.h compat/openssl_support.h compat/pcre.h compat/getent.h compat/getent-bb.h PARENT_SCOPE) set(COMPAT_SOURCES compat/getutent.c compat/glib.c compat/inet_aton.c compat/memrchr.c compat/pio.c compat/strcasestr.c compat/strtok_r.c compat/time.c compat/openssl_support.c compat/getent.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/compat/Makefile.am000066400000000000000000000012341321171025300215220ustar00rootroot00000000000000compatincludedir = ${pkgincludedir}/compat compatinclude_HEADERS = \ lib/compat/compat.h \ lib/compat/getutent.h \ lib/compat/glib.h \ lib/compat/lfs.h \ lib/compat/pio.h \ lib/compat/socket.h \ lib/compat/string.h \ lib/compat/time.h \ lib/compat/openssl_support.h \ lib/compat/pcre.h \ lib/compat/getent.h \ lib/compat/getent-bb.h compat_sources = \ lib/compat/getutent.c \ lib/compat/inet_aton.c \ lib/compat/memrchr.c \ lib/compat/pio.c \ lib/compat/glib.c \ lib/compat/strcasestr.c \ lib/compat/strtok_r.c \ lib/compat/time.c \ lib/compat/openssl_support.c \ lib/compat/getent.c include lib/compat/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/compat/compat.h000066400000000000000000000061661321171025300211330ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ /* * The compat subdirectory is a placeholder for missing functionality on * various platforms. Here are the rules to follow when a specific platform * lacks a given functionality. * * NOTE: compat is the place for simple functions and fixups that should * have been defined by the system but isn't for some reason (old version, * weird platform etc). It is not the place for extensive logic, complex * implementations and so on. It is a strong indicator that we are doing * something wrong if a .c file in compat is more than a 100 lines. For * those, a proper syslog-ng style API with several implementations is the * way to go. * * NOTE/2: please don't implement dummy, empty functions for things that * make no sense on a specific platforms. In that case, please modify the * call-site instead. Whenever you read a call-site of code that resides in * compat it shouldn't misguide you that it doesn't do anything. For these * changing the call-site is better. * * File organization, call sites: * * 1) Add a header for that subsystem under lib/compat, this should in turn * include "compat/compat.h" first, and then add all headers required by * the interface itself. * * 2) compat.h will take care about including no code under * compat should do the same. * * 3) Add the implementation to one or more .c files. If the functions are * unrelated, it's preferred to have a separate .c file for each, with a * single header. In other cases you can simply use the same name for * the .c as you did for the .h * * 4) call sites should include compat/XXXX.h, preferably _instead_ of the * system header that defines the given functionality. The compat header * will include the required system headers anyway, no need to do that * multiple times. * * 5) compat.h shouldn't be included by call-sites directly. * * If a function is missing on a set of platforms, they should be named as * POSIX named them (if they are standard), or if not, they should be named * as on Linux. */ #ifndef COMPAT_COMPAT_H_INCLUDED #define COMPAT_COMPAT_H_INCLUDED #include #endif syslog-ng-syslog-ng-3.13.2/lib/compat/getent-bb.h000066400000000000000000000032411321171025300215060ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef GETENT_BB_H_INCLUDED #define GETENT_BB_H_INCLUDED #if defined(sun) || defined(__sun) #include #include #include #include int bb__getprotobynumber_r(int proto, struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result); int bb__getprotobyname_r(const char *name, struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result); int bb__getservbyport_r(int port, const char *proto, struct servent *result_buf, char *buf, size_t buflen, struct servent **result); int bb__getservbyname_r(const char *name, const char *proto, struct servent *result_buf, char *buf, size_t buflen, struct servent **result); #endif #endif syslog-ng-syslog-ng-3.13.2/lib/compat/getent.c000066400000000000000000000042071321171025300211230ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #if defined(sun) || defined(__sun) #include "compat/getent-bb.h" #include int bb__getprotobynumber_r(int proto, struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result) { *result = getprotobynumber_r(proto, result_buf, buf, buflen); return (*result ? NULL : errno); } int bb__getprotobyname_r(const char *name, struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result) { *result = getprotobyname_r(name, result_buf, buf, buflen); return (*result ? NULL : errno); } int bb__getservbyport_r(int port, const char *proto, struct servent *result_buf, char *buf, size_t buflen, struct servent **result) { *result = getservbyport_r(port, proto, result_buf, buf, buflen); return (*result ? NULL : errno); } int bb__getservbyname_r(const char *name, const char *proto, struct servent *result_buf, char *buf, size_t buflen, struct servent **result) { *result = getservbyname_r(name, proto, result_buf, buf, buflen); return (*result ? NULL : errno); } #endif syslog-ng-syslog-ng-3.13.2/lib/compat/getent.h000066400000000000000000000025311321171025300211260ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef GETENT_COMPAT_H_INCLUDED #define GETENT_COMPAT_H_INCLUDED #include #include #include #include #if defined(sun) || defined(__sun) #define getprotobynumber_r bb__getprotobynumber_r #define getprotobyname_r bb__getprotobyname_r #define getservbyport_r bb__getservbyport_r #define getservbyname_r bb__getservbyname_r #include "getent-bb.h" #endif // Solaris #endif syslog-ng-syslog-ng-3.13.2/lib/compat/getutent.c000066400000000000000000000034031321171025300214710ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "compat/getutent.h" #include #include #include #include #if !defined(SYSLOG_NG_HAVE_GETUTENT) && !defined(SYSLOG_NG_HAVE_GETUTXENT) && defined(SYSLOG_NG_HAVE_UTMP_H) static int utent_fd = -1; #ifndef _PATH_UTMP #define _PATH_UTMP "/var/log/utmp" #endif struct utmp *getutent(void) { static struct utmp ut; int rc; if (utent_fd == -1) { utent_fd = open(_PATH_UTMP, O_RDONLY | O_NOCTTY); } if (utent_fd == -1) return NULL; rc = read(utent_fd, &ut, sizeof(ut)); if (rc <= 0) { close(utent_fd); utent_fd = -1; return NULL; } else { return &ut; } } void endutent(void) { if (utent_fd != -1) { close(utent_fd); utent_fd = -1; } } #endif syslog-ng-syslog-ng-3.13.2/lib/compat/getutent.h000066400000000000000000000025301321171025300214760ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef COMPAT_GETUTENT_H_INCLUDED #define COMPAT_GETUTENT_H_INCLUDED #include "compat/compat.h" #include #include #ifdef SYSLOG_NG_HAVE_UTMPX_H #include #else #include #endif #if !defined(SYSLOG_NG_HAVE_GETUTENT) && !defined(SYSLOG_NG_HAVE_GETUTXENT) struct utmp *getutent(void); void endutent(void); #endif #endif syslog-ng-syslog-ng-3.13.2/lib/compat/glib.c000066400000000000000000000033721321171025300205540ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "glib.h" #if !SYSLOG_NG_HAVE_G_LIST_COPY_DEEP /* Less efficient than the original implementation in glib 2.53.2 that I wanted to port back, because this version iterates through the list twice. Though the original version depends on the internal api of GList (for example in terms on memory allocation), so I felt safer to reduce the problem to use public glib api only: g_list_copy and iteration. */ GList * g_list_copy_deep(GList *list, GCopyFunc func, gpointer user_data) { if (!list) return NULL; GList *new_list = g_list_copy(list); if (func) { GList *iter = new_list; while (iter != NULL) { iter->data = func(iter->data, user_data); iter = g_list_next(iter); } } return new_list; } #endif syslog-ng-syslog-ng-3.13.2/lib/compat/glib.h000066400000000000000000000024721321171025300205610ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef COMPAT_GLIB_H_INCLUDED #define COMPAT_GLIB_H_INCLUDED 1 #include "compat/compat.h" #define GLIB_DISABLE_DEPRECATION_WARNINGS 1 #include #if !SYSLOG_NG_HAVE_G_MAPPED_FILE_UNREF #define g_mapped_file_unref g_mapped_file_free #endif #if !SYSLOG_NG_HAVE_G_LIST_COPY_DEEP GList *g_list_copy_deep (GList *list, GCopyFunc func, gpointer user_data); #endif #endif syslog-ng-syslog-ng-3.13.2/lib/compat/inet_aton.c000066400000000000000000000022511321171025300216120ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "compat/socket.h" #ifndef SYSLOG_NG_HAVE_INET_ATON int inet_aton(const char *cp, struct in_addr *dst) { in_addr_t s = 0; s = inet_addr(cp); if (s == INADDR_NONE) return 0; dst->s_addr = s; return 1; } #endif syslog-ng-syslog-ng-3.13.2/lib/compat/lfs.h000066400000000000000000000021711321171025300204240ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ /* largefile support */ #ifndef COMPAT_LFS_H_INCLUDED #define COMPAT_LFS_H_INCLUDED #include "compat/compat.h" #ifndef SYSLOG_NG_HAVE_O_LARGEFILE #define O_LARGEFILE 0 #endif #endif syslog-ng-syslog-ng-3.13.2/lib/compat/memrchr.c000066400000000000000000000024311321171025300212670ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "compat/string.h" #ifndef SYSLOG_NG_HAVE_MEMRCHR #include void * memrchr(const void *s, int c, size_t n) { unsigned char *p = (unsigned char *) s + n - 1; while (p >= (unsigned char *) s) { if (*p == c) return p; p--; } return NULL; } #endif syslog-ng-syslog-ng-3.13.2/lib/compat/openssl_support.c000066400000000000000000000077751321171025300231310ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "compat/openssl_support.h" #include "syslog-ng.h" #include "thread-utils.h" #include #if !SYSLOG_NG_HAVE_DECL_SSL_CTX_GET0_PARAM X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) { return ctx->param; } #endif #if !SYSLOG_NG_HAVE_DECL_X509_STORE_CTX_GET0_CERT X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) { return ctx->cert; } #endif #if !SYSLOG_NG_HAVE_DECL_X509_GET_EXTENSION_FLAGS uint32_t X509_get_extension_flags(X509 *x) { return x->ex_flags; } #endif /* locking callbacks for OpenSSL prior to 1.1.0 */ #if OPENSSL_VERSION_NUMBER < 0x10100000L static gint ssl_lock_count; static GStaticMutex *ssl_locks; static void _ssl_locking_callback(int mode, int type, const char *file, int line) { if (mode & CRYPTO_LOCK) { g_static_mutex_lock(&ssl_locks[type]); } else { g_static_mutex_unlock(&ssl_locks[type]); } } static void _init_locks(void) { gint i; ssl_lock_count = CRYPTO_num_locks(); ssl_locks = g_new(GStaticMutex, ssl_lock_count); for (i = 0; i < ssl_lock_count; i++) { g_static_mutex_init(&ssl_locks[i]); } CRYPTO_set_locking_callback(_ssl_locking_callback); } static void _deinit_locks(void) { gint i; for (i = 0; i < ssl_lock_count; i++) { g_static_mutex_free(&ssl_locks[i]); } g_free(ssl_locks); } #else static void _init_locks(void) { } static void _deinit_locks(void) { } #endif /* ThreadID callbacks for various OpenSSL versions */ #if OPENSSL_VERSION_NUMBER < 0x10000000 static unsigned long _ssl_thread_id(void) { return (unsigned long) get_thread_id(); } static void _init_threadid_callback(void) { CRYPTO_set_id_callback(_ssl_thread_id); } #else static void _ssl_thread_id2(CRYPTO_THREADID *id) { CRYPTO_THREADID_set_numeric(id, (unsigned long) get_thread_id()); } static void _init_threadid_callback(void) { CRYPTO_THREADID_set_callback(_ssl_thread_id2); } #endif void openssl_crypto_init_threading(void) { _init_locks(); _init_threadid_callback(); } void openssl_crypto_deinit_threading(void) { _deinit_locks(); } void openssl_init(void) { #if OPENSSL_VERSION_NUMBER < 0x10100000L SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); #endif } void openssl_ctx_setup_ecdh(SSL_CTX *ctx) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L /* No need to setup as ECDH auto is the default */ #elif OPENSSL_VERSION_NUMBER >= 0x10002000L SSL_CTX_set_ecdh_auto(ctx, 1); #elif OPENSSL_VERSION_NUMBER >= 0x10001000L EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (!ecdh) return; SSL_CTX_set_tmp_ecdh(ctx, ecdh); EC_KEY_free(ecdh); #endif } #if !SYSLOG_NG_HAVE_DECL_DH_SET0_PQG int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) { if ((dh->p == NULL && p == NULL) || (dh->g == NULL && g == NULL)) return 0; if (p != NULL) { BN_free(dh->p); dh->p = p; } if (q != NULL) { BN_free(dh->q); dh->q = q; } if (g != NULL) { BN_free(dh->g); dh->g = g; } if (q != NULL) dh->length = BN_num_bits(q); return 1; } #endif syslog-ng-syslog-ng-3.13.2/lib/compat/openssl_support.h000066400000000000000000000041711321171025300231210ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef OPENSSL_SUPPORT_H_INCLUDED #define OPENSSL_SUPPORT_H_INCLUDED #include "compat/compat.h" #include #include #if !SYSLOG_NG_HAVE_DECL_SSL_CTX_GET0_PARAM X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx); #endif #if !SYSLOG_NG_HAVE_DECL_X509_STORE_CTX_GET0_CERT X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx); #endif #if !SYSLOG_NG_HAVE_DECL_X509_GET_EXTENSION_FLAGS #include uint32_t X509_get_extension_flags(X509 *x); #endif #if SYSLOG_NG_HAVE_DECL_EVP_MD_CTX_RESET #include #define EVP_MD_CTX_cleanup EVP_MD_CTX_reset #define DECLARE_EVP_MD_CTX(md_ctx) EVP_MD_CTX * md_ctx = EVP_MD_CTX_create() #else #define DECLARE_EVP_MD_CTX(md_ctx) EVP_MD_CTX _##md_ctx; EVP_MD_CTX * md_ctx = & _##md_ctx #define EVP_MD_CTX_destroy(md_ctx) EVP_MD_CTX_cleanup(md_ctx) #endif #if !SYSLOG_NG_HAVE_DECL_ASN1_STRING_GET0_DATA #define ASN1_STRING_get0_data ASN1_STRING_data #endif #if !SYSLOG_NG_HAVE_DECL_DH_SET0_PQG int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); #endif void openssl_ctx_setup_ecdh(SSL_CTX *ctx); void openssl_init(void); void openssl_crypto_init_threading(void); void openssl_crypto_deinit_threading(void); #endif syslog-ng-syslog-ng-3.13.2/lib/compat/pcre.h000066400000000000000000000025011321171025300205660ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef COMPAT_PCRE_H_INCLUDED #define COMPAT_PCRE_H_INCLUDED #include "compat/compat.h" #include #ifndef PCRE_CONFIG_JIT #define pcre_free_study pcre_free #endif #ifndef PCRE_STUDY_JIT_COMPILE #define PCRE_STUDY_JIT_COMPILE 0 #endif #ifndef PCRE_NEWLINE_ANYCRLF #define PCRE_NEWLINE_ANYCRLF 0 #endif #endif /* COMPAT_PCRE_H_INCLUDED */ syslog-ng-syslog-ng-3.13.2/lib/compat/pio.c000066400000000000000000000035441321171025300204270ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "compat/pio.h" #if !SYSLOG_NG_HAVE_PREAD || SYSLOG_NG_HAVE_BROKEN_PREAD #include #include ssize_t bb__pread(int fd, void *buf, size_t count, off_t offset) { ssize_t ret; off_t old_offset; old_offset = lseek(fd, 0, SEEK_CUR); if (old_offset == -1) return -1; if (lseek(fd, offset, SEEK_SET) < 0) return -1; ret = read(fd, buf, count); if (ret < 0) return -1; if (lseek(fd, old_offset, SEEK_SET) < 0) return -1; return ret; } ssize_t bb__pwrite(int fd, const void *buf, size_t count, off_t offset) { ssize_t ret; off_t old_offset; old_offset = lseek(fd, 0, SEEK_CUR); if (old_offset == -1) return -1; if (lseek(fd, offset, SEEK_SET) < 0) return -1; ret = write(fd, buf, count); if (ret < 0) return -1; if (lseek(fd, old_offset, SEEK_SET) < 0) return -1; return ret; } #endif syslog-ng-syslog-ng-3.13.2/lib/compat/pio.h000066400000000000000000000027701321171025300204340ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef COMPAT_PIO_H_INCLUCED #define COMPAT_PIO_H_INCLUDED 1 #include "compat.h" #include #include /* NOTE: bb__ prefix is used for function names that might clash with system * supplied symbols. */ #if !SYSLOG_NG_HAVE_PREAD || SYSLOG_NG_HAVE_BROKEN_PREAD # ifdef pread # undef pread # endif # ifdef pwrite # undef pwrite # endif #define pread bb__pread #define pwrite bb__pwrite ssize_t bb__pread(int fd, void *buf, size_t count, off_t offset); ssize_t bb__pwrite(int fd, const void *buf, size_t count, off_t offset); #endif #endif syslog-ng-syslog-ng-3.13.2/lib/compat/socket.h000066400000000000000000000030161321171025300211270ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef COMPAT_SOCKET_H_INCLUDED #define COMPAT_SOCKET_H_INCLUDED 1 #include "compat/compat.h" #include #include #include #include #include #ifndef SYSLOG_NG_HAVE_STRUCT_SOCKADDR_STORAGE struct sockaddr_storage { union { sa_family_t ss_family; struct sockaddr __sa; struct sockaddr_un __sun; struct sockaddr_in __sin; #if SYSLOG_NG_ENABLE_IPV6 struct sockaddr_in6 __sin6; #endif }; }; #endif #ifndef SYSLOG_NG_HAVE_INET_ATON int inet_aton(const char *cp, struct in_addr *dst); #endif #endif syslog-ng-syslog-ng-3.13.2/lib/compat/strcasestr.c000066400000000000000000000067571321171025300220460ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (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 "compat/string.h" #ifndef SYSLOG_NG_HAVE_STRCASESTR #include #include #include char * strcasestr(const char *haystack, const char *needle) { char c; size_t len; if ((c = *needle++) != 0) { c = tolower((unsigned char) c); len = strlen(needle); do { for (; *haystack && tolower((unsigned char) *haystack) != c; haystack++) ; if (!(*haystack)) return NULL; haystack++; } while (strncasecmp(haystack, needle, len) != 0); haystack--; } return (char *) haystack; } #endif syslog-ng-syslog-ng-3.13.2/lib/compat/string.h000066400000000000000000000032251321171025300211470ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef COMPAT_STRING_H_INCLUDED #define COMPAT_STRING_H_INCLUDED #include "compat.h" #include #if !SYSLOG_NG_HAVE_STRTOLL # if SYSLOG_NG_HAVE_STRTOIMAX || defined(strtoimax) /* HP-UX has an strtoimax macro, not a function */ #define strtoll(nptr, endptr, base) strtoimax(nptr, endptr, base) # else /* this requires Glib 2.12 */ #define strtoll(nptr, endptr, base) g_ascii_strtoll(nptr, endptr, base) # endif #endif #if !SYSLOG_NG_HAVE_STRCASESTR char *strcasestr(const char *s, const char *find); #endif #if !SYSLOG_NG_HAVE_MEMRCHR void *memrchr(const void *s, int c, size_t n); #endif #ifndef SYSLOG_NG_HAVE_STRTOK_R char *strtok_r(char *string, const char *delim, char **saveptr); #endif #endif syslog-ng-syslog-ng-3.13.2/lib/compat/strtok_r.c000066400000000000000000000030651321171025300215050ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "compat/string.h" #if !defined(SYSLOG_NG_HAVE_STRTOK_R) || TEST_STRTOK_R char * strtok_r(char *str, const char *delim, char **saveptr) { char *it; char *head; if (str) *saveptr = str; if (!*saveptr) return NULL; it = *saveptr; /*find the first non-delimiter*/ it += strspn(it, delim); head = it; if (!it || !*it) { *saveptr = NULL; return NULL; } /* find the first delimiter */ it = strpbrk(it, delim); /* skip all the delimiters */ while (it && *it && strchr(delim, *it)) { *it = '\0'; it++; } *saveptr = it; return head; } #endif syslog-ng-syslog-ng-3.13.2/lib/compat/tests/000077500000000000000000000000001321171025300206305ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/compat/tests/Makefile.am000066400000000000000000000005151321171025300226650ustar00rootroot00000000000000lib_compat_tests_TESTS = \ lib/compat/tests/test_strtok_r check_PROGRAMS += ${lib_compat_tests_TESTS} lib_compat_tests_test_strtok_r_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/compat/tests lib_compat_tests_test_strtok_r_LDADD = $(TEST_LDADD) lib_compat_tests_test_strtok_r_SOURCES = \ lib/compat/tests/test_strtok_r.c syslog-ng-syslog-ng-3.13.2/lib/compat/tests/test_strtok_r.c000066400000000000000000000111471321171025300237060ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "syslog-ng.h" #include "testutils.h" #include #include #include #include #include #include #include #include /* * NOTE: this macro magic is needed in order to make this program test the * internal strtok_r implementation even if the system has an implementation * available. * * We include the implementation file directly, redefining the name of the * function to something else. */ #ifdef strtok_r #undef strtok_r #endif #define TEST_STRTOK_R 1 #define strtok_r __test_strtok_r #include "../strtok_r.c" #undef strtok_r #undef TEST_STRTOK_R typedef char *(STRTOK_R_FUN)(char *str, const char *delim, char **saveptr); void assert_if_tokenizer_concatenated_result_not_match(STRTOK_R_FUN tokenizer, const char *delim, const char *input, const char *expected) { gchar *token; gchar *saveptr; gchar *result = (char *)g_malloc(strlen(input)+1); gchar *raw_string; gchar *result_ref = NULL; int result_idx = 0; int token_length; raw_string = g_strdup(input); for (token = tokenizer(raw_string, delim, &saveptr); token; token = tokenizer(NULL, delim, &saveptr)) { token_length = strlen(token); memcpy(result + result_idx, token, token_length); result_idx += token_length; } result[result_idx] = '\0'; if (result_idx) result_ref = result; assert_string(result_ref, expected, "strtok return value mismatch"); g_free(raw_string); g_free(result); } void test_strtok_with_literals(STRTOK_R_FUN tokenizer_func) { assert_if_tokenizer_concatenated_result_not_match(tokenizer_func, ".", "token1.token2", "token1token2"); assert_if_tokenizer_concatenated_result_not_match(tokenizer_func, ".", ".token", "token"); assert_if_tokenizer_concatenated_result_not_match(tokenizer_func, ".", "token.", "token"); assert_if_tokenizer_concatenated_result_not_match(tokenizer_func, ".", ".", NULL); assert_if_tokenizer_concatenated_result_not_match(tokenizer_func, "...", ".", NULL); assert_if_tokenizer_concatenated_result_not_match(tokenizer_func, "... ", " ", NULL); assert_if_tokenizer_concatenated_result_not_match(tokenizer_func, "..*,;-", ";-*token1...*****token2**,;;;.", "token1token2"); assert_if_tokenizer_concatenated_result_not_match(tokenizer_func, "..*,;- ", ";-*token1...*****token2**,;;;.token3", "token1token2token3"); assert_if_tokenizer_concatenated_result_not_match(tokenizer_func, "..*,;- ", ";-*token1...*****token2**,;;;.token3 ", "token1token2token3"); } int main(int argc, char *argv[]) { test_strtok_with_literals(__test_strtok_r); return EXIT_SUCCESS; } syslog-ng-syslog-ng-3.13.2/lib/compat/time.c000066400000000000000000000027201321171025300205710ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "compat/time.h" #if !defined(SYSLOG_NG_HAVE_CLOCK_GETTIME) && defined(__APPLE__) && defined(__MACH__) int clock_gettime(clock_t clock_id, struct timespec *timestamp) { clock_serv_t clock_server; mach_timespec_t mach_timestamp; host_get_clock_service(mach_host_self(), clock_id, &clock_server); clock_get_time(clock_server, &mach_timestamp); timestamp->tv_sec = mach_timestamp.tv_sec; timestamp->tv_nsec = mach_timestamp.tv_nsec; mach_port_deallocate(mach_task_self(), clock_server); return 0; } #endif syslog-ng-syslog-ng-3.13.2/lib/compat/time.h000066400000000000000000000030671321171025300206030ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef COMPAT_TIME_H_INCLUDED #define COMPAT_TIME_H_INCLUDED #include "compat/compat.h" #include #if !defined(SYSLOG_NG_HAVE_CLOCK_GETTIME) && defined(__APPLE__) && defined(__MACH__) #include #include #define CLOCK_REALTIME CALENDAR_CLOCK #define CLOCK_MONOTONIC SYSTEM_CLOCK int clock_gettime(clock_t clock_id, struct timespec *timestamp); #else #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC CLOCK_REALTIME #endif #endif /* !SYSLOG_NG_HAVE_CLOCK_GETTIME && __APPLE__ && __MACH__ */ #endif /* COMPAT_TIME_H_INCLUDED */ syslog-ng-syslog-ng-3.13.2/lib/control/000077500000000000000000000000001321171025300176635ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/control/CMakeLists.txt000066400000000000000000000004211321171025300224200ustar00rootroot00000000000000set(CONTROL_HEADERS control/control.h control/control-commands.h control/control-main.h control/control-server.h PARENT_SCOPE) set(CONTROL_SOURCES control/control-commands.c control/control-main.c control/control-server.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/control/Makefile.am000066400000000000000000000006231321171025300217200ustar00rootroot00000000000000controlincludedir = ${pkgincludedir}/control controlinclude_HEADERS = \ lib/control/control.h \ lib/control/control-commands.h \ lib/control/control-main.h \ lib/control/control-server.h control_sources = \ lib/control/control-commands.c \ lib/control/control-main.c \ lib/control/control-server.c EXTRA_DIST += lib/control/control-server-unix.c include lib/control/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/control/control-commands.c000066400000000000000000000102341321171025300233060ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "control/control.h" #include "control/control-main.h" #include "mainloop.h" #include "messages.h" #include "apphook.h" #include "stats/stats-query-commands.h" static GList *command_list = NULL; GList * get_control_command_list(void) { return command_list; } void reset_control_command_list(void) { g_list_free_full(command_list, (GDestroyNotify)g_free); command_list = NULL; } void control_register_command(const gchar *command_name, const gchar *description, CommandFunction function, gpointer user_data) { ControlCommand *new_command = g_new0(ControlCommand, 1); new_command->command_name = command_name; new_command->description = description; new_command->func = function; new_command->user_data = user_data; command_list = g_list_append(command_list, new_command); } static GString * control_connection_message_log(GString *command, gpointer user_data) { gchar **cmds = g_strsplit(command->str, " ", 3); gboolean on; int *type = NULL; GString *result = g_string_sized_new(128); if (!cmds[1]) { g_string_assign(result,"Invalid arguments received, expected at least one argument"); goto exit; } if (g_str_equal(cmds[1], "DEBUG")) type = &debug_flag; else if (g_str_equal(cmds[1], "VERBOSE")) type = &verbose_flag; else if (g_str_equal(cmds[1], "TRACE")) type = &trace_flag; if (type) { if (cmds[2]) { on = g_str_equal(cmds[2], "ON"); if (*type != on) { msg_info("Verbosity changed", evt_tag_str("type", cmds[1]), evt_tag_int("on", on)); *type = on; } g_string_assign(result,"OK"); } else { g_string_printf(result,"%s=%d", cmds[1], *type); } } else g_string_assign(result, "Invalid arguments received"); exit: g_strfreev(cmds); return result; } static GString * control_connection_stop_process(GString *command, gpointer user_data) { GString *result = g_string_new("OK Shutdown initiated"); MainLoop *main_loop = (MainLoop *) user_data; main_loop_exit(main_loop); return result; } static GString * control_connection_reload(GString *command, gpointer user_data) { GString *result = g_string_new("OK Config reload initiated"); MainLoop *main_loop = (MainLoop *) user_data; main_loop_reload_config(main_loop); return result; } static GString * control_connection_reopen(GString *command, gpointer user_data) { GString *result = g_string_new("OK Re-open of log destination files initiated"); app_reopen(); return result; } ControlCommand default_commands[] = { { "LOG", NULL, control_connection_message_log }, { "STOP", NULL, control_connection_stop_process }, { "RELOAD", NULL, control_connection_reload }, { "REOPEN", NULL, control_connection_reopen }, { "QUERY", NULL, process_query_command }, { NULL, NULL, NULL }, }; GList * control_register_default_commands(MainLoop *main_loop) { int i; ControlCommand *cmd; for (i = 0; default_commands[i].command_name != NULL; i++) { cmd = &default_commands[i]; control_register_command(cmd->command_name, cmd->description, cmd->func, main_loop); } return command_list; } syslog-ng-syslog-ng-3.13.2/lib/control/control-commands.h000066400000000000000000000025741321171025300233230ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CONTROL_COMMANDS_H_INCLUDED #define CONTROL_COMMANDS_H_INCLUDED #include "control/control.h" #include "mainloop.h" void control_register_command(const gchar *command_name, const gchar *description, CommandFunction function, gpointer user_data); GList *control_register_default_commands(MainLoop *main_loop); GList *get_control_command_list(void); void reset_control_command_list(void); #endif syslog-ng-syslog-ng-3.13.2/lib/control/control-main.c000066400000000000000000000026471321171025300224420ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "control-main.h" #include "control-server.h" #include "control-commands.h" static ControlServer *control_server; void control_init(MainLoop *main_loop, const gchar *control_name) { control_server = control_server_new(control_name, control_register_default_commands(main_loop)); control_server_start(control_server); } void control_destroy(void) { control_server_free(control_server); } syslog-ng-syslog-ng-3.13.2/lib/control/control-main.h000066400000000000000000000023221321171025300224350ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CONTROL_MAIN_H_INCLUDED #define CONTROL_MAIN_H_INCLUDED #include "mainloop.h" #include "control/control-commands.h" void control_init(MainLoop *main_loop, const gchar *control_name); void control_destroy(void); #endif syslog-ng-syslog-ng-3.13.2/lib/control/control-server-unix.c000066400000000000000000000132501321171025300237750ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "gsocket.h" #include typedef struct _ControlServerUnix { ControlServer super; gint control_socket; struct iv_fd control_listen; } ControlServerUnix; typedef struct _ControlConnectionUnix { ControlConnection super; struct iv_fd control_io; gint fd; } ControlConnectionUnix; gint control_connection_unix_write(ControlConnection *s, gpointer buffer, gsize size) { ControlConnectionUnix *self = (ControlConnectionUnix *)s; return write(self->control_io.fd, buffer, size); } gint control_connection_unix_read(ControlConnection *s, gpointer buffer, gsize size) { ControlConnectionUnix *self = (ControlConnectionUnix *)s; return read(self->control_io.fd, buffer, size); } void control_connection_start_watches(ControlConnection *s) { ControlConnectionUnix *self = (ControlConnectionUnix *)s; IV_FD_INIT(&self->control_io); self->control_io.cookie = self; self->control_io.fd = self->fd; iv_fd_register(&self->control_io); control_connection_update_watches(s); } void control_connection_stop_watches(ControlConnection *s) { ControlConnectionUnix *self = (ControlConnectionUnix *)s; iv_fd_unregister(&self->control_io); } void control_connection_update_watches(ControlConnection *s) { ControlConnectionUnix *self = (ControlConnectionUnix *)s; if (s->output_buffer->len > s->pos) { iv_fd_set_handler_out(&self->control_io, s->handle_output); iv_fd_set_handler_in(&self->control_io, NULL); } else { iv_fd_set_handler_out(&self->control_io, NULL); iv_fd_set_handler_in(&self->control_io, s->handle_input); } } void control_connection_unix_free(ControlConnection *s) { ControlConnectionUnix *self = (ControlConnectionUnix *)s; close(self->control_io.fd); } ControlConnection * control_connection_new(ControlServer *server, gint sock) { ControlConnectionUnix *self = g_new0(ControlConnectionUnix, 1); control_connection_init_instance(&self->super, server); self->fd = sock; self->super.free_fn = control_connection_unix_free; self->super.read = control_connection_unix_read; self->super.write = control_connection_unix_write; control_connection_start_watches(&self->super); return &self->super; } static void control_socket_accept(void *cookie) { ControlServerUnix *self = (ControlServerUnix *)cookie; gint conn_socket; GSockAddr *peer_addr; GIOStatus status; if (self->control_socket == -1) return; status = g_accept(self->control_socket, &conn_socket, &peer_addr); if (status != G_IO_STATUS_NORMAL) { msg_error("Error accepting control socket connection", evt_tag_errno("error", errno)); goto error; } /* NOTE: the connection will free itself if the peer terminates */ control_connection_new(&self->super, conn_socket); g_sockaddr_unref(peer_addr); error: ; } void control_server_start(ControlServer *s) { ControlServerUnix *self = (ControlServerUnix *)s; GSockAddr *saddr; saddr = g_sockaddr_unix_new(self->super.control_socket_name); self->control_socket = socket(PF_UNIX, SOCK_STREAM, 0); if (self->control_socket == -1) { msg_error("Error opening control socket, external controls will not be available", evt_tag_str("socket", self->super.control_socket_name)); return; } if (g_bind(self->control_socket, saddr) != G_IO_STATUS_NORMAL) { msg_error("Error opening control socket, bind() failed", evt_tag_str("socket", self->super.control_socket_name), evt_tag_errno("error", errno)); goto error; } if (listen(self->control_socket, 255) < 0) { msg_error("Error opening control socket, listen() failed", evt_tag_str("socket", self->super.control_socket_name), evt_tag_errno("error", errno)); goto error; } self->control_listen.fd = self->control_socket; self->control_listen.cookie = self; iv_fd_register(&self->control_listen); iv_fd_set_handler_in(&self->control_listen, control_socket_accept); g_sockaddr_unref(saddr); return; error: if (self->control_socket != -1) { close(self->control_socket); self->control_socket = -1; } g_sockaddr_unref(saddr); return; } void control_server_unix_free(ControlServer *s) { ControlServerUnix *self = (ControlServerUnix *)s; if (iv_fd_registered(&self->control_listen)) { iv_fd_unregister(&self->control_listen); } if (self->control_socket != -1) { close(self->control_socket); } } ControlServer * control_server_new(const gchar *path, GList *commands) { ControlServerUnix *self = g_new(ControlServerUnix,1); control_server_init_instance(&self->super, path, commands); IV_FD_INIT(&self->control_listen); self->super.free_fn = control_server_unix_free; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/control/control-server.c000066400000000000000000000133321321171025300230150ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "control-server.h" #include "messages.h" #include "str-utils.h" #ifndef CONTROL_UNITTEST #include "control-server-unix.c" #endif #include #include void control_server_init_instance(ControlServer *self, const gchar *path, GList *control_commands) { self->control_socket_name = g_strdup(path); self->control_commands = control_commands; } void control_connection_free(ControlConnection *self) { if (self->free_fn) { self->free_fn(self); } g_string_free(self->output_buffer, TRUE); g_string_free(self->input_buffer, TRUE); g_free(self); } static void control_connection_send_reply(ControlConnection *self, GString *reply) { g_string_assign(self->output_buffer, reply->str); g_string_free(reply, TRUE); self->pos = 0; if (self->output_buffer->str[self->output_buffer->len - 1] != '\n') { g_string_append_c(self->output_buffer, '\n'); } g_string_append(self->output_buffer, ".\n"); control_connection_update_watches(self); } static void control_connection_io_output(gpointer s) { ControlConnection *self = (ControlConnection *) s; gint rc; rc = self->write(self, self->output_buffer->str + self->pos, self->output_buffer->len - self->pos); if (rc < 0) { if (errno != EAGAIN) { msg_error("Error writing control channel", evt_tag_errno("error", errno)); control_connection_stop_watches(self); control_connection_free(self); return; } } else { self->pos += rc; } control_connection_update_watches(self); } static void control_connection_io_input(void *s) { ControlConnection *self = (ControlConnection *) s; GString *command = NULL; GString *reply = NULL; gchar *nl; gint rc; gint orig_len; GList *iter; if (self->input_buffer->len > MAX_CONTROL_LINE_LENGTH) { /* too much data in input, drop the connection */ msg_error("Too much data in the control socket input buffer"); control_connection_stop_watches(self); control_connection_free(self); return; } orig_len = self->input_buffer->len; /* NOTE: plus one for the terminating NUL */ g_string_set_size(self->input_buffer, self->input_buffer->len + 128 + 1); rc = self->read(self, self->input_buffer->str + orig_len, 128); if (rc < 0) { if (errno != EAGAIN) { msg_error("Error reading command on control channel, closing control channel", evt_tag_errno("error", errno)); goto destroy_connection; } /* EAGAIN, should try again when data comes */ control_connection_update_watches(self); return; } else if (rc == 0) { msg_debug("EOF on control channel, closing connection"); goto destroy_connection; } else { self->input_buffer->len = orig_len + rc; self->input_buffer->str[self->input_buffer->len] = 0; } /* here we have finished reading the input, check if there's a newline somewhere */ nl = strchr(self->input_buffer->str, '\n'); if (nl) { command = g_string_sized_new(128); /* command doesn't contain NL */ g_string_assign_len(command, self->input_buffer->str, nl - self->input_buffer->str); /* strip NL */ /*g_string_erase(self->input_buffer, 0, command->len + 1);*/ g_string_truncate(self->input_buffer, 0); } else { /* no EOL in the input buffer, wait for more data */ control_connection_update_watches(self); return; } for (iter = self->server->control_commands; iter != NULL; iter = iter->next) { ControlCommand *cmd_desc = (ControlCommand *) iter->data; if (strncmp(cmd_desc->command_name, command->str, strlen(cmd_desc->command_name)) == 0) { reply = cmd_desc->func(command, cmd_desc->user_data); control_connection_send_reply(self, reply); break; } } if (iter == NULL) { msg_error("Unknown command read on control channel, closing control channel", evt_tag_str("command", command->str)); g_string_free(command, TRUE); goto destroy_connection; } control_connection_update_watches(self); g_string_free(command, TRUE); return; destroy_connection: control_connection_stop_watches(self); control_connection_free(self); } void control_connection_init_instance(ControlConnection *self, ControlServer *server) { self->server = server; self->output_buffer = g_string_sized_new(256); self->input_buffer = g_string_sized_new(128); self->handle_input = control_connection_io_input; self->handle_output = control_connection_io_output; return; } void control_server_free(ControlServer *self) { if (self->free_fn) { self->free_fn(self); } g_free(self->control_socket_name); g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/control/control-server.h000066400000000000000000000044351321171025300230260ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CONTROL_SERVER_H #define CONTROL_SERVER_H #include "syslog-ng.h" #include "control.h" #include #define MAX_CONTROL_LINE_LENGTH 4096 typedef struct _ControlServer ControlServer; typedef struct _ControlConnection ControlConnection; struct _ControlConnection { GString *input_buffer; GString *output_buffer; gsize pos; ControlServer *server; int (*read)(ControlConnection *self, gpointer buffer, gsize size); int (*write)(ControlConnection *self, gpointer buffer, gsize size); void (*handle_input)(gpointer s); void (*handle_output)(gpointer s); void (*free_fn)(ControlConnection *self); }; struct _ControlServer { gchar *control_socket_name; GList *control_commands; void (*free_fn)(ControlServer *self); }; ControlServer *control_server_new(const gchar *path, GList *control_commands); void control_server_start(ControlServer *self); void control_server_free(ControlServer *self); void control_server_init_instance(ControlServer *self, const gchar *path, GList *control_commands); void control_connection_start_watches(ControlConnection *self); void control_connection_update_watches(ControlConnection *self); void control_connection_stop_watches(ControlConnection *self); void control_connection_free(ControlConnection *self); void control_connection_init_instance(ControlConnection *self, ControlServer *server); #endif syslog-ng-syslog-ng-3.13.2/lib/control/control.h000066400000000000000000000024431321171025300215170ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CONTROL_H_INCLUDED #define CONTROL_H_INCLUDED #include "syslog-ng.h" typedef GString *(*CommandFunction)(GString *, gpointer user_data); typedef struct _ControlCommand { const gchar *command_name; const gchar *description; CommandFunction func; gpointer user_data; } ControlCommand; #endif syslog-ng-syslog-ng-3.13.2/lib/control/tests/000077500000000000000000000000001321171025300210255ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/control/tests/Makefile.am000066400000000000000000000012431321171025300230610ustar00rootroot00000000000000lib_control_tests_TESTS = \ lib/control/tests/test_control_cmds \ lib/control/tests/test_control_connection check_PROGRAMS += ${lib_control_tests_TESTS} lib_control_tests_test_control_cmds_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/control/tests lib_control_tests_test_control_cmds_LDADD = $(TEST_LDADD) lib_control_tests_test_control_cmds_SOURCES = \ lib/control/tests/test_control_cmds.c lib_control_tests_test_control_connection_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/control/tests lib_control_tests_test_control_connection_LDADD = $(TEST_LDADD) lib_control_tests_test_control_connection_SOURCES = \ lib/control/tests/test_control_connection.c syslog-ng-syslog-ng-3.13.2/lib/control/tests/test_control_cmds.c000066400000000000000000000113471321171025300247240ustar00rootroot00000000000000/* * Copyright (c) 2013-2015 Balabit * Copyright (c) 2013 Juhász Viktor * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "control/control-server.h" #include "control/control-commands.c" #include "stats/stats-control.c" #include "stats/stats-cluster.h" #include "stats/stats-registry.h" #include "apphook.h" void test_log(void) { GString *command = g_string_sized_new(128); GString *reply; g_string_assign(command,"LOG"); reply = control_connection_message_log(command, NULL); assert_string(reply->str, "Invalid arguments received, expected at least one argument", "Bad reply"); g_string_free(reply, TRUE); g_string_assign(command,"LOG fakelog"); reply = control_connection_message_log(command, NULL); assert_string(reply->str, "Invalid arguments received", "Bad reply"); g_string_free(reply, TRUE); verbose_flag = 0; debug_flag = 1; trace_flag = 1; g_string_assign(command,"LOG VERBOSE"); reply = control_connection_message_log(command, NULL); assert_string(reply->str, "VERBOSE=0", "Bad reply"); g_string_free(reply, TRUE); g_string_assign(command,"LOG VERBOSE ON"); reply = control_connection_message_log(command, NULL); assert_string(reply->str, "OK", "Bad reply"); assert_gint(verbose_flag,1,"Flag isn't changed"); g_string_free(reply, TRUE); g_string_assign(command,"LOG VERBOSE OFF"); reply = control_connection_message_log(command, NULL); assert_string(reply->str, "OK", "Bad reply"); assert_gint(verbose_flag,0,"Flag isn't changed"); g_string_free(reply, TRUE); debug_flag = 0; verbose_flag = 1; trace_flag = 1; g_string_assign(command,"LOG DEBUG"); reply = control_connection_message_log(command, NULL); assert_string(reply->str, "DEBUG=0", "Bad reply"); g_string_free(reply, TRUE); trace_flag = 0; verbose_flag = 1; debug_flag = 1; g_string_assign(command,"LOG TRACE"); reply = control_connection_message_log(command, NULL); assert_string(reply->str, "TRACE=0", "Bad reply"); g_string_free(reply, TRUE); g_string_free(command, TRUE); return; } void test_stats(void) { GString *reply = NULL; GString *command = g_string_sized_new(128); StatsCounterItem *counter = NULL; gchar **stats_result; stats_init(); stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_CENTER, "id", "received" ); stats_register_counter(0, &sc_key, SC_TYPE_PROCESSED, &counter); stats_unlock(); g_string_assign(command,"STATS"); reply = control_connection_send_stats(command, NULL); stats_result = g_strsplit(reply->str, "\n", 2); assert_string(stats_result[0], "SourceName;SourceId;SourceInstance;State;Type;Number", "Bad reply"); g_strfreev(stats_result); g_string_free(reply, TRUE); g_string_free(command, TRUE); stats_destroy(); return; } void test_reset_stats(void) { GString *reply = NULL; GString *command = g_string_sized_new(128); StatsCounterItem *counter = NULL; stats_init(); stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_CENTER, "id", "received" ); stats_register_counter(0, &sc_key, SC_TYPE_PROCESSED, &counter); stats_counter_set(counter, 666); stats_unlock(); g_string_assign(command, "RESET_STATS"); reply = control_connection_reset_stats(command, NULL); assert_string(reply->str, "The statistics of syslog-ng have been reset to 0.", "Bad reply"); g_string_free(reply, TRUE); g_string_assign(command, "STATS"); reply = control_connection_send_stats(command, NULL); assert_string(reply->str, "SourceName;SourceId;SourceInstance;State;Type;Number\ncenter;id;received;a;processed;0\n", "Bad reply"); g_string_free(reply, TRUE); stats_destroy(); g_string_free(command, TRUE); return; } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { msg_init(FALSE); test_log(); test_stats(); test_reset_stats(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/control/tests/test_control_connection.c000066400000000000000000000125541321171025300261360ustar00rootroot00000000000000/* * Copyright (c) 2013-2014 Balabit * Copyright (c) 2013 Juhász Viktor * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "control/control.h" #include "control/control-server.h" #include "apphook.h" #define CONTROL_UNITTEST 1 #include "control/control-server.c" #undef CONTROL_UNITTEST typedef struct _PositionedBuffer { GString *buffer; gint pos; } PositionedBuffer; typedef struct _ControlConnectionMoc { ControlConnection super; PositionedBuffer *source_buffer; PositionedBuffer *destination_buffer; gsize transaction_size; } ControlConnectionMoc; ControlServer moc_server = {0}; ControlConnectionMoc *moc_connection; GString *result_string; void (*next_step)(gpointer s); PositionedBuffer * positioned_buffer_new(gsize size) { PositionedBuffer *self = g_new0(PositionedBuffer,1); self->buffer = g_string_sized_new(size); return self; } void positioned_buffer_free(PositionedBuffer *self) { g_string_free(self->buffer, TRUE); g_free(self); } int control_connection_moc_read(ControlConnection *s, gpointer buffer, gsize size) { ControlConnectionMoc *self = (ControlConnectionMoc *)s; gsize bytes_to_read; if (self->source_buffer->pos >= self->source_buffer->buffer->len) { return 0; } if (self->transaction_size > 0) { bytes_to_read = MIN(self->transaction_size, size); bytes_to_read = MIN(self->source_buffer->buffer->len - self->source_buffer->pos, bytes_to_read); } else { bytes_to_read = MIN(self->source_buffer->buffer->len - self->source_buffer->pos, size); } memcpy(buffer, self->source_buffer->buffer->str + self->source_buffer->pos, bytes_to_read); self->source_buffer->pos += bytes_to_read; return bytes_to_read; } int control_connection_moc_write(ControlConnection *s, gpointer buffer, gsize size) { ControlConnectionMoc *self = (ControlConnectionMoc *)s; gsize bytes_to_write; if (self->transaction_size > 0) { bytes_to_write = self->transaction_size; } else { bytes_to_write = size; } g_string_append_len(self->destination_buffer->buffer, buffer, bytes_to_write); return bytes_to_write; } void control_connection_moc_free(ControlConnection *s) { ControlConnectionMoc *self = (ControlConnectionMoc *)s; positioned_buffer_free(self->source_buffer); positioned_buffer_free(self->destination_buffer); } ControlConnection * control_connection_moc_new(ControlServer *server) { ControlConnectionMoc *self = g_new0(ControlConnectionMoc,1); control_connection_init_instance(&self->super, server); self->source_buffer = positioned_buffer_new(128); self->destination_buffer = positioned_buffer_new(128); self->super.read = control_connection_moc_read; self->super.write = control_connection_moc_write; self->super.free_fn = control_connection_moc_free; return &self->super; } GString * test_command(GString *command, gpointer user_data) { assert_string(command->str,"test command", "Bad command handling"); return g_string_new("OK"); } ControlCommand command = { .command_name = "test", .description = NULL, .func = test_command }; void control_connection_update_watches(ControlConnection *s) { if (s->output_buffer->len > s->pos) { next_step = s->handle_output; } else { next_step = s->handle_input; } } void control_connection_stop_watches(ControlConnection *s) { ControlConnectionMoc *self = (ControlConnectionMoc *)s; if (result_string) { g_string_free(result_string, TRUE); result_string = NULL; } result_string = g_string_new(self->destination_buffer->buffer->str); next_step = NULL; } void control_connection_start_watches(ControlConnection *s) { next_step = s->handle_input; while(next_step) { next_step(s); } } void test_control_connection(gsize transaction_size) { moc_connection = (ControlConnectionMoc *)control_connection_moc_new(&moc_server); g_string_assign(moc_connection->source_buffer->buffer,"test command\n"); moc_connection->transaction_size = transaction_size; control_connection_start_watches((ControlConnection *)moc_connection); assert_string(result_string->str, "OK\n.\n", "BAD Behaviour transaction_size: %d",transaction_size); } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { GList *commands = g_list_append(NULL, &command); moc_server.control_commands = commands; gsize i = 0; app_startup(); for (i = 0; i < 100; i++) { test_control_connection(i); } app_shutdown(); g_list_free(commands); return 0; } syslog-ng-syslog-ng-3.13.2/lib/crypto.c000066400000000000000000000044551321171025300176770ustar00rootroot00000000000000/* * Copyright (c) 2011-2015 Balabit * Copyright (c) 2011-2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ /* This file becomes part of libsyslog-ng-crypto.so, the shared object * that contains all crypto related stuff to be used by plugins. This * includes the TLS wrappers, random number initialization, and so on. */ #include "crypto.h" #include "apphook.h" #include "thread-utils.h" #include "compat/openssl_support.h" #include #include #include #include #include static gboolean randfile_loaded; void crypto_deinit(void) { char rnd_file[256]; if (randfile_loaded) { RAND_file_name(rnd_file, sizeof(rnd_file)); if (rnd_file[0]) RAND_write_file(rnd_file); } #if OPENSSL_VERSION_NUMBER < 0x10100000L ERR_free_strings(); EVP_cleanup(); #endif openssl_crypto_deinit_threading(); } void crypto_init(void) { openssl_init(); openssl_crypto_init_threading(); if (RAND_status() < 0 || getenv("RANDFILE")) { char rnd_file[256]; RAND_file_name(rnd_file, sizeof(rnd_file)); if (rnd_file[0]) { RAND_load_file(rnd_file, -1); randfile_loaded = TRUE; } if (RAND_status() < 0) fprintf(stderr, "WARNING: a trusted random number source is not available, crypto operations will probably fail. Please set the RANDFILE environment variable."); } } syslog-ng-syslog-ng-3.13.2/lib/crypto.h000066400000000000000000000021611321171025300176740ustar00rootroot00000000000000/* * Copyright (c) 2011-2015 Balabit * Copyright (c) 2011-2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #ifndef CRYPTO_H_INCLUDED #define CRYPTO_H_INCLUDED #include "syslog-ng.h" void crypto_init(void); void crypto_deinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/debugger/000077500000000000000000000000001321171025300177675ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/debugger/CMakeLists.txt000066400000000000000000000003451321171025300225310ustar00rootroot00000000000000set(DEBUGGER_HEADERS debugger/debugger.h debugger/tracer.h debugger/debugger-main.h PARENT_SCOPE) set(DEBUGGER_SOURCES debugger/debugger.c debugger/tracer.c debugger/debugger-main.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/debugger/Makefile.am000066400000000000000000000004641321171025300220270ustar00rootroot00000000000000debuggerincludedir = ${pkgincludedir}/debugger debuggerinclude_HEADERS = \ lib/debugger/debugger.h \ lib/debugger/tracer.h \ lib/debugger/debugger-main.h debugger_sources = \ lib/debugger/debugger.c \ lib/debugger/tracer.c \ lib/debugger/debugger-main.c include lib/debugger/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/debugger/debugger-main.c000066400000000000000000000030021321171025300226340ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "debugger/debugger.h" #include "logpipe.h" static Debugger *current_debugger; static gboolean _pipe_hook(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options) { return debugger_stop_at_breakpoint(current_debugger, s, msg); } void debugger_start(MainLoop *main_loop, GlobalConfig *cfg) { /* we don't support threaded mode (yet), force it to non-threaded */ cfg->threaded = FALSE; current_debugger = debugger_new(main_loop, cfg); pipe_single_step_hook = _pipe_hook; debugger_start_console(current_debugger); } syslog-ng-syslog-ng-3.13.2/lib/debugger/debugger-main.h000066400000000000000000000022601321171025300226460ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DEBUGGER_DEBUGGER_MAIN_H_INCLUDED #define DEBUGGER_DEBUGGER_MAIN_H_INCLUDED 1 #include "debugger/debugger.h" #include "cfg.h" void debugger_start(MainLoop *main_loop, GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/lib/debugger/debugger.c000066400000000000000000000213621321171025300217230ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "debugger/debugger.h" #include "debugger/tracer.h" #include "logmsg/logmsg.h" #include "logpipe.h" #include "mainloop.h" #include #include struct _Debugger { Tracer *tracer; MainLoop *main_loop; GlobalConfig *cfg; gchar *command_buffer; LogTemplate *display_template; LogMessage *current_msg; LogPipe *current_pipe; gboolean drop_current_message; }; static gboolean _format_nvpair(NVHandle handle, const gchar *name, const gchar *value, gssize length, gpointer user_data) { printf("%s=%.*s\n", name, (gint) length, value); return FALSE; } static void _display_msg_details(Debugger *self, LogMessage *msg) { GString *output = g_string_sized_new(128); log_msg_values_foreach(msg, _format_nvpair, NULL); g_string_truncate(output, 0); log_msg_print_tags(msg, output); printf("TAGS=%s\n", output->str); printf("\n"); g_string_free(output, TRUE); } static void _display_msg_with_template(Debugger *self, LogMessage *msg, LogTemplate *template) { GString *output = g_string_sized_new(128); log_template_format(template, msg, NULL, LTZ_LOCAL, 0, NULL, output); printf("%s\n", output->str); g_string_free(output, TRUE); } static gboolean _display_msg_with_template_string(Debugger *self, LogMessage *msg, const gchar *template_string, GError **error) { LogTemplate *template; template = log_template_new(self->cfg, NULL); if (!log_template_compile(template, template_string, error)) { return FALSE; } _display_msg_with_template(self, msg, template); log_template_unref(template); return TRUE; } static void _display_source_line(LogExprNode *expr_node) { FILE *f; gint lineno = 1; gchar buf[1024]; if (!expr_node || !expr_node->filename) return; f = fopen(expr_node->filename, "r"); if (f) { while (fgets(buf, sizeof(buf), f) && lineno < expr_node->line) lineno++; if (lineno != expr_node->line) buf[0] = 0; fclose(f); } else { buf[0] = 0; } printf("%-8d %s", expr_node->line, buf); if (buf[0] == 0 || buf[strlen(buf) - 1] != '\n') putc('\n', stdout); fflush(stdout); } static gboolean _cmd_help(Debugger *self, gint argc, gchar *argv[]) { printf("syslog-ng interactive console, the following commands are available\n\n" " help, h, or ? Display this help\n" " continue or c Continue until the next breakpoint\n" " print, p Print the current log message\n" " drop, d Drop the current message\n" " quit, q Tell syslog-ng to exit\n" ); return TRUE; } static gboolean _cmd_continue(Debugger *self, gint argc, gchar *argv[]) { return FALSE; } static gboolean _cmd_print(Debugger *self, gint argc, gchar *argv[]) { if (argc == 1) _display_msg_details(self, self->current_msg); else if (argc == 2) { GError *error = NULL; if (!_display_msg_with_template_string(self, self->current_msg, argv[1], &error)) { printf("print: %s\n", error->message); g_clear_error(&error); } } else printf("print: expected no arguments or exactly one\n"); return TRUE; } static gboolean _cmd_display(Debugger *self, gint argc, gchar *argv[]) { if (argc == 2) { GError *error = NULL; if (!log_template_compile(self->display_template, argv[1], &error)) { printf("display: Error compiling template: %s\n", error->message); g_clear_error(&error); return TRUE; } } printf("display: The template is set to: \"%s\"\n", self->display_template->template); return TRUE; } static gboolean _cmd_drop(Debugger *self, gint argc, gchar *argv[]) { self->drop_current_message = TRUE; return FALSE; } static gboolean _cmd_quit(Debugger *self, gint argc, gchar *argv[]) { main_loop_exit(self->main_loop); self->drop_current_message = TRUE; return FALSE; } typedef gboolean (*DebuggerCommandFunc)(Debugger *self, gint argc, gchar *argv[]); struct { const gchar *name; DebuggerCommandFunc command; } command_table[] = { { "help", _cmd_help }, { "h", _cmd_help }, { "?", _cmd_help }, { "continue", _cmd_continue }, { "c", _cmd_continue }, { "print", _cmd_print }, { "p", _cmd_print }, { "display", _cmd_display }, { "drop", _cmd_drop }, { "quit", _cmd_quit }, { "q", _cmd_quit }, { NULL, NULL } }; gchar * debugger_builtin_fetch_command(void) { gchar buf[1024]; gsize len; printf("(syslog-ng) "); fflush(stdout); if (!fgets(buf, sizeof(buf), stdin)) return NULL; /* strip NL */ len = strlen(buf); if (buf[len - 1] == '\n') { buf[len - 1] = 0; } return g_strdup(buf); } FetchCommandFunc fetch_command_func = debugger_builtin_fetch_command; void debugger_register_command_fetcher(FetchCommandFunc fetcher) { fetch_command_func = fetcher; } static void _fetch_command(Debugger *self) { gchar *command; command = fetch_command_func(); if (command && strlen(command) > 0) { if (self->command_buffer) g_free(self->command_buffer); self->command_buffer = command; } else { if (command) g_free(command); } } static gboolean _handle_command(Debugger *self) { gint i; gint argc; gchar **argv; GError *error = NULL; gboolean result = TRUE; DebuggerCommandFunc command = NULL; if (!g_shell_parse_argv(self->command_buffer ? : "", &argc, &argv, &error)) { printf("%s\n", error->message); g_clear_error(&error); return TRUE; } for (i = 0; command_table[i].name; i++) { if (strcmp(command_table[i].name, argv[0]) == 0) { command = command_table[i].command; break; } } if (!command) { printf("Undefined command %s, try \"help\"\n", argv[0]); return TRUE; } result = command(self, argc, argv); g_strfreev(argv); return result; } static void _handle_interactive_prompt(Debugger *self) { gchar buf[1024]; LogPipe *current_pipe = self->current_pipe; printf("Breakpoint hit %s\n", log_expr_node_format_location(current_pipe->expr_node, buf, sizeof(buf))); _display_source_line(current_pipe->expr_node); _display_msg_with_template(self, self->current_msg, self->display_template); while (1) { _fetch_command(self); if (!_handle_command(self)) break; } printf("(continuing)\n"); } static gpointer _interactive_console_thread_func(Debugger *self) { printf("Waiting for breakpoint...\n"); while (1) { tracer_wait_for_breakpoint(self->tracer); _handle_interactive_prompt(self); tracer_resume_after_breakpoint(self->tracer); } return NULL; } void debugger_start_console(Debugger *self) { g_thread_create((GThreadFunc) _interactive_console_thread_func, self, FALSE, NULL); } gboolean debugger_stop_at_breakpoint(Debugger *self, LogPipe *pipe_, LogMessage *msg) { self->drop_current_message = FALSE; self->current_msg = log_msg_ref(msg); self->current_pipe = log_pipe_ref(pipe_); tracer_stop_on_breakpoint(self->tracer); log_msg_unref(self->current_msg); log_pipe_unref(self->current_pipe); self->current_msg = NULL; self->current_pipe = NULL; return !self->drop_current_message; } Debugger * debugger_new(MainLoop *main_loop, GlobalConfig *cfg) { Debugger *self = g_new0(Debugger, 1); self->main_loop = main_loop; self->tracer = tracer_new(cfg); self->cfg = cfg; self->display_template = log_template_new(cfg, NULL); self->command_buffer = g_strdup("help"); log_template_compile(self->display_template, "$DATE $HOST $MSGHDR$MSG", NULL); return self; } void debugger_free(Debugger *self) { log_template_unref(self->display_template); tracer_free(self->tracer); g_free(self->command_buffer); g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/debugger/debugger.h000066400000000000000000000030341321171025300217240ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DEBUGGER_DEBUGGER_H_INCLUDED #define DEBUGGER_DEBUGGER_H_INCLUDED 1 #include "syslog-ng.h" #include "cfg.h" #include "mainloop.h" typedef struct _Debugger Debugger; typedef gchar *(*FetchCommandFunc)(void); Debugger *debugger_new(MainLoop *main_loop, GlobalConfig *cfg); void debugger_free(Debugger *self); gchar *debugger_builtin_fetch_command(void); void debugger_register_command_fetcher(FetchCommandFunc fetcher); void debugger_start_console(Debugger *self); gboolean debugger_stop_at_breakpoint(Debugger *self, LogPipe *pipe, LogMessage *msg); #endif syslog-ng-syslog-ng-3.13.2/lib/debugger/tests/000077500000000000000000000000001321171025300211315ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/debugger/tests/Makefile.am000066400000000000000000000005401321171025300231640ustar00rootroot00000000000000lib_debugger_tests_TESTS = \ lib/debugger/tests/test_debugger check_PROGRAMS += ${lib_debugger_tests_TESTS} lib_debugger_tests_test_debugger_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/debugger/tests lib_debugger_tests_test_debugger_LDADD = $(TEST_LDADD) lib_debugger_tests_test_debugger_SOURCES = \ lib/debugger/tests/test-debugger.c syslog-ng-syslog-ng-3.13.2/lib/debugger/tests/test-debugger.c000066400000000000000000000025141321171025300240400ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "debugger/debugger.h" #include "apphook.h" void test_debugger(void) { MainLoop *main_loop = main_loop_get_instance(); Debugger *debugger = debugger_new(main_loop, configuration); debugger_free(debugger); } int main(void) { app_startup(); configuration = cfg_new_snippet(); test_debugger(); cfg_free(configuration); } syslog-ng-syslog-ng-3.13.2/lib/debugger/tracer.c000066400000000000000000000043131321171025300214140ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "debugger/tracer.h" void tracer_stop_on_breakpoint(Tracer *self) { g_mutex_lock(self->breakpoint_mutex); /* send break point */ self->breakpoint_hit = TRUE; g_cond_signal(self->breakpoint_cond); /* wait for resume */ while (!self->resume_requested) g_cond_wait(self->resume_cond, self->breakpoint_mutex); self->resume_requested = FALSE; g_mutex_unlock(self->breakpoint_mutex); } void tracer_wait_for_breakpoint(Tracer *self) { g_mutex_lock(self->breakpoint_mutex); while (!self->breakpoint_hit) g_cond_wait(self->breakpoint_cond, self->breakpoint_mutex); self->breakpoint_hit = FALSE; g_mutex_unlock(self->breakpoint_mutex); } void tracer_resume_after_breakpoint(Tracer *self) { g_mutex_lock(self->breakpoint_mutex); self->resume_requested = TRUE; g_cond_signal(self->resume_cond); g_mutex_unlock(self->breakpoint_mutex); } Tracer * tracer_new(GlobalConfig *cfg) { Tracer *self = g_new0(Tracer, 1); self->breakpoint_mutex = g_mutex_new(); self->breakpoint_cond = g_cond_new(); self->resume_cond = g_cond_new(); return self; } void tracer_free(Tracer *self) { g_mutex_free(self->breakpoint_mutex); g_cond_free(self->breakpoint_cond); g_cond_free(self->resume_cond); g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/debugger/tracer.h000066400000000000000000000027131321171025300214230ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DEBUGGER_TRACER_H_INCLUDED #define DEBUGGER_TRACER_H_INCLUDED 1 #include "syslog-ng.h" typedef struct _Tracer { GMutex *breakpoint_mutex; GCond *breakpoint_cond; GCond *resume_cond; gboolean breakpoint_hit; gboolean resume_requested; } Tracer; void tracer_stop_on_breakpoint(Tracer *self); void tracer_wait_for_breakpoint(Tracer *self); void tracer_resume_after_breakpoint(Tracer *self); Tracer *tracer_new(GlobalConfig *cfg); void tracer_free(Tracer *self); #endif syslog-ng-syslog-ng-3.13.2/lib/dnscache.c000066400000000000000000000315261321171025300201260ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "dnscache.h" #include "messages.h" #include "timeutils.h" #include "tls-support.h" #include #include #include #include #include #include #include #include #include #include typedef struct _DNSCacheEntry DNSCacheEntry; typedef struct _DNSCacheKey DNSCacheKey; struct _DNSCacheKey { gint family; union { struct in_addr ip; #if SYSLOG_NG_ENABLE_IPV6 struct in6_addr ip6; #endif } addr; }; struct _DNSCacheEntry { struct iv_list_head list; DNSCacheKey key; time_t resolved; gchar *hostname; gsize hostname_len; /* whether this entry is a positive (successful DNS lookup) or negative (failed DNS lookup, contains an IP address) match */ gboolean positive; }; struct _DNSCache { GHashTable *cache; const DNSCacheOptions *options; struct iv_list_head cache_list; struct iv_list_head persist_list; gint persistent_count; time_t hosts_mtime; time_t hosts_checktime; }; static gboolean dns_cache_key_equal(DNSCacheKey *e1, DNSCacheKey *e2) { if (e1->family == e2->family) { if ((e1->family == AF_INET && memcmp(&e1->addr.ip, &e2->addr.ip, sizeof(e1->addr.ip)) == 0)) return TRUE; #if SYSLOG_NG_ENABLE_IPV6 if ((e1->family == AF_INET6 && memcmp(&e1->addr.ip6, &e2->addr.ip6, sizeof(e1->addr.ip6)) == 0)) return TRUE; #endif } return FALSE; } static guint dns_cache_key_hash(DNSCacheKey *e) { if (e->family == AF_INET) { return ntohl(e->addr.ip.s_addr); } #if SYSLOG_NG_ENABLE_IPV6 else if (e->family == AF_INET6) { guint32 *a32 = (guint32 *) &e->addr.ip6.s6_addr; return (0x80000000 | (a32[0] ^ a32[1] ^ a32[2] ^ a32[3])); } #endif else { g_assert_not_reached(); return 0; } } static void dns_cache_entry_free(DNSCacheEntry *e) { iv_list_del(&e->list); g_free(e->hostname); g_free(e); } static inline void dns_cache_fill_key(DNSCacheKey *key, gint family, void *addr) { key->family = family; switch (family) { case AF_INET: key->addr.ip = *(struct in_addr *) addr; break; #if SYSLOG_NG_ENABLE_IPV6 case AF_INET6: key->addr.ip6 = *(struct in6_addr *) addr; break; #endif default: g_assert_not_reached(); break; } } static void dns_cache_store(DNSCache *self, gboolean persistent, gint family, void *addr, const gchar *hostname, gboolean positive) { DNSCacheEntry *entry; guint hash_size; entry = g_new(DNSCacheEntry, 1); dns_cache_fill_key(&entry->key, family, addr); entry->hostname = g_strdup(hostname); entry->hostname_len = strlen(hostname); entry->positive = positive; INIT_IV_LIST_HEAD(&entry->list); if (!persistent) { entry->resolved = cached_g_current_time_sec(); iv_list_add(&entry->list, &self->cache_list); } else { entry->resolved = 0; iv_list_add(&entry->list, &self->persist_list); } hash_size = g_hash_table_size(self->cache); g_hash_table_replace(self->cache, &entry->key, entry); if (persistent && hash_size != g_hash_table_size(self->cache)) self->persistent_count++; /* persistent elements are not counted */ if ((gint) (g_hash_table_size(self->cache) - self->persistent_count) > self->options->cache_size) { DNSCacheEntry *entry_to_remove = iv_list_entry(self->cache_list.next, DNSCacheEntry, list); /* remove oldest element */ g_hash_table_remove(self->cache, &entry_to_remove->key); } } void dns_cache_store_persistent(DNSCache *self, gint family, void *addr, const gchar *hostname) { dns_cache_store(self, TRUE, family, addr, hostname, TRUE); } void dns_cache_store_dynamic(DNSCache *self, gint family, void *addr, const gchar *hostname, gboolean positive) { dns_cache_store(self, FALSE, family, addr, hostname, positive); } static void dns_cache_cleanup_persistent_hosts(DNSCache *self) { struct iv_list_head *ilh, *ilh2; iv_list_for_each_safe(ilh, ilh2, &self->persist_list) { DNSCacheEntry *entry = iv_list_entry(ilh, DNSCacheEntry, list); g_hash_table_remove(self->cache, &entry->key); self->persistent_count--; } } static void dns_cache_check_hosts(DNSCache *self, glong t) { struct stat st; if (G_LIKELY(self->hosts_checktime == t)) return; self->hosts_checktime = t; if (!self->options->hosts || stat(self->options->hosts, &st) < 0) { dns_cache_cleanup_persistent_hosts(self); return; } if (self->hosts_mtime == -1 || st.st_mtime > self->hosts_mtime) { FILE *hosts; self->hosts_mtime = st.st_mtime; dns_cache_cleanup_persistent_hosts(self); hosts = fopen(self->options->hosts, "r"); if (hosts) { gchar buf[4096]; char *strtok_saveptr; while (fgets(buf, sizeof(buf), hosts)) { gchar *p, *ip; gint len; gint family; union { struct in_addr ip4; #if SYSLOG_NG_ENABLE_IPV6 struct in6_addr ip6; #endif } ia; if (buf[0] == 0 || buf[0] == '\n' || buf[0] == '#') continue; len = strlen(buf); if (buf[len - 1] == '\n') buf[len-1] = 0; p = strtok_r(buf, " \t", &strtok_saveptr); if (!p) continue; ip = p; #if SYSLOG_NG_ENABLE_IPV6 if (strchr(ip, ':') != NULL) family = AF_INET6; else #endif family = AF_INET; p = strtok_r(NULL, " \t", &strtok_saveptr); if (!p) continue; inet_pton(family, ip, &ia); dns_cache_store_persistent(self, family, &ia, p); } fclose(hosts); } else { msg_error("Error loading dns cache hosts file", evt_tag_str("filename", self->options->hosts), evt_tag_errno("error", errno)); } } } /* * @hostname is set to the stored hostname, * @positive is set whether the match was a DNS match or failure * * Returns TRUE if the cache was able to serve the request (e.g. had a * matching entry at all). */ gboolean dns_cache_lookup(DNSCache *self, gint family, void *addr, const gchar **hostname, gsize *hostname_len, gboolean *positive) { DNSCacheKey key; DNSCacheEntry *entry; time_t now; now = cached_g_current_time_sec(); dns_cache_check_hosts(self, now); dns_cache_fill_key(&key, family, addr); entry = g_hash_table_lookup(self->cache, &key); if (entry) { if (entry->resolved && ((entry->positive && entry->resolved < now - self->options->expire) || (!entry->positive && entry->resolved < now - self->options->expire_failed))) { /* the entry is not persistent and is too old */ } else { *hostname = entry->hostname; *hostname_len = entry->hostname_len; *positive = entry->positive; return TRUE; } } *hostname = NULL; *positive = FALSE; return FALSE; } DNSCache * dns_cache_new(const DNSCacheOptions *options) { DNSCache *self = g_new0(DNSCache, 1); self->cache = g_hash_table_new_full((GHashFunc) dns_cache_key_hash, (GEqualFunc) dns_cache_key_equal, NULL, (GDestroyNotify) dns_cache_entry_free); INIT_IV_LIST_HEAD(&self->cache_list); INIT_IV_LIST_HEAD(&self->persist_list); self->hosts_mtime = -1; self->hosts_checktime = 0; self->persistent_count = 0; self->options = options; return self; } void dns_cache_free(DNSCache *self) { g_hash_table_destroy(self->cache); g_free(self); } void dns_cache_options_defaults(DNSCacheOptions *options) { options->cache_size = 1007; options->expire = 3600; options->expire_failed = 60; options->hosts = NULL; } void dns_cache_options_destroy(DNSCacheOptions *options) { g_free(options->hosts); options->hosts = NULL; } /************************************************************************** * The global API that manages DNSCache instances on its own. Callers need * not be aware of underlying data structures and locking, they can simply * call these functions to lookup/query the DNS cache. * * I would prefer these to be moved into a higher level implementation * detail. **************************************************************************/ TLS_BLOCK_START { DNSCache *dns_cache; } TLS_BLOCK_END; #define dns_cache __tls_deref(dns_cache) /* DNS cache related options are global, independent of the configuration * (e.g. GlobalConfig instance), and they are stored in the * "effective_dns_cache_options" variable below. * * The reasons for using the global variable are as explained below. * * Some notes: * 1) DNS cache contents are better retained between configuration reloads * 2) There are multiple DNSCache instances as they are per-thread data structs. * * The usual pattern would be: * DNSCache->options -> DNSCacheOptions * * And options would be a reference and would point inside a DNSCacheOptions * instance contained within the GlobalConfig. * * The problem with this approach is that we don't want to recreate DNSCache * instances when reloading the configuration (as we want to keep their * config), and this would mean that we'd have to update the "options" * pointers in each of the existing instances. And those instances are * per-thread variables, making it a bit more difficult to track them. * * For this reason, it was a lot simpler to use a global variable to hold * configuration options, one that can be updated as the configuration is * reloaded. Then DNSCache instances transparently take the options changes * into account as they continue to resolve names. * * I could come up with even better solutions to this problem (like using a * layer above GlobalConfig, a state that encapsulates per-execution state * of syslog-ng), however, right now that would be an overkill and I want to * get the DNSCache refactors into the master tree. */ static DNSCacheOptions effective_dns_cache_options; G_LOCK_DEFINE_STATIC(unused_dns_caches); static GList *unused_dns_caches; gboolean dns_caching_lookup(gint family, void *addr, const gchar **hostname, gsize *hostname_len, gboolean *positive) { return dns_cache_lookup(dns_cache, family, addr, hostname, hostname_len, positive); } void dns_caching_store(gint family, void *addr, const gchar *hostname, gboolean positive) { dns_cache_store_dynamic(dns_cache, family, addr, hostname, positive); } void dns_caching_update_options(const DNSCacheOptions *new_options) { DNSCacheOptions *options = &effective_dns_cache_options; if (options->hosts) g_free(options->hosts); options->cache_size = new_options->cache_size; options->expire = new_options->expire; options->expire_failed = new_options->expire_failed; options->hosts = g_strdup(new_options->hosts); } void dns_caching_thread_init(void) { g_assert(dns_cache == NULL); G_LOCK(unused_dns_caches); if (unused_dns_caches) { dns_cache = unused_dns_caches->data; unused_dns_caches = g_list_delete_link(unused_dns_caches, unused_dns_caches); } G_UNLOCK(unused_dns_caches); if (!dns_cache) dns_cache = dns_cache_new(&effective_dns_cache_options); } void dns_caching_thread_deinit(void) { g_assert(dns_cache != NULL); G_LOCK(unused_dns_caches); unused_dns_caches = g_list_prepend(unused_dns_caches, dns_cache); G_UNLOCK(unused_dns_caches); dns_cache = NULL; } void dns_caching_global_init(void) { dns_cache_options_defaults(&effective_dns_cache_options); } void dns_caching_global_deinit(void) { G_LOCK(unused_dns_caches); g_list_foreach(unused_dns_caches, (GFunc) dns_cache_free, NULL); g_list_free(unused_dns_caches); unused_dns_caches = NULL; G_UNLOCK(unused_dns_caches); dns_cache_options_destroy(&effective_dns_cache_options); } syslog-ng-syslog-ng-3.13.2/lib/dnscache.h000066400000000000000000000042671321171025300201350ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DNSCACHE_H_INCLUDED #define DNSCACHE_H_INCLUDED #include "syslog-ng.h" typedef struct { gint cache_size; gint expire; gint expire_failed; gchar *hosts; } DNSCacheOptions; typedef struct _DNSCache DNSCache; void dns_cache_store_persistent(DNSCache *self, gint family, void *addr, const gchar *hostname); void dns_cache_store_dynamic(DNSCache *self, gint family, void *addr, const gchar *hostname, gboolean positive); gboolean dns_cache_lookup(DNSCache *self, gint family, void *addr, const gchar **hostname, gsize *hostname_len, gboolean *positive); DNSCache *dns_cache_new(const DNSCacheOptions *options); void dns_cache_free(DNSCache *self); void dns_cache_options_defaults(DNSCacheOptions *options); void dns_cache_options_destroy(DNSCacheOptions *options); gboolean dns_caching_lookup(gint family, void *addr, const gchar **hostname, gsize *hostname_len, gboolean *positive); void dns_caching_store(gint family, void *addr, const gchar *hostname, gboolean positive); void dns_caching_update_options(const DNSCacheOptions *dns_cache_options); void dns_caching_thread_init(void); void dns_caching_thread_deinit(void); void dns_caching_global_init(void); void dns_caching_global_deinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/driver.c000066400000000000000000000223321321171025300176440ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "driver.h" #include "logqueue-fifo.h" #include "afinter.h" #include "cfg-tree.h" #include /* LogDriverPlugin */ void log_driver_plugin_free_method(LogDriverPlugin *self) { g_free(self); } void log_driver_plugin_init_instance(LogDriverPlugin *self) { self->free_fn = log_driver_plugin_free_method; } /* LogDriver */ void log_driver_add_plugin(LogDriver *self, LogDriverPlugin *plugin) { self->plugins = g_list_append(self->plugins, plugin); } gboolean log_driver_init_method(LogPipe *s) { LogDriver *self = (LogDriver *) s; gboolean success = TRUE; GList *l; for (l = self->plugins; l; l = l->next) { if (!log_driver_plugin_attach((LogDriverPlugin *) l->data, self)) success = FALSE; } return success; } gboolean log_driver_deinit_method(LogPipe *s) { LogDriver *self = (LogDriver *) s; gboolean success = TRUE; GList *l; for (l = self->plugins; l; l = l->next) { log_driver_plugin_detach((LogDriverPlugin *) l->data, self); } return success; } /* NOTE: intentionally static, as only cDriver or LogDestDriver will derive from LogDriver */ static void log_driver_free(LogPipe *s) { LogDriver *self = (LogDriver *) s; GList *l; for (l = self->plugins; l; l = l->next) { log_driver_plugin_free((LogDriverPlugin *) l->data); } if (self->plugins) { g_list_free(self->plugins); } if (self->group) g_free(self->group); if (self->id) g_free(self->id); log_pipe_free_method(s); } /* NOTE: intentionally static, as only LogSrcDriver or LogDestDriver will derive from LogDriver */ static void log_driver_init_instance(LogDriver *self, GlobalConfig *cfg) { log_pipe_init_instance(&self->super, cfg); self->super.free_fn = log_driver_free; self->super.init = log_driver_init_method; self->super.deinit = log_driver_deinit_method; } /* LogSrcDriver */ gboolean log_src_driver_init_method(LogPipe *s) { LogSrcDriver *self = (LogSrcDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_driver_init_method(s)) return FALSE; if (!self->super.group) { self->super.group = cfg_tree_get_rule_name(&cfg->tree, ENC_SOURCE, s->expr_node); self->group_len = strlen(self->super.group); self->super.id = cfg_tree_get_child_id(&cfg->tree, ENC_SOURCE, s->expr_node); } stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_SOURCE | SCS_GROUP, self->super.group, NULL ); stats_register_counter(0, &sc_key, SC_TYPE_PROCESSED, &self->super.processed_group_messages); stats_cluster_logpipe_key_set(&sc_key, SCS_CENTER, NULL, "received" ); stats_register_counter(0, &sc_key, SC_TYPE_PROCESSED, &self->received_global_messages); stats_unlock(); return TRUE; } gboolean log_src_driver_deinit_method(LogPipe *s) { LogSrcDriver *self = (LogSrcDriver *) s; if (!log_driver_deinit_method(s)) return FALSE; stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_SOURCE | SCS_GROUP, self->super.group, NULL ); stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &self->super.processed_group_messages); stats_cluster_logpipe_key_set(&sc_key, SCS_CENTER, NULL, "received" ); stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &self->received_global_messages); stats_unlock(); return TRUE; } void log_src_driver_queue_method(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { LogSrcDriver *self = (LogSrcDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); /* $SOURCE */ if (msg->flags & LF_LOCAL) afinter_postpone_mark(cfg->mark_freq); log_msg_set_value(msg, LM_V_SOURCE, self->super.group, self->group_len); stats_counter_inc(self->super.processed_group_messages); stats_counter_inc(self->received_global_messages); log_pipe_forward_msg(s, msg, path_options); } void log_src_driver_init_instance(LogSrcDriver *self, GlobalConfig *cfg) { log_driver_init_instance(&self->super, cfg); self->super.super.init = log_src_driver_init_method; self->super.super.deinit = log_src_driver_deinit_method; self->super.super.queue = log_src_driver_queue_method; self->super.super.flags |= PIF_SOURCE; } void log_src_driver_free(LogPipe *s) { log_driver_free(s); } /* LogDestDriver */ /* returns a reference */ static LogQueue * log_dest_driver_acquire_queue_method(LogDestDriver *self, const gchar *persist_name, gpointer user_data) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super); LogQueue *queue = NULL; g_assert(user_data == NULL); if (persist_name) queue = cfg_persist_config_fetch(cfg, persist_name); if (!queue) { queue = log_queue_fifo_new(self->log_fifo_size < 0 ? cfg->log_fifo_size : self->log_fifo_size, persist_name); log_queue_set_throttle(queue, self->throttle); } return queue; } /* consumes the reference in @q */ static void log_dest_driver_release_queue_method(LogDestDriver *self, LogQueue *q, gpointer user_data) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super); /* we only save the LogQueue instance if it contains data */ if (q->persist_name && log_queue_keep_on_reload(q) > 0) { cfg_persist_config_add(cfg, q->persist_name, q, (GDestroyNotify) log_queue_unref, FALSE); } else { log_queue_unref(q); } } void log_dest_driver_queue_method(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { LogDestDriver *self = (LogDestDriver *) s; stats_counter_inc(self->super.processed_group_messages); stats_counter_inc(self->queued_global_messages); log_pipe_forward_msg(s, msg, path_options); } gboolean log_dest_driver_init_method(LogPipe *s) { LogDestDriver *self = (LogDestDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_driver_init_method(s)) return FALSE; if (!self->super.group) { self->super.group = cfg_tree_get_rule_name(&cfg->tree, ENC_DESTINATION, s->expr_node); self->super.id = cfg_tree_get_child_id(&cfg->tree, ENC_DESTINATION, s->expr_node); } stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_DESTINATION | SCS_GROUP, self->super.group, NULL ); stats_register_counter(0, &sc_key, SC_TYPE_PROCESSED, &self->super.processed_group_messages); stats_cluster_logpipe_key_set(&sc_key, SCS_CENTER, NULL, "queued" ); stats_register_counter(0, &sc_key, SC_TYPE_PROCESSED, &self->queued_global_messages); stats_unlock(); return TRUE; } gboolean log_dest_driver_deinit_method(LogPipe *s) { LogDestDriver *self = (LogDestDriver *) s; GList *l, *l_next; for (l = self->queues; l; l = l_next) { LogQueue *q = (LogQueue *) l->data; /* the GList struct will be freed by log_dest_driver_release_queue */ l_next = l->next; /* we have to pass a reference to log_dest_driver_release_queue(), * which automatically frees the ref on the list too */ log_dest_driver_release_queue(self, log_queue_ref(q)); } g_assert(self->queues == NULL); stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_DESTINATION | SCS_GROUP, self->super.group, NULL ); stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &self->super.processed_group_messages); stats_cluster_logpipe_key_set(&sc_key, SCS_CENTER, NULL, "queued" ); stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &self->queued_global_messages); stats_unlock(); if (!log_driver_deinit_method(s)) return FALSE; return TRUE; } void log_dest_driver_init_instance(LogDestDriver *self, GlobalConfig *cfg) { log_driver_init_instance(&self->super, cfg); self->super.super.init = log_dest_driver_init_method; self->super.super.deinit = log_dest_driver_deinit_method; self->super.super.queue = log_dest_driver_queue_method; self->acquire_queue = log_dest_driver_acquire_queue_method; self->release_queue = log_dest_driver_release_queue_method; self->log_fifo_size = -1; self->throttle = 0; } void log_dest_driver_free(LogPipe *s) { LogDestDriver *self = (LogDestDriver *) s; GList *l; for (l = self->queues; l; l = l->next) { log_queue_unref((LogQueue *) l->data); } g_list_free(self->queues); log_driver_free(s); } syslog-ng-syslog-ng-3.13.2/lib/driver.h000066400000000000000000000141041321171025300176470ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DRIVER_H_INCLUDED #define DRIVER_H_INCLUDED #include "syslog-ng.h" #include "logpipe.h" #include "logqueue.h" #include "cfg.h" /* * Drivers overview * ================ * * In syslog-ng nomenclature a driver is either responsible for handling * incoming messages (also known as source driver), or to send them out to * another party (also known as the destination driver). Source drivers are * created in "source" statements and destination drivers are similarly * created in "destination" statements. * * Drivers are derived from LogPipes, in essence they use the same "queue" * method to forward messages further down the processing pipeline. * * Driver plugins * ============== * * It is possible to change the behaviour of a driver somewhat by adding * "plugins" to drivers. These plugins basically get a chance to override * LogDriver virtual methods, change their semantics and possibly rely on * the original behaviour too. This way, functionalities that are present * in all destination drivers can easily be shared, without having to recode * the same stuff multiple times. * * Driver plugins are activated with the "attach" virtual method, which in * turn may redirect any of the LogDriver virtual methods to themselves. * They can even have a "user_data" pointer, so that they can locate their * associated state. * * Multiple plugins can hook into the same method, by saving the original * address & original user_data value. * */ /* direction agnostic driver class: LogDriver, see specialized source & destination drivers below */ typedef struct _LogDriver LogDriver; typedef struct _LogDriverPlugin LogDriverPlugin; struct _LogDriverPlugin { /* this function is called when the plugin is attached to a LogDriver * instance. It should do whatever it is necessary to extend the * functionality of the driver specified (e.g. hook into various * methods). */ gboolean (*attach)(LogDriverPlugin *s, LogDriver *d); void (*detach)(LogDriverPlugin *s, LogDriver *d); void (*free_fn)(LogDriverPlugin *s); }; static inline gboolean log_driver_plugin_attach(LogDriverPlugin *self, LogDriver *d) { return self->attach(self, d); } static inline void log_driver_plugin_detach(LogDriverPlugin *self, LogDriver *d) { if (self->detach) self->detach(self, d); } static inline void log_driver_plugin_free(LogDriverPlugin *self) { self->free_fn(self); } void log_driver_plugin_init_instance(LogDriverPlugin *self); void log_driver_plugin_free_method(LogDriverPlugin *self); struct _LogDriver { LogPipe super; gboolean optional; gchar *group; gchar *id; GList *plugins; StatsCounterItem *processed_group_messages; }; void log_driver_add_plugin(LogDriver *self, LogDriverPlugin *plugin); void log_driver_append(LogDriver *self, LogDriver *next); /* methods registered to the init/deinit virtual functions */ gboolean log_driver_init_method(LogPipe *s); gboolean log_driver_deinit_method(LogPipe *s); /* source driver class: LogSourceDriver */ typedef struct _LogSrcDriver LogSrcDriver; struct _LogSrcDriver { LogDriver super; gint group_len; StatsCounterItem *received_global_messages; }; gboolean log_src_driver_init_method(LogPipe *s); gboolean log_src_driver_deinit_method(LogPipe *s); void log_src_driver_queue_method(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data); void log_src_driver_init_instance(LogSrcDriver *self, GlobalConfig *cfg); void log_src_driver_free(LogPipe *s); /* destination driver class: LogDestDriver */ typedef struct _LogDestDriver LogDestDriver; struct _LogDestDriver { LogDriver super; gpointer acquire_queue_data; LogQueue *(*acquire_queue)(LogDestDriver *s, const gchar *persist_name, gpointer user_data); gpointer release_queue_data; void (*release_queue)(LogDestDriver *s, LogQueue *q, gpointer user_data); /* queues managed by this LogDestDriver, all constructed queues come * here and are automatically saved into cfg_persist & persist_state. */ GList *queues; gint log_fifo_size; gint throttle; StatsCounterItem *queued_global_messages; }; /* returns a reference */ static inline LogQueue * log_dest_driver_acquire_queue(LogDestDriver *self, const gchar *persist_name) { LogQueue *q; q = self->acquire_queue(self, persist_name, self->acquire_queue_data); if (q) { self->queues = g_list_prepend(self->queues, q); } return q; } /* consumes the reference in @q */ static inline void log_dest_driver_release_queue(LogDestDriver *self, LogQueue *q) { if (q) { self->queues = g_list_remove(self->queues, q); /* this drops the reference passed by the caller */ self->release_queue(self, q, self->release_queue_data); /* this drops the reference stored on the list */ log_queue_unref(q); } } gboolean log_dest_driver_init_method(LogPipe *s); gboolean log_dest_driver_deinit_method(LogPipe *s); void log_dest_driver_queue_method(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data); void log_dest_driver_init_instance(LogDestDriver *self, GlobalConfig *cfg); void log_dest_driver_free(LogPipe *s); #endif syslog-ng-syslog-ng-3.13.2/lib/early_ack_tracker.c000066400000000000000000000055301321171025300220170ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 2014 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "ack_tracker.h" #include "bookmark.h" #include "syslog-ng.h" typedef struct _EarlyAckRecord { AckRecord super; void *padding; /* bookmark contains a binary container which has to be aligned */ Bookmark bookmark; } EarlyAckRecord; typedef struct _EarlyAckTracker { AckTracker super; EarlyAckRecord ack_record_storage; } EarlyAckTracker; static Bookmark * early_ack_tracker_request_bookmark(AckTracker *s) { EarlyAckTracker *self = (EarlyAckTracker *)s; return &(self->ack_record_storage.bookmark); } static void early_ack_tracker_track_msg(AckTracker *s, LogMessage *msg) { EarlyAckTracker *self = (EarlyAckTracker *)s; log_pipe_ref((LogPipe *)self->super.source); msg->ack_record = (AckRecord *)(&self->ack_record_storage); } static void early_ack_tracker_manage_msg_ack(AckTracker *s, LogMessage *msg, AckType ack_type) { EarlyAckTracker *self = (EarlyAckTracker *)s; if (ack_type == AT_SUSPENDED) log_source_flow_control_suspend(self->super.source); else log_source_flow_control_adjust(self->super.source, 1); log_msg_unref(msg); log_pipe_unref((LogPipe *)self->super.source); } static void early_ack_tracker_init_instance(EarlyAckTracker *self, LogSource *source) { self->super.late = FALSE; self->super.source = source; source->ack_tracker = (AckTracker *)self; self->super.request_bookmark = early_ack_tracker_request_bookmark; self->super.track_msg = early_ack_tracker_track_msg; self->super.manage_msg_ack = early_ack_tracker_manage_msg_ack; self->ack_record_storage.super.tracker = (AckTracker *)self; } AckTracker * early_ack_tracker_new(LogSource *source) { EarlyAckTracker *self = (EarlyAckTracker *)g_new0(EarlyAckTracker, 1); early_ack_tracker_init_instance(self, source); return (AckTracker *)self; } void early_ack_tracker_free(AckTracker *s) { EarlyAckTracker *self = (EarlyAckTracker *)s; g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/eventlog/000077500000000000000000000000001321171025300200265ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/eventlog/AUTHORS000066400000000000000000000001011321171025300210660ustar00rootroot00000000000000EventLog has been written by Balazs Scheidler syslog-ng-syslog-ng-3.13.2/lib/eventlog/COPYING000066400000000000000000000026241321171025300210650ustar00rootroot00000000000000 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of BalaBit nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY BALABIT AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. syslog-ng-syslog-ng-3.13.2/lib/eventlog/CREDITS000066400000000000000000000003441321171025300210470ustar00rootroot00000000000000EventLog contains a couple of ideas which are based on the discussion on the log-analysis mailing list. Namely: Tina Bird Marcus J. Ranum Darren Reed marc Rainer Gerhards Thanks for their comments. syslog-ng-syslog-ng-3.13.2/lib/eventlog/ChangeLog000066400000000000000000000115211321171025300216000ustar00rootroot00000000000000# do not edit -- automatically generated by arch changelog # arch-tag: automatic-ChangeLog--bazsi@balabit.hu--bazsi-1/eventlog--mainline--1.0 # 2005-12-03 11:21:29 GMT Balazs Scheidler patch-9 Summary: some more build system specific fixes, eventlog can now be released with ZBS Revision: eventlog--mainline--1.0--patch-9 new files: .arch-ids/VERSION.id .arch-ids/dist.conf.in.id VERSION dist.conf.in modified files: ChangeLog Makefile.am NEWS configure.in debian/changelog.in renamed files: debian/.arch-ids/changelog.id ==> debian/.arch-ids/changelog.in.id debian/changelog ==> debian/changelog.in 2005-12-03 10:11:14 GMT Balazs Scheidler patch-8 Summary: added Debianization files, released 0.2.4 Revision: eventlog--mainline--1.0--patch-8 2005-12-03 Balazs Scheidler * configure.in: bumped to 0.2.4 * debian/*: added Debianization new files: .arch-ids/ChangeLog.id ChangeLog debian/.arch-ids/=id debian/.arch-ids/changelog.id debian/.arch-ids/compat.id debian/.arch-ids/control.id debian/.arch-ids/copyright.id debian/.arch-ids/libevtlog-dev.install.id debian/.arch-ids/libevtlog0.install.id debian/.arch-ids/libevtlog0.shlibs.id debian/.arch-ids/rules.id debian/changelog debian/compat debian/control debian/copyright debian/libevtlog-dev.install debian/libevtlog0.install debian/libevtlog0.shlibs debian/rules modified files: Makefile.am NEWS PORTS configure.in doc/DESIGN.txt renamed files: .arch-ids/ChangeLog.id ==> .arch-ids/ChangeLog.0.id ChangeLog ==> ChangeLog.0 new directories: debian debian/.arch-ids 2005-08-08 07:40:56 GMT Balazs Scheidler patch-7 Summary: added AUTHORS and cleaned up non-tla managed files by adding an .arch-inventory Revision: eventlog--mainline--1.0--patch-7 new files: .arch-ids/.arch-inventory.id .arch-inventory modified files: {arch}/=tagging-method 2005-08-08 07:39:15 GMT Balazs Scheidler patch-6 Summary: added AUTHORS file Revision: eventlog--mainline--1.0--patch-6 new files: .arch-ids/AUTHORS.id AUTHORS 2005-02-12 23:03:30 GMT Balazs Scheidler patch-5 Summary: Committed the version number change, however eventlog has been released earlier. Revision: eventlog--mainline--1.0--patch-5 removed files: .arch-ids/Makefile.in.id Makefile.in src/.arch-ids/Makefile.in.id src/Makefile.in tests/.arch-ids/Makefile.in.id tests/Makefile.in modified files: configure.in eventlog.pc.in 2005-01-16 14:54:22 GMT Balazs Scheidler patch-4 Summary: inherit CFLAGS from the environment Revision: eventlog--mainline--1.0--patch-4 modified files: configure.in 2005-01-16 14:51:11 GMT Balazs Scheidler patch-3 Summary: Added COPYING file Revision: eventlog--mainline--1.0--patch-3 new files: .arch-ids/COPYING.id COPYING modified files: README configure.in eventlog.pc.in 2004-12-27 23:28:34 GMT Balazs Scheidler patch-2 Summary: changed default context flags Revision: eventlog--mainline--1.0--patch-2 2004-12-28 Balazs Scheidler * evtctx.c (evt_ctx_init): set default flags not to add extra tags by default modified files: ChangeLog configure.in src/evtctx.c 2004-12-26 23:13:56 GMT Balazs Scheidler patch-1 Summary: Fixed memory leak and out-of-tree builds Revision: eventlog--mainline--1.0--patch-1 2004-12-27 Balazs Scheidler * evtctx.c (evt_ctx_free): fixed tag-hook leak * tests/Makefile.am: fixed out-of-tree builds modified files: ChangeLog src/evtctx.c tests/Makefile.am tests/Makefile.in 2004-12-26 20:41:48 GMT Balazs Scheidler base-0 Summary: initial import Revision: eventlog--mainline--1.0--base-0 (automatically generated log message) new files: CREDITS ChangeLog Makefile Makefile.am Makefile.in NEWS PORTS README aclocal.m4 autogen.sh configure.in doc/API.txt doc/DESIGN.txt doc/configuration.txt eventlog.pc.in questions src/Makefile src/Makefile.am src/Makefile.in src/evt_internals.h src/evtctx.c src/evtfmt.c src/evtlog.h src/evtmaps.h src/evtout.c src/evtrec.c src/evtstr.c src/evtsyslog.c src/evttags.c tests/Makefile tests/Makefile.am tests/Makefile.in tests/evtfmt.c tests/evtrec.c tests/evtsyslog.c syslog-ng-syslog-ng-3.13.2/lib/eventlog/ChangeLog.0000066400000000000000000000055251321171025300217450ustar00rootroot000000000000002004-12-28 Balazs Scheidler * evtctx.c (evt_ctx_init): set default flags not to add extra tags by default 2004-12-27 Balazs Scheidler * evtctx.c (evt_ctx_free): fixed tag-hook leak * tests/Makefile.am: fixed out-of-tree builds 2004-08-20 Balazs Scheidler * configure.in: bumped version number to 0.2 * configure.in: updated to autoconf 2.59 and automake 1.7.1, * src/evtlog.h: added support to several independent logging contexts, constructors directly return the constructed object instead of returning it through an argument, renamed evtstr_ prefix to evt_str_ to be more consistent, * src/evt_internals.h: renamed EVTCONFIG to EVTCONTEXT, made it reference counted, separated EVTSYSLOG from EVTCONTEXT, made it a separate global variable (as EVTCONFIG is not global anymore), reference counting functions are moved here (e.g. it is not publicly accessible) * src/*.c: followed changes in evtlog.h and evt_internals.h 2003-01-10 Balazs Scheidler * doc/API.txt: added doc on syslog compatibility * COPYING: changed to BSD license * src/evtout.c: instead of calling syslog() functions directly, call them through the function pointer * src/evtlog.h: added syslog compatibility by wrapper macros, only defined if EVENTLOG_SYSLOG_MACROS preprocessor symbol is defined * src/evtlog.c: call evt_syslog_wrapper_init() upon initialization * src/evt_internals.h: added EVTSYSLOG structure which contains function pointers for the libc syslog routines (it is needed to avoid direct calling of openlog, closelog, syslog as they might be defined inside the shared object) * src/evtsyslog.c: new file, contains the syslog-like functions and the dlsym based wrapper provided ENABLE_SYSLOG_WRAPPER is defined * configure.in: new configure option, --enable-syslog-wrapper which enables the dlsym based syslog() wrapper 2003-01-07 Balazs Scheidler * src/evt_internals.h (EVTTAG): et_prio member was dropped, log format is consistent, so it is easy to reorder tags at log analysis time * src/evtlog.h (evt_tag_*): removed prio argument, (evt_rec_ref): moved from internal to public API as it might be needed to avoid the free evt_log() does * src/evttags.c (evt_tag_*): removed prio argument * src/evtout.c (evt_log): the function consumes its argument, so no need for explicit free * src/evtmaps.h: removed priorities completely * src/evtrec.c: all tags are prepended to the list, no specific order is kept * tests/evtfmt.c, tests/evtrec.c: updated test programs * doc/configuration.txt: new file, contains the configuration file format * doc/DESIGN.txt: updated * doc/API.txt: updated 2003-01-06 Balazs Scheidler * configure.in: version 0.1 released * changelog started syslog-ng-syslog-ng-3.13.2/lib/eventlog/NEWS000066400000000000000000000030111321171025300205200ustar00rootroot00000000000000eventlog 0.2.8 Tue, 25 Mar 2008 21:03:00 +0100 Build system fixes. eventlog 0.2.7 Thu, 3 Jan 2008 13:27:28 +0100 Fixed eventlog.conf parsing to avoid crash for invalid syntax. eventlog 0.2.6 Mon, 30 Oct 2006 19:42:35 +0100 Added build scripts for RHEL3/4, Solaris, and AIX 5.2 eventlog 0.2.5 Sat, 15 Jul 2006 17:22:32 +0200 The order of tags is reversed. Previously eventlog generated messages with the tag ordering opposite of what the application requested. This is now fixed. eventlog 0.2.4 Sat, 03 Dec 2005 11:09:40 +0100 A proper release in a long time, syslog-ng itself relied on the latest snapshot until now. Added debianization files. ChangeLog is generated automatically based on tla commits. eventlog 0.1.2 Fri, 10 Jan 2003 10:15:48 +0100 Added two implementations of the syslog wrapper (macro and dlsym based). The dlsym() based can be enabled by configure-ing with the --enable-dlsym-wrapper option. The macro based can be used by defining the symbol EVENTLOG_SYSLOG_MACROS preprocessor symbol prior to including evtlog.h. eventlog 0.1.1 Tue, 7 Jan 2003 20:11:13 +0100 Incorporated first comments, evt_log now consumes its parameter, the tag ordering scheme was completely dropped. Also updated documentation, added a PORTS file and configuration.txt file eventlog 0.1 Mon, 6 Jan 2003 17:09:58 +0100 This is the initial release of eventlog, a structured event logging API. Not all features are implemented, but the basic building blocks are in place. syslog-ng-syslog-ng-3.13.2/lib/eventlog/README000066400000000000000000000023111321171025300207030ustar00rootroot00000000000000 The EventLog library aims to be a replacement of the simple syslog() API provided on UNIX systems. The major difference between EventLog and syslog is that EventLog tries to add structure to messages. Where you had a simple non-structrured string in syslog() you have a combination of description and tag/value pairs. EventLog provides an interface to build, format and output an event record. The exact format and output method can be customized by the administrator via a configuration file. Installation ------------ Installing this library is quite straightforward as it does not depend on anything but libc. First grab your copy of the library. It is a tarball named eventlog-x.x.x.x.tar.gz where x.x.x.x is the library revision. tar xvfz eventlog-x.x.x.x.tar.gz cd eventlog-x.x.x.x ./configure make && make install If you want to package the library or move the binaries to another system, you can use the DESTDIR argument to 'make install' like this: make DESTDIR=/tmp/staging install which will use the /tmp/staging directory as root and copy all files beneath as it were a real system. Copyright --------- EventLog is distributed under the terms of a BSD style license, for details see the file COPYING. syslog-ng-syslog-ng-3.13.2/lib/eventlog/doc/000077500000000000000000000000001321171025300205735ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/eventlog/doc/API.txt000066400000000000000000000043611321171025300217510ustar00rootroot00000000000000 Application Programming Interface --------------------------------- The EventLog library implements a set of functions to construct, format and output event records. The public symbols are defined in the header file named , for a list and documentation of functions please consult that file as it contains inline function descriptions in gtk-doc format. It is very important to use consistent tag naming and that different applications use identify the same data with the same tag name. Therefore please use the predefined tag name if one is available. Predefined tag names are defined in the header file . This header is included by therefore you will not need to reference it explicitly. A third header file named "evt_internals.h" is defines the internals of the EventLog library. Please do not depend on its contents and don't include it directly. As this header file is not meant to be used in applications, it is not installed when the library is installed. Syslog compatibility -------------------- Most UNIX systems and therefore the programs running under UNIX use the syslog() API found in the libc for logging. Because of the large installed base it is worth supporting legacy applications before they are converted to use EventLog. Two different implementations of syslog compatibility is provided: macro and linker based. * Macro based compatibility This works by defining the syslog() function names as macros to refer to the compatibility functions found in EventLog. To use the macro based wrapper you will need to recompile the program from source: $ cc -DEVENTLOG_SYSLOG_MACROS syslogapp.c -levtlog * Linker based compatibility Some dynamic linker implementations (most notably: Linux and Solaris) support symbol overloading. EventLog can use this feature if the dlsym() function is present which supports RTLD_NEXT to fetch symbols hidden by EventLog itself. To enable this wrapper configure EventLog with the --enable-dlsym-wrapper configure option. To use the wrapper you simply need to preload the event log shared object like: $ LD_PRELOAD=/usr/lib/libeventlog.so.0 syslogapp Where syslogapp is the program to be run. As you can see the application itself did not need to be recompiled.syslog-ng-syslog-ng-3.13.2/lib/eventlog/doc/DESIGN.txt000066400000000000000000000031731321171025300223110ustar00rootroot00000000000000Overview -------- This library was designed to support several event formats and multiple means of delivering messages. Therefore the process of sending a message to a log is separated to three independent parts: * Building the event record This is done by the application program using the library. It is a sequence of calling the following functions: evt_rec_init(...) evt_tag_str(...) / evt_tag_int(...) / evt_tag_printf(...) evt_log(...) /* consumes the log record, no need to free it */ The event record itself consists of the following properties: - a simple, constant human readable description of the event - an unordered set of tag/value pairs - a syslog compatible priority value (debug .. emerg) The record initialized by evt_rec_init() may contain a couple of tags by default (like pid, timestamp etc.) * Formatting the event record The way an event is formatted can be customized by the administrator. Several simple formats are available within the library, each having a unique identifier. The administrator refers to one of the formatters by using the "format" keyword in the /etc/eventlog.conf file. See the file configuration.txt to see the list of valid formatters. * Logging the event record The way an event record is sent to the log might also be customized by the administrator. Currently a single output method is implemented named 'local' which sends the message off by using syslog(). Additional methods are planned to be implemented like: - file - UDP syslog protocol (RFC3164) - plain TCP syslog protocol (as used by syslog-ng) - RFC3195 syslog-ng-syslog-ng-3.13.2/lib/eventlog/doc/configuration.txt000066400000000000000000000006061321171025300242050ustar00rootroot00000000000000Configuration ------------- The library contains a very cruft configuration file parser which reads /etc/eventlog.conf. Each line in this file is in the form of: keyword value The following keywords are defined: * format: specifies which formatter to use (currently implemented: plain, xmlattr, xmltag) * outmethod: specifies which output method to use (currently implemented: local) syslog-ng-syslog-ng-3.13.2/lib/eventlog/questions000066400000000000000000000002571321171025300220070ustar00rootroot00000000000000 * tag naming, namespaces * tag ordering * character set? * output modules character conversion * how to store the (prio, tag name) tuple? * syslog facility/priority mapping? syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/000077500000000000000000000000001321171025300206155ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/.gitignore000066400000000000000000000000031321171025300225760ustar00rootroot00000000000000*~ syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/Makefile.am000066400000000000000000000012001321171025300226420ustar00rootroot00000000000000 lib_LTLIBRARIES += lib/eventlog/src/libevtlog.la lib_eventlog_src_libevtlog_la_SOURCES = \ lib/eventlog/src/evtrec.c \ lib/eventlog/src/evtfmt.c \ lib/eventlog/src/evtout.c \ lib/eventlog/src/evtstr.c \ lib/eventlog/src/evtctx.c \ lib/eventlog/src/evttags.c \ lib/eventlog/src/evtsyslog.c lib_eventlog_src_libevtlog_la_LDFLAGS = -no-undefined -release ${LSNG_RELEASE} \ -version-info ${LSNG_CURRENT}:${LSNG_REVISION}:${LSNG_AGE} lib_eventlog_src_libevtlog_la_CFLAGS = $(AM_CFLAGS) noinst_HEADERS = lib/eventlog/src/evt_internals.h pkginclude_HEADERS += \ lib/eventlog/src/evtmaps.h \ lib/eventlog/src/evtlog.h syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/evt_internals.h000066400000000000000000000103371321171025300236470ustar00rootroot00000000000000/* * Event Logging API * Copyright (c) 2003 BalaBit IT Ltd. * All rights reserved. * Author: Balazs Scheidler * * EventLog library internal functions/typedefs. * * $Id: evt_internals.h,v 1.4 2004/08/20 19:46:28 bazsi Exp $ * * Some of the ideas are based on the discussions on the log-analysis * mailing list (http://www.loganalysis.org/). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of BalaBit nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BALABIT AND CONTRIBUTORS S IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #ifndef __EVT_INTERNALS_H_INCLUDED #define __EVT_INTERNALS_H_INCLUDED #include "evtlog.h" #if HAVE_CONFIG_H #include #endif #ifdef _MSC_VER #include #endif #include /* whether to add the given default tag */ #define EF_ADD_PID 0x0001 #define EF_ADD_PROG 0x0002 #define EF_ADD_ISOSTAMP 0x0004 #define EF_ADD_UTCSTAMP 0x0008 #define EF_ADD_TIMEZONE 0x0010 #define EF_ADD_MSGID 0x0020 #define EF_ADD_ALL 0x003F #define EF_INITIALIZED 0x8000 #define __PATH_ETC_EVENTLOG_CONF "/etc/eventlog.conf" typedef struct __evttaghook EVTTAGHOOK; typedef struct __evtsyslogopts EVTSYSLOGOPTS; typedef struct __evtstr EVTSTR; struct __evtsyslogopts { void (*es_openlog)(const char *ident, int option, int facility); void (*es_closelog)(void); void (*es_syslog)(int priority, const char *format, ...); int es_options; }; struct __evtcontext { int ec_ref; char ec_formatter[32]; char *(*ec_formatter_fn)(EVTREC *e); char ec_outmethod[32]; int (*ec_outmethod_fn)(EVTREC *e); char *ec_prog; int ec_syslog_fac; EVTTAGHOOK *ec_tag_hooks; unsigned long ec_flags; }; struct __evttaghook { struct __evttaghook *et_next; int (*et_callback)(EVTREC *e, void *user_ptr); void *et_userptr; }; struct __evtrec { int ev_ref; int ev_syslog_pri; char *ev_desc; EVTTAG *ev_pairs; EVTTAG *ev_last_pair; EVTCONTEXT *ev_ctx; }; struct __evttag { EVTTAG *et_next; char *et_tag; char *et_value; }; struct __evtstr { size_t es_allocated; /* number of allocated characters in es_buf */ size_t es_length; /* length of string without trailing NUL */ char *es_buf; }; /* internal functions */ /* event context */ EVTCONTEXT *evt_ctx_ref(EVTCONTEXT *ctx); /* event records */ EVTREC *evt_rec_ref(EVTREC *e); /* event tag */ void evt_tag_free(EVTTAG *et); /* event strings */ EVTSTR *evt_str_init(size_t init_alloc); void evt_str_free(EVTSTR *es, int free_buf); int evt_str_append(EVTSTR *es, char *str); int evt_str_append_len(EVTSTR *es, char *str, size_t len); int evt_str_append_escape_bs(EVTSTR *es, char *unescaped, size_t unescaped_len, char escape_char); int evt_str_append_escape_xml_attr(EVTSTR *es, char *unescaped, size_t unescaped_len); int evt_str_append_escape_xml_pcdata(EVTSTR *es, char *unescaped, size_t unescaped_len); char *evt_str_get_str(EVTSTR *es); /* syslog linked wrapper */ extern EVTSYSLOGOPTS syslog_opts; void evt_syslog_wrapper_init(void); #endif syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/evtctx.c000066400000000000000000000123041321171025300222760ustar00rootroot00000000000000/* * Event Logging API * Copyright (c) 2003 BalaBit IT Ltd. * All rights reserved. * Author: Balazs Scheidler * * $Id: evtctx.c,v 1.3 2004/08/20 19:46:28 bazsi Exp $ * * Some of the ideas are based on the discussions on the log-analysis * mailing list (http://www.loganalysis.org/). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of BalaBit nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BALABIT AND CONTRIBUTORS S IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * This is the main module which is responsible for managing the * configuration and to perform initialization. */ #include "evt_internals.h" #include #include #include #include #include #include #ifdef _MSC_VER #define getpid GetCurrentProcessId #endif static int evtrec_add_standard_tags(EVTREC *e, void *userptr) { time_t now; struct tm *tm = NULL; char buf[128]; EVTCONTEXT *ctx = e->ev_ctx; time(&now); if (ctx->ec_flags & EF_ADD_PID) evt_rec_add_tag(e, evt_tag_int(EVT_TAG_PID, (int) getpid())); if (ctx->ec_flags & EF_ADD_PROG) evt_rec_add_tag(e, evt_tag_str(EVT_TAG_PROG, ctx->ec_prog)); if (ctx->ec_flags & EF_ADD_ISOSTAMP) { tm = localtime(&now); strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", tm); evt_rec_add_tag(e, evt_tag_str(EVT_TAG_ISOSTAMP, buf)); } if (ctx->ec_flags & EF_ADD_UTCSTAMP) evt_rec_add_tag(e, evt_tag_int(EVT_TAG_UTCSTAMP, (int) now)); if (ctx->ec_flags & EF_ADD_TIMEZONE) { if (!tm) tm = localtime(&now); strftime(buf, sizeof(buf), "%z", tm); evt_rec_add_tag(e, evt_tag_str(EVT_TAG_TIMEZONE, buf)); } if (ctx->ec_flags & EF_ADD_MSGID) { evt_rec_add_tag(e, evt_tag_int(EVT_TAG_MSGID, 123456)); } return 1; } static void evt_read_config(EVTCONTEXT *ctx) { FILE *fp; char line[1024]; fp = fopen(__PATH_ETC_EVENTLOG_CONF, "r"); if (!fp) return; fgets(line, sizeof(line), fp); while (!feof(fp)) { char *keyword, *value; if (line[0] == '#' || line[0] == '\n') goto next; keyword = strtok(line, " \t\n"); value = strtok(NULL, " \t\n"); if (!keyword || !value) goto next; while (*value == ' ' || *value == '\t' || *value == '\n') value++; if (strcmp(keyword, "format") == 0) { strncpy(ctx->ec_formatter, value, sizeof(ctx->ec_formatter)); } else if (strcmp(keyword, "outmethod") == 0) { strncpy(ctx->ec_outmethod, value, sizeof(ctx->ec_outmethod)); } else if (strcmp(keyword, "implicit_tags") == 0) { ctx->ec_flags = strtoul(value, NULL, 0) & EF_ADD_ALL; } next: fgets(line, sizeof(line), fp); } } int evt_ctx_tag_hook_add(EVTCONTEXT *ctx, int (*func)(EVTREC *e, void *user_ptr), void *user_ptr) { EVTTAGHOOK *cb = malloc(sizeof(EVTTAGHOOK)); if (!cb) return 0; cb->et_callback = func; cb->et_userptr = user_ptr; cb->et_next = ctx->ec_tag_hooks; ctx->ec_tag_hooks = cb; return 1; } EVTCONTEXT * evt_ctx_init(const char *prog, int syslog_fac) { EVTCONTEXT *ctx; ctx = (EVTCONTEXT *) calloc(sizeof(*ctx), 1); if (ctx) { strcpy(ctx->ec_formatter, "plain"); strcpy(ctx->ec_outmethod, "local"); ctx->ec_ref = 1; ctx->ec_flags = EF_INITIALIZED; ctx->ec_prog = (char *) prog; ctx->ec_syslog_fac = syslog_fac; evt_ctx_tag_hook_add(ctx, evtrec_add_standard_tags, NULL); #ifndef _MSC_VER evt_syslog_wrapper_init(); #endif evt_read_config(ctx); } return ctx; } EVTCONTEXT * evt_ctx_ref(EVTCONTEXT *ctx) { assert(ctx->ec_ref > 0); ctx->ec_ref++; return ctx; } void evt_ctx_free(EVTCONTEXT *ctx) { assert(ctx->ec_ref > 0); if (--ctx->ec_ref == 0) { EVTTAGHOOK *p, *p_next; p = ctx->ec_tag_hooks; while (p) { p_next = p->et_next; free(p); p = p_next; } free(ctx); } } syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/evtfmt.c000066400000000000000000000113011321171025300222620ustar00rootroot00000000000000/* * Event Logging API * Copyright (c) 2003 BalaBit IT Ltd. * All rights reserved. * Author: Balazs Scheidler * * $Id: evtfmt.c,v 1.3 2004/08/20 19:46:28 bazsi Exp $ * * Some of the ideas are based on the discussions on the log-analysis * mailing list (http://www.loganalysis.org/). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of BalaBit nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BALABIT AND CONTRIBUTORS S IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * Formatting implementations. This module is responsible for formatting * EVENT records. Each formatter has a unique ID and the administrator is * free to select which output format to use. */ #include "evt_internals.h" #include #include static char * evtrec_format_plain(EVTREC *e) { EVTSTR *es; EVTTAG *et; char *res; if (!(es = evt_str_init(128))) return NULL; evt_str_append_escape_bs(es, e->ev_desc, strlen(e->ev_desc), ';'); evt_str_append(es, ";"); if (e->ev_pairs) evt_str_append(es, " "); for (et = e->ev_pairs; et; et = et->et_next) { evt_str_append(es, et->et_tag); evt_str_append(es, "='"); evt_str_append_escape_bs(es, et->et_value, strlen(et->et_value), '\''); if (et->et_next) evt_str_append(es, "', "); else evt_str_append(es, "'"); } res = evt_str_get_str(es); evt_str_free(es, 0); return res; } static char * evtrec_format_xmlattr(EVTREC *e) { EVTSTR *es; EVTTAG *et; char *res; if (!(es = evt_str_init(128))) return NULL; evt_str_append(es, "ev_pairs; et; et = et->et_next) { evt_str_append(es, et->et_tag); evt_str_append(es, "=\""); evt_str_append_escape_xml_attr(es, et->et_value, strlen(et->et_value)); if (et->et_next) evt_str_append(es, "\" "); else evt_str_append(es, "\">"); } evt_str_append_escape_xml_pcdata(es, e->ev_desc, strlen(e->ev_desc)); evt_str_append(es, ""); res = evt_str_get_str(es); evt_str_free(es, 0); return res; } static char * evtrec_format_xmltags(EVTREC *e) { EVTSTR *es; EVTTAG *et; char *res; if (!(es = evt_str_init(256))) return NULL; evt_str_append(es, ""); for (et = e->ev_pairs; et; et = et->et_next) { evt_str_append(es, "<"); evt_str_append(es, et->et_tag); evt_str_append(es, ">"); evt_str_append_escape_xml_pcdata(es, et->et_value, strlen(et->et_value)); evt_str_append(es, "et_tag); evt_str_append(es, ">"); } evt_str_append_escape_xml_pcdata(es, e->ev_desc, strlen(e->ev_desc)); evt_str_append(es, ""); res = evt_str_get_str(es); evt_str_free(es, 0); return res; } static struct { char *ef_name; char *(*ef_formatter)(EVTREC *e); } evt_formatters[] = { { "plain", evtrec_format_plain }, { "xmlattr", evtrec_format_xmlattr }, { "xmltag", evtrec_format_xmltags }, { NULL, NULL } }; char * evt_format(EVTREC *e) { EVTCONTEXT *ctx = e->ev_ctx; if (!ctx->ec_formatter_fn) { int i; for (i = 0; evt_formatters[i].ef_name; i++) { if (strcmp(evt_formatters[i].ef_name, ctx->ec_formatter) == 0) { ctx->ec_formatter_fn = evt_formatters[i].ef_formatter; break; } } if (evt_formatters[i].ef_name == NULL) ctx->ec_formatter_fn = evtrec_format_plain; } return (*ctx->ec_formatter_fn)(e); } syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/evtlog.h000066400000000000000000000154241321171025300222740ustar00rootroot00000000000000/* * Event Logging API * Copyright (c) 2003 BalaBit IT Ltd. * All rights reserved. * Author: Balazs Scheidler * * EventLog library public functions. * * $Id: evtlog.h,v 1.5 2004/08/20 19:53:52 bazsi Exp $ * * Some of the ideas are based on the discussions on the log-analysis * mailing list (http://www.loganalysis.org/). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of BalaBit nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BALABIT AND CONTRIBUTORS `AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #ifndef __EVTLOG_H_INCLUDED #define __EVTLOG_H_INCLUDED #ifndef _MSC_VER # include #endif #include #include "evtmaps.h" #define EVT_PRI_EMERG 0 /* system is unusable */ #define EVT_PRI_ALERT 1 /* action must be taken immediately */ #define EVT_PRI_CRIT 2 /* critical conditions */ #define EVT_PRI_ERR 3 /* error conditions */ #define EVT_PRI_WARNING 4 /* warning conditions */ #define EVT_PRI_NOTICE 5 /* normal but significant condition */ #define EVT_PRI_INFO 6 /* informational */ #define EVT_PRI_DEBUG 7 /* debug-level messages */ #define EVT_FAC_KERN (0<<3) /* kernel messages */ #define EVT_FAC_USER (1<<3) /* random user-level messages */ #define EVT_FAC_MAIL (2<<3) /* mail system */ #define EVT_FAC_DAEMON (3<<3) /* system daemons */ #define EVT_FAC_AUTH (4<<3) /* security/authorization messages */ #define EVT_FAC_SYSLOG (5<<3) /* messages generated internally by syslogd */ #define EVT_FAC_LPR (6<<3) /* line printer subsystem */ #define EVT_FAC_NEWS (7<<3) /* network news subsystem */ #define EVT_FAC_UUCP (8<<3) /* UUCP subsystem */ #define EVT_FAC_CRON (9<<3) /* clock daemon */ #define EVT_FAC_AUTHPRIV (10<<3) /* security/authorization messages (private) */ #define EVT_FAC_FTP (11<<3) /* ftp daemon */ /* other codes through 15 reserved for system use */ #define EVT_FAC_LOCAL0 (16<<3) /* reserved for local use */ #define EVT_FAC_LOCAL1 (17<<3) /* reserved for local use */ #define EVT_FAC_LOCAL2 (18<<3) /* reserved for local use */ #define EVT_FAC_LOCAL3 (19<<3) /* reserved for local use */ #define EVT_FAC_LOCAL4 (20<<3) /* reserved for local use */ #define EVT_FAC_LOCAL5 (21<<3) /* reserved for local use */ #define EVT_FAC_LOCAL6 (22<<3) /* reserved for local use */ #define EVT_FAC_LOCAL7 (23<<3) /* reserved for local use */ #ifdef __GNUC__ #define EVT_GNUC_PRINTF_FUNC(format_idx, first_arg_idx) __attribute__((format(printf, format_idx, first_arg_idx))) #else #define EVT_GNUC_PRINTF_FUNC(format_idx, first_arg_idx) #endif /* EVTCONTEXT encapsulates logging specific parameters like the * program name and facility to use */ typedef struct __evtcontext EVTCONTEXT; /* EVTREC is an event log record, contains a description and one or more * name/value pairs */ typedef struct __evtrec EVTREC; /* EVTTAG is a name value pair, comprising an event record */ typedef struct __evttag EVTTAG; /* eventlog contexts */ /** * evt_ctx_init: * @prog: program name to use to identify this process as * @syslog_fac: syslog facility code, like EVT_FAC_AUTH * * This function creates a new eventlog context. * * Returns: the new context, or NULL on failure **/ EVTCONTEXT *evt_ctx_init(const char *prog, int syslog_fac); /** * evt_ctx_free: * @ctx: context to free * * This function frees an eventlog context. **/ void evt_ctx_free(EVTCONTEXT *ctx); /** * evt_ctx_tag_hook_add: **/ int evt_ctx_tag_hook_add(EVTCONTEXT *ctx, int (*func)(EVTREC *e, void *user_ptr), void *user_ptr); /* event record manipulation */ EVTREC *evt_rec_init(EVTCONTEXT *ctx, int syslog_pri, const char *desc); void evt_rec_add_tag(EVTREC *e, EVTTAG *tag); void evt_rec_add_tagsv(EVTREC *e, va_list tags); void evt_rec_add_tags(EVTREC *e, EVTTAG *first, ...); int evt_rec_get_syslog_pri(EVTREC *e); void evt_rec_free(EVTREC *e); /** * evt_rec_tag_*: * @tag: specifies tag name as string * @value: specifies a value in the given type * * Adds the specified tag/value pair to EVTREC. * * Return value: 0 to indicate failure and 1 for success **/ EVTTAG *evt_tag_str(const char *tag, const char *value); EVTTAG *evt_tag_int(const char *tag, int value); EVTTAG *evt_tag_long(const char *tag, long value); EVTTAG *evt_tag_errno(const char *tag, int err); EVTTAG *evt_tag_printf(const char *tag, const char *format, ...) EVT_GNUC_PRINTF_FUNC(2, 3); /** * evt_format: * @e: event record * * Formats the given event as specified by the current configuration. * * Return value: returns a newly allocated string. The caller is responsible * for freeing the returned value. **/ char *evt_format(EVTREC *e); /** * evt_log: * @e: event record * * Formats and sends the given event as specified by the current * configuration. This function blocks and will not return until the message * is sent. The function consumes its argument, that is the caller does not * need to free the event record after passing it to evt_log(). * * Return value: 0 to indicate failure and 1 for success * **/ int evt_log(EVTREC *e); /* syslog wrapper */ void evt_openlog(const char *ident, int option, int facility); void evt_closelog(void); void evt_vsyslog(int pri, const char *format, va_list ap); void evt_syslog(int pri, const char *format, ...) EVT_GNUC_PRINTF_FUNC(2, 3); #ifdef EVENTLOG_SYSLOG_MACROS #define openlog evt_openlog #define syslog evt_syslog #define vsyslog evt_vsyslog #define closelog evt_closelog #endif #endif syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/evtmaps.h000066400000000000000000000041701321171025300224470ustar00rootroot00000000000000/* * Event Logging API * Copyright (c) 2003 BalaBit IT Ltd. * All rights reserved. * Author: Balazs Scheidler * * $Id: evtmaps.h,v 1.3 2003/01/10 09:24:51 bazsi Exp $ * * Some of the ideas are based on the discussions on the log-analysis * mailing list (http://www.loganalysis.org/). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of BalaBit nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BALABIT AND CONTRIBUTORS S IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #ifndef __EVTMAPS_H_INCLUDED #define __EVTMAPS_H_INCLUDED /* base event map, with no namespace */ #define EVT_TAG_PID "pid" #define EVT_TAG_PROG "prog" #define EVT_TAG_ISOSTAMP "isostamp" #define EVT_TAG_UTCSTAMP "utcstamp" #define EVT_TAG_TIMEZONE "tz" #define EVT_TAG_MSGID "msgid" #define EVT_TAG_FD "fd" #define EVT_TAG_OSERROR "error" #define EVT_TAG_FILENAME "filename" #endif syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/evtout.c000066400000000000000000000064321321171025300223140ustar00rootroot00000000000000/* * Event Logging API * Copyright (c) 2003 BalaBit IT Ltd. * All rights reserved. * Author: Balazs Scheidler * * $Id: evtout.c,v 1.4 2004/08/20 19:46:29 bazsi Exp $ * * Some of the ideas are based on the discussions on the log-analysis * mailing list (http://www.loganalysis.org/). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of BalaBit nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BALABIT AND CONTRIBUTORS S IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * Output implementations. An output method is responsible for delivering a * message. Each output method has a unique ID and the administrator is * free to select which method to use. */ #include "evt_internals.h" #include #include #include /* local method implementation */ static int evt_output_local(EVTREC *e) { static int initialized = 0; char *msg; EVTCONTEXT *ctx = e->ev_ctx; if (!initialized) { /* * there's a small window of race here, if this is used in a * multithreaded program, but it's a small race, and can only occur * when the first message is sent */ initialized = 1; syslog_opts.es_openlog(ctx->ec_prog, syslog_opts.es_options, ctx->ec_syslog_fac); } msg = evt_format(e); syslog_opts.es_syslog(e->ev_syslog_pri, "%s", msg); free(msg); return 1; } static struct { char *eo_name; int (*eo_outmethod_fn)(EVTREC *e); } evt_outmethods[] = { { "local", evt_output_local }, { NULL, NULL } }; int evt_log(EVTREC *e) { int res; EVTCONTEXT *ctx = e->ev_ctx; if (!ctx->ec_outmethod_fn) { int i; for (i = 0; evt_outmethods[i].eo_name; i++) { if (strcmp(evt_outmethods[i].eo_name, ctx->ec_outmethod) == 0) { ctx->ec_outmethod_fn = evt_outmethods[i].eo_outmethod_fn; break; } } if (evt_outmethods[i].eo_name == NULL) ctx->ec_outmethod_fn = evt_output_local; } res = (*ctx->ec_outmethod_fn)(e); evt_rec_free(e); return res; } syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/evtrec.c000066400000000000000000000066741321171025300222660ustar00rootroot00000000000000/* * Event Logging API * Copyright (c) 2003 BalaBit IT Ltd. * All rights reserved. * Author: Balazs Scheidler * * $Id: evtrec.c,v 1.4 2004/08/20 19:46:29 bazsi Exp $ * * Some of the ideas are based on the discussions on the log-analysis * mailing list (http://www.loganalysis.org/). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of BalaBit nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BALABIT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "evt_internals.h" #include #include #include /* for snprintf */ void evt_rec_add_tag(EVTREC *e, EVTTAG *tag) { /* make it the last in list */ tag->et_next = NULL; if (e->ev_last_pair) e->ev_last_pair->et_next = tag; else e->ev_pairs = tag; e->ev_last_pair = tag; } void evt_rec_add_tagsv(EVTREC *e, va_list tags) { EVTTAG *t; t = va_arg(tags, EVTTAG *); while (t) { evt_rec_add_tag(e, t); t = va_arg(tags, EVTTAG *); } } void evt_rec_add_tags(EVTREC *e, EVTTAG *first, ...) { va_list ap; va_start(ap, first); evt_rec_add_tagsv(e, ap); va_end(ap); } int evt_rec_get_syslog_pri(EVTREC *e) { return e->ev_syslog_pri; } static int evt_rec_call_hooks(EVTREC *e) { EVTTAGHOOK *et; int res = 1; for (et = e->ev_ctx->ec_tag_hooks; et; et = et->et_next) { if (!et->et_callback(e, et->et_userptr)) res = 0; } return res; } EVTREC * evt_rec_init(EVTCONTEXT *ctx, int syslog_pri, const char *desc) { EVTREC *e; e = (EVTREC *) malloc(sizeof(EVTREC)); if (e) { e->ev_ctx = evt_ctx_ref(ctx); e->ev_desc = strdup(desc); e->ev_pairs = NULL; e->ev_last_pair = NULL; e->ev_ref = 1; e->ev_syslog_pri = syslog_pri; if (!evt_rec_call_hooks(e)) { free(e); e = NULL; } } return e; } EVTREC * evt_rec_ref(EVTREC *e) { e->ev_ref++; return e; } void evt_rec_free(EVTREC *e) { EVTTAG *p, *p_next; if (--e->ev_ref == 0) { free(e->ev_desc); for (p = e->ev_pairs; p; p = p_next) { p_next = p->et_next; evt_tag_free(p); } evt_ctx_free(e->ev_ctx); free(e); } } syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/evtstr.c000066400000000000000000000134441321171025300223160ustar00rootroot00000000000000/* * Event Logging API * Copyright (c) 2003 BalaBit IT Ltd. * All rights reserved. * Author: Balazs Scheidler * * $Id: evtstr.c,v 1.3 2004/08/20 19:46:29 bazsi Exp $ * * Some of the ideas are based on the discussions on the log-analysis * mailing list (http://www.loganalysis.org/). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of BalaBit nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BALABIT AND CONTRIBUTORS S IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * A couple of string support functions which make it easy to output * escaped strings. It is used by event formatting functions. */ #include "evt_internals.h" #include #include #include #include #ifdef HAVE_MALLOC_H #include #endif #ifdef HAVE_ALLOCA_H #include #endif /* event string handling */ static int evt_str_grow(EVTSTR *es, size_t new_alloc) { es->es_buf = realloc(es->es_buf, new_alloc); return es->es_buf != NULL; } int evt_str_append_len(EVTSTR *es, char *str, size_t len) { /* make sure we have room new string + trailing zero */ if (es->es_allocated < es->es_length + len + 1) { if (!evt_str_grow(es, es->es_length + len + 1)) return 0; } memcpy(es->es_buf + es->es_length, str, len); es->es_length += len; es->es_buf[es->es_length] = 0; /* trailing zero */ return 1; } int evt_str_append(EVTSTR *es, char *str) { return evt_str_append_len(es, str, strlen(str)); } int evt_str_append_escape_bs(EVTSTR *es, char *unescaped, size_t unescaped_len, char escape_char) { /* a single character is escaped to at most 4 characters: \xXX */ char *buf = (char *)alloca(4*unescaped_len + 1); int i, dst; for (i = 0, dst = 0; i < unescaped_len; i++) { unsigned c = (unsigned) unescaped[i]; if (c < 32 && c != '\t') { sprintf(&buf[dst], "\\x%02x", (unsigned char) unescaped[i]); dst += 4; } else if (unescaped[i] == escape_char) { buf[dst++] = '\\'; buf[dst++] = escape_char; } else { buf[dst++] = unescaped[i]; } assert(dst <= 4*unescaped_len); } return evt_str_append_len(es, buf, dst); } int evt_str_append_escape_xml_attr(EVTSTR *es, char *unescaped, size_t unescaped_len) { /* a single character is escaped to at most 6 characters: '&#xXX;' or '"' */ /* FIXME: this is a gcc extension, alternative would be to use alloca(), * which is not portable */ char *buf = (char *)alloca(6*unescaped_len + 1); int i, dst; for (i = 0, dst = 0; i < unescaped_len; i++) { if ((unsigned) unescaped[i] < 32) { sprintf(&buf[dst], "&#x%02x;", (unsigned char) unescaped[i]); dst += 6; } else if (unescaped[i] == '"') { strcpy(&buf[dst], """); dst += 6; } else { buf[dst++] = unescaped[i]; } assert(dst <= 6*unescaped_len); } return evt_str_append_len(es, buf, dst); } int evt_str_append_escape_xml_pcdata(EVTSTR *es, char *unescaped, size_t unescaped_len) { /* a single character is escaped to at most 6 characters: '&#xXX;' or '>' or '<' */ /* FIXME: this is a gcc extension, alternative would be to use alloca(), * which is not portable */ char *buf = (char *)alloca(6*unescaped_len + 1); int i, dst; for (i = 0, dst = 0; i < unescaped_len; i++) { if ((unsigned) unescaped[i] < 32) { sprintf(&buf[dst], "&#x%02x;", (unsigned char) unescaped[i]); dst += 6; } else if (unescaped[i] == '<') { strcpy(&buf[dst], "<"); dst += 4; } else if (unescaped[i] == '>') { strcpy(&buf[dst], ">"); dst += 4; } else { buf[dst++] = unescaped[i]; } assert(dst <= 6*unescaped_len); } return evt_str_append_len(es, buf, dst); } char * evt_str_get_str(EVTSTR *es) { return es->es_buf; } EVTSTR * evt_str_init(size_t init_alloc) { EVTSTR *es; es = (EVTSTR *) malloc(sizeof(EVTSTR)); if (es) { /* make room for init_alloc characters + trailing zero */ init_alloc++; es->es_allocated = init_alloc; es->es_length = 0; es->es_buf = malloc(init_alloc); es->es_buf[0] = 0; } return es; } void evt_str_free(EVTSTR *es, int free_buf) { if (free_buf) free(es->es_buf); free(es); } syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/evtsyslog.c000066400000000000000000000067411321171025300230300ustar00rootroot00000000000000/* * Event Logging API * Copyright (c) 2003 BalaBit IT Ltd. * All rights reserved. * Author: Balazs Scheidler * * $Id: evtsyslog.c,v 1.3 2004/08/20 20:27:54 bazsi Exp $ * * Some of the ideas are based on the discussions on the log-analysis * mailing list (http://www.loganalysis.org/). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of BalaBit nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BALABIT AND CONTRIBUTORS S IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "evt_internals.h" #include #include #include EVTCONTEXT *syslog_context; EVTSYSLOGOPTS syslog_opts; void evt_openlog(const char *ident, int options, int facility) { syslog_context = evt_ctx_init(ident, facility); /* NOTE: we save the legacy syslog option value, so that our local target * can use it */ syslog_opts.es_options = options; } void evt_closelog(void) { } void evt_vsyslog(int pri, const char *format, va_list ap) { EVTREC *e; char msgbuf[1024]; vsnprintf(msgbuf, sizeof(msgbuf), format, ap); e = evt_rec_init(syslog_context, pri, msgbuf); evt_log(e); } void evt_syslog(int pri, const char *format, ...) { va_list ap; va_start(ap, format); evt_vsyslog(pri, format, ap); va_end(ap); } #if ENABLE_DLSYM_WRAPPER #include void openlog(const char *ident, int option, int facility) { evt_openlog(ident, option, facility); } void syslog(int pri, const char *format, ...) { va_list ap; va_start(ap, format); evt_vsyslog(pri, format, ap); va_end(ap); } void closelog(void) { evt_closelog(); } void evt_syslog_wrapper_init(void) { static int initialized = 0; if (!initialized) { syslog_opts.es_openlog = dlsym(RTLD_NEXT, "openlog"); syslog_opts.es_closelog = dlsym(RTLD_NEXT, "closelog"); syslog_opts.es_syslog = dlsym(RTLD_NEXT, "syslog"); syslog_opts.es_options = LOG_PID | LOG_NOWAIT; initialized = 1; } } #else void evt_syslog_wrapper_init(void) { static int initialized = 0; if (!initialized) { syslog_opts.es_openlog = openlog; syslog_opts.es_closelog = closelog; syslog_opts.es_syslog = syslog; syslog_opts.es_options = LOG_PID | LOG_NOWAIT; initialized = 1; } } #endif syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/evttags.c000066400000000000000000000061751321171025300224470ustar00rootroot00000000000000/* * Event Logging API * Copyright (c) 2003 BalaBit IT Ltd. * All rights reserved. * Author: Balazs Scheidler * * $Id: evttags.c,v 1.4 2004/08/20 19:46:29 bazsi Exp $ * * Some of the ideas are based on the discussions on the log-analysis * mailing list (http://www.loganalysis.org/). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of BalaBit nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BALABIT AND CONTRIBUTORS S IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * This module implements tag support functions. */ #include "evt_internals.h" #include #include #include #include #include #ifdef _MSC_VER #ifndef snprintf #define snprintf _snprintf #endif #endif void evt_tag_free(EVTTAG *et) { free(et->et_tag); free(et->et_value); free(et); } EVTTAG * evt_tag_str(const char *tag, const char *value) { EVTTAG *p; /* neither tag nor value can be NULL */ assert(tag); if (!value) value = "(null)"; p = (EVTTAG *) malloc(sizeof(EVTTAG)); if (p) { p->et_tag = strdup(tag); p->et_value = strdup(value); } return p; } EVTTAG * evt_tag_int(const char *tag, int value) { char buf[32]; /* a 64 bit int fits into 20 characters */ snprintf(buf, sizeof(buf), "%d", value); return evt_tag_str(tag, buf); } EVTTAG * evt_tag_long(const char *tag, long value) { char buf[32]; /* a 64 bit int fits into 20 characters */ snprintf(buf, sizeof(buf), "%ld", value); return evt_tag_str(tag, buf); } EVTTAG * evt_tag_errno(const char *tag, int err) { char buf[128]; snprintf(buf, sizeof(buf), "%s (%d)", strerror(err), err); return evt_tag_str(tag, buf); } EVTTAG * evt_tag_printf(const char *tag, const char *format, ...) { va_list ap; char buf[1024]; va_start(ap, format); vsnprintf(buf, sizeof(buf), format, ap); va_end(ap); return evt_tag_str(tag, buf); } syslog-ng-syslog-ng-3.13.2/lib/eventlog/src/makefile.msc000066400000000000000000000044231321171025300231010ustar00rootroot00000000000000## Use: nmake -f makefile.msc !IFNDEF COMPILE_ENV COMPILE_ENV=c:\build !ENDIF !IFNDEF COMPILE_ENV ROOT=$(COMPILE_ENV)\out !ENDIF !IFNDEF DEBUG # Full optimization: OPTIMIZE = -Ox /Zi CRUNTIME = -MD /WL # Line number debug info only DEBUGINFO = -Zi LINKDEBUG = /debug !ELSE # Debugging: OPTIMIZE = CRUNTIME = -MDd DEBUGINFO = -Zi -DG_ENABLE_DEBUG=1 LINKDEBUG = /debug !ENDIF LDFLAGS = /link /machine:ix86 $(LINKDEBUG) TOP = $(COMPILE_ENV) DEP = $(TOP)\dep ################ # Compiler to use. CCOMPILER = cl CC = $(CCOMPILER) -GF $(CRUNTIME) -W3 -nologo ################ # Linker LINK=link /nologo /MANIFEST ################ # The including makefile should define INCLUDES, DEFINES and # DEPCFLAGS. INCLUDES are the includes related to the module being # built. DEFINES similarly. DEPCFLAGS should be set to a set of # GLIB_CFLAGS, GTK_CFLAGS etc corresponding to what other modules we # depend on. CFLAGS = -I$(TOP)\include -I$(DEP)\include\ -L$(DEP)\lib $(OPTIMIZE) $(DEBUGINFO) $(INCLUDES) $(DEFINES) $(DEPCFLAGS) -D_CRT_SECURE_NO_WARNINGS -D_WIN32_WINNNT=0x0500 -D_WIN32_WINDOWS=0x0500 -D_WIN32 -D_WINDOWS -D_VC80_UPGRADE=0x0710 .c.i :: $(CC) $(CFLAGS) -E $< # The default target should be "all" default: all clean:: -@del *.obj >NUL 2>&1 -@del *.res >NUL 2>&1 -@del *.i >NUL 2>&1 -@del *.exe >NUL 2>&1 -@del *.dll >NUL 2>&1 -@del *.lib >NUL 2>&1 -@del *.err >NUL 2>&1 -@del *.map >NUL 2>&1 -@del *.sym >NUL 2>&1 -@del *.exp >NUL 2>&1 -@del *.lk1 >NUL 2>&1 -@del *.mk1 >NUL 2>&1 -@del *.pdb >NUL 2>&1 -@del *.ilk >NUL 2>&1 # Needed by hacker rule to make makefile.msc from makefile.msc.in: SED = e:\cygwin\bin\sed ################################################################ INCLUDES = -I . all: install OUTPUTS = \ evtlog.lib OBJECTS = \ evtctx.obj \ evtfmt.obj \ evtrec.obj \ evtstr.obj \ evttags.obj DLLOBJECTS = evtlog.res evtlog.lib: $(OBJECTS) lib /out:$@ $(OBJECTS) install: evtlog.lib if not exist $(ROOT)\include\eventlog mkdir $(ROOT)\include\eventlog copy /y evtlog.h $(ROOT)\include\eventlog copy /y evtmaps.h $(ROOT)\include\eventlog if not exist $(ROOT)\lib mkdir $(ROOT)\lib if not exist $(ROOT)\lib\pkgconfig mkdir $(ROOT)\lib\pkgconfig copy /y .\evtlog.lib $(ROOT)\lib if exist ..\eventlog.pc copy /y ..\eventlog.pc $(ROOT)\lib\pkgconfig syslog-ng-syslog-ng-3.13.2/lib/eventlog/tests/000077500000000000000000000000001321171025300211705ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/eventlog/tests/Makefile.am000066400000000000000000000017251321171025300232310ustar00rootroot00000000000000lib_eventlog_tests_TESTS = \ lib/eventlog/tests/evtrec \ lib/eventlog/tests/evtfmt \ lib/eventlog/tests/evtsyslog \ lib/eventlog/tests/evtsyslog-macros check_PROGRAMS += ${lib_eventlog_tests_TESTS} lib_eventlog_tests_evtrec_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/lib/eventlog/src lib_eventlog_tests_evtrec_LDADD = $(top_builddir)/lib/eventlog/src/libevtlog.la lib_eventlog_tests_evtfmt_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/lib/eventlog/src lib_eventlog_tests_evtfmt_LDADD = $(top_builddir)/lib/eventlog/src/libevtlog.la lib_eventlog_tests_evtsyslog_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/lib/eventlog/src lib_eventlog_tests_evtsyslog_LDADD = $(top_builddir)/lib/eventlog/src/libevtlog.la lib_eventlog_tests_evtsyslog_macros_SOURCES = lib/eventlog/tests/evtsyslog.c lib_eventlog_tests_evtsyslog_macros_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/lib/eventlog/src -DEVENTLOG_SYSLOG_MACROS=1 lib_eventlog_tests_evtsyslog_macros_LDADD = $(top_builddir)/lib/eventlog/src/libevtlog.la syslog-ng-syslog-ng-3.13.2/lib/eventlog/tests/evtfmt.c000066400000000000000000000013241321171025300226410ustar00rootroot00000000000000#include "evtlog.h" #include #include #include int main(void) { EVTCONTEXT *ctx; EVTREC *e; char *es; ctx = evt_ctx_init("evtfmt", LOG_AUTH); e = evt_rec_init(ctx, LOG_INFO, "Test message with an embedded ';' in it. It also contains an like tag."); evt_rec_add_tags(e, evt_tag_str("test:tag", "'value'"), evt_tag_str("test:tag2", "\n\n\n\n"), evt_tag_int("test:fd", fileno(stderr)), evt_tag_errno("test:error", EAGAIN), evt_tag_printf("test:printf", "%d %d", 5, 6), NULL); es = evt_format(e); printf("%s\n", es); free(es); evt_log(e); return 0; } syslog-ng-syslog-ng-3.13.2/lib/eventlog/tests/evtrec.c000066400000000000000000000006761321171025300226350ustar00rootroot00000000000000#include "evtlog.h" #include #include int main(void) { EVTREC *e; EVTCONTEXT *ctx; ctx = evt_ctx_init("evtrec", LOG_AUTH); e = evt_rec_init(ctx, LOG_INFO, "Test message"); evt_rec_add_tags(e, evt_tag_str("test:tag", "value"), evt_tag_int("test:fd", fileno(stderr)), evt_tag_errno("test:error", EAGAIN), NULL); evt_log(e); return 0; } syslog-ng-syslog-ng-3.13.2/lib/eventlog/tests/evtsyslog.c000066400000000000000000000003211321171025300233670ustar00rootroot00000000000000#include #ifdef EVENTLOG_SYSLOG_MACROS #include #endif int main(void) { openlog("evtsyslog", LOG_PID, 0); syslog(LOG_AUTH | LOG_NOTICE, "test message"); closelog(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/fdhelpers.c000066400000000000000000000031521321171025300203240ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "fdhelpers.h" #include #include gboolean g_fd_set_nonblock(int fd, gboolean enable) { int flags; if ((flags = fcntl(fd, F_GETFL)) == -1) return FALSE; if (enable) flags |= O_NONBLOCK; else flags &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) < 0) { return FALSE; } return TRUE; } gboolean g_fd_set_cloexec(int fd, gboolean enable) { int flags; if ((flags = fcntl(fd, F_GETFD)) == -1) return FALSE; if (enable) flags |= FD_CLOEXEC; else flags &= ~FD_CLOEXEC; if (fcntl(fd, F_SETFD, flags) < 0) { return FALSE; } return TRUE; } syslog-ng-syslog-ng-3.13.2/lib/fdhelpers.h000066400000000000000000000022631321171025300203330ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FDHELPERS_H_INCLUDED #define FDHELPERS_H_INCLUDED 1 #include "syslog-ng.h" gboolean g_fd_set_nonblock(int fd, gboolean enable); gboolean g_fd_set_cloexec(int fd, gboolean enable); #endif syslog-ng-syslog-ng-3.13.2/lib/file-perms.c000066400000000000000000000156351321171025300204240ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "file-perms.h" #include "userdb.h" #include "messages.h" #include "cfg.h" #include "gprocess.h" #include #include #include #include #define DONTCHANGE -2 void file_perm_options_set_file_uid(FilePermOptions *self, const gchar *file_uid) { self->file_uid = 0; if (!resolve_user(file_uid, &self->file_uid)) { msg_error("Error resolving user", evt_tag_str("user", file_uid)); } } void file_perm_options_dont_change_file_uid(FilePermOptions *self) { self->file_uid = DONTCHANGE; } void file_perm_options_set_file_gid(FilePermOptions *self, const gchar *file_gid) { self->file_gid = 0; if (!resolve_group(file_gid, &self->file_gid)) { msg_error("Error resolving group", evt_tag_str("group", file_gid)); } } void file_perm_options_dont_change_file_gid(FilePermOptions *self) { self->file_gid = DONTCHANGE; } void file_perm_options_set_file_perm(FilePermOptions *self, gint file_perm) { self->file_perm = file_perm; } void file_perm_options_dont_change_file_perm(FilePermOptions *self) { self->file_perm = DONTCHANGE; } void file_perm_options_set_dir_uid(FilePermOptions *self, const gchar *dir_uid) { self->dir_uid = 0; if (!resolve_user(dir_uid, &self->dir_uid)) { msg_error("Error resolving user", evt_tag_str("user", dir_uid)); } } void file_perm_options_dont_change_dir_uid(FilePermOptions *self) { self->dir_uid = DONTCHANGE; } void file_perm_options_set_dir_gid(FilePermOptions *self, const gchar *dir_gid) { self->dir_gid = 0; if (!resolve_group(dir_gid, &self->dir_gid)) { msg_error("Error resolving group", evt_tag_str("group", dir_gid)); } } void file_perm_options_dont_change_dir_gid(FilePermOptions *self) { self->dir_gid = DONTCHANGE; } void file_perm_options_set_dir_perm(FilePermOptions *self, gint dir_perm) { self->dir_perm = dir_perm; } void file_perm_options_dont_change_dir_perm(FilePermOptions *self) { self->dir_perm = DONTCHANGE; } void file_perm_options_defaults(FilePermOptions *self) { self->file_uid = self->file_gid = -1; self->file_perm = -1; self->dir_uid = self->dir_gid = -1; self->dir_perm = -1; } void file_perm_options_global_defaults(FilePermOptions *self) { self->file_uid = 0; self->file_gid = 0; self->file_perm = 0600; self->dir_uid = 0; self->dir_gid = 0; self->dir_perm = 0700; } void file_perm_options_inherit_from(FilePermOptions *self, const FilePermOptions *from) { if (self->file_uid == -1) self->file_uid = from->file_uid; if (self->file_gid == -1) self->file_gid = from->file_gid; if (self->file_perm == -1) self->file_perm = from->file_perm; if (self->dir_uid == -1) self->dir_uid = from->dir_uid; if (self->dir_gid == -1) self->dir_gid = from->dir_gid; if (self->dir_perm == -1) self->dir_perm = from->dir_perm; } void file_perm_options_inherit_dont_change(FilePermOptions *self) { FilePermOptions dont_change = { .file_uid = DONTCHANGE, .file_gid = DONTCHANGE, .file_perm = DONTCHANGE, .dir_uid = DONTCHANGE, .dir_gid = DONTCHANGE, .dir_perm = DONTCHANGE, }; file_perm_options_inherit_from(self, &dont_change); } gboolean file_perm_options_apply_file(const FilePermOptions *self, gchar *name) { #ifndef _MSC_VER gboolean result = TRUE; if (self->file_uid >= 0 && chown(name, (uid_t) self->file_uid, -1) < 0) result = FALSE; if (self->file_gid >= 0 && chown(name, -1, (gid_t) self->file_gid) < 0) result = FALSE; if (self->file_perm >= 0 && chmod(name, (mode_t) self->file_perm) < 0) result = FALSE; return result; #endif } gboolean file_perm_options_apply_dir(const FilePermOptions *self, gchar *name) { #ifndef _MSC_VER gboolean result = TRUE; if (self->dir_uid >= 0 && chown(name, (uid_t) self->dir_uid, -1) < 0) result = FALSE; if (self->dir_gid >= 0 && chown(name, -1, (gid_t) self->dir_gid) < 0) result = FALSE; if (self->dir_perm >= 0 && chmod(name, (mode_t) self->dir_perm) < 0) result = FALSE; return result; #endif } gboolean file_perm_options_apply_fd(const FilePermOptions *self, gint fd) { #ifndef _MSC_VER gboolean result = TRUE; if (self->file_uid >= 0 && fchown(fd, (uid_t) self->file_uid, -1) < 0) result = FALSE; if (self->file_gid >= 0 && fchown(fd, -1, (gid_t) self->file_gid) < 0) result = FALSE; if (self->file_perm >= 0 && fchmod(fd, (mode_t) self->file_perm) < 0) result = FALSE; return result; #endif } /** * * This function receives a complete path (directory + filename) and creates * the directory portion if it does not exist. The point is that the caller * wants to ensure that the given filename can be opened after this function * returns. (at least it won't fail because of missing directories). **/ gboolean file_perm_options_create_containing_directory(const FilePermOptions *self, gchar *name) { gchar *dirname; struct stat st; gint rc; gchar *p; cap_t saved_caps; /* check that the directory exists */ dirname = g_path_get_dirname(name); rc = stat(dirname, &st); g_free(dirname); if (rc == 0) { /* directory already exists */ return TRUE; } else if (rc < 0 && errno != ENOENT) { /* some real error occurred */ return FALSE; } /* directory does not exist */ p = name + 1; p = strchr(p, '/'); while (p) { *p = 0; if (stat(name, &st) == 0) { if (!S_ISDIR(st.st_mode)) return FALSE; } else if (errno == ENOENT) { if (mkdir(name, self->dir_perm < 0 ? 0700 : (mode_t) self->dir_perm) == -1) return FALSE; saved_caps = g_process_cap_save(); g_process_cap_modify(CAP_CHOWN, TRUE); g_process_cap_modify(CAP_FOWNER, TRUE); file_perm_options_apply_dir(self, name); g_process_cap_restore(saved_caps); } *p = '/'; p = strchr(p + 1, '/'); } return TRUE; } syslog-ng-syslog-ng-3.13.2/lib/file-perms.h000066400000000000000000000052431321171025300204230ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILE_PERMS_H_INCLUDED #define FILE_PERMS_H_INCLUDED #include "syslog-ng.h" typedef struct _FilePermOptions { gint file_uid; gint file_gid; gint file_perm; gint dir_uid; gint dir_gid; gint dir_perm; } FilePermOptions; void file_perm_options_set_file_uid(FilePermOptions *s, const gchar *file_uid); void file_perm_options_dont_change_file_uid(FilePermOptions *s); void file_perm_options_set_file_gid(FilePermOptions *s, const gchar *file_gid); void file_perm_options_dont_change_file_gid(FilePermOptions *s); void file_perm_options_set_file_perm(FilePermOptions *s, gint file_perm); void file_perm_options_dont_change_file_perm(FilePermOptions *s); void file_perm_options_set_dir_uid(FilePermOptions *s, const gchar *dir_uid); void file_perm_options_dont_change_dir_uid(FilePermOptions *s); void file_perm_options_set_dir_gid(FilePermOptions *s, const gchar *dir_gid); void file_perm_options_dont_change_dir_gid(FilePermOptions *s); void file_perm_options_set_dir_perm(FilePermOptions *s, gint dir_perm); void file_perm_options_dont_change_dir_perm(FilePermOptions *s); void file_perm_options_defaults(FilePermOptions *self); void file_perm_options_global_defaults(FilePermOptions *self); void file_perm_options_inherit_from(FilePermOptions *self, const FilePermOptions *from); void file_perm_options_inherit_dont_change(FilePermOptions *self); gboolean file_perm_options_apply_file(const FilePermOptions *self, gchar *name); gboolean file_perm_options_apply_dir(const FilePermOptions *self, gchar *name); gboolean file_perm_options_apply_fd(const FilePermOptions *self, gint fd); gboolean file_perm_options_create_containing_directory(const FilePermOptions *self, gchar *name); #endif syslog-ng-syslog-ng-3.13.2/lib/filter/000077500000000000000000000000001321171025300174705ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/filter/CMakeLists.txt000066400000000000000000000013031321171025300222250ustar00rootroot00000000000000set(FILTER_HEADERS filter/filter-expr.h filter/filter-op.h filter/filter-cmp.h filter/filter-in-list.h filter/filter-tags.h filter/filter-netmask.h filter/filter-netmask6.h filter/filter-call.h filter/filter-re.h filter/filter-pri.h filter/filter-pipe.h filter/filter-expr-parser.h PARENT_SCOPE ) set(FILTER_SOURCES filter/filter-expr.c filter/filter-op.c filter/filter-cmp.c filter/filter-in-list.c filter/filter-tags.c filter/filter-netmask.c filter/filter-netmask6.c filter/filter-call.c filter/filter-re.c filter/filter-pri.c filter/filter-pipe.c filter/filter-expr-parser.c PARENT_SCOPE ) syslog-ng-syslog-ng-3.13.2/lib/filter/Makefile.am000066400000000000000000000020571321171025300215300ustar00rootroot00000000000000filterincludedir = ${pkgincludedir}/filter filterinclude_HEADERS = \ lib/filter/filter-expr.h \ lib/filter/filter-op.h \ lib/filter/filter-cmp.h \ lib/filter/filter-in-list.h \ lib/filter/filter-tags.h \ lib/filter/filter-netmask.h \ lib/filter/filter-netmask6.h \ lib/filter/filter-call.h \ lib/filter/filter-re.h \ lib/filter/filter-pri.h \ lib/filter/filter-pipe.h \ lib/filter/filter-expr-parser.h filter_sources = \ lib/filter/filter-expr.c \ lib/filter/filter-op.c \ lib/filter/filter-cmp.c \ lib/filter/filter-in-list.c \ lib/filter/filter-tags.c \ lib/filter/filter-netmask.c \ lib/filter/filter-netmask6.c \ lib/filter/filter-call.c \ lib/filter/filter-re.c \ lib/filter/filter-pri.c \ lib/filter/filter-pipe.c \ lib/filter/filter-expr-parser.c \ lib/filter/filter-expr-grammar.y BUILT_SOURCES += \ lib/filter/filter-expr-grammar.y \ lib/filter/filter-expr-grammar.c \ lib/filter/filter-expr-grammar.h EXTRA_DIST += lib/filter/filter-expr-grammar.ym include lib/filter/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/filter/filter-call.c000066400000000000000000000072101321171025300220320ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter-call.h" #include "cfg.h" #include "filter-pipe.h" typedef struct _FilterCall { FilterExprNode super; FilterExprNode *filter_expr; gchar *rule; } FilterCall; static gboolean filter_call_eval(FilterExprNode *s, LogMessage **msgs, gint num_msg) { gboolean res = FALSE; FilterCall *self = (FilterCall *) s; if (self->filter_expr) { /* rule is assumed to contain a single filter pipe */ res = filter_expr_eval_with_context(self->filter_expr, msgs, num_msg); } if (res) stats_counter_inc(self->super.matched); else stats_counter_inc(self->super.not_matched); return res ^ s->comp; } static void filter_call_init(FilterExprNode *s, GlobalConfig *cfg) { FilterCall *self = (FilterCall *) s; LogExprNode *rule; rule = cfg_tree_get_object(&cfg->tree, ENC_FILTER, self->rule); if (rule) { /* this is quite fragile and would break whenever the parsing code in * cfg-grammar.y changes to parse a filter rule. We assume that a * filter rule has a single child, which contains a LogFilterPipe * instance as its object. */ LogFilterPipe *filter_pipe = (LogFilterPipe *) rule->children->object; self->filter_expr = filter_expr_ref(filter_pipe->expr); filter_expr_init(self->filter_expr, cfg); self->super.modify = self->filter_expr->modify; stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_FILTER, self->rule, NULL ); stats_register_counter(1, &sc_key, SC_TYPE_MATCHED, &self->super.matched); stats_register_counter(1, &sc_key, SC_TYPE_NOT_MATCHED, &self->super.not_matched); stats_unlock(); } else { msg_error("Referenced filter rule not found in filter() expression", evt_tag_str("rule", self->rule)); } } static void filter_call_free(FilterExprNode *s) { FilterCall *self = (FilterCall *) s; filter_expr_unref(self->filter_expr); stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_FILTER, self->rule, NULL ); stats_unregister_counter(&sc_key, SC_TYPE_MATCHED, &self->super.matched); stats_unregister_counter(&sc_key, SC_TYPE_NOT_MATCHED, &self->super.not_matched); stats_unlock(); g_free((gchar *) self->super.type); g_free(self->rule); } FilterExprNode * filter_call_new(gchar *rule, GlobalConfig *cfg) { FilterCall *self = g_new0(FilterCall, 1); filter_expr_node_init_instance(&self->super); self->super.init = filter_call_init; self->super.eval = filter_call_eval; self->super.free_fn = filter_call_free; self->super.type = g_strdup_printf("filter(%s)", rule); self->rule = g_strdup(rule); return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/filter/filter-call.h000066400000000000000000000022271321171025300220420ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILTER_CALL_H_INCLUDED #define FILTER_CALL_H_INCLUDED #include "filter-expr.h" FilterExprNode *filter_call_new(gchar *rule, struct _GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/lib/filter/filter-cmp.c000066400000000000000000000105751321171025300217060ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter/filter-cmp.h" #include "filter/filter-expr-grammar.h" #include "scratch-buffers.h" #include #include #define FCMP_EQ 0x0001 #define FCMP_LT 0x0002 #define FCMP_GT 0x0004 #define FCMP_NUM 0x0010 typedef struct _FilterCmp { FilterExprNode super; LogTemplate *left, *right; gint cmp_op; } FilterCmp; gboolean fop_cmp_eval(FilterExprNode *s, LogMessage **msgs, gint num_msg) { FilterCmp *self = (FilterCmp *) s; ScratchBuffersMarker marker; GString *left_buf = scratch_buffers_alloc_and_mark(&marker); GString *right_buf = scratch_buffers_alloc(); gboolean result = FALSE; gint cmp; log_template_format_with_context(self->left, msgs, num_msg, NULL, LTZ_LOCAL, 0, NULL, left_buf); log_template_format_with_context(self->right, msgs, num_msg, NULL, LTZ_LOCAL, 0, NULL, right_buf); if (self->cmp_op & FCMP_NUM) { gint l, r; l = atoi(left_buf->str); r = atoi(right_buf->str); if (l == r) cmp = 0; else if (l < r) cmp = -1; else cmp = 1; } else { cmp = strcmp(left_buf->str, right_buf->str); } if (cmp == 0) { result = self->cmp_op & FCMP_EQ; } else if (cmp < 0) { result = self->cmp_op & FCMP_LT || self->cmp_op == 0; } else { result = self->cmp_op & FCMP_GT || self->cmp_op == 0; } scratch_buffers_reclaim_marked(marker); return result ^ s->comp; } void fop_cmp_free(FilterExprNode *s) { FilterCmp *self = (FilterCmp *) s; log_template_unref(self->left); log_template_unref(self->right); } FilterExprNode * fop_cmp_new(LogTemplate *left, LogTemplate *right, gint op) { FilterCmp *self = g_new0(FilterCmp, 1); filter_expr_node_init_instance(&self->super); self->super.eval = fop_cmp_eval; self->super.free_fn = fop_cmp_free; self->left = left; self->right = right; switch (op) { case KW_NUM_LT: self->cmp_op = FCMP_NUM; case KW_LT: self->cmp_op |= FCMP_LT; self->super.type = "<"; break; case KW_NUM_LE: self->cmp_op = FCMP_NUM; case KW_LE: self->cmp_op |= FCMP_LT | FCMP_EQ; self->super.type = "<="; break; case KW_NUM_EQ: self->cmp_op = FCMP_NUM; case KW_EQ: self->cmp_op |= FCMP_EQ; self->super.type = "=="; break; case KW_NUM_NE: self->cmp_op = FCMP_NUM; case KW_NE: self->cmp_op |= 0; self->super.type = "!="; break; case KW_NUM_GE: self->cmp_op = FCMP_NUM; case KW_GE: self->cmp_op |= FCMP_GT | FCMP_EQ; self->super.type = ">="; break; case KW_NUM_GT: self->cmp_op = FCMP_NUM; case KW_GT: self->cmp_op |= FCMP_GT; self->super.type = ">"; break; default: g_assert_not_reached(); } if (self->cmp_op & FCMP_NUM && cfg_is_config_version_older(left->cfg, VERSION_VALUE_3_8)) { msg_warning("WARNING: due to a bug in versions before " VERSION_3_8 "numeric comparison operators like '!=' in filter " "expressions were evaluated as string operators. This is fixed in " VERSION_3_8 ". " "As we are operating in compatibility mode, syslog-ng will exhibit the buggy " "behaviour as previous versions until you bump the @version value in your " "configuration file"); self->cmp_op &= ~FCMP_NUM; } return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/filter/filter-cmp.h000066400000000000000000000022711321171025300217050ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILTER_CMP_H_INCLUDED #define FILTER_CMP_H_INCLUDED #include "filter-expr.h" #include "template/templates.h" FilterExprNode *fop_cmp_new(LogTemplate *left, LogTemplate *right, gint op); #endif syslog-ng-syslog-ng-3.13.2/lib/filter/filter-expr-grammar.ym000066400000000000000000000223051321171025300237260ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code requires { #include "filter/filter-expr-parser.h" } %code { #include "filter/filter-expr-grammar.h" #include "filter/filter-netmask.h" #include "filter/filter-netmask6.h" #include "filter/filter-op.h" #include "filter/filter-cmp.h" #include "filter/filter-in-list.h" #include "filter/filter-tags.h" #include "filter/filter-call.h" #include "filter/filter-re.h" #include "filter/filter-pri.h" #include "messages.h" #include "template/templates.h" #include "syslog-names.h" #include "plugin.h" #include "cfg-grammar.h" FilterRE *last_re_filter; } %name-prefix "filter_expr_" %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {FilterExprNode **result} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_PROGRAM %token KW_IN_LIST %token KW_VALUE %left ';' %left KW_OR %left KW_AND %left KW_NOT %left KW_LT KW_LE KW_EQ KW_NE KW_GE KW_GT %left KW_NUM_LT KW_NUM_LE KW_NUM_EQ KW_NUM_NE KW_NUM_GE KW_NUM_GT %type filter_expr %type filter_simple_expr %type filter_plugin %type filter_comparison %type filter_fac_list %type filter_fac %type filter_level_list %type filter_level %type operator %% start : filter_expr { *result = $1; if (yychar != YYEMPTY) { cfg_lexer_unput_token(lexer, &yylval); } YYACCEPT; } ; filter_expr : filter_simple_expr { $$ = $1; if (!$1) YYERROR; } | KW_NOT filter_expr { ((FilterExprNode *) $2)->comp = !(((FilterExprNode *) $2)->comp); $$ = $2; } | filter_expr KW_OR filter_expr { $$ = fop_or_new($1, $3); } | filter_expr KW_AND filter_expr { $$ = fop_and_new($1, $3); } | filter_expr ';' filter_expr { $$ = fop_and_new($1, $3); } | filter_expr ';' { $$ = $1; } | '(' filter_expr ')' { $$ = $2; } ; filter_simple_expr : KW_FACILITY '(' filter_fac_list ')' { $$ = filter_facility_new($3); } | KW_FACILITY '(' LL_NUMBER ')' { $$ = filter_facility_new(0x80000000 | $3); } | KW_LEVEL '(' filter_level_list ')' { $$ = filter_level_new($3); } | KW_FILTER '(' string ')' { $$ = filter_call_new($3, configuration); free($3); } | KW_NETMASK '(' string ')' { $$ = filter_netmask_new($3); free($3); } | KW_NETMASK6 '(' string ')' { #if SYSLOG_NG_ENABLE_IPV6 $$ = filter_netmask6_new($3); #else YYERROR; #endif free($3); } | KW_TAGS '(' string_list ')' { $$ = filter_tags_new($3); } | KW_IN_LIST '(' string string ')' { const gchar *p = $4; if (p[0] == '$') { msg_warning("Value references in filters should not use the '$' prefix, those are only needed in templates", evt_tag_str("value", $4), cfg_lexer_format_location_tag(lexer, &@4)); p++; } $$ = filter_in_list_new($3, p); free($3); free($4); } | KW_IN_LIST '(' string KW_VALUE '(' string ')' ')' { const gchar *p = $6; if (p[0] == '$') { msg_warning("Value references in filters should not use the '$' prefix, those are only needed in templates", evt_tag_str("value", $6), cfg_lexer_format_location_tag(lexer, &@6)); p++; } $$ = filter_in_list_new($3, p); free($3); free($6); } | filter_re { $$ = &last_re_filter->super; } | filter_plugin | filter_comparison ; filter_plugin : LL_IDENTIFIER { Plugin *p; gint context = LL_CONTEXT_FILTER; FilterExprNode *node; p = cfg_find_plugin(configuration, context, $1); CHECK_ERROR(p, @1, "%s plugin %s not found OR you may not used double quotes in your filter expression", cfg_lexer_lookup_context_name_by_type(context), $1); node = (FilterExprNode *) cfg_parse_plugin(configuration, p, &@1, NULL); free($1); if (!node) { YYERROR; } $$ = node; } ; filter_comparison : LL_STRING operator LL_STRING { LogTemplate *left, *right; GError *error = NULL; left = log_template_new(configuration, NULL); right = log_template_new(configuration, NULL); CHECK_ERROR_GERROR(log_template_compile(left, $1, &error), @1, error, "error compiling left template"); CHECK_ERROR_GERROR(log_template_compile(right, $3, &error), @3, error, "error compiling right template"); free($1); free($3); $$ = fop_cmp_new(left, right, $2); } ; operator : KW_NUM_LT { $$ = yylval.token; } | KW_NUM_LE { $$ = yylval.token; } | KW_NUM_EQ { $$ = yylval.token; } | KW_NUM_NE { $$ = yylval.token; } | KW_NUM_GE { $$ = yylval.token; } | KW_NUM_GT { $$ = yylval.token; } | KW_LT { $$ = yylval.token; } | KW_LE { $$ = yylval.token; } | KW_EQ { $$ = yylval.token; } | KW_NE { $$ = yylval.token; } | KW_GE { $$ = yylval.token; } | KW_GT { $$ = yylval.token; } ; filter_re : KW_PROGRAM { last_re_filter = filter_re_new(LM_V_PROGRAM); } filter_re_params | KW_HOST { last_re_filter = filter_re_new(LM_V_HOST); } filter_re_params | KW_MESSAGE { last_re_filter = filter_re_new(LM_V_MESSAGE); } filter_re_params | KW_SOURCE { last_re_filter = filter_source_new(); } filter_re_params | KW_MATCH { last_re_filter = filter_match_new(); } filter_match_params ; filter_re_params : '(' string filter_re_opts ')' { GError *error = NULL; CHECK_ERROR_GERROR(filter_re_compile_pattern(last_re_filter, configuration, $2, &error), @2, error, "error compiling search pattern"); free($2); } ; filter_re_opts : filter_re_opt filter_re_opts | ; filter_re_opt : { last_matcher_options = &last_re_filter->matcher_options; } matcher_option ; filter_match_params : '(' string filter_match_opts ')' { GError *error = NULL; CHECK_ERROR_GERROR(filter_re_compile_pattern(last_re_filter, configuration, $2, &error), @2, error, "error compiling search pattern"); free($2); if (last_re_filter->value_handle == 0) { static gboolean warn_written = FALSE; if (!warn_written) { msg_warning("WARNING: the match() filter without the use of the value() " "option is deprecated and hinders performance, please use a " "more specific filter like message() and/or program() instead", cfg_lexer_format_location_tag(lexer, &@0)); warn_written = TRUE; } } } filter_match_opts : filter_match_opt filter_match_opts | ; filter_match_opt : filter_re_opt | KW_VALUE '(' string ')' { const gchar *p = $3; if (p[0] == '$') { msg_warning("Value references in filters should not use the '$' prefix, those are only needed in templates", evt_tag_str("value", $3), cfg_lexer_format_location_tag(lexer, &@3)); p++; } last_re_filter->value_handle = log_msg_get_value_handle(p); free($3); } ; filter_fac_list : filter_fac filter_fac_list { $$ = $1 | $2; } | filter_fac { $$ = $1; } ; filter_fac : facility_string LL_DOTDOT facility_string { $$ = syslog_make_range($1 >> 3, $3 >> 3); } | facility_string { $$ = 1 << ($1 >> 3); } ; filter_level_list : filter_level filter_level_list { $$ = $1 | $2; } | filter_level { $$ = $1; } ; filter_level : level_string LL_DOTDOT level_string { $$ = syslog_make_range($1, $3); } | level_string { $$ = 1 << $1; } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/lib/filter/filter-expr-parser.c000066400000000000000000000052101321171025300233650ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter/filter-expr-parser.h" #include "filter/filter-expr-grammar.h" #include "filter/filter-expr.h" extern int filter_expr_debug; int filter_expr_parse(CfgLexer *lexer, FilterExprNode **node, gpointer arg); static CfgLexerKeyword filter_expr_keywords[] = { { "or", KW_OR }, { "and", KW_AND }, { "not", KW_NOT }, { "lt", KW_LT }, { "le", KW_LE }, { "eq", KW_EQ }, { "ne", KW_NE }, { "ge", KW_GE }, { "gt", KW_GT }, { "<", KW_NUM_LT }, { "<=", KW_NUM_LE }, { "==", KW_NUM_EQ }, { "!=", KW_NUM_NE }, { ">=", KW_NUM_GE }, { ">", KW_NUM_GT }, { "level", KW_LEVEL }, { "priority", KW_LEVEL }, { "facility", KW_FACILITY }, { "program", KW_PROGRAM }, { "host", KW_HOST }, { "message", KW_MESSAGE }, { "match", KW_MATCH }, { "netmask", KW_NETMASK }, { "tags", KW_TAGS }, { "in_list", KW_IN_LIST }, #if SYSLOG_NG_ENABLE_IPV6 { "netmask6", KW_NETMASK6 }, #endif { "value", KW_VALUE }, { "flags", KW_FLAGS }, { NULL } }; CfgParser filter_expr_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &filter_expr_debug, #endif .name = "filter expression", .context = LL_CONTEXT_FILTER, .keywords = filter_expr_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer)) filter_expr_parse, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(filter_expr_, FilterExprNode **) syslog-ng-syslog-ng-3.13.2/lib/filter/filter-expr-parser.h000066400000000000000000000023431321171025300233760ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILTER_EXPR_PARSER_H_INCLUDED #define FILTER_EXPR_PARSER_H_INCLUDED #include "cfg-parser.h" #include "filter/filter-expr.h" extern CfgParser filter_expr_parser; CFG_PARSER_DECLARE_LEXER_BINDING(filter_expr_, FilterExprNode **) #endif syslog-ng-syslog-ng-3.13.2/lib/filter/filter-expr.c000066400000000000000000000054531321171025300221040ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter/filter-expr.h" #include "messages.h" /**************************************************************** * Filter expression nodes ****************************************************************/ void filter_expr_node_init_instance(FilterExprNode *self) { self->ref_cnt = 1; } /* * In case the filter would modify the message the caller has to make sure * that the message is writable. You can always archieve that with * filter_expr_eval_root() below, but you have to be on a processing path to * do that. */ gboolean filter_expr_eval_with_context(FilterExprNode *self, LogMessage **msg, gint num_msg) { gboolean res; g_assert(num_msg > 0); res = self->eval(self, msg, num_msg); msg_debug("Filter node evaluation result", evt_tag_printf("msg", "%p", *msg), evt_tag_str("result", res ? "match" : "not-match"), evt_tag_str("type", self->type)); return res; } gboolean filter_expr_eval(FilterExprNode *self, LogMessage *msg) { return filter_expr_eval_with_context(self, &msg, 1); } gboolean filter_expr_eval_root_with_context(FilterExprNode *self, LogMessage **msg, gint num_msg, const LogPathOptions *path_options) { g_assert(num_msg > 0); if (self->modify) log_msg_make_writable(&msg[num_msg - 1], path_options); return filter_expr_eval_with_context(self, msg, num_msg); } gboolean filter_expr_eval_root(FilterExprNode *self, LogMessage **msg, const LogPathOptions *path_options) { return filter_expr_eval_root_with_context(self, msg, 1, path_options); } FilterExprNode * filter_expr_ref(FilterExprNode *self) { self->ref_cnt++; return self; } void filter_expr_unref(FilterExprNode *self) { if (self && (--self->ref_cnt == 0)) { if (self->free_fn) self->free_fn(self); g_free(self); } } syslog-ng-syslog-ng-3.13.2/lib/filter/filter-expr.h000066400000000000000000000044171321171025300221100ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILTER_H_INCLUDED #define FILTER_H_INCLUDED #include "syslog-ng.h" #include "logpipe.h" #include "stats/stats-registry.h" struct _GlobalConfig; typedef struct _FilterExprNode FilterExprNode; struct _FilterExprNode { guint32 ref_cnt; guint32 comp:1, /* this not is negated */ modify:1; /* this filter changes the log message */ const gchar *type; void (*init)(FilterExprNode *self, GlobalConfig *cfg); gboolean (*eval)(FilterExprNode *self, LogMessage **msg, gint num_msg); void (*free_fn)(FilterExprNode *self); StatsCounterItem *matched; StatsCounterItem *not_matched; }; static inline void filter_expr_init(FilterExprNode *self, GlobalConfig *cfg) { if (self->init) self->init(self, cfg); } gboolean filter_expr_eval(FilterExprNode *self, LogMessage *msg); gboolean filter_expr_eval_with_context(FilterExprNode *self, LogMessage **msgs, gint num_msg); gboolean filter_expr_eval_root(FilterExprNode *self, LogMessage **msg, const LogPathOptions *path_options); gboolean filter_expr_eval_root_with_context(FilterExprNode *self, LogMessage **msgs, gint num_msg, const LogPathOptions *path_options); void filter_expr_node_init_instance(FilterExprNode *self); FilterExprNode *filter_expr_ref(FilterExprNode *self); void filter_expr_unref(FilterExprNode *self); #endif syslog-ng-syslog-ng-3.13.2/lib/filter/filter-in-list.c000066400000000000000000000056131321171025300225030ustar00rootroot00000000000000/* * Copyright (c) 2013, 2014 Balabit * Copyright (c) 2013, 2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter-in-list.h" #include "logmsg/logmsg.h" #include "str-utils.h" #include #include #include #include typedef struct _FilterInList { FilterExprNode super; NVHandle value_handle; GTree *tree; } FilterInList; static gboolean filter_in_list_eval(FilterExprNode *s, LogMessage **msgs, gint num_msg) { FilterInList *self = (FilterInList *)s; LogMessage *msg = msgs[num_msg - 1]; const gchar *value; gssize len = 0; value = log_msg_get_value(msg, self->value_handle, &len); APPEND_ZERO(value, value, len); gboolean result = (g_tree_lookup(self->tree, value) != NULL) ^ s->comp; msg_debug("Filter in-list node evaluation result", evt_tag_printf("msg", "%p", msg), evt_tag_str("value", value), evt_tag_str("result", result ? "match" : "not-match")); return result; } static void filter_in_list_free(FilterExprNode *s) { FilterInList *self = (FilterInList *)s; g_tree_destroy(self->tree); } FilterExprNode * filter_in_list_new(const gchar *list_file, const gchar *property) { FilterInList *self; FILE *stream; gchar line[16384]; stream = fopen(list_file, "r"); if (!stream) { msg_error("Error opening in-list filter list file", evt_tag_str("file", list_file), evt_tag_errno("errno", errno)); return NULL; } self = g_new0(FilterInList, 1); filter_expr_node_init_instance(&self->super); self->value_handle = log_msg_get_value_handle(property); self->tree = g_tree_new_full((GCompareDataFunc)strcmp, NULL, g_free, NULL); while (fgets(line, sizeof(line), stream) != NULL) { line[strlen(line) - 1] = '\0'; if (line[0]) g_tree_insert(self->tree, g_strdup(line), GINT_TO_POINTER(1)); } fclose(stream); self->super.eval = filter_in_list_eval; self->super.free_fn = filter_in_list_free; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/filter/filter-in-list.h000066400000000000000000000023211321171025300225010ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILTER_IN_LIST_H_INCLUDED #define FILTER_IN_LIST_H_INCLUDED #include "filter-expr.h" FilterExprNode *filter_in_list_new(const gchar *list_file, const gchar *property); #endif syslog-ng-syslog-ng-3.13.2/lib/filter/filter-netmask.c000066400000000000000000000054371321171025300225720ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter-netmask.h" #include "gsocket.h" #include "logmsg/logmsg.h" #include #include typedef struct _FilterNetmask { FilterExprNode super; struct in_addr address; struct in_addr netmask; } FilterNetmask; static gboolean filter_netmask_eval(FilterExprNode *s, LogMessage **msgs, gint num_msg) { FilterNetmask *self = (FilterNetmask *) s; struct in_addr addr; LogMessage *msg = msgs[num_msg - 1]; if (msg->saddr && g_sockaddr_inet_check(msg->saddr)) { addr = ((struct sockaddr_in *) &msg->saddr->sa)->sin_addr; } else if (!msg->saddr || msg->saddr->sa.sa_family == AF_UNIX) { addr.s_addr = htonl(INADDR_LOOPBACK); } else { /* no address information, return FALSE */ return s->comp; } return ((addr.s_addr & self->netmask.s_addr) == (self->address.s_addr)) ^ s->comp; } FilterExprNode * filter_netmask_new(gchar *cidr) { FilterNetmask *self = g_new0(FilterNetmask, 1); gchar buf[32]; gchar *slash; filter_expr_node_init_instance(&self->super); slash = strchr(cidr, '/'); if (strlen(cidr) >= sizeof(buf) || !slash) { g_inet_aton(cidr, &self->address); self->netmask.s_addr = htonl(0xFFFFFFFF); } else { strncpy(buf, cidr, slash - cidr + 1); buf[slash - cidr] = 0; g_inet_aton(buf, &self->address); if (strchr(slash + 1, '.')) { g_inet_aton(slash + 1, &self->netmask); } else { gint prefix = strtol(slash + 1, NULL, 10); if (prefix == 32) self->netmask.s_addr = htonl(0xFFFFFFFF); else self->netmask.s_addr = htonl(((1 << prefix) - 1) << (32 - prefix)); } } self->address.s_addr &= self->netmask.s_addr; self->super.eval = filter_netmask_eval; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/filter/filter-netmask.h000066400000000000000000000022051321171025300225650ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILTER_NETMASK_H_INCLUDED #define FILTER_NETMASK_H_INCLUDED #include "filter-expr.h" FilterExprNode *filter_netmask_new(gchar *cidr); #endif syslog-ng-syslog-ng-3.13.2/lib/filter/filter-netmask6.c000066400000000000000000000077721321171025300226640ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Zoltan Fried * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter-netmask6.h" #include "gsocket.h" #include "logmsg/logmsg.h" #include #include #include #include #if SYSLOG_NG_ENABLE_IPV6 typedef struct _FilterNetmask6 { FilterExprNode super; struct in6_addr address; int prefix; gboolean is_valid; } FilterNetmask6; static inline uint64_t _calculate_mask_by_prefix(int prefix) { return (uint64_t) (~0) << (64 - prefix); } static inline uint64_t _mask(uint64_t base, uint64_t mask) { if (G_BYTE_ORDER == G_BIG_ENDIAN) return base & mask; else return GUINT64_SWAP_LE_BE(GUINT64_SWAP_LE_BE(base) & mask); } void get_network_address(unsigned char *ipv6, int prefix, struct in6_addr *network) { struct ipv6_parts { uint64_t lo; uint64_t hi; } ipv6_parts; int length; memcpy(&ipv6_parts, ipv6, sizeof(ipv6_parts)); if (prefix <= 64) { ipv6_parts.lo = _mask(ipv6_parts.lo, _calculate_mask_by_prefix(prefix)); length = sizeof(uint64_t); } else { ipv6_parts.hi = _mask(ipv6_parts.hi, _calculate_mask_by_prefix(prefix - 64)); length = 2 * sizeof(uint64_t); } memcpy(network->s6_addr, &ipv6_parts, length); } static inline gboolean _in6_addr_compare(const struct in6_addr *address1, const struct in6_addr *address2) { return memcmp(address1, address2, sizeof(struct in6_addr)) == 0; } static gboolean _eval(FilterExprNode *s, LogMessage **msgs, gint num_msg) { FilterNetmask6 *self = (FilterNetmask6 *) s; LogMessage *msg = msgs[num_msg - 1]; gboolean result = FALSE; struct in6_addr network_address; struct in6_addr address; if (!self->is_valid) return s->comp; if (msg->saddr && g_sockaddr_inet6_check(msg->saddr)) { address = ((struct sockaddr_in6 *) &msg->saddr->sa)->sin6_addr; } else if (!msg->saddr || msg->saddr->sa.sa_family == AF_UNIX) { address = in6addr_loopback; } else { return s->comp; } memset(&network_address, 0, sizeof(struct in6_addr)); get_network_address((unsigned char *) &address, self->prefix, &network_address); result = _in6_addr_compare(&network_address, &self->address); return result ^ s->comp; } FilterExprNode * filter_netmask6_new(gchar *cidr) { FilterNetmask6 *self = g_new0(FilterNetmask6, 1); struct in6_addr packet_addr; gchar address[INET6_ADDRSTRLEN] = ""; gchar *slash = strchr(cidr, '/'); filter_expr_node_init_instance(&self->super); if (strlen(cidr) >= INET6_ADDRSTRLEN + 5 || !slash) { strcpy(address, cidr); self->prefix = 128; } else { self->prefix = atol(slash + 1); if (self->prefix > 0 && self->prefix < 129) { strncpy(address, cidr, slash - cidr); address[slash - cidr] = 0; } } self->is_valid = ((strlen(address) > 0) && inet_pton(AF_INET6, address, &packet_addr) == 1); if (self->is_valid) get_network_address((unsigned char *) &packet_addr, self->prefix, &self->address); else self->address = in6addr_loopback; self->super.eval = _eval; return &self->super; } #endif syslog-ng-syslog-ng-3.13.2/lib/filter/filter-netmask6.h000066400000000000000000000023161321171025300226560ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Zoltan Fried * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILTER_NETMASK6_H_INCLUDED #define FILTER_NETMASK6_H_INCLUDED #include "filter-expr.h" FilterExprNode *filter_netmask6_new(gchar *cidr); void get_network_address(unsigned char *ipv6, int prefix, struct in6_addr *network); #endif syslog-ng-syslog-ng-3.13.2/lib/filter/filter-op.c000066400000000000000000000054211321171025300215370ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter-op.h" typedef struct _FilterOp { FilterExprNode super; FilterExprNode *left, *right; } FilterOp; static void fop_init(FilterExprNode *s, GlobalConfig *cfg) { FilterOp *self = (FilterOp *) s; if (self->left && self->left->init) self->left->init(self->left, cfg); if (self->right && self->right->init) self->right->init(self->right, cfg); self->super.modify = self->left->modify || self->right->modify; } static void fop_free(FilterExprNode *s) { FilterOp *self = (FilterOp *) s; filter_expr_unref(self->left); filter_expr_unref(self->right); } static void fop_init_instance(FilterOp *self) { filter_expr_node_init_instance(&self->super); self->super.init = fop_init; self->super.free_fn = fop_free; } static gboolean fop_or_eval(FilterExprNode *s, LogMessage **msgs, gint num_msg) { FilterOp *self = (FilterOp *) s; return (filter_expr_eval_with_context(self->left, msgs, num_msg) || filter_expr_eval_with_context(self->right, msgs, num_msg)) ^ s->comp; } FilterExprNode * fop_or_new(FilterExprNode *e1, FilterExprNode *e2) { FilterOp *self = g_new0(FilterOp, 1); fop_init_instance(self); self->super.eval = fop_or_eval; self->left = e1; self->right = e2; self->super.type = "OR"; return &self->super; } static gboolean fop_and_eval(FilterExprNode *s, LogMessage **msgs, gint num_msg) { FilterOp *self = (FilterOp *) s; return (filter_expr_eval_with_context(self->left, msgs, num_msg) && filter_expr_eval_with_context(self->right, msgs, num_msg)) ^ s->comp; } FilterExprNode * fop_and_new(FilterExprNode *e1, FilterExprNode *e2) { FilterOp *self = g_new0(FilterOp, 1); fop_init_instance(self); self->super.eval = fop_and_eval; self->left = e1; self->right = e2; self->super.type = "AND"; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/filter/filter-op.h000066400000000000000000000023231321171025300215420ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILTER_OP_H_INCLUDED #define FILTER_OP_H_INCLUDED #include "filter-expr.h" FilterExprNode *fop_or_new(FilterExprNode *e1, FilterExprNode *e2); FilterExprNode *fop_and_new(FilterExprNode *e1, FilterExprNode *e2); #endif syslog-ng-syslog-ng-3.13.2/lib/filter/filter-pipe.c000066400000000000000000000075011321171025300220570ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter/filter-pipe.h" #include "stats/stats-registry.h" /******************************************************************* * LogFilterPipe *******************************************************************/ static gboolean log_filter_pipe_init(LogPipe *s) { LogFilterPipe *self = (LogFilterPipe *) s; GlobalConfig *cfg = log_pipe_get_config(s); filter_expr_init(self->expr, log_pipe_get_config(s)); if (!self->name) self->name = cfg_tree_get_rule_name(&cfg->tree, ENC_FILTER, s->expr_node); stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_FILTER, self->name, NULL ); stats_register_counter(1, &sc_key, SC_TYPE_MATCHED, &self->matched); stats_register_counter(1, &sc_key, SC_TYPE_NOT_MATCHED, &self->not_matched); stats_unlock(); return TRUE; } static void log_filter_pipe_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { LogFilterPipe *self = (LogFilterPipe *) s; gboolean res; msg_debug("Filter rule evaluation begins", evt_tag_printf("msg", "%p", msg), evt_tag_str("rule", self->name), log_pipe_location_tag(s)); res = filter_expr_eval_root(self->expr, &msg, path_options); msg_debug("Filter rule evaluation result", evt_tag_printf("msg", "%p", msg), evt_tag_str("result", res ? "match" : "not-match"), evt_tag_str("rule", self->name), log_pipe_location_tag(s)); if (res) { log_pipe_forward_msg(s, msg, path_options); stats_counter_inc(self->matched); } else { if (path_options->matched) (*path_options->matched) = FALSE; log_msg_drop(msg, path_options, AT_PROCESSED); stats_counter_inc(self->not_matched); } } static LogPipe * log_filter_pipe_clone(LogPipe *s) { LogFilterPipe *self = (LogFilterPipe *) s; LogPipe *cloned = log_filter_pipe_new(filter_expr_ref(self->expr), s->cfg); ((LogFilterPipe *)cloned)->name = g_strdup(self->name); return cloned; } static void log_filter_pipe_free(LogPipe *s) { LogFilterPipe *self = (LogFilterPipe *) s; stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_FILTER, self->name, NULL ); stats_unregister_counter(&sc_key, SC_TYPE_MATCHED, &self->matched); stats_unregister_counter(&sc_key, SC_TYPE_NOT_MATCHED, &self->not_matched); stats_unlock(); g_free(self->name); filter_expr_unref(self->expr); log_pipe_free_method(s); } LogPipe * log_filter_pipe_new(FilterExprNode *expr, GlobalConfig *cfg) { LogFilterPipe *self = g_new0(LogFilterPipe, 1); log_pipe_init_instance(&self->super, cfg); self->super.init = log_filter_pipe_init; self->super.queue = log_filter_pipe_queue; self->super.free_fn = log_filter_pipe_free; self->super.clone = log_filter_pipe_clone; self->expr = expr; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/filter/filter-pipe.h000066400000000000000000000027731321171025300220720ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILTER_PIPE_H_INCLUDED #define FILTER_PIPE_H_INCLUDED #include "filter/filter-expr.h" #include "logpipe.h" /* convert a filter expression into a drop/accept LogPipe */ /* * This class encapsulates a LogPipe that either drops/allows a LogMessage * to go through. */ typedef struct _LogFilterPipe { LogPipe super; FilterExprNode *expr; gchar *name; StatsCounterItem *matched; StatsCounterItem *not_matched; } LogFilterPipe; LogPipe *log_filter_pipe_new(FilterExprNode *expr, GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/lib/filter/filter-pri.c000066400000000000000000000046501321171025300217160ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter/filter-pri.h" #include "syslog-names.h" #include "logmsg/logmsg.h" typedef struct _FilterPri { FilterExprNode super; guint32 valid; } FilterPri; static gboolean filter_facility_eval(FilterExprNode *s, LogMessage **msgs, gint num_msg) { FilterPri *self = (FilterPri *) s; LogMessage *msg = msgs[num_msg - 1]; guint32 fac_num = (msg->pri & LOG_FACMASK) >> 3; if (G_UNLIKELY(self->valid & 0x80000000)) { /* exact number specified */ return ((self->valid & ~0x80000000) == fac_num) ^ s->comp; } else { return !!(self->valid & (1 << fac_num)) ^ self->super.comp; } return self->super.comp; } FilterExprNode * filter_facility_new(guint32 facilities) { FilterPri *self = g_new0(FilterPri, 1); filter_expr_node_init_instance(&self->super); self->super.eval = filter_facility_eval; self->valid = facilities; self->super.type = "facility"; return &self->super; } static gboolean filter_level_eval(FilterExprNode *s, LogMessage **msgs, gint num_msg) { FilterPri *self = (FilterPri *) s; LogMessage *msg = msgs[num_msg - 1]; guint32 pri = msg->pri & LOG_PRIMASK; return !!((1 << pri) & self->valid) ^ self->super.comp; } FilterExprNode * filter_level_new(guint32 levels) { FilterPri *self = g_new0(FilterPri, 1); filter_expr_node_init_instance(&self->super); self->super.eval = filter_level_eval; self->valid = levels; self->super.type = "level"; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/filter/filter-pri.h000066400000000000000000000022671321171025300217250ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILTER_PRI_H_INCLUDED #define FILTER_PRI_H_INCLUDED #include "filter-expr.h" FilterExprNode *filter_facility_new(guint32 facilities); FilterExprNode *filter_level_new(guint32 levels); #endif syslog-ng-syslog-ng-3.13.2/lib/filter/filter-re.c000066400000000000000000000107421321171025300215310ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter-re.h" #include "str-utils.h" #include "messages.h" #include static gboolean filter_re_eval_string(FilterExprNode *s, LogMessage *msg, gint value_handle, const gchar *str, gssize str_len) { FilterRE *self = (FilterRE *) s; gboolean result; if (str_len < 0) str_len = strlen(str); result = log_matcher_match(self->matcher, msg, value_handle, str, str_len) ^ self->super.comp; msg_debug("Filter regexp node evaluation result", evt_tag_printf("msg", "%p", msg), evt_tag_str("input", str), evt_tag_str("result", result ? "match" : "not-match")); return result; } static gboolean filter_re_eval(FilterExprNode *s, LogMessage **msgs, gint num_msg) { FilterRE *self = (FilterRE *) s; const gchar *value; LogMessage *msg = msgs[num_msg - 1]; gssize len = 0; value = log_msg_get_value(msg, self->value_handle, &len); APPEND_ZERO(value, value, len); return filter_re_eval_string(s, msg, self->value_handle, value, len); } static void filter_re_free(FilterExprNode *s) { FilterRE *self = (FilterRE *) s; log_matcher_unref(self->matcher); log_matcher_options_destroy(&self->matcher_options); } static void filter_re_init(FilterExprNode *s, GlobalConfig *cfg) { FilterRE *self = (FilterRE *) s; if (self->matcher_options.flags & LMF_STORE_MATCHES) self->super.modify = TRUE; } gboolean filter_re_compile_pattern(FilterRE *self, GlobalConfig *cfg, gchar *re, GError **error) { log_matcher_options_init(&self->matcher_options, cfg); self->matcher = log_matcher_new(cfg, &self->matcher_options); return log_matcher_compile(self->matcher, re, error); } static void filter_re_init_instance(FilterRE *self, NVHandle value_handle) { filter_expr_node_init_instance(&self->super); self->value_handle = value_handle; self->super.init = filter_re_init; self->super.eval = filter_re_eval; self->super.free_fn = filter_re_free; self->super.type = "regexp"; log_matcher_options_defaults(&self->matcher_options); self->matcher_options.flags |= LMF_MATCH_ONLY; } FilterRE * filter_re_new(NVHandle value_handle) { FilterRE *self = g_new0(FilterRE, 1); filter_re_init_instance(self, value_handle); return self; } FilterRE * filter_source_new(void) { FilterRE *self = filter_re_new(LM_V_SOURCE); if (!log_matcher_options_set_type(&self->matcher_options, "string")) { /* this can only happen if the plain text string matcher will cease to exist */ g_assert_not_reached(); } return self; } static gboolean filter_match_eval(FilterExprNode *s, LogMessage **msgs, gint num_msg) { FilterRE *self = (FilterRE *) s; gchar *str; gboolean res; LogMessage *msg = msgs[num_msg - 1]; if (G_UNLIKELY(!self->value_handle)) { const gchar *pid; gssize pid_len; pid = log_msg_get_value(msg, LM_V_PID, &pid_len); /* compatibility mode */ str = g_strdup_printf("%s%s%s%s: %s", log_msg_get_value(msg, LM_V_PROGRAM, NULL), pid_len > 0 ? "[" : "", pid, pid_len > 0 ? "]" : "", log_msg_get_value(msg, LM_V_MESSAGE, NULL)); res = filter_re_eval_string(s, msg, LM_V_NONE, str, -1); g_free(str); } else { res = filter_re_eval(s, msgs, num_msg); } return res; } FilterRE * filter_match_new(void) { FilterRE *self = g_new0(FilterRE, 1); filter_re_init_instance(self, 0); self->super.eval = filter_match_eval; return self; } syslog-ng-syslog-ng-3.13.2/lib/filter/filter-re.h000066400000000000000000000027711321171025300215410ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILTER_RE_H_INCLUDED #define FILTER_RE_H_INCLUDED #include "filter-expr.h" #include "logmatcher.h" typedef struct _FilterRE { FilterExprNode super; NVHandle value_handle; LogMatcherOptions matcher_options; LogMatcher *matcher; } FilterRE; typedef struct _FilterMatch FilterMatch; gboolean filter_re_compile_pattern(FilterRE *self, GlobalConfig *cfg, gchar *re, GError **error); FilterRE *filter_re_new(NVHandle value_handle); FilterRE *filter_source_new(void); FilterRE *filter_match_new(void); #endif syslog-ng-syslog-ng-3.13.2/lib/filter/filter-tags.c000066400000000000000000000044741321171025300220660ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Balázs Scheidler * Copyright (c) 2013 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter-tags.h" #include "logmsg/logmsg.h" typedef struct _FilterTags { FilterExprNode super; GArray *tags; } FilterTags; static gboolean filter_tags_eval(FilterExprNode *s, LogMessage **msgs, gint num_msg) { FilterTags *self = (FilterTags *)s; LogMessage *msg = msgs[num_msg - 1]; gint i; for (i = 0; i < self->tags->len; i++) { if (log_msg_is_tag_by_id(msg, g_array_index(self->tags, LogTagId, i))) return TRUE ^ s->comp; } return FALSE ^ s->comp; } void filter_tags_add(FilterExprNode *s, GList *tags) { FilterTags *self = (FilterTags *)s; LogTagId id; while (tags) { id = log_tags_get_by_name((gchar *) tags->data); g_free(tags->data); tags = g_list_delete_link(tags, tags); g_array_append_val(self->tags, id); } } static void filter_tags_free(FilterExprNode *s) { FilterTags *self = (FilterTags *)s; g_array_free(self->tags, TRUE); } FilterExprNode * filter_tags_new(GList *tags) { FilterTags *self = g_new0(FilterTags, 1); filter_expr_node_init_instance(&self->super); self->tags = g_array_new(FALSE, FALSE, sizeof(LogTagId)); filter_tags_add(&self->super, tags); self->super.eval = filter_tags_eval; self->super.free_fn = filter_tags_free; self->super.type = "tags"; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/filter/filter-tags.h000066400000000000000000000022621321171025300220640ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FILTER_TAGS_H_INCLUDED #define FILTER_TAGS_H_INCLUDED #include "filter-expr.h" void filter_tags_add(FilterExprNode *s, GList *tags); FilterExprNode *filter_tags_new(GList *tags); #endif syslog-ng-syslog-ng-3.13.2/lib/filter/tests/000077500000000000000000000000001321171025300206325ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/filter/tests/Makefile.am000066400000000000000000000023241321171025300226670ustar00rootroot00000000000000lib_filter_tests_TESTS = \ lib/filter/tests/test_filters \ lib/filter/tests/test_filters_in_list \ lib/filter/tests/test_filters_netmask6 check_PROGRAMS += ${lib_filter_tests_TESTS} lib_filter_tests_test_filters_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/filter/tests lib_filter_tests_test_filters_LDADD = $(TEST_LDADD) \ $(PREOPEN_SYSLOGFORMAT) lib_filter_tests_test_filters_SOURCES = \ lib/filter/tests/test_filters.c lib_filter_tests_test_filters_in_list_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/filter/tests lib_filter_tests_test_filters_in_list_LDADD = $(TEST_LDADD) \ $(PREOPEN_SYSLOGFORMAT) lib_filter_tests_test_filters_netmask6_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/filter/tests lib_filter_tests_test_filters_netmask6_LDADD = $(TEST_LDADD) \ $(PREOPEN_SYSLOGFORMAT) if ENABLE_CRITERION lib_filter_tests_TESTS += lib/filter/tests/test_filters_statistics lib_filter_tests_test_filters_statistics_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/filter/tests lib_filter_tests_test_filters_statistics_LDADD = $(TEST_LDADD) \ $(PREOPEN_SYSLOGFORMAT) endif include lib/filter/tests/filters-in-list/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/filter/tests/filters-in-list/000077500000000000000000000000001321171025300236575ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/filter/tests/filters-in-list/Makefile.am000066400000000000000000000004171321171025300257150ustar00rootroot00000000000000EXTRA_DIST += \ lib/filter/tests/filters-in-list/test.list \ lib/filter/tests/filters-in-list/empty.list \ lib/filter/tests/filters-in-list/lot_of_lines.list \ lib/filter/tests/filters-in-list/ip.list \ lib/filter/tests/filters-in-list/long_line.list syslog-ng-syslog-ng-3.13.2/lib/filter/tests/filters-in-list/empty.list000066400000000000000000000000001321171025300257000ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/filter/tests/filters-in-list/ip.list000066400000000000000000000000341321171025300251610ustar00rootroot00000000000000192.168.1.1 192.168.255.254 syslog-ng-syslog-ng-3.13.2/lib/filter/tests/filters-in-list/long_line.list000066400000000000000000000023211321171025300265200ustar00rootroot00000000000000foo-bar1 foo-bar2 foo-bar3 foo-bar4 foo-bar5 foo-bar6 foo-bar7 foo-bar8 foo-bar9 foo-bar10 test-hostAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA foo-bar11 foo-bar12 foo-bar13 foo-bar14 foo-bar15 foo-bar16 foo-bar17 foo-bar18 foo-bar19 foo-bar20 foo-bar21 foo-bar22 foo-bar23 foo-bar24 foo-bar25 foo-bar26 foo-bar27 foo-bar28 foo-bar29 foo-bar30 foo-bar31 foo-bar32 foo-bar33 foo-bar34 foo-bar35 foo-bar36 foo-bar37 foo-bar38 foo-bar39 foo-bar40 foo-bar41 foo-bar42 foo-bar43 foo-bar44 foo-bar45 foo-bar46 foo-bar47 foo-bar48 foo-bar49 foo-bar50 foo-bar51 foo-bar52 foo-bar53 foo-bar54 foo-bar55 foo-bar56 foo-bar57 foo-bar58 foo-bar59 foo-bar60 foo-bar61 foo-bar62 foo-bar63 foo-bar64 foo-bar65 foo-bar66 foo-bar67 foo-bar68 foo-bar69 foo-bar70 foo-bar71 foo-bar72 foo-bar73 foo-bar74 foo-bar75 foo-bar76 foo-bar77 foo-bar78 foo-bar79 foo-bar80 foo-bar81 foo-bar82 foo-bar83 foo-bar84 foo-bar85 foo-bar86 foo-bar87 foo-bar88 foo-bar89 foo-bar90 foo-bar91 foo-bar92 foo-bar93 foo-bar94 foo-bar95 foo-bar96 foo-bar97 foo-bar98 foo-bar99 foo-bar100 syslog-ng-syslog-ng-3.13.2/lib/filter/tests/filters-in-list/lot_of_lines.list000066400000000000000000000017551321171025300272400ustar00rootroot00000000000000test-program foo-bar1 foo-bar2 foo-bar3 foo-bar4 foo-bar5 foo-bar6 foo-bar7 foo-bar8 foo-bar9 foo-bar10 foo-bar11 foo-bar12 foo-bar13 foo-bar14 foo-bar15 foo-bar16 foo-bar17 foo-bar18 foo-bar19 foo-bar20 foo-bar21 foo-bar22 foo-bar23 foo-bar24 foo-bar25 foo-bar26 foo-bar27 foo-bar28 foo-bar29 foo-bar30 foo-bar31 foo-bar32 foo-bar33 foo-bar34 foo-bar35 foo-bar36 foo-bar37 foo-bar38 foo-bar39 foo-bar40 foo-bar41 foo-bar42 foo-bar43 foo-bar44 foo-bar45 foo-bar46 foo-bar47 foo-bar48 foo-bar49 foo-bar50 foo-bar51 foo-bar52 foo-bar53 foo-bar54 foo-bar55 foo-bar56 foo-bar57 foo-bar58 foo-bar59 foo-bar60 foo-bar61 foo-bar62 foo-bar63 foo-bar64 foo-bar65 foo-bar66 foo-bar67 foo-bar68 foo-bar69 foo-bar70 foo-bar71 foo-bar72 foo-bar73 foo-bar74 foo-bar75 foo-bar76 foo-bar77 foo-bar78 foo-bar79 foo-bar80 foo-bar81 foo-bar82 foo-bar83 foo-bar84 foo-bar85 foo-bar86 foo-bar87 foo-bar88 foo-bar89 foo-bar90 foo-bar91 foo-bar92 foo-bar93 foo-bar94 foo-bar95 foo-bar96 foo-bar97 foo-bar98 foo-bar99 foo-bar100 syslog-ng-syslog-ng-3.13.2/lib/filter/tests/filters-in-list/test.list000066400000000000000000000000151321171025300255270ustar00rootroot00000000000000test-program syslog-ng-syslog-ng-3.13.2/lib/filter/tests/test_filters.c000066400000000000000000000717301321171025300235150ustar00rootroot00000000000000/* * Copyright (c) 2005-2015 Balabit * Copyright (c) 2005-2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "filter/filter-expr.h" #include "filter/filter-expr-grammar.h" #include "filter/filter-netmask.h" #include "filter/filter-netmask6.h" #include "filter/filter-op.h" #include "filter/filter-cmp.h" #include "filter/filter-tags.h" #include "filter/filter-re.h" #include "filter/filter-pri.h" #include "cfg.h" #include "messages.h" #include "syslog-names.h" #include "logmsg/logmsg.h" #include "apphook.h" #include "plugin.h" #include #include #include #include int debug = 1; GSockAddr *sender_saddr; MsgFormatOptions parse_options; static gint facility_bits(gchar *fac) { return 1 << (syslog_name_lookup_facility_by_name(fac) >> 3); } static gint level_bits(gchar *lev) { return 1 << syslog_name_lookup_level_by_name(lev); } static gint level_range(gchar *from, gchar *to) { int r1, r2; r1 = syslog_name_lookup_level_by_name(from); r2 = syslog_name_lookup_level_by_name(to); return syslog_make_range(r1, r2); } FilterExprNode * compile_pattern(FilterRE *f, gchar *regexp, const gchar *type, gint flags) { gboolean result; log_matcher_options_defaults(&f->matcher_options); f->matcher_options.flags = flags; log_matcher_options_set_type(&f->matcher_options, type); result = filter_re_compile_pattern(f, configuration, regexp, NULL); if (result) return &f->super; filter_expr_unref(&f->super); return NULL; } FilterExprNode * create_posix_regexp_filter(NVHandle handle, gchar *regexp, gint flags) { return compile_pattern(filter_re_new(handle), regexp, "posix", flags); } FilterExprNode * create_posix_regexp_match(gchar *regexp, gint flags) { return compile_pattern(filter_match_new(), regexp, "posix", flags); } FilterExprNode * create_pcre_regexp_filter(gint field, gchar *regexp, gint flags) { return compile_pattern(filter_re_new(field), regexp, "pcre", flags); } FilterExprNode * create_pcre_regexp_match(gchar *regexp, gint flags) { return compile_pattern(filter_match_new(), regexp, "pcre", flags); } LogTemplate * create_template(const gchar *template) { LogTemplate *t; t = log_template_new(configuration, NULL); log_template_compile(t, template, NULL); return t; } void testcase(gchar *msg, FilterExprNode *f, gboolean expected_result) { LogMessage *logmsg; gboolean res; static gint testno = 0; filter_expr_init(f, configuration); testno++; logmsg = log_msg_new(msg, strlen(msg), NULL, &parse_options); logmsg->saddr = g_sockaddr_ref(sender_saddr); res = filter_expr_eval(f, logmsg); if (res != expected_result) { fprintf(stderr, "Filter test failed; num='%d', msg='%s'\n", testno, msg); exit(1); } f->comp = 1; res = filter_expr_eval(f, logmsg); if (res != !expected_result) { fprintf(stderr, "Filter test failed (negated); num='%d', msg='%s'\n", testno, msg); exit(1); } log_msg_unref(logmsg); filter_expr_unref(f); } void testcase_with_backref_chk(gchar *msg, FilterExprNode *f, gboolean expected_result, const gchar *name, const gchar *value ) { LogMessage *logmsg; const gchar *value_msg; NVTable *nv_table; gboolean res; static gint testno = 0; gssize length; NVHandle nonasciiz = log_msg_get_value_handle("NON-ASCIIZ"); gssize msglen; gchar buf[1024]; testno++; logmsg = log_msg_new(msg, strlen(msg), NULL, &parse_options); logmsg->saddr = g_sockaddr_inet_new("10.10.0.1", 5000); /* NOTE: we test how our filters cope with non-zero terminated values. We don't change message_len, only the value */ g_snprintf(buf, sizeof(buf), "%sAAAAAAAAAAAA", log_msg_get_value(logmsg, LM_V_MESSAGE, &msglen)); log_msg_set_value_by_name(logmsg, "MESSAGE2", buf, -1); /* add a non-zero terminated indirect value which contains the whole message */ log_msg_set_value_indirect(logmsg, nonasciiz, log_msg_get_value_handle("MESSAGE2"), 0, 0, msglen); nv_table = nv_table_ref(logmsg->payload); res = filter_expr_eval(f, logmsg); if (res != expected_result) { fprintf(stderr, "Filter test failed; num='%d', msg='%s'\n", testno, msg); exit(1); } nv_table_unref(nv_table); f->comp = 1; nv_table = nv_table_ref(logmsg->payload); res = filter_expr_eval(f, logmsg); if (res != !expected_result) { fprintf(stderr, "Filter test failed (negated); num='%d', msg='%s'\n", testno, msg); exit(1); } value_msg = log_msg_get_value_by_name(logmsg, name, &length); nv_table_unref(nv_table); if(value == NULL || value[0] == 0) { if (value_msg != NULL && value_msg[0] != 0) { fprintf(stderr, "Filter test failed (NULL value chk); num='%d', msg='%s', expected_value='%s', value_in_msg='%s'", testno, msg, value, value_msg); exit(1); } } else { if (strncmp(value_msg, value, length) != 0) { fprintf(stderr, "Filter test failed (value chk); num='%d', msg='%s', expected_value='%s', value_in_msg='%s'", testno, msg, value, value_msg); exit(1); } } log_msg_unref(logmsg); filter_expr_unref(f); } #define TEST_ASSERT(cond) \ if (!(cond)) \ { \ fprintf(stderr, "Test assertion failed at %d\n", __LINE__); \ exit(1); \ } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { gint i; app_startup(); configuration = cfg_new_snippet(); cfg_load_module(configuration, "syslogformat"); msg_format_options_defaults(&parse_options); msg_format_options_init(&parse_options, configuration); testcase("<15> openvpn[2499]: PTHREAD support initialized", filter_facility_new(facility_bits("user")), 1); testcase("<15> openvpn[2499]: PTHREAD support initialized", filter_facility_new(facility_bits("daemon")), 0); testcase("<15> openvpn[2499]: PTHREAD support initialized", filter_facility_new(facility_bits("daemon") | facility_bits("user")), 1); testcase("<15> openvpn[2499]: PTHREAD support initialized", filter_facility_new(facility_bits("uucp") | facility_bits("local4")), 0); testcase("<15> openvpn[2499]: PTHREAD support initialized", filter_facility_new(0x80000000 | (LOG_USER >> 3)), 1); testcase("<15> openvpn[2499]: PTHREAD support initialized", filter_facility_new(0x80000000 | (LOG_DAEMON >> 3)), 0); testcase("<2> openvpn[2499]: PTHREAD support initialized", filter_facility_new(facility_bits("kern")), 1); testcase("<2> openvpn[2499]: PTHREAD support initialized", filter_facility_new(0x80000000 | (LOG_KERN >> 3)), 1); testcase("<128> openvpn[2499]: PTHREAD support initialized", filter_facility_new(facility_bits("local0")), 1); testcase("<128> openvpn[2499]: PTHREAD support initialized", filter_facility_new(0x80000000 | (LOG_LOCAL0 >> 3)), 1); testcase("<32> openvpn[2499]: PTHREAD support initialized", filter_facility_new(facility_bits("local1")), 0); testcase("<32> openvpn[2499]: PTHREAD support initialized", filter_facility_new(facility_bits("auth")), 1); testcase("<32> openvpn[2499]: PTHREAD support initialized", filter_facility_new(0x80000000 | (LOG_AUTH >> 3)), 1); #ifdef LOG_AUTHPRIV testcase("<80> openvpn[2499]: PTHREAD support initialized", filter_facility_new(facility_bits("authpriv")), 1); testcase("<80> openvpn[2499]: PTHREAD support initialized", filter_facility_new(0x80000000 | (LOG_AUTHPRIV >> 3)), 1); #endif testcase("<15> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_bits("debug") | level_bits("emerg")), 1); testcase("<15> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_bits("emerg")), 0); testcase("<8> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("crit", "emerg")), 1); testcase("<9> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("crit", "emerg")), 1); testcase("<10> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("crit", "emerg")), 1); testcase("<11> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("crit", "emerg")), 0); testcase("<12> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("crit", "emerg")), 0); testcase("<13> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("crit", "emerg")), 0); testcase("<14> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("crit", "emerg")), 0); testcase("<15> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("crit", "emerg")), 0); testcase("<8> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("debug", "notice")), 0); testcase("<9> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("debug", "notice")), 0); testcase("<10> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("debug", "notice")), 0); testcase("<11> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("debug", "notice")), 0); testcase("<12> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("debug", "notice")), 0); testcase("<13> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("debug", "notice")), 1); testcase("<14> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("debug", "notice")), 1); testcase("<15> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_range("debug", "notice")), 1); for (i = 0; i < 10; i++) { testcase("<0> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_bits("emerg")), 1); testcase("<1> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_bits("alert")), 1); testcase("<2> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_bits("crit")), 1); testcase("<3> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_bits("err")), 1); testcase("<4> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_bits("warning")), 1); testcase("<5> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_bits("notice")), 1); testcase("<6> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_bits("info")), 1); testcase("<7> openvpn[2499]: PTHREAD support initialized", filter_level_new(level_bits("debug")), 1); } testcase("<15> openvpn[2499]: PTHREAD support initialized", create_posix_regexp_filter(LM_V_PROGRAM, "^openvpn$", 0), 1); testcase("<15> openvpn[2499]: PTHREAD support initialized", create_posix_regexp_filter(LM_V_PROGRAM, "^open$", 0), 0); TEST_ASSERT(create_posix_regexp_filter(LM_V_PROGRAM, "((", 0) == NULL); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_posix_regexp_filter(LM_V_HOST, "^host$", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_posix_regexp_filter(LM_V_HOST, "^hos$", 0), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_posix_regexp_filter(LM_V_HOST, "pthread", 0), 0); TEST_ASSERT(create_posix_regexp_filter(LM_V_HOST, "((", 0) == NULL); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_posix_regexp_filter(LM_V_MESSAGE, "^PTHREAD ", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_posix_regexp_filter(LM_V_MESSAGE, "PTHREAD s", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_posix_regexp_filter(LM_V_MESSAGE, "^PTHREAD$", 0), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_posix_regexp_filter(LM_V_MESSAGE, "(?i)pthread", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_posix_regexp_match(" PTHREAD ", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_posix_regexp_match("^openvpn\\[2499\\]: PTHREAD", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_posix_regexp_match("^PTHREAD$", 0), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_posix_regexp_match("(?i)pthread", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_posix_regexp_match("pthread", LMF_ICASE), 1); TEST_ASSERT(create_posix_regexp_match("((", 0) == NULL); #if SYSLOG_NG_ENABLE_IPV6 sender_saddr = g_sockaddr_inet6_new("2001:db80:85a3:8d30:1319:8a2e:3700:7348", 5000); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::/1"), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("2001:db80:85a3:8d30:1319:8a2e::/95"), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("2001:db80:85a3:8d30:1319:8a2e:3700:7348/60"), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("2001:db80:85a3:8d30:1319:8a2e:3700::/114"), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::85a3:8d30:1319:8a2e:3700::/114"), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("aaaaaa/32"), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("/8"), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::"), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new(""), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::1/8"), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::1/128"), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::2/32"), 0); g_sockaddr_unref(sender_saddr); sender_saddr = NULL; testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("aaaaaa/32"), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("/8"), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new(""), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::1"), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::/32"), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::1/8"), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::1/128"), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::/16"), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::/599"), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask6_new("::/aaa"), 0); #endif sender_saddr = g_sockaddr_inet_new("10.10.0.1", 5000); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask_new("10.10.0.0/16"), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask_new("10.10.0.0/24"), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask_new("10.10.10.0/24"), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask_new("0.0.10.10/24"), 0); g_sockaddr_unref(sender_saddr); sender_saddr = NULL; testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask_new("127.0.0.1/32"), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", filter_netmask_new("127.0.0.2/32"), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_or_new(create_posix_regexp_match(" PTHREAD ", 0), create_posix_regexp_match("PTHREAD", 0)), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_or_new(create_posix_regexp_match(" PTHREAD ", 0), create_posix_regexp_match("^PTHREAD$", 0)), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_or_new(create_posix_regexp_match("^PTHREAD$", 0), create_posix_regexp_match(" PTHREAD ", 0)), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_or_new(create_posix_regexp_match(" PAD ", 0), create_posix_regexp_match("^PTHREAD$", 0)), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_and_new(create_posix_regexp_match(" PTHREAD ", 0), create_posix_regexp_match("PTHREAD", 0)), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_and_new(create_posix_regexp_match(" PTHREAD ", 0), create_posix_regexp_match("^PTHREAD$", 0)), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_and_new(create_posix_regexp_match("^PTHREAD$", 0), create_posix_regexp_match(" PTHREAD ", 0)), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_and_new(create_posix_regexp_match(" PAD ", 0), create_posix_regexp_match("^PTHREAD$", 0)), 0); /* LEVEL_NUM is 7 */ testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("$LEVEL_NUM"), create_template("7"), KW_NUM_EQ), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("$LEVEL_NUM"), create_template("5"), KW_NUM_NE), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("$LEVEL_NUM"), create_template("8"), KW_NUM_LT), 1); /* 7 < 10 is TRUE */ testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("$LEVEL_NUM"), create_template("10"), KW_NUM_LT), 1); /* 7 lt 10 is FALSE as 10 orders lower when interpreted as a string */ testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("$LEVEL_NUM"), create_template("10"), KW_LT), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("$LEVEL_NUM"), create_template("5"), KW_NUM_GT), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("$LEVEL_NUM"), create_template("7"), KW_NUM_GE), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("$LEVEL_NUM"), create_template("7"), KW_NUM_LE), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("alma"), create_template("korte"), KW_LT), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("alma"), create_template("korte"), KW_LE), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("alma"), create_template("korte"), KW_EQ), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("alma"), create_template("korte"), KW_NE), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("alma"), create_template("korte"), KW_GE), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("alma"), create_template("korte"), KW_GT), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("korte"), create_template("alma"), KW_LT), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("korte"), create_template("alma"), KW_LE), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("korte"), create_template("alma"), KW_EQ), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("korte"), create_template("alma"), KW_NE), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("korte"), create_template("alma"), KW_GE), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("korte"), create_template("alma"), KW_GT), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("alma"), create_template("alma"), KW_LT), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("alma"), create_template("alma"), KW_LE), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("alma"), create_template("alma"), KW_EQ), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("alma"), create_template("alma"), KW_NE), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("alma"), create_template("alma"), KW_GE), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_cmp_new(create_template("alma"), create_template("alma"), KW_GT), 0); testcase_with_backref_chk("<15>Oct 15 16:17:01 host openvpn[2499]: al fa", create_posix_regexp_filter(LM_V_MESSAGE, "(a)(l) (fa)", LMF_STORE_MATCHES), 1, "1","a"); testcase_with_backref_chk("<15>Oct 15 16:17:01 host openvpn[2499]: al fa", create_posix_regexp_filter(LM_V_MESSAGE, "(a)(l) (fa)", LMF_STORE_MATCHES), 1, "0","al fa"); testcase_with_backref_chk("<15>Oct 15 16:17:01 host openvpn[2499]: al fa", create_posix_regexp_filter(LM_V_MESSAGE, "(a)(l) (fa)", LMF_STORE_MATCHES), 1, "232", NULL); testcase("<15> openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_filter(LM_V_PROGRAM, "^openvpn$", 0), 1); testcase("<15> openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_filter(LM_V_PROGRAM, "^open$", 0), 0); TEST_ASSERT(create_pcre_regexp_filter(LM_V_PROGRAM, "((", 0) == NULL); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_filter(LM_V_HOST, "^host$", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_filter(LM_V_HOST, "^hos$", 0), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_filter(LM_V_HOST, "pthread", 0), 0); TEST_ASSERT(create_pcre_regexp_filter(LM_V_HOST, "((", 0) == NULL); TEST_ASSERT(create_posix_regexp_filter(LM_V_HOST, "(?iana", 0) == NULL); TEST_ASSERT(create_pcre_regexp_filter(LM_V_HOST, "(?iana", 0) == NULL); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_filter(LM_V_MESSAGE, "^PTHREAD ", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_filter(LM_V_MESSAGE, "PTHREAD s", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_filter(LM_V_MESSAGE, "^PTHREAD$", 0), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_filter(LM_V_MESSAGE, "(?i)pthread", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_and_new(create_pcre_regexp_match(" PTHREAD ", 0), create_posix_regexp_match("PTHREAD", 0)), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_and_new(create_pcre_regexp_match(" PTHREAD ", 0), create_posix_regexp_match("^PTHREAD$", 0)), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_and_new(create_pcre_regexp_match("^PTHREAD$", 0), create_posix_regexp_match(" PTHREAD ", 0)), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_and_new(create_pcre_regexp_match(" PAD ", 0), create_posix_regexp_match("^PTHREAD$", 0)), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_or_new(create_pcre_regexp_match(" PTHREAD ", 0), create_pcre_regexp_match("PTHREAD", 0)), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_or_new(create_pcre_regexp_match(" PTHREAD ", 0), create_pcre_regexp_match("^PTHREAD$", 0)), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_or_new(create_pcre_regexp_match("^PTHREAD$", 0), create_pcre_regexp_match(" PTHREAD ", 0)), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", fop_or_new(create_pcre_regexp_match(" PAD ", 0), create_pcre_regexp_match("^PTHREAD$", 0)), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_match(" PTHREAD ", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_match("^openvpn\\[2499\\]: PTHREAD", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_match("^PTHREAD$", 0), 0); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_match("(?i)pthread", 0), 1); testcase("<15>Oct 15 16:17:01 host openvpn[2499]: PTHREAD support initialized", create_pcre_regexp_match("pthread", LMF_ICASE), 1); TEST_ASSERT(create_pcre_regexp_match("((", 0) == NULL); testcase_with_backref_chk("<15>Oct 15 16:17:01 host openvpn[2499]: alma fa", create_pcre_regexp_filter(LM_V_MESSAGE, "(?Pa)(?Pl)(?Pm)(?Pa) (?Pfa)", LMF_STORE_MATCHES), 1, "MM","m"); testcase_with_backref_chk("<15>Oct 15 16:17:01 host openvpn[2499]: alma fa", create_pcre_regexp_filter(LM_V_MESSAGE, "(?Pa)(?Pl)(?Pm)(?Pa) (?Pfa)", LMF_STORE_MATCHES), 1, "aaaa", NULL); testcase_with_backref_chk("<15>Oct 15 16:17:01 host openvpn[2499]: alma fa", create_pcre_regexp_filter(LM_V_MESSAGE, "(?Pa)(?Pl)(?Pm)(?Pa) (?Pfa)", LMF_STORE_MATCHES), 1, "fa_name","fa"); testcase_with_backref_chk("<15>Oct 15 16:17:01 host openvpn[2499]: al fa", create_pcre_regexp_filter(LM_V_MESSAGE, "(a)(l) (fa)", LMF_STORE_MATCHES), 1, "2","l"); testcase_with_backref_chk("<15>Oct 15 16:17:01 host openvpn[2499]: al fa", create_pcre_regexp_filter(LM_V_MESSAGE, "(a)(l) (fa)", LMF_STORE_MATCHES), 1, "0","al fa"); testcase_with_backref_chk("<15>Oct 15 16:17:01 host openvpn[2499]: al fa", create_pcre_regexp_filter(LM_V_MESSAGE, "(a)(l) (fa)", LMF_STORE_MATCHES), 1, "233",NULL); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/filter/tests/test_filters_in_list.c000066400000000000000000000141371321171025300252340ustar00rootroot00000000000000/* * Copyright (c) 2013, 2014 Balabit * Copyright (c) 2013, 2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include #include "cfg.h" #include "messages.h" #include "syslog-names.h" #include "logmsg/logmsg.h" #include "apphook.h" #include "plugin.h" #include "filter/filter-in-list.h" #include "testutils.h" #define MSG_1 "<15>Sep 4 15:03:55 localhost test-program[3086]: some random message" #define MSG_2 "<15>Sep 4 15:03:55 localhost foo[3086]: some random message" #define MSG_3 "<15>Sep 4 15:03:55 192.168.1.1 foo[3086]: some random message" #define MSG_LONG "<15>Sep 4 15:03:55 test-hostAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA foo[3086]: some random message" #define LIST_FILE_DIR "%s/lib/filter/tests/filters-in-list/" static MsgFormatOptions parse_options; gboolean evaluate_testcase(gchar *msg, FilterExprNode *filter_node) { LogMessage *log_msg; gboolean result; assert_not_null(filter_node, "Constructing an in-list filter"); log_msg = log_msg_new(msg, strlen(msg), NULL, &parse_options); result = filter_expr_eval(filter_node, log_msg); log_msg_unref(log_msg); filter_expr_unref(filter_node); return result; } void test_filter_returns_false_when_list_is_empty(const char *top_srcdir) { gchar *list_file_with_zero_lines = g_strdup_printf(LIST_FILE_DIR "empty.list", top_srcdir); assert_gboolean(evaluate_testcase(MSG_1, filter_in_list_new(list_file_with_zero_lines, "PROGRAM")), FALSE, "in-list filter matches"); g_free(list_file_with_zero_lines); } void test_string_searched_for_is_not_in_the_list(const char *top_srcdir) { gchar *list_file_with_one_line = g_strdup_printf(LIST_FILE_DIR "test.list", top_srcdir); assert_gboolean(evaluate_testcase(MSG_2, filter_in_list_new(list_file_with_one_line, "PROGRAM")), FALSE, "in-list filter matches"); g_free(list_file_with_one_line); } void test_given_macro_is_not_available_in_this_message(const char *top_srcdir) { gchar *list_file_with_one_line = g_strdup_printf(LIST_FILE_DIR "test.list", top_srcdir); assert_gboolean(evaluate_testcase(MSG_2, filter_in_list_new(list_file_with_one_line, "FOO_MACRO")), FALSE, "in-list filter matches"); g_free(list_file_with_one_line); } void test_list_file_doesnt_exist(const char *top_srcdir) { gchar *list_file_which_doesnt_exist = g_strdup_printf(LIST_FILE_DIR "notexisting.list", top_srcdir); assert_null(filter_in_list_new(list_file_which_doesnt_exist, "PROGRAM"), "in-list filter should fail, when the list file does not exist"); g_free(list_file_which_doesnt_exist); } void test_list_file_contains_only_one_line(const char *top_srcdir) { gchar *list_file_with_one_line = g_strdup_printf(LIST_FILE_DIR "test.list", top_srcdir); assert_gboolean(evaluate_testcase(MSG_1, filter_in_list_new(list_file_with_one_line, "PROGRAM")), TRUE, "in-list filter matches"); g_free(list_file_with_one_line); } void test_list_file_contains_lot_of_lines(const char *top_srcdir) { gchar *list_file_which_has_a_lot_of_lines = g_strdup_printf(LIST_FILE_DIR "lot_of_lines.list", top_srcdir); assert_gboolean(evaluate_testcase(MSG_1, filter_in_list_new(list_file_which_has_a_lot_of_lines, "PROGRAM")), TRUE, "in-list filter matches"); g_free(list_file_which_has_a_lot_of_lines); } void test_filter_with_ip_address(const char *top_srcdir) { gchar *list_file_with_ip_address = g_strdup_printf(LIST_FILE_DIR "ip.list", top_srcdir); assert_gboolean(evaluate_testcase(MSG_3, filter_in_list_new(list_file_with_ip_address, "HOST")), TRUE, "in-list filter matches"); g_free(list_file_with_ip_address); } void test_filter_with_long_line(const char *top_srcdir) { gchar *list_file_with_long_line = g_strdup_printf(LIST_FILE_DIR "long_line.list", top_srcdir); assert_gboolean(evaluate_testcase(MSG_LONG, filter_in_list_new(list_file_with_long_line, "HOST")), TRUE, "in-list filter matches"); g_free(list_file_with_long_line); } void run_testcases(const char *top_srcdir) { test_filter_returns_false_when_list_is_empty(top_srcdir); test_string_searched_for_is_not_in_the_list(top_srcdir); test_given_macro_is_not_available_in_this_message(top_srcdir); test_list_file_doesnt_exist(top_srcdir); test_list_file_contains_only_one_line(top_srcdir); test_list_file_contains_lot_of_lines(top_srcdir); test_filter_with_ip_address(top_srcdir); test_filter_with_long_line(top_srcdir); } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { char *top_srcdir = getenv("top_srcdir"); app_startup(); configuration = cfg_new_snippet(); cfg_load_module(configuration, "syslogformat"); msg_format_options_defaults(&parse_options); msg_format_options_init(&parse_options, configuration); assert_not_null(top_srcdir, "The $top_srcdir environment variable MUST NOT be empty!"); run_testcases(top_srcdir); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/filter/tests/test_filters_netmask6.c000066400000000000000000000115521321171025300253210ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Zoltan Fried * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "gsocket.h" #include "logmsg/logmsg.h" #include #include #include #include #include "testutils.h" #include "filter/filter-netmask6.h" static void _replace_last_zero_with_wildcard(gchar *ipv6) { if (!ipv6) return; gsize n = strlen(ipv6); if ((n >= 2) && (ipv6[n-2] == ':') && (ipv6[n-1] == '0')) ipv6[n-1] = ':'; } gchar * calculate_network6(const gchar *ipv6, int prefix, gchar *calculated_network) { struct in6_addr network; struct in6_addr address; memset(&network, 0, sizeof(struct in6_addr)); inet_pton(AF_INET6, ipv6, &address); get_network_address((unsigned char *)&address, prefix, &network); inet_ntop(AF_INET6, &network, calculated_network, INET6_ADDRSTRLEN); _replace_last_zero_with_wildcard(calculated_network); return calculated_network; } void assert_netmask6(const gchar *ipv6, gint prefix, gchar *expected_network) { char error_msg[64]; sprintf(error_msg, "prefix: %d", prefix); gchar *calculated_network = g_new0(char, INET6_ADDRSTRLEN); calculate_network6(ipv6, prefix, calculated_network); assert_string(calculated_network, expected_network, error_msg); g_free(calculated_network); } int main(void) { const gchar *ipv6 = "2001:db80:85a3:8d30:1319:8a2e:3700:7348"; assert_netmask6(ipv6, 1, "::"); assert_netmask6(ipv6, 3, "2000::"); assert_netmask6(ipv6, 16, "2001::"); assert_netmask6(ipv6, 17, "2001:8000::"); assert_netmask6(ipv6, 18, "2001:c000::"); assert_netmask6(ipv6, 20, "2001:d000::"); assert_netmask6(ipv6, 21, "2001:d800::"); assert_netmask6(ipv6, 23, "2001:da00::"); assert_netmask6(ipv6, 24, "2001:db00::"); assert_netmask6(ipv6, 25, "2001:db80::"); assert_netmask6(ipv6, 33, "2001:db80:8000::"); assert_netmask6(ipv6, 38, "2001:db80:8400::"); assert_netmask6(ipv6, 40, "2001:db80:8500::"); assert_netmask6(ipv6, 41, "2001:db80:8580::"); assert_netmask6(ipv6, 43, "2001:db80:85a0::"); assert_netmask6(ipv6, 47, "2001:db80:85a2::"); assert_netmask6(ipv6, 48, "2001:db80:85a3::"); assert_netmask6(ipv6, 49, "2001:db80:85a3:8000::"); assert_netmask6(ipv6, 54, "2001:db80:85a3:8c00::"); assert_netmask6(ipv6, 56, "2001:db80:85a3:8d00::"); assert_netmask6(ipv6, 59, "2001:db80:85a3:8d20::"); assert_netmask6(ipv6, 60, "2001:db80:85a3:8d30::"); assert_netmask6(ipv6, 68, "2001:db80:85a3:8d30:1000::"); assert_netmask6(ipv6, 71, "2001:db80:85a3:8d30:1200::"); assert_netmask6(ipv6, 72, "2001:db80:85a3:8d30:1300::"); assert_netmask6(ipv6, 76, "2001:db80:85a3:8d30:1310::"); assert_netmask6(ipv6, 77, "2001:db80:85a3:8d30:1318::"); assert_netmask6(ipv6, 80, "2001:db80:85a3:8d30:1319::"); assert_netmask6(ipv6, 81, "2001:db80:85a3:8d30:1319:8000::"); assert_netmask6(ipv6, 87, "2001:db80:85a3:8d30:1319:8a00::"); assert_netmask6(ipv6, 91, "2001:db80:85a3:8d30:1319:8a20::"); assert_netmask6(ipv6, 93, "2001:db80:85a3:8d30:1319:8a28::"); assert_netmask6(ipv6, 94, "2001:db80:85a3:8d30:1319:8a2c::"); assert_netmask6(ipv6, 95, "2001:db80:85a3:8d30:1319:8a2e::"); assert_netmask6(ipv6, 99, "2001:db80:85a3:8d30:1319:8a2e:2000::"); assert_netmask6(ipv6, 100, "2001:db80:85a3:8d30:1319:8a2e:3000::"); assert_netmask6(ipv6, 102, "2001:db80:85a3:8d30:1319:8a2e:3400::"); assert_netmask6(ipv6, 103, "2001:db80:85a3:8d30:1319:8a2e:3600::"); assert_netmask6(ipv6, 104, "2001:db80:85a3:8d30:1319:8a2e:3700::"); assert_netmask6(ipv6, 114, "2001:db80:85a3:8d30:1319:8a2e:3700:4000"); assert_netmask6(ipv6, 115, "2001:db80:85a3:8d30:1319:8a2e:3700:6000"); assert_netmask6(ipv6, 116, "2001:db80:85a3:8d30:1319:8a2e:3700:7000"); assert_netmask6(ipv6, 119, "2001:db80:85a3:8d30:1319:8a2e:3700:7200"); assert_netmask6(ipv6, 120, "2001:db80:85a3:8d30:1319:8a2e:3700:7300"); assert_netmask6(ipv6, 122, "2001:db80:85a3:8d30:1319:8a2e:3700:7340"); assert_netmask6(ipv6, 125, "2001:db80:85a3:8d30:1319:8a2e:3700:7348"); return 0; } syslog-ng-syslog-ng-3.13.2/lib/filter/tests/test_filters_statistics.c000066400000000000000000000057771321171025300257770ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include #include "plugin.h" #include "apphook.h" #include "syslog-names.h" #include "stats/stats-registry.h" #include "filter/filter-pipe.h" #include "filter/filter-pri.h" static gint level_bits(gchar *lev) { return 1 << syslog_name_lookup_level_by_name(lev); } MsgFormatOptions parse_options; static LogFilterPipe * create_log_filter_pipe(void) { FilterExprNode *filter = filter_level_new(level_bits("debug")); filter_expr_init(filter, configuration); LogFilterPipe *p = (LogFilterPipe *)log_filter_pipe_new(filter, configuration); stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_FILTER, "filter-matching", NULL ); stats_register_counter(1, &sc_key, SC_TYPE_MATCHED, &p->matched); stats_register_counter(1, &sc_key, SC_TYPE_NOT_MATCHED, &p->not_matched); stats_unlock(); return p; } static void queue_and_assert_statistics(LogFilterPipe *pipe, gchar *msg, guint32 matched_expected, guint32 not_matched_expected) { LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; LogMessage *logmsg = log_msg_new(msg, strlen(msg), NULL, &parse_options); LogPipe *p = (LogPipe *)pipe; p->queue(p, logmsg, &path_options, NULL); cr_assert_eq(stats_counter_get(pipe->not_matched), not_matched_expected); cr_assert_eq(stats_counter_get(pipe->matched), matched_expected); } Test(test_filters_statistics, filter_stastistics) { app_startup(); configuration = cfg_new_snippet(); configuration->stats_options.level = 1; cfg_load_module(configuration, "syslogformat"); cr_assert(cfg_init(configuration)); msg_format_options_defaults(&parse_options); msg_format_options_init(&parse_options, configuration); LogFilterPipe *p = create_log_filter_pipe(); queue_and_assert_statistics(p, "<15> openvpn[2499]: PTHREAD support initialized", 1, 0); queue_and_assert_statistics(p, "<16> openvpn[2499]: PTHREAD support initialized", 1, 1); queue_and_assert_statistics(p, "<16> openvpn[2499]: PTHREAD support initialized", 1, 2); cfg_deinit(configuration); cfg_free(configuration); app_shutdown(); } syslog-ng-syslog-ng-3.13.2/lib/find-crlf.c000066400000000000000000000057121321171025300202200ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "find-crlf.h" #include /** * This is an optimized version of finding either a CR or LF or NUL * character in a buffer. It is used to find these line terminators in * syslog traffic. * * It uses an algorithm very similar to what there's in libc memchr/strchr. **/ gchar * find_cr_or_lf(gchar *s, gsize n) { gchar *char_ptr; gulong *longword_ptr; gulong longword, magic_bits, cr_charmask, lf_charmask; const char CR = '\r'; const char LF = '\n'; /* align input to long boundary */ for (char_ptr = s; n > 0 && ((gulong) char_ptr & (sizeof(longword) - 1)) != 0; ++char_ptr, n--) { if (*char_ptr == CR || *char_ptr == LF) return char_ptr; else if (*char_ptr == 0) return NULL; } longword_ptr = (gulong *) char_ptr; #if GLIB_SIZEOF_LONG == 8 magic_bits = 0x7efefefefefefeffL; #elif GLIB_SIZEOF_LONG == 4 magic_bits = 0x7efefeffL; #else #error "unknown architecture" #endif memset(&cr_charmask, CR, sizeof(cr_charmask)); memset(&lf_charmask, LF, sizeof(lf_charmask)); while (n > sizeof(longword)) { longword = *longword_ptr++; if ((((longword + magic_bits) ^ ~longword) & ~magic_bits) != 0 || ((((longword ^ cr_charmask) + magic_bits) ^ ~(longword ^ cr_charmask)) & ~magic_bits) != 0 || ((((longword ^ lf_charmask) + magic_bits) ^ ~(longword ^ lf_charmask)) & ~magic_bits) != 0) { gint i; char_ptr = (gchar *) (longword_ptr - 1); for (i = 0; i < sizeof(longword); i++) { if (*char_ptr == CR || *char_ptr == LF) return char_ptr; else if (*char_ptr == 0) return NULL; char_ptr++; } } n -= sizeof(longword); } char_ptr = (gchar *) longword_ptr; while (n-- > 0) { if (*char_ptr == CR || *char_ptr == LF) return char_ptr; else if (*char_ptr == 0) return NULL; ++char_ptr; } return NULL; } syslog-ng-syslog-ng-3.13.2/lib/find-crlf.h000066400000000000000000000021621321171025300202210ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef FIND_CRLF_H_INCLUDED #define FIND_CRLF_H_INCLUDED 1 #include "syslog-ng.h" gchar *find_cr_or_lf(gchar *s, gsize n); #endif syslog-ng-syslog-ng-3.13.2/lib/globals.c000066400000000000000000000020701321171025300177710ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "syslog-ng.h" GlobalConfig *configuration; int cfg_parser_debug; syslog-ng-syslog-ng-3.13.2/lib/gprocess.c000066400000000000000000001233111321171025300201750ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "gprocess.h" #include "userdb.h" #include "messages.h" #include "reloc.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if SYSLOG_NG_ENABLE_LINUX_CAPS # include # include #endif /* * NOTES: * * * pidfile is created and removed by the daemon (e.g. the child) itself, * the parent does not touch that * * * we communicate with the user using stderr (using fprintf) as long as it * is available and using syslog() afterwards * * * there are 3 processes involved in safe_background mode (e.g. auto-restart) * - startup process which was started by the user (zorpctl) * - supervisor process which automatically restarts the daemon when it exits abnormally * - daemon processes which perform the actual task at hand * * The startup process delivers the result of the first startup to its * caller, if we can deliver a failure in this case then restarts will not * be performed (e.g. if the first startup fails, the daemon will not be * restarted even if auto-restart was enabled). After the first successful * start, the startup process exits (delivering that startup was * successful) and the supervisor process wait()s for the daemon processes * to exit. If they exit prematurely (e.g. they crash) they will be * restarted, if the startup is not successful in this case the restart * will be attempted again just as if they crashed. * * The processes communicate with two pairs of pipes, startup_result_pipe * is used to indicate success/failure to the startup process, * init_result_pipe (as in "initialization") is used to deliver success * reports from the daemon to the supervisor. */ typedef enum { G_PK_STARTUP, G_PK_SUPERVISOR, G_PK_DAEMON, } GProcessKind; #define SAFE_STRING(x) ((x) ? (x) : "NULL") #define G_PROCESS_FD_LIMIT_RESERVE 64 #define G_PROCESS_FAILURE_NOTIFICATION SYSLOG_NG_PATH_PREFIX "/sbin/syslog-ng-failure" /* pipe used to deliver the initialization result to the calling process */ static gint startup_result_pipe[2] = { -1, -1 }; /* pipe used to deliver initialization result to the supervisor */ static gint init_result_pipe[2] = { -1, -1 }; static GProcessKind process_kind = G_PK_STARTUP; static gboolean stderr_present = TRUE; #if SYSLOG_NG_ENABLE_LINUX_CAPS static int have_capsyslog = FALSE; #endif /* global variables */ static struct { GProcessMode mode; const gchar *name; const gchar *user; gint uid; const gchar *group; gint gid; const gchar *chroot_dir; const gchar *pidfile; const gchar *pidfile_dir; const gchar *cwd; const gchar *caps; gint argc; gchar **argv; gchar *argv_start; size_t argv_env_len; gchar *argv_orig; gboolean core; gint fd_limit_min; gint check_period; gboolean (*check_fn)(void); } process_opts = { .mode = G_PM_SAFE_BACKGROUND, .argc = 0, .argv = NULL, .argv_start = NULL, .argv_env_len = 0, .fd_limit_min = 0, .check_period = -1, .check_fn = NULL, .uid = -1, .gid = -1 }; #if SYSLOG_NG_ENABLE_SYSTEMD /** * Inherits systemd socket activation from parent process updating the pid * in LISTEN_PID to the pid of the child process. * * @return same as sd_listen_fds * r == 0: no socket activation or this process is not responsible * r > 0: success, number of sockets * r < 0: an error occured */ static int inherit_systemd_activation(void) { const char *e; char buf[24] = { '\0' }; char *p = NULL; unsigned long l; /* fetch listen pid */ if (!(e = getenv("LISTEN_PID"))) return 0; errno = 0; l = strtoul(e, &p, 10); if (errno != 0 || !p || *p || l == 0) return (errno) ? -errno : -EINVAL; /* was it for our parent? */ if (getppid() != (pid_t)l) return 0; /* verify listen fds */ if (!(e = getenv("LISTEN_FDS"))) return 0; errno = 0; l = strtoul(e, &p, 10); if (errno != 0 || !p || *p) return (errno) ? -errno : -EINVAL; /* update the listen pid to ours */ snprintf(buf, sizeof(buf), "%d", getpid()); if (errno != 0 || !*buf) return (errno) ? -errno : -EINVAL; if (setenv("LISTEN_PID", buf, 1) == 0) return (int)l; return -1; } #else #define inherit_systemd_activation() #endif #if SYSLOG_NG_ENABLE_LINUX_CAPS /** * g_process_cap_modify: * @capability: capability to turn off or on * @onoff: specifies whether the capability should be enabled or disabled * * This function modifies the current permitted set of capabilities by * enabling or disabling the capability specified in @capability. * * Returns: whether the operation was successful. **/ gboolean g_process_cap_modify(int capability, int onoff) { cap_t caps; if (!process_opts.caps) return TRUE; /* * if libcap or kernel doesn't support cap_syslog, then resort to * cap_sys_admin */ if (capability == CAP_SYSLOG && (!have_capsyslog || CAP_SYSLOG == -1)) capability = CAP_SYS_ADMIN; caps = cap_get_proc(); if (!caps) return FALSE; if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &capability, onoff) == -1) { msg_error("Error managing capability set, cap_set_flag returned an error", evt_tag_errno("error", errno)); cap_free(caps); return FALSE; } if (cap_set_proc(caps) == -1) { gchar *cap_text; cap_text = cap_to_text(caps, NULL); msg_error("Error managing capability set, cap_set_proc returned an error", evt_tag_str("caps", cap_text), evt_tag_errno("error", errno)); cap_free(cap_text); cap_free(caps); return FALSE; } cap_free(caps); return TRUE; } /** * g_process_cap_save: * * Save the set of current capabilities and return it. The caller might * restore the saved set of capabilities by using cap_restore(). * * Returns: the current set of capabilities **/ cap_t g_process_cap_save(void) { if (!process_opts.caps) return NULL; return cap_get_proc(); } /** * cap_restore: * @r: capability set saved by cap_save() * * Restore the set of current capabilities specified by @r. * * Returns: whether the operation was successful. **/ void g_process_cap_restore(cap_t r) { gboolean rc; if (!process_opts.caps) return; rc = cap_set_proc(r) != -1; cap_free(r); if (!rc) { gchar *cap_text; cap_text = cap_to_text(r, NULL); msg_error("Error managing capability set, cap_set_proc returned an error", evt_tag_str("caps", cap_text), evt_tag_errno("error", errno)); cap_free(cap_text); return; } return; } #ifndef PR_CAPBSET_READ /* old glibc versions don't have PR_CAPBSET_READ, we define it to the * value as defined in newer versions. */ #define PR_CAPBSET_READ 23 #endif gboolean g_process_check_cap_syslog(void) { int ret; if (have_capsyslog) return TRUE; if (CAP_SYSLOG == -1) return FALSE; ret = prctl(PR_CAPBSET_READ, CAP_SYSLOG); if (ret == -1) return FALSE; ret = cap_from_name("cap_syslog", NULL); if (ret == -1) { fprintf (stderr, "CAP_SYSLOG seems to be supported by the system, but " "libcap can't parse it. Falling back to CAP_SYS_ADMIN!\n"); return FALSE; } have_capsyslog = TRUE; return TRUE; } #endif /** * g_process_set_mode: * @mode: an element from ZProcessMode * * This function should be called by the daemon to set the processing mode * as specified by @mode. **/ void g_process_set_mode(GProcessMode mode) { process_opts.mode = mode; } /** * g_process_get_mode: * * Return the processing mode applied to the daemon. **/ GProcessMode g_process_get_mode(void) { return process_opts.mode; } /** * g_process_set_name: * @name: the name of the process to be reported as program name * * This function should be called by the daemon to set the program name * which is present in various error message and might influence the PID * file if not overridden by g_process_set_pidfile(). **/ void g_process_set_name(const gchar *name) { process_opts.name = name; } /** * g_process_set_user: * @user: the name of the user the process should switch to during startup * * This function should be called by the daemon to set the user name. **/ void g_process_set_user(const gchar *user) { if (!process_opts.user) process_opts.user = user; } /** * g_process_set_group: * @group: the name of the group the process should switch to during startup * * This function should be called by the daemon to set the group name. **/ void g_process_set_group(const gchar *group) { if (!process_opts.group) process_opts.group = group; } /** * g_process_set_chroot: * @chroot_dir: the name of the chroot directory the process should switch to during startup * * This function should be called by the daemon to set the chroot directory **/ void g_process_set_chroot(const gchar *chroot_dir) { if (!process_opts.chroot_dir) process_opts.chroot_dir = chroot_dir; } /** * g_process_set_pidfile: * @pidfile: the name of the complete pid file with full path * * This function should be called by the daemon to set the PID file name to * store the pid of the process. This value will be used as the pidfile * directly, neither name nor pidfile_dir influences the pidfile location if * this is set. **/ void g_process_set_pidfile(const gchar *pidfile) { if (!process_opts.pidfile) process_opts.pidfile = pidfile; } /** * g_process_set_pidfile_dir: * @pidfile_dir: name of the pidfile directory * * This function should be called by the daemon to set the PID file * directory. This value is not used if set_pidfile() was called. **/ void g_process_set_pidfile_dir(const gchar *pidfile_dir) { if (!process_opts.pidfile_dir) process_opts.pidfile_dir = pidfile_dir; } /** * g_process_set_working_dir: * @working_dir: name of the working directory * * This function should be called by the daemon to set the working * directory. The process will change its current directory to this value or * to pidfile_dir if it is unset. **/ void g_process_set_working_dir(const gchar *cwd) { if (!process_opts.cwd) process_opts.cwd = cwd; } /** * g_process_set_caps: * @caps: capability specification in text form * * This function should be called by the daemon to set the initial * capability set. The process will change its capabilities to this value * during startup, provided it has enough permissions to do so. **/ void g_process_set_caps(const gchar *caps) { if (!process_opts.caps) process_opts.caps = caps; } /** * g_process_set_argv_space: * @argc: Original argc, as received by the main function in it's first parameter * @argv: Original argv, as received by the main function in it's second parameter * * This function should be called by the daemon if it wants to enable * process title manipulation in the supervisor process. **/ void g_process_set_argv_space(gint argc, gchar **argv) { #ifdef SYSLOG_NG_HAVE_ENVIRON extern char **environ; gchar *lastargv = NULL; gchar **envp = environ; gint i; if (process_opts.argv) return; process_opts.argv = argv; process_opts.argc = argc; for (i = 0; envp[i] != NULL; i++) ; environ = g_new(char *, i + 1); /* * Find the last argv string or environment variable within * our process memory area. */ for (i = 0; i < process_opts.argc; i++) { if (lastargv == NULL || lastargv + 1 == process_opts.argv[i]) lastargv = process_opts.argv[i] + strlen(process_opts.argv[i]); } for (i = 0; envp[i] != NULL; i++) { if (lastargv + 1 == envp[i]) lastargv = envp[i] + strlen(envp[i]); } process_opts.argv_start = process_opts.argv[0]; process_opts.argv_env_len = lastargv - process_opts.argv[0] - 1; process_opts.argv_orig = malloc(sizeof(gchar) * process_opts.argv_env_len); memcpy(process_opts.argv_orig, process_opts.argv_start, process_opts.argv_env_len); /* * Copy environment * XXX - will truncate env on strdup fail */ for (i = 0; envp[i] != NULL; i++) environ[i] = g_strdup(envp[i]); environ[i] = NULL; #endif } /** * g_process_set_check: * @check_period: check period in seconds * @check_fn: checker function * * Installs a checker function that is called at the specified rate. * The checked process is allowed to run as long as this function * returns TRUE. */ void g_process_set_check(gint check_period, gboolean (*check_fn)(void)) { process_opts.check_period = check_period; process_opts.check_fn = check_fn; } /** * g_process_message: * @fmt: format string * @...: arguments to @fmt * * This function sends a message to the client preferring to use the stderr * channel as long as it is available and switching to using syslog() if it * isn't. Generally the stderr channell will be available in the startup * process and in the beginning of the first startup in the * supervisor/daemon processes. Later on the stderr fd will be closed and we * have to fall back to using the system log. **/ void g_process_message(const gchar *fmt, ...) { gchar buf[2048]; va_list ap; va_start(ap, fmt); g_vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); if (stderr_present) fprintf(stderr, "%s: %s\n", process_opts.name, buf); else { gchar name[32]; g_snprintf(name, sizeof(name), "%s/%s", process_kind == G_PK_SUPERVISOR ? "supervise" : "daemon", process_opts.name); openlog(name, LOG_PID, LOG_DAEMON); syslog(LOG_CRIT, "%s\n", buf); closelog(); } } /** * g_process_detach_tty: * * This function is called from g_process_start() to detach from the * controlling tty. **/ static void g_process_detach_tty(void) { if (process_opts.mode != G_PM_FOREGROUND) { /* detach ourselves from the tty when not staying in the foreground */ if (isatty(STDIN_FILENO)) { #ifdef TIOCNOTTY ioctl(STDIN_FILENO, TIOCNOTTY, 0); #endif } setsid(); } } /** * g_process_change_limits: * * Set fd limit. * **/ static void g_process_change_limits(void) { struct rlimit limit; getrlimit(RLIMIT_NOFILE, &limit); limit.rlim_cur = limit.rlim_max; if (process_opts.fd_limit_min) { limit.rlim_cur = limit.rlim_max = process_opts.fd_limit_min; } if (setrlimit(RLIMIT_NOFILE, &limit) < 0) g_process_message("Error setting file number limit; limit='%d'; error='%s'", process_opts.fd_limit_min, g_strerror(errno)); } /** * g_process_detach_stdio: * * Use /dev/null as input/output/error. This function is idempotent, can be * called any number of times without harm. **/ static void g_process_detach_stdio(void) { gint devnull_fd; if (process_opts.mode != G_PM_FOREGROUND && stderr_present) { devnull_fd = open("/dev/null", O_RDONLY); if (devnull_fd >= 0) { dup2(devnull_fd, STDIN_FILENO); close(devnull_fd); } devnull_fd = open("/dev/null", O_WRONLY); if (devnull_fd >= 0) { dup2(devnull_fd, STDOUT_FILENO); dup2(devnull_fd, STDERR_FILENO); close(devnull_fd); } stderr_present = FALSE; } } /** * g_process_enable_core: * * Enable core file dumping by setting PR_DUMPABLE and changing the core * file limit to infinity. **/ static void g_process_enable_core(void) { struct rlimit limit; if (process_opts.core) { #if SYSLOG_NG_ENABLE_LINUX_CAPS if (!prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) { gint rc; rc = prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); if (rc < 0) g_process_message("Cannot set process to be dumpable; error='%s'", g_strerror(errno)); } #endif limit.rlim_cur = limit.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_CORE, &limit) < 0) g_process_message("Error setting core limit to infinity; error='%s'", g_strerror(errno)); } } /** * g_process_format_pidfile_name: * @buf: buffer to store the pidfile name * @buflen: size of @buf * * Format the pid file name according to the settings specified by the * process. **/ static const gchar * g_process_format_pidfile_name(gchar *buf, gsize buflen) { const gchar *pidfile = process_opts.pidfile; if (pidfile == NULL) { g_snprintf(buf, buflen, "%s/%s.pid", process_opts.pidfile_dir ? process_opts.pidfile_dir : get_installation_path_for(SYSLOG_NG_PATH_PIDFILEDIR), process_opts.name); pidfile = buf; } else if (pidfile[0] != '/') { /* complete path to pidfile not specified, assume it is a relative path to pidfile_dir */ g_snprintf(buf, buflen, "%s/%s", process_opts.pidfile_dir ? process_opts.pidfile_dir : get_installation_path_for( SYSLOG_NG_PATH_PIDFILEDIR), pidfile); pidfile = buf; } return pidfile; } /** * g_process_write_pidfile: * @pid: pid to write into the pidfile * * Write the pid to the pidfile. **/ static void g_process_write_pidfile(pid_t pid) { gchar buf[256]; const gchar *pidfile; FILE *fd; pidfile = g_process_format_pidfile_name(buf, sizeof(buf)); fd = fopen(pidfile, "w"); if (fd != NULL) { fprintf(fd, "%d\n", (int) pid); fclose(fd); } else { g_process_message("Error creating pid file; file='%s', error='%s'", pidfile, g_strerror(errno)); } } /** * g_process_remove_pidfile: * * Remove the pidfile. **/ static void g_process_remove_pidfile(void) { gchar buf[256]; const gchar *pidfile; pidfile = g_process_format_pidfile_name(buf, sizeof(buf)); if (unlink(pidfile) < 0) { g_process_message("Error removing pid file; file='%s', error='%s'", pidfile, g_strerror(errno)); } } /** * g_process_change_root: * * Change the current root to the value specified by the user, causes the * startup process to fail if this function returns FALSE. (e.g. the user * specified a chroot but we could not change to that directory) * * Returns: TRUE to indicate success **/ static gboolean g_process_change_root(void) { if (process_opts.chroot_dir) { if (chroot(process_opts.chroot_dir) < 0) { g_process_message("Error in chroot(); chroot='%s', error='%s'\n", process_opts.chroot_dir, g_strerror(errno)); return FALSE; } if (chdir("/") < 0) { g_process_message("Error in chdir() after chroot; chroot='%s', error='%s'\n", process_opts.chroot_dir, g_strerror(errno)); return FALSE; } } return TRUE; } /** * g_process_change_user: * * Change the current user/group/groups to the value specified by the user. * causes the startup process to fail if this function returns FALSE. (e.g. * the user requested the uid/gid to change we could not change to that uid) * * Returns: TRUE to indicate success **/ static gboolean g_process_change_user(void) { #if SYSLOG_NG_ENABLE_LINUX_CAPS if (process_opts.caps) prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); #endif if (process_opts.gid >= 0) { if (setgid((gid_t) process_opts.gid) < 0) { g_process_message("Error in setgid(); group='%s', gid='%d', error='%s'", process_opts.group, process_opts.gid, g_strerror(errno)); if (getuid() == 0) return FALSE; } if (process_opts.user && initgroups(process_opts.user, (gid_t) process_opts.gid) < 0) { g_process_message("Error in initgroups(); user='%s', error='%s'", process_opts.user, g_strerror(errno)); if (getuid() == 0) return FALSE; } } if (process_opts.uid >= 0) { if (setuid((uid_t) process_opts.uid) < 0) { g_process_message("Error in setuid(); user='%s', uid='%d', error='%s'", process_opts.user, process_opts.uid, g_strerror(errno)); if (getuid() == 0) return FALSE; } } return TRUE; } #if SYSLOG_NG_ENABLE_LINUX_CAPS /** * g_process_change_caps: * * Change the current capset to the value specified by the user. causes the * startup process to fail if this function returns FALSE, but we only do * this if the capset cannot be parsed, otherwise a failure changing the * capabilities will not result in failure * * Returns: TRUE to indicate success **/ static gboolean g_process_change_caps(void) { if (process_opts.caps) { cap_t cap = cap_from_text(process_opts.caps); if (cap == NULL) { g_process_message("Error parsing capabilities: %s", process_opts.caps); process_opts.caps = NULL; return FALSE; } else { if (cap_set_proc(cap) == -1) { g_process_message("Error setting capabilities, capability management disabled; error='%s'", g_strerror(errno)); process_opts.caps = NULL; } cap_free(cap); } } return TRUE; } #else static gboolean g_process_change_caps(void) { return TRUE; } #endif static void g_process_resolve_names(void) { if (process_opts.user && !resolve_user(process_opts.user, &process_opts.uid)) { g_process_message("Error resolving user; user='%s'", process_opts.user); process_opts.uid = -1; } if (process_opts.group && !resolve_group(process_opts.group, &process_opts.gid)) { g_process_message("Error resolving group; group='%s'", process_opts.group); process_opts.gid = -1; } } /** * g_process_change_dir: * * Change the current working directory to the value specified by the user * and verify that the daemon would be able to dump core to that directory * if that is requested. **/ static void g_process_change_dir(void) { const gchar *cwd = NULL; if (process_opts.mode != G_PM_FOREGROUND) { if (process_opts.cwd) cwd = process_opts.cwd; else if (process_opts.pidfile_dir) cwd = process_opts.pidfile_dir; if (!cwd) cwd = get_installation_path_for(SYSLOG_NG_PATH_PIDFILEDIR); if (cwd) if (chdir(cwd)) g_process_message("Error changing to directory=%s, errcode=%d", cwd, errno); } /* this check is here to avoid having to change directory early in the startup process */ if ((process_opts.core) && access(".", W_OK) < 0) { gchar buf[256]; if (!getcwd(buf, sizeof(buf))) strncpy(buf, "unable-to-query", sizeof(buf)); g_process_message("Unable to write to current directory, core dumps will not be generated; dir='%s', error='%s'", buf, g_strerror(errno)); } } /** * g_process_send_result: * @ret_num: exit code of the process * * This function is called to notify our parent process (which is the same * executable process but separated with a fork()) about the result of the * process startup phase. Specifying ret_num == 0 means that everything was * dandy, all other values mean that the initialization failed and the * parent should exit using ret_num as the exit code. The function behaves * differently depending on which process it was called from, determined by * the value of the process_kind global variable. In the daemon process it * writes to init_result_pipe, in the startup process it writes to the * startup_result_pipe. * * This function can only be called once, further invocations will do nothing. **/ static void g_process_send_result(guint ret_num) { gchar buf[10]; guint buf_len; gint *fd; if (process_kind == G_PK_SUPERVISOR) fd = &startup_result_pipe[1]; else if (process_kind == G_PK_DAEMON) fd = &init_result_pipe[1]; else g_assert_not_reached(); if (*fd != -1) { buf_len = g_snprintf(buf, sizeof(buf), "%d\n", ret_num); if (write(*fd, buf, buf_len) < buf_len) g_assert_not_reached(); close(*fd); *fd = -1; } } /** * g_process_recv_result: * * Retrieves an exit code value from one of the result pipes depending on * which process the function was called from. This function can be called * only once, further invocations will return non-zero result code. **/ static gint g_process_recv_result(void) { gchar ret_buf[6]; gint ret_num = 1; gint *fd; /* FIXME: use a timer */ if (process_kind == G_PK_SUPERVISOR) fd = &init_result_pipe[0]; else if (process_kind == G_PK_STARTUP) fd = &startup_result_pipe[0]; else g_assert_not_reached(); if (*fd != -1) { memset(ret_buf, 0, sizeof(ret_buf)); if (read(*fd, ret_buf, sizeof(ret_buf)) > 0) { ret_num = atoi(ret_buf); } else { /* the process probably crashed without telling a proper exit code */ ret_num = 1; } close(*fd); *fd = -1; } return ret_num; } /** * g_process_perform_startup: * * This function is the startup process, never returns, the startup process exits here. **/ static void g_process_perform_startup(void) { /* startup process */ exit(g_process_recv_result()); } #define SPT_PADCHAR '\0' static void g_process_setproctitle(const gchar *proc_title) { #ifdef SYSLOG_NG_HAVE_ENVIRON size_t len; g_assert(process_opts.argv_start != NULL); len = g_strlcpy(process_opts.argv_start, proc_title, process_opts.argv_env_len); for (; len < process_opts.argv_env_len; ++len) process_opts.argv_start[len] = SPT_PADCHAR; #endif } #define PROC_TITLE_SPACE 1024 /** * g_process_perform_supervise: * * Supervise process, returns only in the context of the daemon process, the * supervisor process exits here. **/ static void g_process_perform_supervise(void) { pid_t pid; gboolean first = TRUE, exited = FALSE; gchar proc_title[PROC_TITLE_SPACE]; struct sigaction sa; g_snprintf(proc_title, PROC_TITLE_SPACE, "supervising %s", process_opts.name); g_process_setproctitle(proc_title); memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; sigaction(SIGHUP, &sa, NULL); while (1) { if (pipe(init_result_pipe) != 0) { g_process_message("Error daemonizing process, cannot open pipe; error='%s'", g_strerror(errno)); g_process_startup_failed(1, TRUE); } /* fork off a child process */ if ((pid = fork()) < 0) { g_process_message("Error forking child process; error='%s'", g_strerror(errno)); g_process_startup_failed(1, TRUE); } else if (pid != 0) { gint rc; gboolean deadlock = FALSE; /* this is the supervisor process */ /* shut down init_result_pipe write side */ close(init_result_pipe[1]); init_result_pipe[1] = -1; rc = g_process_recv_result(); if (first) { /* first time encounter, we have a chance to report back, do it */ g_process_send_result(rc); if (rc != 0) break; g_process_detach_stdio(); } first = FALSE; if (rc != 0) { gint i = 0; /* initialization failed in daemon, it will probably exit soon, wait and restart */ while (i < 6 && waitpid(pid, &rc, WNOHANG) == 0) { if (i > 3) kill(pid, i > 4 ? SIGKILL : SIGTERM); sleep(1); i++; } if (i == 6) g_process_message("Initialization failed but the daemon did not exit, even when forced to, trying to recover; pid='%d'", pid); continue; } if (process_opts.check_fn && (process_opts.check_period >= 0)) { gint i = 1; while (!(exited = waitpid(pid, &rc, WNOHANG))) { if (i >= process_opts.check_period) { if (!process_opts.check_fn()) break; i = 0; } sleep(1); i++; } if (!exited) { gint j = 0; g_process_message("Daemon deadlock detected, killing process;"); deadlock = TRUE; while (j < 6 && waitpid(pid, &rc, WNOHANG) == 0) { if (j > 3) kill(pid, j > 4 ? SIGKILL : SIGABRT); sleep(1); j++; } if (j == 6) g_process_message("The daemon did not exit after deadlock, even when forced to, trying to recover; pid='%d'", pid); } } else { waitpid(pid, &rc, 0); } if (deadlock || WIFSIGNALED(rc) || (WIFEXITED(rc) && WEXITSTATUS(rc) != 0)) { gchar argbuf[64]; if (!access(G_PROCESS_FAILURE_NOTIFICATION, R_OK | X_OK)) { const gchar *notify_reason; pid_t npid = fork(); gint nrc; switch (npid) { case -1: g_process_message("Could not fork for external notification; reason='%s'", strerror(errno)); break; case 0: switch(fork()) { case -1: g_process_message("Could not fork for external notification; reason='%s'", strerror(errno)); exit(1); break; case 0: if (deadlock) { notify_reason = "deadlock detected"; argbuf[0] = 0; } else { snprintf(argbuf, sizeof(argbuf), "%d", WIFSIGNALED(rc) ? WTERMSIG(rc) : WEXITSTATUS(rc)); if (WIFSIGNALED(rc)) notify_reason = "signalled"; else notify_reason = "non-zero exit code"; } execlp(G_PROCESS_FAILURE_NOTIFICATION, G_PROCESS_FAILURE_NOTIFICATION, SAFE_STRING(process_opts.name), SAFE_STRING(process_opts.chroot_dir), SAFE_STRING(process_opts.pidfile_dir), SAFE_STRING(process_opts.pidfile), SAFE_STRING(process_opts.cwd), SAFE_STRING(process_opts.caps), notify_reason, argbuf, (deadlock || !WIFSIGNALED(rc) || WTERMSIG(rc) != SIGKILL) ? "restarting" : "not-restarting", (gchar *) NULL); g_process_message("Could not execute external notification; reason='%s'", strerror(errno)); break; default: exit(0); break; } /* child process */ default: waitpid(npid, &nrc, 0); break; } } if (deadlock || !WIFSIGNALED(rc) || WTERMSIG(rc) != SIGKILL) { g_process_message("Daemon exited due to a deadlock/signal/failure, restarting; exitcode='%d'", rc); sleep(1); } else { g_process_message("Daemon was killed, not restarting; exitcode='%d'", rc); break; } } else { g_process_message("Daemon exited gracefully, not restarting; exitcode='%d'", rc); break; } } else { /* this is the daemon process, thus we should return to the caller of g_process_start() */ /* shut down init_result_pipe read side */ process_kind = G_PK_DAEMON; close(init_result_pipe[0]); init_result_pipe[0] = -1; /* update systemd socket activation pid */ inherit_systemd_activation(); memcpy(process_opts.argv_start, process_opts.argv_orig, process_opts.argv_env_len); return; } } exit(0); } /** * g_process_start: * * Start the process as directed by the options set by various * g_process_set_*() functions. **/ void g_process_start(void) { pid_t pid; g_process_detach_tty(); g_process_change_limits(); g_process_resolve_names(); if (process_opts.mode == G_PM_BACKGROUND) { /* no supervisor, sends result to startup process directly */ if (pipe(init_result_pipe) != 0) { g_process_message("Error daemonizing process, cannot open pipe; error='%s'", g_strerror(errno)); exit(1); } if ((pid = fork()) < 0) { g_process_message("Error forking child process; error='%s'", g_strerror(errno)); exit(1); } else if (pid != 0) { /* shut down init_result_pipe write side */ close(init_result_pipe[1]); /* connect startup_result_pipe with init_result_pipe */ startup_result_pipe[0] = init_result_pipe[0]; init_result_pipe[0] = -1; g_process_perform_startup(); /* NOTE: never returns */ g_assert_not_reached(); } process_kind = G_PK_DAEMON; /* shut down init_result_pipe read side */ close(init_result_pipe[0]); init_result_pipe[0] = -1; /* update systemd socket activation pid */ inherit_systemd_activation(); } else if (process_opts.mode == G_PM_SAFE_BACKGROUND) { /* full blown startup/supervisor/daemon */ if (pipe(startup_result_pipe) != 0) { g_process_message("Error daemonizing process, cannot open pipe; error='%s'", g_strerror(errno)); exit(1); } /* first fork off supervisor process */ if ((pid = fork()) < 0) { g_process_message("Error forking child process; error='%s'", g_strerror(errno)); exit(1); } else if (pid != 0) { /* this is the startup process */ /* shut down startup_result_pipe write side */ close(startup_result_pipe[1]); startup_result_pipe[1] = -1; /* NOTE: never returns */ g_process_perform_startup(); g_assert_not_reached(); } /* this is the supervisor process */ /* shut down startup_result_pipe read side */ close(startup_result_pipe[0]); startup_result_pipe[0] = -1; /* update systemd socket activation pid */ inherit_systemd_activation(); process_kind = G_PK_SUPERVISOR; g_process_perform_supervise(); /* we only return in the daamon process here */ } else if (process_opts.mode == G_PM_FOREGROUND) { process_kind = G_PK_DAEMON; } else { g_assert_not_reached(); } /* daemon process, we should return to the caller to perform work */ /* Only call setsid() for backgrounded processes. */ if (process_opts.mode != G_PM_FOREGROUND) { setsid(); } /* NOTE: we need to signal the parent in case of errors from this point. * This is accomplished by writing the appropriate exit code to * init_result_pipe, the easiest way doing so is calling g_process_startup_failed. * */ if (!g_process_change_root() || !g_process_change_user() || !g_process_change_caps()) { g_process_startup_failed(1, TRUE); } g_process_enable_core(); g_process_change_dir(); } /** * g_process_startup_failed: * @ret_num: exit code * @may_exit: whether to exit the process * * This is a public API function to be called by the user code when * initialization failed. **/ void g_process_startup_failed(guint ret_num, gboolean may_exit) { if (process_kind != G_PK_STARTUP) g_process_send_result(ret_num); if (may_exit) { exit(ret_num); } else { g_process_detach_stdio(); } } /** * g_process_startup_ok: * * This is a public API function to be called by the user code when * initialization was successful, we can report back to the user. **/ void g_process_startup_ok(void) { g_process_write_pidfile(getpid()); g_process_send_result(0); g_process_detach_stdio(); } /** * g_process_finish: * * This is a public API function to be called by the user code when the * daemon exits after properly initialized (e.g. when it terminates because * of SIGTERM). This function currently only removes the PID file. **/ void g_process_finish(void) { #ifdef SYSLOG_NG_HAVE_ENVIRON /** * There is a memory leak for **environ and elements that should be * freed here theoretically. * * The reason why environ is copied during g_process_set_argv_space * so to be able to overwrite process title in ps/top commands to * supervisor. In bsd there is setproctitle call which solve this, * but currently it is not available for linux. * * The problem is that modules can add their own env variables to the * list, which must not be freed here, otherwise it would result * double free (e.g some version of Oracle Java). One might also would * try to track which environment variables are added by syslog-ng, * and free only those. There is still a problem with this, **environ * itself cannot be freed in some cases. For example libcurl registers * an atexit function which needs an environment variable, that would * be freed here before at_exit is called, resulting in invalid read. * * As this leak does not cause any real problem like accumulating over * time, it is safe to leave it as it is. */ #endif g_process_remove_pidfile(); } static gboolean g_process_process_mode_arg(const gchar *option_name G_GNUC_UNUSED, const gchar *value, gpointer data G_GNUC_UNUSED, GError **error) { if (strcmp(value, "foreground") == 0) { process_opts.mode = G_PM_FOREGROUND; } else if (strcmp(value, "background") == 0) { process_opts.mode = G_PM_BACKGROUND; } else if (strcmp(value, "safe-background") == 0) { process_opts.mode = G_PM_SAFE_BACKGROUND; } else { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Error parsing process-mode argument"); return FALSE; } return TRUE; } static gboolean g_process_process_no_caps(const gchar *option_name G_GNUC_UNUSED, const gchar *value G_GNUC_UNUSED, gpointer data G_GNUC_UNUSED, GError *error) { process_opts.caps = NULL; return TRUE; } static GOptionEntry g_process_option_entries[] = { { "foreground", 'F', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &process_opts.mode, "Do not go into the background after initialization", NULL }, { "process-mode", 0, 0, G_OPTION_ARG_CALLBACK, g_process_process_mode_arg , "Set process running mode", "" }, { "user", 'u', 0, G_OPTION_ARG_STRING, &process_opts.user, "Set the user to run as", "" }, { "uid", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &process_opts.user, NULL, NULL }, { "group", 'g', 0, G_OPTION_ARG_STRING, &process_opts.group, "Set the group to run as", "" }, { "gid", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &process_opts.group, NULL, NULL }, { "chroot", 'C', 0, G_OPTION_ARG_STRING, &process_opts.chroot_dir, "Chroot to this directory", "" }, { "caps", 0, 0, G_OPTION_ARG_STRING, &process_opts.caps, "Set default capability set", "" }, { "no-caps", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, g_process_process_no_caps, "Disable managing Linux capabilities", NULL }, { "pidfile", 'p', 0, G_OPTION_ARG_STRING, &process_opts.pidfile, "Set path to pid file", "" }, { "enable-core", 0, 0, G_OPTION_ARG_NONE, &process_opts.core, "Enable dumping core files", NULL }, { "fd-limit", 0, 0, G_OPTION_ARG_INT, &process_opts.fd_limit_min, "The minimum required number of fds", NULL }, { NULL, 0, 0, 0, NULL, NULL, NULL }, }; void g_process_add_option_group(GOptionContext *ctx) { GOptionGroup *group; group = g_option_group_new("process", "Process options", "Process options", NULL, NULL); g_option_group_add_entries(group, g_process_option_entries); g_option_context_add_group(ctx, group); } syslog-ng-syslog-ng-3.13.2/lib/gprocess.h000066400000000000000000000050471321171025300202070ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef GPROCESS_H_INCLUDED #define GPROCESS_H_INCLUDED #include "syslog-ng.h" #include #if SYSLOG_NG_ENABLE_LINUX_CAPS # include #endif typedef enum { G_PM_FOREGROUND, G_PM_BACKGROUND, G_PM_SAFE_BACKGROUND, } GProcessMode; #if SYSLOG_NG_ENABLE_LINUX_CAPS gboolean g_process_cap_modify(int capability, int onoff); cap_t g_process_cap_save(void); void g_process_cap_restore(cap_t r); #ifndef CAP_SYSLOG #define CAP_SYSLOG -1 #endif #else typedef gpointer cap_t; #define g_process_cap_modify(cap, onoff) #define g_process_cap_save() NULL #define g_process_cap_restore(cap) cap = cap #endif void g_process_message(const gchar *fmt, ...); void g_process_set_mode(GProcessMode mode); GProcessMode g_process_get_mode(void); void g_process_set_name(const gchar *name); void g_process_set_user(const gchar *user); void g_process_set_group(const gchar *group); void g_process_set_chroot(const gchar *chroot); void g_process_set_pidfile(const gchar *pidfile); void g_process_set_pidfile_dir(const gchar *pidfile_dir); void g_process_set_working_dir(const gchar *cwd); void g_process_set_caps(const gchar *caps); void g_process_set_argv_space(gint argc, gchar **argv); void g_process_set_use_fdlimit(gboolean use); void g_process_set_check(gint check_period, gboolean (*check_fn)(void)); gboolean g_process_check_cap_syslog(void); void g_process_start(void); void g_process_startup_failed(guint ret_num, gboolean may_exit); void g_process_startup_ok(void); void g_process_finish(void); void g_process_add_option_group(GOptionContext *ctx); #endif syslog-ng-syslog-ng-3.13.2/lib/gsockaddr.c000066400000000000000000000335571321171025300203250ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "gsockaddr.h" #include "gsocket.h" #include #include #include #include #include #include #include #include #include #include #include #include /* general GSockAddr functions */ /** * g_sockaddr_new: * @sa: libc sockaddr * pointer to convert * @salen: size of sa * * General function to allocate and initialize a GSockAddr structure, * and convert a libc style sockaddr * pointer to our representation. * * Returns: a GSockAddr instance or NULL if failure * **/ GSockAddr * g_sockaddr_new(struct sockaddr *sa, int salen) { GSockAddr *addr = NULL; switch (sa->sa_family) { #if SYSLOG_NG_ENABLE_IPV6 case AF_INET6: if (salen >= sizeof(struct sockaddr_in6)) addr = g_sockaddr_inet6_new2((struct sockaddr_in6 *) sa); break; #endif case AF_INET: if (salen == sizeof(struct sockaddr_in)) addr = g_sockaddr_inet_new2((struct sockaddr_in *) sa); break; case AF_UNIX: addr = g_sockaddr_unix_new2((struct sockaddr_un *) sa, salen); break; default: /*LOG This message indicates an internal error, Zorp tries to use an address family it doesn't support. */ g_error("Unsupported socket family in g_sockaddr_new(); family='%d'", sa->sa_family); break; } return addr; } /** * g_sockaddr_format: * @a instance pointer of a GSockAddr * @text destination buffer * @n the size of text * * Format a GSockAddr into human readable form, calls the format * virtual method of GSockAddr. * * Returns: text is filled with a human readable representation of a, and a * pointer to text is returned. * **/ char * g_sockaddr_format(GSockAddr *a, gchar *text, gulong n, gint format) { return a->sa_funcs->format(a, text, n, format); } guint16 g_sockaddr_get_port(GSockAddr *a) { g_assert(a->sa_funcs->get_port != NULL); return a->sa_funcs->get_port(a); } void g_sockaddr_set_port(GSockAddr *a, guint16 port) { g_assert(a->sa_funcs->set_port != NULL); return a->sa_funcs->set_port(a, port); } /*+ Increment the reference count of a GSockAddr instance. Parameters: a pointer to GSockAddr Returns: the same instance +*/ GSockAddr * g_sockaddr_ref(GSockAddr *a) { if (a) g_atomic_counter_inc(&a->refcnt); return a; } static gsize g_sockaddr_len(GSockAddr *); /*+ Decrement the reference count of a GSockAddr instance, and free if the refcnt reaches 0. Parameters: a GSockAddr instance Returns: none +*/ void g_sockaddr_unref(GSockAddr *a) { /* FIXME: maybe add a callback to funcs table */ if (a) { if (g_atomic_counter_dec_and_test(&a->refcnt)) { g_slice_free1(g_sockaddr_len(a), a); } } } /* AF_INET socket address */ /*+ GSockAddrInet is an implementation of the GSockAddr interface, encapsulating an IPv4 host address and port number. +*/ typedef struct _GSockAddrInet { GAtomicCounter refcnt; guint32 flags; GSockAddrFuncs *sa_funcs; int salen; struct sockaddr_in sin; } GSockAddrInet; /*+ private function to prepare an IPv4 style bind, e.g. set SO_REUSEADDR +*/ static GIOStatus g_sockaddr_inet_bind_prepare(int sock, GSockAddr *addr) { int tmp = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp)); return G_IO_STATUS_NORMAL; } /*+ format an IPv4 address into human readable form */ gchar * g_sockaddr_inet_format(GSockAddr *addr, gchar *text, gulong n, gint format) { GSockAddrInet *self = (GSockAddrInet *) addr; char buf[32]; if (format == GSA_FULL) g_snprintf(text, n, "AF_INET(%s:%d)", g_inet_ntoa(buf, sizeof(buf), self->sin.sin_addr), htons(self->sin.sin_port)); else if (format == GSA_ADDRESS_ONLY) g_inet_ntoa(text, n, self->sin.sin_addr); else g_assert_not_reached(); return text; } /** * g_sockaddr_inet_get_port: * @s: GSockAddrInet instance * * This GSockAddrInet specific function returns the port part of the * address. * * Returns: the port in host byte order * **/ static guint16 g_sockaddr_inet_get_port(GSockAddr *s) { return ntohs(g_sockaddr_inet_get_sa(s)->sin_port); } /** * g_sockaddr_inet_set_port: * @s: GSockAddrInet instance * @port: new port in host byte order * * **/ static void g_sockaddr_inet_set_port(GSockAddr *s, guint16 port) { g_sockaddr_inet_get_sa(s)->sin_port = htons(port); } static GSockAddrFuncs inet_sockaddr_funcs = { .bind_prepare = g_sockaddr_inet_bind_prepare, NULL, .format = g_sockaddr_inet_format, .get_port = g_sockaddr_inet_get_port, .set_port = g_sockaddr_inet_set_port, }; gboolean g_sockaddr_inet_check(GSockAddr *a) { return a->sa_funcs == &inet_sockaddr_funcs; } /*+ Allocate and initialize an IPv4 socket address. Parameters: ip text representation of an IP address port port number in host byte order Returns: the new instance +*/ GSockAddr * g_sockaddr_inet_new(const gchar *ip, guint16 port) { GSockAddrInet *self = NULL; struct in_addr ina; if (inet_aton(ip, &ina)) { self = g_slice_new0(GSockAddrInet); g_atomic_counter_set(&self->refcnt, 1); self->flags = 0; self->salen = sizeof(struct sockaddr_in); self->sin.sin_family = AF_INET; self->sin.sin_port = htons(port); self->sin.sin_addr = ina; self->sa_funcs = &inet_sockaddr_funcs; } return (GSockAddr *) self; } /*+ Allocate and initialize an IPv4 socket address using libc sockaddr * structure. Parameters: sin the sockaddr_in structure to convert Returns: the allocated instance. +*/ GSockAddr * g_sockaddr_inet_new2(struct sockaddr_in *sin) { GSockAddrInet *self = g_slice_new0(GSockAddrInet); g_atomic_counter_set(&self->refcnt, 1); self->flags = 0; self->salen = sizeof(struct sockaddr_in); self->sin = *sin; self->sa_funcs = &inet_sockaddr_funcs; return (GSockAddr *) self; } #if SYSLOG_NG_ENABLE_IPV6 /* AF_INET6 socket address */ /*+ GSockAddrInet6 is an implementation of the GSockAddr interface, encapsulating an IPv6 host address and port number. +*/ typedef struct _GSockAddrInet6 { GAtomicCounter refcnt; guint32 flags; GSockAddrFuncs *sa_funcs; int salen; struct sockaddr_in6 sin6; } GSockAddrInet6; /*+ format an IPv6 address into human readable form */ static gchar * g_sockaddr_inet6_format(GSockAddr *s, gchar *text, gulong n, gint format) { GSockAddrInet6 *self = (GSockAddrInet6 *) s; char buf[64]; if (format == GSA_FULL) { inet_ntop(AF_INET6, &self->sin6.sin6_addr, buf, sizeof(buf)); g_snprintf(text, n, "AF_INET6([%s]:%d)", buf, htons(self->sin6.sin6_port)); } else if (format == GSA_ADDRESS_ONLY) { inet_ntop(AF_INET6, &self->sin6.sin6_addr, text, n); } else g_assert_not_reached(); return text; } /** * g_sockaddr_inet6_get_port: * @s: GSockAddrInet instance * * This GSockAddrInet specific function returns the port part of the * address. * * Returns: the port in host byte order * **/ static guint16 g_sockaddr_inet6_get_port(GSockAddr *s) { return ntohs(g_sockaddr_inet6_get_sa(s)->sin6_port); } /** * g_sockaddr_inet6_set_port: * @s: GSockAddrInet instance * @port: new port in host byte order * * **/ static void g_sockaddr_inet6_set_port(GSockAddr *s, guint16 port) { g_sockaddr_inet6_get_sa(s)->sin6_port = htons(port); } static GSockAddrFuncs inet6_sockaddr_funcs = { .bind_prepare = g_sockaddr_inet_bind_prepare, .format = g_sockaddr_inet6_format, .get_port = g_sockaddr_inet6_get_port, .set_port = g_sockaddr_inet6_set_port, }; gboolean g_sockaddr_inet6_check(GSockAddr *a) { return a->sa_funcs == &inet6_sockaddr_funcs; } /*+ Allocate and initialize an IPv6 socket address. Parameters: ip text representation of an IP address port port number in host byte order Returns: the new instance +*/ GSockAddr * g_sockaddr_inet6_new(const gchar *ip, guint16 port) { GSockAddrInet6 *addr = g_slice_new0(GSockAddrInet6); g_atomic_counter_set(&addr->refcnt, 1); addr->flags = 0; addr->salen = sizeof(struct sockaddr_in6); addr->sin6.sin6_family = AF_INET6; inet_pton(AF_INET6, ip, &addr->sin6.sin6_addr); addr->sin6.sin6_port = htons(port); addr->sa_funcs = &inet6_sockaddr_funcs; return (GSockAddr *) addr; } /*+ Allocate and initialize an IPv6 socket address using libc sockaddr * structure. Parameters: sin the sockaddr_in6 structure to convert Returns: the allocated instance. +*/ GSockAddr * g_sockaddr_inet6_new2(struct sockaddr_in6 *sin6) { GSockAddrInet6 *addr = g_slice_new0(GSockAddrInet6); g_atomic_counter_set(&addr->refcnt, 1); addr->flags = 0; addr->salen = sizeof(struct sockaddr_in6); addr->sin6 = *sin6; addr->sa_funcs = &inet6_sockaddr_funcs; return (GSockAddr *) addr; } #endif /* AF_UNIX socket address */ /*+ The GSockAddrUnix class is an implementation of the GSockAddr interface encapsulating AF_UNIX domain socket names. +*/ typedef struct _GSockAddrUnix { GAtomicCounter refcnt; guint32 flags; GSockAddrFuncs *sa_funcs; int salen; struct sockaddr_un saun; } GSockAddrUnix; static GIOStatus g_sockaddr_unix_bind_prepare(int sock, GSockAddr *addr); static GIOStatus g_sockaddr_unix_bind(int sock, GSockAddr *addr); static gchar *g_sockaddr_unix_format(GSockAddr *addr, gchar *text, gulong n, gint format); static GSockAddrFuncs unix_sockaddr_funcs = { .bind_prepare = g_sockaddr_unix_bind_prepare, .bind = g_sockaddr_unix_bind, .format = g_sockaddr_unix_format }; /* anonymous if name == NULL */ /*+ Allocate and initialize a GSockAddrUnix instance. Parameters: name socket filename Returns: the new instance +*/ GSockAddr * g_sockaddr_unix_new(const gchar *name) { GSockAddrUnix *addr = g_slice_new0(GSockAddrUnix); g_atomic_counter_set(&addr->refcnt, 1); addr->flags = 0; addr->sa_funcs = &unix_sockaddr_funcs; addr->saun.sun_family = AF_UNIX; if (name) { strncpy(addr->saun.sun_path, name, sizeof(addr->saun.sun_path) - 1); addr->saun.sun_path[sizeof(addr->saun.sun_path) - 1] = 0; addr->salen = sizeof(addr->saun) - sizeof(addr->saun.sun_path) + strlen(addr->saun.sun_path) + 1; } else { addr->saun.sun_path[0] = 0; addr->salen = 2; } return (GSockAddr *) addr; } /*+ Allocate and initialize a GSockAddrUnix instance, using libc sockaddr_un strucutre. Parameters: saun sockaddr_un structure to convert sunlen size of saun Returns: the new instance +*/ GSockAddr * g_sockaddr_unix_new2(struct sockaddr_un *saun, int sunlen) { GSockAddrUnix *addr = g_slice_new0(GSockAddrUnix); g_atomic_counter_set(&addr->refcnt, 1); addr->flags = 0; addr->sa_funcs = &unix_sockaddr_funcs; addr->salen = sunlen; addr->saun = *saun; return (GSockAddr *) addr; } /*+ private function to prepare a bind on AF_UNIX sockets, e.g. unlink the socket if it exists and is a socket. +*/ static GIOStatus g_sockaddr_unix_bind_prepare(int sock, GSockAddr *addr) { GSockAddrUnix *unix_addr = (GSockAddrUnix *) addr; struct stat st; if (unix_addr->saun.sun_path[0] == 0) return G_IO_STATUS_NORMAL; if (stat(unix_addr->saun.sun_path, &st) == -1 || !S_ISSOCK(st.st_mode)) return G_IO_STATUS_NORMAL; unlink(unix_addr->saun.sun_path); return G_IO_STATUS_NORMAL; } /** * Virtual bind callback for UNIX domain sockets. Avoids binding if the * length of the UNIX domain socket filename is zero. **/ static GIOStatus g_sockaddr_unix_bind(int sock, GSockAddr *addr) { GSockAddrUnix *unix_addr = (GSockAddrUnix *) addr; if (unix_addr->saun.sun_path[0] == 0) return G_IO_STATUS_NORMAL; if (bind(sock, &addr->sa, addr->salen) < 0) { return G_IO_STATUS_ERROR; } return G_IO_STATUS_NORMAL; } /*+ Convert a GSockAddrUnix into human readable form. +*/ gchar * g_sockaddr_unix_format(GSockAddr *addr, gchar *text, gulong n, gint format) { GSockAddrUnix *unix_addr = (GSockAddrUnix *) addr; if (format == GSA_FULL) { g_snprintf(text, n, "AF_UNIX(%s)", unix_addr->salen > sizeof(unix_addr->saun.sun_family) && unix_addr->saun.sun_path[0] ? unix_addr->saun.sun_path : "anonymous"); } else if (format == GSA_ADDRESS_ONLY) { g_snprintf(text, n, "%s", unix_addr->salen > sizeof(unix_addr->saun.sun_family) && unix_addr->saun.sun_path[0] ? unix_addr->saun.sun_path : "anonymous"); } return text; } static gsize g_sockaddr_len(GSockAddr *a) { gsize len; if (a->sa_funcs == &inet_sockaddr_funcs) len = sizeof(GSockAddrInet); #if SYSLOG_NG_ENABLE_IPV6 else if (a->sa_funcs == &inet6_sockaddr_funcs) len = sizeof(GSockAddrInet6); #endif else if (a->sa_funcs == &unix_sockaddr_funcs) len = sizeof(GSockAddrUnix); else g_assert_not_reached(); return len; } syslog-ng-syslog-ng-3.13.2/lib/gsockaddr.h000066400000000000000000000103151321171025300203150ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef G_SOCKADDR_H_INCLUDED #define G_SOCKADDR_H_INCLUDED #include "syslog-ng.h" #include "atomic.h" #include #include #include #include /* sockaddr public interface */ #define MAX_SOCKADDR_STRING 64 #define GSA_FULL 0 #define GSA_ADDRESS_ONLY 1 typedef struct _GSockAddrFuncs GSockAddrFuncs; typedef struct _GSockAddr { GAtomicCounter refcnt; guint32 flags; GSockAddrFuncs *sa_funcs; int salen; struct sockaddr sa; } GSockAddr; struct _GSockAddrFuncs { GIOStatus (*bind_prepare)(gint sock, GSockAddr *addr); GIOStatus (*bind)(int sock, GSockAddr *addr); gchar *(*format)(GSockAddr *addr, gchar *text, gulong n, gint format); guint16 (*get_port) (GSockAddr *addr); void (*set_port) (GSockAddr *addr, guint16 port); }; gchar *g_sockaddr_format(GSockAddr *a, gchar *text, gulong n, gint format); guint16 g_sockaddr_get_port(GSockAddr *a); void g_sockaddr_set_port(GSockAddr *a, guint16 port); GSockAddr *g_sockaddr_new(struct sockaddr *sa, int salen); GSockAddr *g_sockaddr_ref(GSockAddr *a); void g_sockaddr_unref(GSockAddr *a); static inline struct sockaddr * g_sockaddr_get_sa(GSockAddr *self) { return &self->sa; } gboolean g_sockaddr_inet_check(GSockAddr *a); GSockAddr *g_sockaddr_inet_new(const gchar *ip, guint16 port); GSockAddr *g_sockaddr_inet_new2(struct sockaddr_in *sin); static inline struct sockaddr_in * g_sockaddr_inet_get_sa(GSockAddr *s) { g_assert(g_sockaddr_inet_check(s)); return (struct sockaddr_in *) g_sockaddr_get_sa(s); } /** * g_sockaddr_inet_get_address: * @s: GSockAddrInet instance * * This GSockAddrInet specific function returns the address part of the * address. **/ static inline struct in_addr g_sockaddr_inet_get_address(GSockAddr *s) { return g_sockaddr_inet_get_sa(s)->sin_addr; } /** * g_sockaddr_inet_set_address: * @s: GSockAddrInet instance * @addr: new address * * This GSockAddrInet specific function returns the address part of the * address. **/ static inline void g_sockaddr_inet_set_address(GSockAddr *s, struct in_addr addr) { g_sockaddr_inet_get_sa(s)->sin_addr = addr; } #if SYSLOG_NG_ENABLE_IPV6 gboolean g_sockaddr_inet6_check(GSockAddr *a); GSockAddr *g_sockaddr_inet6_new(const gchar *ip, guint16 port); GSockAddr *g_sockaddr_inet6_new2(struct sockaddr_in6 *sin6); static inline struct sockaddr_in6 * g_sockaddr_inet6_get_sa(GSockAddr *s) { g_assert(g_sockaddr_inet6_check(s)); return (struct sockaddr_in6 *) g_sockaddr_get_sa(s); } /** * g_sockaddr_inet6_get_address: * @s: GSockAddrInet instance * * This GSockAddrInet specific function returns the address part of the * address. **/ static inline struct in6_addr * g_sockaddr_inet6_get_address(GSockAddr *s) { return &g_sockaddr_inet6_get_sa(s)->sin6_addr; } /** * g_sockaddr_inet6_set_address: * @s: GSockAddrInet6 instance * @addr: new address * * This GSockAddrInet specific function sets the address part of the * address. **/ static inline void g_sockaddr_inet6_set_address(GSockAddr *s, struct in6_addr *addr) { g_sockaddr_inet6_get_sa(s)->sin6_addr = *addr; } #endif GSockAddr *g_sockaddr_unix_new(const gchar *name); GSockAddr *g_sockaddr_unix_new2(struct sockaddr_un *s_un, int sunlen); #endif syslog-ng-syslog-ng-3.13.2/lib/gsocket.c000066400000000000000000000072531321171025300200150ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "gsocket.h" #include #include /** * g_inet_ntoa: * @buf: store result in this buffer * @bufsize: the available space in buf * @a: address to convert. * * Thread friendly version of inet_ntoa(), converts an IP address to * human readable form. Returns: the address of buf **/ gchar * g_inet_ntoa(char *buf, size_t bufsize, struct in_addr a) { unsigned int ip = ntohl(a.s_addr); g_snprintf(buf, bufsize, "%d.%d.%d.%d", (ip & 0xff000000) >> 24, (ip & 0x00ff0000) >> 16, (ip & 0x0000ff00) >> 8, (ip & 0x000000ff)); return buf; } gint g_inet_aton(char *buf, struct in_addr *a) { return inet_aton(buf, a); } /** * g_bind: * @fd: fd to bind * @addr: address to bind to * * A thin interface around bind() using a GSockAddr structure for * socket address. It enables the NET_BIND_SERVICE capability (should be * in the permitted set. **/ GIOStatus g_bind(int fd, GSockAddr *addr) { GIOStatus rc; if (addr->sa_funcs && addr->sa_funcs->bind_prepare) addr->sa_funcs->bind_prepare(fd, addr); if (addr->sa_funcs && addr->sa_funcs->bind) rc = addr->sa_funcs->bind(fd, addr); else { if (addr && bind(fd, &addr->sa, addr->salen) < 0) { return G_IO_STATUS_ERROR; } rc = G_IO_STATUS_NORMAL; } return rc; } /** * g_accept: * @fd: accept connection on this socket * @newfd: fd of the accepted connection * @addr: store the address of the client here * * Accept a connection on the given fd, returning the newfd and the * address of the client in a Zorp SockAddr structure. * * Returns: glib style I/O error **/ GIOStatus g_accept(int fd, int *newfd, GSockAddr **addr) { char sabuf[1024]; socklen_t salen = sizeof(sabuf); do { *newfd = accept(fd, (struct sockaddr *) sabuf, &salen); } while (*newfd == -1 && errno == EINTR); if (*newfd != -1) { *addr = g_sockaddr_new((struct sockaddr *) sabuf, salen); } else if (errno == EAGAIN) { return G_IO_STATUS_AGAIN; } else { return G_IO_STATUS_ERROR; } return G_IO_STATUS_NORMAL; } /** * g_connect: * @fd: socket to connect * @remote: remote address * * Connect a socket using Zorp style GSockAddr structure. * * Returns: glib style I/O error **/ GIOStatus g_connect(int fd, GSockAddr *remote) { int rc; do { rc = connect(fd, &remote->sa, remote->salen); } while (rc == -1 && errno == EINTR); if (rc == -1) { if (errno == EAGAIN) return G_IO_STATUS_AGAIN; else return G_IO_STATUS_ERROR; } else { return G_IO_STATUS_NORMAL; } } syslog-ng-syslog-ng-3.13.2/lib/gsocket.h000066400000000000000000000025451321171025300200210ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef G_SOCKET_H_INCLUDED #define G_SOCKET_H_INCLUDED #include "syslog-ng.h" #include "gsockaddr.h" GIOStatus g_bind(int fd, GSockAddr *addr); GIOStatus g_accept(int fd, int *newfd, GSockAddr **addr); GIOStatus g_connect(int fd, GSockAddr *remote); gchar *g_inet_ntoa(char *buf, size_t bufsize, struct in_addr a); gint g_inet_aton(char *buf, struct in_addr *a); #endif syslog-ng-syslog-ng-3.13.2/lib/host-id.c000066400000000000000000000042231321171025300177170ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "host-id.h" #include "str-format.h" #include guint32 global_host_id = 0; static guint32 _create_host_id(void) { union { unsigned char _raw[sizeof(guint32)]; guint32 id; } host_id; RAND_bytes(host_id._raw, sizeof(host_id._raw)); return host_id.id; } void host_id_init(PersistState *state) { gsize size; guint8 version; PersistEntryHandle handle; HostIdState *host_id_state; gboolean new_host_id_required = FALSE; handle = persist_state_lookup_entry(state, HOST_ID_PERSIST_KEY, &size, &version); if (handle == 0) { new_host_id_required = TRUE; handle = persist_state_alloc_entry(state, HOST_ID_PERSIST_KEY, sizeof(HostIdState)); } host_id_state = persist_state_map_entry(state, handle); { if (new_host_id_required) { global_host_id = _create_host_id(); host_id_state->host_id = global_host_id; } else { global_host_id = host_id_state->host_id; } } persist_state_unmap_entry(state, handle); } guint32 host_id_get(void) { return global_host_id; } void host_id_append_formatted_id(GString *str, guint32 id) { format_uint32_padded(str, 8, '0', 16, id); } syslog-ng-syslog-ng-3.13.2/lib/host-id.h000066400000000000000000000025571321171025300177340ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef HOST_ID_H #define HOST_ID_H #include "persist-state.h" #include "persistable-state-header.h" #define HOST_ID_PERSIST_KEY "host_id" typedef struct _HostIdState { PersistableStateHeader header; guint32 host_id; } HostIdState; void host_id_init(PersistState *state); void host_id_deinit(void); guint32 host_id_get(void); void host_id_append_formatted_id(GString* str, guint32 id); #endif syslog-ng-syslog-ng-3.13.2/lib/host-resolve.c000066400000000000000000000265031321171025300210070ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "host-resolve.h" #include "hostname.h" #include "dnscache.h" #include "messages.h" #include "cfg.h" #include "tls-support.h" #include "compat/socket.h" #include #include #include #if !defined(SYSLOG_NG_HAVE_GETADDRINFO) || !defined(SYSLOG_NG_HAVE_GETNAMEINFO) G_LOCK_DEFINE_STATIC(resolv_lock); #endif TLS_BLOCK_START { gchar hostname_buffer[256]; } TLS_BLOCK_END; #define hostname_buffer __tls_deref(hostname_buffer) static void normalize_hostname(gchar *result, gsize result_size, const gchar *hostname) { gsize i; for (i = 0; hostname[i] && i < (result_size - 1); i++) { result[i] = g_ascii_tolower(hostname[i]); } result[i] = '\0'; /* the closing \0 is not copied by the previous loop */ } static const gchar * bounce_to_hostname_buffer(const gchar *hname) { if (hname != hostname_buffer) g_strlcpy(hostname_buffer, hname, sizeof(hostname_buffer)); return hostname_buffer; } static const gchar * hostname_apply_options(gssize result_len_orig, gsize *result_len, const gchar *hname, const HostResolveOptions *host_resolve_options) { if (host_resolve_options->normalize_hostnames) { normalize_hostname(hostname_buffer, sizeof(hostname_buffer), hname); hname = hostname_buffer; } if (result_len_orig >= 0) *result_len = result_len_orig; else *result_len = strlen(hname); return hname; } static const gchar * hostname_apply_options_fqdn(gssize result_len_orig, gsize *result_len, const gchar *hname, gboolean positive, const HostResolveOptions *host_resolve_options) { if (positive && !host_resolve_options->use_fqdn) { /* we only truncate hostnames if they were positive * matches (e.g. real hostnames and not IP * addresses) */ hname = bounce_to_hostname_buffer(hname); convert_hostname_to_short_hostname(hostname_buffer, sizeof(hostname_buffer)); result_len_orig = -1; } return hostname_apply_options(result_len_orig, result_len, hname, host_resolve_options); } /**************************************************************************** * Convert a GSockAddr instance to a hostname ****************************************************************************/ static gboolean is_wildcard_hostname(const gchar *name) { return !name || name[0] == 0; } static gboolean resolve_wildcard_hostname_to_sockaddr(GSockAddr **addr, gint family, const gchar *name) { struct sockaddr_storage ss; /* return the wildcard address that can be used as a bind address */ memset(&ss, 0, sizeof(ss)); ss.ss_family = family; switch (family) { case AF_INET: *addr = g_sockaddr_inet_new2(((struct sockaddr_in *) &ss)); break; #if SYSLOG_NG_ENABLE_IPV6 case AF_INET6: *addr = g_sockaddr_inet6_new2((struct sockaddr_in6 *) &ss); break; #endif default: g_assert_not_reached(); break; } return TRUE; } #ifdef SYSLOG_NG_HAVE_GETADDRINFO static gboolean resolve_hostname_to_sockaddr_using_getaddrinfo(GSockAddr **addr, gint family, const gchar *name) { struct addrinfo hints; struct addrinfo *res; memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = 0; hints.ai_protocol = 0; if (getaddrinfo(name, NULL, &hints, &res) == 0) { /* we only use the first entry in the returned list */ switch (family) { case AF_INET: *addr = g_sockaddr_inet_new2(((struct sockaddr_in *) res->ai_addr)); break; #if SYSLOG_NG_ENABLE_IPV6 case AF_INET6: *addr = g_sockaddr_inet6_new2((struct sockaddr_in6 *) res->ai_addr); break; #endif default: g_assert_not_reached(); break; } freeaddrinfo(res); return TRUE; } return FALSE; } #else static gboolean resolve_hostname_to_sockaddr_using_gethostbyname(GSockAddr **addr, gint family, const gchar *name) { struct hostent *he; G_LOCK(resolv_lock); he = gethostbyname(name); if (he) { switch (family) { case AF_INET: { struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_addr = *(struct in_addr *) he->h_addr; sin.sin_port = htons(0); *addr = g_sockaddr_inet_new2(&sin); break; } default: g_assert_not_reached(); break; } } G_UNLOCK(resolv_lock); return he != NULL; } #endif gboolean resolve_hostname_to_sockaddr(GSockAddr **addr, gint family, const gchar *name) { gboolean result; if (is_wildcard_hostname(name)) return resolve_wildcard_hostname_to_sockaddr(addr, family, name); #ifdef SYSLOG_NG_HAVE_GETADDRINFO result = resolve_hostname_to_sockaddr_using_getaddrinfo(addr, family, name); #else result = resolve_hostname_to_sockaddr_using_gethostbyname(addr, family, name); #endif if (!result) { msg_error("Error resolving hostname", evt_tag_str("host", name)); } return result; } /**************************************************************************** * Convert a hostname to a GSockAddr instance ****************************************************************************/ static gboolean is_sockaddr_local(GSockAddr *saddr) { return !saddr || (saddr->sa.sa_family != AF_INET && saddr->sa.sa_family != AF_INET6); } static const gchar * resolve_sockaddr_to_local_hostname(gsize *result_len, GSockAddr *saddr, const HostResolveOptions *host_resolve_options) { const gchar *hname; if (host_resolve_options->use_fqdn) hname = get_local_hostname_fqdn(); else hname = get_local_hostname_short(); return hostname_apply_options(-1, result_len, hname, host_resolve_options); } #ifdef SYSLOG_NG_HAVE_GETNAMEINFO static const gchar * resolve_address_using_getnameinfo(GSockAddr *saddr, gchar *buf, gsize buf_len) { if (getnameinfo(&saddr->sa, saddr->salen, buf, buf_len, NULL, 0, NI_NAMEREQD) == 0) return buf; return NULL; } #else static const gchar * resolve_address_using_gethostbyaddr(GSockAddr *saddr, gchar *buf, gsize buf_len) { const gchar *result = NULL; struct hostent *hp; void *addr; socklen_t addr_len G_GNUC_UNUSED; g_assert(saddr->sa.sa_family == AF_INET); addr = &((struct sockaddr_in *) &saddr->sa)->sin_addr; addr_len = sizeof(struct in_addr); G_LOCK(resolv_lock); hp = gethostbyaddr(addr, addr_len, saddr->sa.sa_family); if (hp && hp->h_name) { strncpy(buf, hp->h_name, buf_len); buf[buf_len - 1] = 0; result = buf; } G_UNLOCK(resolv_lock); return result; } #endif static void * sockaddr_to_dnscache_key(GSockAddr *saddr) { if (saddr->sa.sa_family == AF_INET) return &((struct sockaddr_in *) &saddr->sa)->sin_addr; #if SYSLOG_NG_ENABLE_IPV6 else return &((struct sockaddr_in6 *) &saddr->sa)->sin6_addr; #endif } static const gchar * resolve_sockaddr_to_inet_or_inet6_hostname(gsize *result_len, GSockAddr *saddr, const HostResolveOptions *host_resolve_options) { const gchar *hname; gsize hname_len; gboolean positive; void *dnscache_key; dnscache_key = sockaddr_to_dnscache_key(saddr); hname = NULL; positive = FALSE; if (host_resolve_options->use_dns_cache) { if (dns_caching_lookup(saddr->sa.sa_family, dnscache_key, (const gchar **) &hname, &hname_len, &positive)) return hostname_apply_options_fqdn(hname_len, result_len, hname, positive, host_resolve_options); } if (!hname && host_resolve_options->use_dns && host_resolve_options->use_dns != 2) { #ifdef SYSLOG_NG_HAVE_GETNAMEINFO hname = resolve_address_using_getnameinfo(saddr, hostname_buffer, sizeof(hostname_buffer)); #else hname = resolve_address_using_gethostbyaddr(saddr, hostname_buffer, sizeof(hostname_buffer)); #endif positive = (hname != NULL); } if (!hname) { hname = g_sockaddr_format(saddr, hostname_buffer, sizeof(hostname_buffer), GSA_ADDRESS_ONLY); positive = FALSE; } if (host_resolve_options->use_dns_cache) dns_caching_store(saddr->sa.sa_family, dnscache_key, hname, positive); return hostname_apply_options_fqdn(-1, result_len, hname, positive, host_resolve_options); } const gchar * resolve_sockaddr_to_hostname(gsize *result_len, GSockAddr *saddr, const HostResolveOptions *host_resolve_options) { if (is_sockaddr_local(saddr)) return resolve_sockaddr_to_local_hostname(result_len, saddr, host_resolve_options); else return resolve_sockaddr_to_inet_or_inet6_hostname(result_len, saddr, host_resolve_options); } /**************************************************************************** * Convert a hostname to a hostname with options applied. ****************************************************************************/ const gchar * resolve_hostname_to_hostname(gsize *result_len, const gchar *hname, HostResolveOptions *host_resolve_options) { hname = bounce_to_hostname_buffer(hname); if (host_resolve_options->use_fqdn) convert_hostname_to_fqdn(hostname_buffer, sizeof(hostname_buffer)); else convert_hostname_to_short_hostname(hostname_buffer, sizeof(hostname_buffer)); return hostname_apply_options(-1, result_len, hname, host_resolve_options); } /**************************************************************************** * HostResolveOptions ****************************************************************************/ void host_resolve_options_defaults(HostResolveOptions *options) { options->use_dns = -1; options->use_fqdn = -1; options->use_dns_cache = -1; options->normalize_hostnames = -1; } void host_resolve_options_global_defaults(HostResolveOptions *options) { options->use_fqdn = FALSE; options->use_dns = TRUE; options->use_dns_cache = TRUE; options->normalize_hostnames = FALSE; } static void _init_options(HostResolveOptions *options) { } void host_resolve_options_init_globals(HostResolveOptions *options) { _init_options(options); } void host_resolve_options_init(HostResolveOptions *options, HostResolveOptions *global_options) { if (options->use_dns == -1) options->use_dns = global_options->use_dns; if (options->use_fqdn == -1) options->use_fqdn = global_options->use_fqdn; if (options->use_dns_cache == -1) options->use_dns_cache = global_options->use_dns_cache; if (options->normalize_hostnames == -1) options->normalize_hostnames = global_options->normalize_hostnames; _init_options(options); } void host_resolve_options_destroy(HostResolveOptions *options) { } syslog-ng-syslog-ng-3.13.2/lib/host-resolve.h000066400000000000000000000036511321171025300210130ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef HOST_RESOLVE_H_INCLUDED #define HOST_RESOLVE_H_INCLUDED 1 #include "syslog-ng.h" #include "gsockaddr.h" typedef struct _HostResolveOptions { gboolean use_dns; gboolean use_fqdn; gboolean use_dns_cache; gboolean normalize_hostnames; } HostResolveOptions; /* name resolution */ const gchar *resolve_sockaddr_to_hostname(gsize *result_len, GSockAddr *saddr, const HostResolveOptions *host_resolve_options); gboolean resolve_hostname_to_sockaddr(GSockAddr **addr, gint family, const gchar *name); const gchar *resolve_hostname_to_hostname(gsize *result_len, const gchar *hostname, HostResolveOptions *options); void host_resolve_options_defaults(HostResolveOptions *options); void host_resolve_options_global_defaults(HostResolveOptions *options); void host_resolve_options_init_globals(HostResolveOptions *options); void host_resolve_options_init(HostResolveOptions *options, HostResolveOptions *global_options); void host_resolve_options_destroy(HostResolveOptions *options); #endif syslog-ng-syslog-ng-3.13.2/lib/hostname-unix.c000066400000000000000000000040411321171025300211450ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ /* NOTE: this file is included directly into hostname.c so the set of * includes here only add system dependent headers and not the full set */ #include static struct hostent * _resolve_localhost_from_dns(void) { gchar *local_host; struct hostent *host; local_host = get_local_hostname_from_system(); host = gethostbyname(local_host); g_free(local_host); return host; } static const gchar * _extract_fqdn_from_hostent(struct hostent *host) { gint i; if (is_hostname_fqdn(host->h_name)) return host->h_name; for (i = 0; host->h_aliases[i]; i++) { if (is_hostname_fqdn(host->h_aliases[i])) return host->h_aliases[i]; } return NULL; } /* * NOTE: this function is not thread safe because it uses the non-reentrant * resolver functions. This is not a problem as it is only called once * during initialization when a single thread is active. */ gchar * get_local_fqdn_hostname_from_dns(void) { struct hostent *hostent; hostent = _resolve_localhost_from_dns(); if (hostent) return g_strdup(_extract_fqdn_from_hostent(hostent)); return NULL; } syslog-ng-syslog-ng-3.13.2/lib/hostname.c000066400000000000000000000114271321171025300201720ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "hostname.h" #include "cfg.h" #include "gsockaddr.h" #include "messages.h" #include "dnscache.h" #include #include #include static gchar local_hostname_fqdn[256]; static gchar local_hostname_short[256]; static gchar local_domain[256]; static gboolean local_domain_overridden; static gchar * get_local_hostname_from_system(void) { gchar hostname[256]; gethostname(hostname, sizeof(hostname) - 1); hostname[sizeof(hostname) - 1] = '\0'; return g_strdup(hostname); } static gboolean is_hostname_fqdn(const gchar *hostname) { return strchr(hostname, '.') != NULL; } static const gchar * extract_domain_from_fqdn(const gchar *hostname) { const gchar *dot = strchr(hostname, '.'); if (dot) return dot + 1; return NULL; } #include "hostname-unix.c" static void validate_hostname_cache(void) { g_assert(local_hostname_fqdn[0] != 0); } const gchar * get_local_hostname_fqdn(void) { validate_hostname_cache(); return local_hostname_fqdn; } const gchar * get_local_hostname_short(void) { validate_hostname_cache(); return local_hostname_short; } gchar * convert_hostname_to_fqdn(gchar *hostname, gsize hostname_len) { gchar *end; /* we only change the hostname if domain_override is set. If it is unset, * our best guess is what we got as input. */ if (local_domain_overridden) convert_hostname_to_short_hostname(hostname, hostname_len); if (local_domain_overridden || (!is_hostname_fqdn(hostname) && local_domain[0])) { end = hostname + strlen(hostname); if (end < hostname + hostname_len) { *end = '.'; end++; } strncpy(end, local_domain, hostname_len - (end - hostname)); hostname[hostname_len - 1] = 0; } return hostname; } gchar * convert_hostname_to_short_hostname(gchar *hostname, gsize hostname_len) { gchar *p; p = strchr(hostname, '.'); if (p) *p = '\0'; return hostname; } static void detect_local_fqdn_hostname(void) { gchar *hostname; hostname = get_local_hostname_from_system(); if (!is_hostname_fqdn(hostname)) { /* not fully qualified, resolve it using DNS or /etc/hosts */ g_free(hostname); hostname = get_local_fqdn_hostname_from_dns(); if (!hostname) { msg_verbose("Unable to detect fully qualified hostname for localhost, use_fqdn() will use the short hostname"); hostname = get_local_hostname_from_system(); if (!hostname[0]) { msg_error("Could not resolve local hostname either from the DNS nor gethostname(), assuming localhost"); hostname = g_strdup("localhost"); } } } g_strlcpy(local_hostname_fqdn, hostname, sizeof(local_hostname_fqdn)); g_free(hostname); } static void detect_local_domain(void) { const gchar *domain = extract_domain_from_fqdn(local_hostname_fqdn); if (domain) g_strlcpy(local_domain, domain, sizeof(local_domain)); else local_domain[0] = 0; } static void detect_local_short_hostname(void) { g_strlcpy(local_hostname_short, local_hostname_fqdn, sizeof(local_hostname_short)); convert_hostname_to_short_hostname(local_hostname_short, sizeof(local_hostname_short)); } static void set_domain_override(const gchar *domain_override) { if (domain_override) { g_strlcpy(local_domain, domain_override, sizeof(local_domain)); local_domain_overridden = TRUE; } else local_domain_overridden = FALSE; convert_hostname_to_fqdn(local_hostname_fqdn, sizeof(local_hostname_fqdn)); } void hostname_reinit(const gchar *domain_override) { detect_local_fqdn_hostname(); detect_local_domain(); detect_local_short_hostname(); set_domain_override(domain_override); } void hostname_global_init(void) { hostname_reinit(NULL); } void hostname_global_deinit(void) { } syslog-ng-syslog-ng-3.13.2/lib/hostname.h000066400000000000000000000026001321171025300201700ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef HOSTNAME_H_INCLUDED #define HOSTNAME_H_INCLUDED #include "syslog-ng.h" gchar *convert_hostname_to_fqdn(gchar *hostname, gsize hostname_len); gchar *convert_hostname_to_short_hostname(gchar *hostname, gsize hostname_len); const gchar *get_local_hostname_fqdn(void); const gchar *get_local_hostname_short(void); void hostname_reinit(const gchar *custom_domain); void hostname_global_init(void); void hostname_global_deinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/ivykis/000077500000000000000000000000001321171025300175215ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/jsonc/000077500000000000000000000000001321171025300173175ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/late_ack_tracker.c000066400000000000000000000127741321171025300216400ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 2014 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "ack_tracker.h" #include "bookmark.h" #include "ringbuffer.h" #include "syslog-ng.h" typedef struct _LateAckRecord { AckRecord super; gboolean acked; Bookmark bookmark; } LateAckRecord; typedef struct LateAckTracker { AckTracker super; LateAckRecord *pending_ack_record; RingBuffer ack_record_storage; GStaticMutex storage_mutex; } LateAckTracker; static inline void late_ack_record_destroy(LateAckRecord *self) { if (self->bookmark.destroy) self->bookmark.destroy(&(self->bookmark)); } static inline void _late_tracker_lock(LateAckTracker *self) { g_static_mutex_lock(&self->storage_mutex); } static inline void _late_tracker_unlock(LateAckTracker *self) { g_static_mutex_unlock(&self->storage_mutex); } static inline gboolean _ack_range_is_continuous(void *data) { LateAckRecord *ack_rec = (LateAckRecord *)data; return ack_rec->acked; } static inline guint32 _get_continuous_range_length(LateAckTracker *self) { return ring_buffer_get_continual_range_length(&self->ack_record_storage, _ack_range_is_continuous); } static inline void _drop_range(LateAckTracker *self, guint32 n) { int i; LateAckRecord *ack_rec; for (i = 0; i < n; i++) { ack_rec = ring_buffer_element_at(&self->ack_record_storage, i); ack_rec->acked = FALSE; late_ack_record_destroy(ack_rec); ack_rec->bookmark.save = NULL; ack_rec->bookmark.destroy = NULL; } ring_buffer_drop(&self->ack_record_storage, n); } static void late_ack_tracker_track_msg(AckTracker *s, LogMessage *msg) { LateAckTracker *self = (LateAckTracker *)s; LogSource *source = self->super.source; g_assert(self->pending_ack_record != NULL); log_pipe_ref((LogPipe *)source); msg->ack_record = (AckRecord *)self->pending_ack_record; _late_tracker_lock(self); { LateAckRecord *ack_rec; ack_rec = (LateAckRecord *)ring_buffer_push(&self->ack_record_storage); g_assert(ack_rec == self->pending_ack_record); } _late_tracker_unlock(self); self->pending_ack_record = NULL; } static void late_ack_tracker_manage_msg_ack(AckTracker *s, LogMessage *msg, AckType ack_type) { LateAckTracker *self = (LateAckTracker *)s; LateAckRecord *ack_rec = (LateAckRecord *)msg->ack_record; LateAckRecord *last_in_range = NULL; guint32 ack_range_length = 0; ack_rec->acked = TRUE; _late_tracker_lock(self); { ack_range_length = _get_continuous_range_length(self); if (ack_range_length > 0) { last_in_range = ring_buffer_element_at(&self->ack_record_storage, ack_range_length - 1); if (ack_type != AT_ABORTED) { Bookmark *bookmark = &(last_in_range->bookmark); bookmark->save(bookmark); } _drop_range(self, ack_range_length); if (ack_type == AT_SUSPENDED) log_source_flow_control_suspend(self->super.source); else log_source_flow_control_adjust(self->super.source, ack_range_length); } } _late_tracker_unlock(self); log_msg_unref(msg); log_pipe_unref((LogPipe *)self->super.source); } static Bookmark * late_ack_tracker_request_bookmark(AckTracker *s) { LateAckTracker *self = (LateAckTracker *)s; _late_tracker_lock(self); { self->pending_ack_record = ring_buffer_tail(&self->ack_record_storage); } _late_tracker_unlock(self); if (self->pending_ack_record) { self->pending_ack_record->bookmark.persist_state = s->source->super.cfg->state; self->pending_ack_record->super.tracker = (AckTracker *)self; return &(self->pending_ack_record->bookmark); } return NULL; } static void late_ack_tracker_init_instance(LateAckTracker *self, LogSource *source) { self->super.late = TRUE; self->super.source = source; source->ack_tracker = (AckTracker *)self; self->super.request_bookmark = late_ack_tracker_request_bookmark; self->super.track_msg = late_ack_tracker_track_msg; self->super.manage_msg_ack = late_ack_tracker_manage_msg_ack; ring_buffer_alloc(&self->ack_record_storage, sizeof(LateAckRecord), log_source_get_init_window_size(source)); g_static_mutex_init(&self->storage_mutex); } AckTracker * late_ack_tracker_new(LogSource *source) { LateAckTracker *self = g_new0(LateAckTracker, 1); late_ack_tracker_init_instance(self, source); return (AckTracker *)self; } void late_ack_tracker_free(AckTracker *s) { LateAckTracker *self = (LateAckTracker *)s; guint32 count = ring_buffer_count(&self->ack_record_storage); g_static_mutex_free(&self->storage_mutex); _drop_range(self, count); ring_buffer_free(&self->ack_record_storage); g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/logmatcher.c000066400000000000000000000643471321171025300205120ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logmatcher.h" #include "messages.h" #include "cfg.h" #include "str-utils.h" #include "compat/string.h" #include "compat/pcre.h" static gboolean _shall_set_values_indirectly(NVHandle value_handle) { return value_handle != LM_V_NONE && !log_msg_is_handle_macro(value_handle) && !log_msg_is_handle_match(value_handle); } static void log_matcher_init(LogMatcher *self, const LogMatcherOptions *options) { self->ref_cnt = 1; self->flags = options->flags; } typedef struct _LogMatcherPosixRe { LogMatcher super; regex_t pattern; } LogMatcherPosixRe; static gboolean log_matcher_posix_re_compile(LogMatcher *s, const gchar *re, GError **error) { LogMatcherPosixRe *self = (LogMatcherPosixRe *) s; gint rc; const gchar *re_comp = re; gint flags = REG_EXTENDED; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); if (re[0] == '(' && re[1] == '?') { gint i; for (i = 2; re[i] && re[i] != ')'; i++) { if (re[i] == 'i') { /* deprecated */ msg_warning_once("WARNING: Your configuration file uses an obsoleted regexp option, please update your configuration", evt_tag_str("option", "(?i)"), evt_tag_str("change", "use ignore-case flag instead of (?i)")); flags |= REG_ICASE; } } if (re[i]) { re_comp = &re[i + 1]; } else { g_set_error(error, LOG_MATCHER_ERROR, 0, "missing closing parentheses in regexp flags"); return FALSE; } } if (self->super.flags & LMF_ICASE) flags |= REG_ICASE; if (self->super.flags & LMF_NEWLINE) flags |= REG_NEWLINE; if ((self->super.flags & (LMF_MATCH_ONLY + LMF_STORE_MATCHES)) == LMF_MATCH_ONLY) flags |= REG_NOSUB; rc = regcomp(&self->pattern, re_comp, flags); if (rc) { gchar buf[256]; regerror(rc, &self->pattern, buf, sizeof(buf)); g_set_error(error, LOG_MATCHER_ERROR, 0, "Error compiling regular expression: %s", buf); return FALSE; } return TRUE; } static void log_matcher_posix_re_feed_backrefs(LogMatcher *s, LogMessage *msg, gint value_handle, regmatch_t *matches, const gchar *value) { gint i; gboolean indirect = _shall_set_values_indirectly(value_handle); for (i = 0; i < RE_MAX_MATCHES && matches[i].rm_so != -1; i++) { if (indirect) { log_msg_set_match_indirect(msg, i, value_handle, 0, matches[i].rm_so, matches[i].rm_eo - matches[i].rm_so); } else { log_msg_set_match(msg, i, &value[matches[i].rm_so], matches[i].rm_eo - matches[i].rm_so); } } } static gboolean log_matcher_posix_re_match(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len) { LogMatcherPosixRe *self = (LogMatcherPosixRe *) s; regmatch_t matches[RE_MAX_MATCHES]; gboolean rc; const gchar *buf; APPEND_ZERO(buf, value, value_len); rc = !regexec(&self->pattern, buf, RE_MAX_MATCHES, matches, 0); if (rc && (s->flags & LMF_STORE_MATCHES)) { log_matcher_posix_re_feed_backrefs(s, msg, value_handle, matches, value); } return rc; } static gchar * log_matcher_posix_re_replace(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len, LogTemplate *replacement, gssize *new_length) { LogMatcherPosixRe *self = (LogMatcherPosixRe *) s; regmatch_t matches[RE_MAX_MATCHES]; gboolean rc; GString *new_value = NULL; gsize current_ofs = 0; gboolean first_round = TRUE; gchar *buf; APPEND_ZERO(buf, value, value_len); do { if (current_ofs == value_len) break; rc = !regexec(&self->pattern, buf + current_ofs, RE_MAX_MATCHES, matches, current_ofs > 0 ? REG_NOTBOL : 0); if (rc) { /* start_ofs & end_ofs are relative to the original string */ gsize start_ofs = matches[0].rm_so + current_ofs; gsize end_ofs = matches[0].rm_eo + current_ofs; if (start_ofs == end_ofs && !first_round) { start_ofs++; end_ofs++; } log_matcher_posix_re_feed_backrefs(s, msg, value_handle, matches, buf + current_ofs); if (!new_value) new_value = g_string_sized_new(value_len); g_string_append_len(new_value, buf + current_ofs, start_ofs - current_ofs); log_template_append_format(replacement, msg, NULL, LTZ_LOCAL, 0, NULL, new_value); current_ofs = end_ofs; if ((self->super.flags & LMF_GLOBAL) == 0) { g_string_append_len(new_value, buf + current_ofs, value_len - current_ofs); break; } } else { if (new_value) { /* no more matches, append the end of the string */ g_string_append_len(new_value, buf + current_ofs, value_len - current_ofs); } } first_round = FALSE; } while (rc && (self->super.flags & LMF_GLOBAL)); if (new_value) { if (new_length) *new_length = new_value->len; return g_string_free(new_value, FALSE); } return NULL; } static void log_matcher_posix_re_free(LogMatcher *s) { LogMatcherPosixRe *self = (LogMatcherPosixRe *) s; regfree(&self->pattern); } LogMatcher * log_matcher_posix_re_new(GlobalConfig *cfg, const LogMatcherOptions *options) { LogMatcherPosixRe *self = g_new0(LogMatcherPosixRe, 1); log_matcher_init(&self->super, options); self->super.compile = log_matcher_posix_re_compile; self->super.match = log_matcher_posix_re_match; self->super.replace = log_matcher_posix_re_replace; self->super.free_fn = log_matcher_posix_re_free; return &self->super; } typedef struct _LogMatcherString { LogMatcher super; gchar *pattern; gint pattern_len; } LogMatcherString; static gboolean log_matcher_string_compile(LogMatcher *s, const gchar *pattern, GError **error) { LogMatcherString *self = (LogMatcherString *) s; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); self->pattern = g_strdup(pattern); self->pattern_len = strlen(self->pattern); return TRUE; } static const gchar * log_matcher_string_match_string(LogMatcherString *self, const gchar *value, gsize value_len) { const gchar *result = NULL; gboolean match = FALSE; if (self->pattern_len > value_len) return NULL; if (G_LIKELY((self->super.flags & (LMF_SUBSTRING + LMF_PREFIX)) == 0)) { if (self->super.flags & LMF_ICASE) match = strncasecmp(value, self->pattern, value_len) == 0; else match = strncmp(value, self->pattern, value_len) == 0; } else if (self->super.flags & LMF_PREFIX) { if (self->super.flags & LMF_ICASE) match = strncasecmp(value, self->pattern, MIN(value_len, self->pattern_len)) == 0; else match = strncmp(value, self->pattern, MIN(value_len, self->pattern_len)) == 0; } else if (self->super.flags & LMF_SUBSTRING) { if (self->super.flags & LMF_ICASE) { gchar *buf; gchar *res; APPEND_ZERO(buf, value, value_len); res = strcasestr(buf, self->pattern); if (res) result = value + (res - buf); } else { result = g_strstr_len(value, value_len, self->pattern); } } if (match && !result) result = value; return result; } static gboolean log_matcher_string_match(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len) { LogMatcherString *self = (LogMatcherString *) s; return log_matcher_string_match_string(self, value, value_len) != NULL; } static gchar * log_matcher_string_replace(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len, LogTemplate *replacement, gssize *new_length) { LogMatcherString *self = (LogMatcherString *) s; GString *new_value = NULL; gsize current_ofs = 0; gboolean first_round = TRUE; if (value_len < 0) value_len = strlen(value); const gchar *match; do { if (current_ofs == value_len) break; match = log_matcher_string_match_string(self, value + current_ofs, value_len - current_ofs); if (match != NULL) { /* start_ofs & end_ofs are relative to the original string */ gsize start_ofs = match - value; gsize end_ofs = start_ofs + self->pattern_len; if (start_ofs == end_ofs && !first_round) { start_ofs++; end_ofs++; } if ((s->flags & LMF_STORE_MATCHES)) log_msg_clear_matches(msg); if (!new_value) new_value = g_string_sized_new(value_len); g_string_append_len(new_value, value + current_ofs, start_ofs - current_ofs); log_template_append_format(replacement, msg, NULL, LTZ_LOCAL, 0, NULL, new_value); current_ofs = end_ofs; if ((self->super.flags & LMF_GLOBAL) == 0) { g_string_append_len(new_value, value + current_ofs, value_len - current_ofs); break; } } else { if (new_value) { /* no more matches, append the end of the string */ g_string_append_len(new_value, value + current_ofs, value_len - current_ofs); } } first_round = FALSE; } while (match && (self->super.flags & LMF_GLOBAL)); if (new_value) { if (new_length) *new_length = new_value->len; return g_string_free(new_value, FALSE); } return NULL; } static void log_matcher_string_free(LogMatcher *s) { LogMatcherString *self = (LogMatcherString *) s; g_free(self->pattern); } LogMatcher * log_matcher_string_new(GlobalConfig *cfg, const LogMatcherOptions *options) { LogMatcherString *self = g_new0(LogMatcherString, 1); log_matcher_init(&self->super, options); self->super.compile = log_matcher_string_compile; self->super.match = log_matcher_string_match; self->super.replace = log_matcher_string_replace; self->super.free_fn = log_matcher_string_free; return &self->super; } typedef struct _LogMatcherGlob { LogMatcher super; GPatternSpec *pattern; } LogMatcherGlob; static gboolean log_matcher_glob_compile(LogMatcher *s, const gchar *pattern, GError **error) { LogMatcherGlob *self = (LogMatcherGlob *)s; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); self->pattern = g_pattern_spec_new(pattern); return TRUE; } /* GPattern only works with utf8 strings, if the input is not utf8, we risk * a crash */ static gboolean log_matcher_glob_match(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len) { LogMatcherGlob *self = (LogMatcherGlob *) s; if (G_LIKELY((msg->flags & LF_UTF8) || g_utf8_validate(value, value_len, NULL))) { static gboolean warned = FALSE; gchar *buf; if (G_UNLIKELY(!warned && (msg->flags & LF_UTF8) == 0)) { msg_warning("Input is valid utf8, but the log message is not tagged as such, this performs worse than enabling validate-utf8 flag on input", evt_tag_printf("value", "%.*s", (gint) value_len, value)); warned = TRUE; } APPEND_ZERO(buf, value, value_len); return g_pattern_match(self->pattern, value_len, buf, NULL); } else { msg_warning("Input is not valid utf8, glob match requires utf8 input, thus it never matches in this case", evt_tag_printf("value", "%.*s", (gint) value_len, value)); } return FALSE; } static void log_matcher_glob_free(LogMatcher *s) { LogMatcherGlob *self = (LogMatcherGlob *)s; g_pattern_spec_free(self->pattern); } LogMatcher * log_matcher_glob_new(GlobalConfig *cfg, const LogMatcherOptions *options) { LogMatcherGlob *self = g_new0(LogMatcherGlob, 1); log_matcher_init(&self->super, options); self->super.compile = log_matcher_glob_compile; self->super.match = log_matcher_glob_match; self->super.replace = NULL; self->super.free_fn = log_matcher_glob_free; return &self->super; } /* libpcre support */ typedef struct _LogMatcherPcreRe { LogMatcher super; pcre *pattern; pcre_extra *extra; gint match_options; } LogMatcherPcreRe; static gboolean log_matcher_pcre_re_compile(LogMatcher *s, const gchar *re, GError **error) { LogMatcherPcreRe *self = (LogMatcherPcreRe *) s; gint rc; const gchar *re_comp = re; const gchar *errptr; gint erroffset; gint flags = 0; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); if (self->super.flags & LMF_ICASE) flags |= PCRE_CASELESS; if (self->super.flags & LMF_NEWLINE) { if (!PCRE_NEWLINE_ANYCRLF) msg_warning("syslog-ng was compiled against an old PCRE which doesn't support the 'newline' flag"); flags |= PCRE_NEWLINE_ANYCRLF; } if (self->super.flags & LMF_UTF8) { gint support; flags |= PCRE_UTF8 | PCRE_NO_UTF8_CHECK; self->match_options |= PCRE_NO_UTF8_CHECK; pcre_config(PCRE_CONFIG_UTF8, &support); if (!support) { g_set_error(error, LOG_TEMPLATE_ERROR, 0, "PCRE library is compiled without UTF8 support and utf8 flag was present"); return FALSE; } pcre_config(PCRE_CONFIG_UNICODE_PROPERTIES, &support); if (!support) { g_set_error(error, LOG_TEMPLATE_ERROR, 0, "PCRE library is compiled without UTF8 properties support and utf8 flag was present"); return FALSE; } } /* complile the regexp */ self->pattern = pcre_compile2(re_comp, flags, &rc, &errptr, &erroffset, NULL); if (!self->pattern) { g_set_error(error, LOG_TEMPLATE_ERROR, 0, "Error while compiling PCRE expression, error=%s, error_at=%d", errptr, erroffset); return FALSE; } /* optimize regexp */ self->extra = pcre_study(self->pattern, PCRE_STUDY_JIT_COMPILE, &errptr); if (errptr != NULL) { g_set_error(error, LOG_TEMPLATE_ERROR, 0, "Error while optimizing regular expression, error=%s", errptr); return FALSE; } return TRUE; } static void log_matcher_pcre_re_feed_backrefs(LogMatcher *s, LogMessage *msg, gint value_handle, int *matches, gint match_num, const gchar *value) { gint i; gboolean indirect = _shall_set_values_indirectly(value_handle); for (i = 0; i < (RE_MAX_MATCHES) && i < match_num; i++) { if (indirect) { log_msg_set_match_indirect(msg, i, value_handle, 0, matches[2 * i], matches[2 * i + 1] - matches[2 * i]); } else { log_msg_set_match(msg, i, &value[matches[2 * i]], matches[2 * i + 1] - matches[2 * i]); } } } static void log_matcher_pcre_re_feed_named_substrings(LogMatcher *s, LogMessage *msg, int *matches, const gchar *value) { gchar *name_table = NULL; gint i = 0; gint namecount = 0; gint name_entry_size = 0; LogMatcherPcreRe *self = (LogMatcherPcreRe *) s; pcre_fullinfo(self->pattern, self->extra, PCRE_INFO_NAMECOUNT, &namecount); if (namecount > 0) { gchar *tabptr; /* Before we can access the substrings, we must extract the table for translating names to numbers, and the size of each entry in the table. */ pcre_fullinfo(self->pattern, self->extra, PCRE_INFO_NAMETABLE, &name_table); pcre_fullinfo(self->pattern, self->extra, PCRE_INFO_NAMEENTRYSIZE, &name_entry_size); /* Now we can scan the table and, for each entry, print the number, the name, and the substring itself. */ tabptr = name_table; for (i = 0; i < namecount; i++) { int n = (tabptr[0] << 8) | tabptr[1]; log_msg_set_value_by_name(msg, tabptr + 2, value + matches[2*n], matches[2*n+1] - matches[2*n]); tabptr += name_entry_size; } } } static gboolean log_matcher_pcre_re_match(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len) { LogMatcherPcreRe *self = (LogMatcherPcreRe *) s; gint *matches; gsize matches_size; gint num_matches; gint rc; if (value_len == -1) value_len = strlen(value); if (pcre_fullinfo(self->pattern, self->extra, PCRE_INFO_CAPTURECOUNT, &num_matches) < 0) g_assert_not_reached(); if (num_matches > RE_MAX_MATCHES) num_matches = RE_MAX_MATCHES; matches_size = 3 * (num_matches + 1); matches = g_alloca(matches_size * sizeof(gint)); rc = pcre_exec(self->pattern, self->extra, value, value_len, 0, self->match_options, matches, matches_size); if (rc < 0) { switch (rc) { case PCRE_ERROR_NOMATCH: break; default: /* Handle other special cases */ msg_error("Error while matching regexp", evt_tag_int("error_code", rc)); break; } return FALSE; } if (rc == 0) { msg_error("Error while storing matching substrings"); } else { if ((s->flags & LMF_STORE_MATCHES)) { log_matcher_pcre_re_feed_backrefs(s, msg, value_handle, matches, rc, value); log_matcher_pcre_re_feed_named_substrings(s, msg, matches, value); } } return TRUE; } static gchar * log_matcher_pcre_re_replace(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len, LogTemplate *replacement, gssize *new_length) { LogMatcherPcreRe *self = (LogMatcherPcreRe *) s; GString *new_value = NULL; gint *matches; gsize matches_size; gint num_matches; gint rc; gint start_offset, last_offset; gint options; gboolean last_match_was_empty; if (pcre_fullinfo(self->pattern, self->extra, PCRE_INFO_CAPTURECOUNT, &num_matches) < 0) g_assert_not_reached(); if (num_matches > RE_MAX_MATCHES) num_matches = RE_MAX_MATCHES; matches_size = 3 * (num_matches + 1); matches = g_alloca(matches_size * sizeof(gint)); /* we need zero initialized offsets for the last match as the * algorithm tries uses that as the base position */ matches[0] = matches[1] = matches[2] = 0; if (value_len == -1) value_len = strlen(value); last_offset = start_offset = 0; last_match_was_empty = FALSE; do { /* loop over the string, replacing one occurence at a time. */ /* NOTE: zero length matches need special care, as we could spin * forever otherwise (since the current position wouldn't be * advanced). * * A zero-length match can be as simple as "a*" which will be * returned unless PCRE_NOTEMPTY is specified. * * By supporting zero-length matches, we basically make it * possible to insert replacement between each incoming * character. * * For example: * pattern: a* * replacement: # * input: message * result: #m#e#s#s#a#g#e# * * This mimics Perl behaviour. */ if (last_match_was_empty) { /* Otherwise, arrange to run another match at the same point * to see if a non-empty match can be found. */ options = PCRE_NOTEMPTY | PCRE_ANCHORED; } else { options = 0; } rc = pcre_exec(self->pattern, self->extra, value, value_len, start_offset, (self->match_options | options), matches, matches_size); if (rc < 0 && rc != PCRE_ERROR_NOMATCH) { msg_error("Error while matching regexp", evt_tag_int("error_code", rc)); break; } else if (rc < 0) { if ((options & PCRE_NOTEMPTY) == 0) { /* we didn't match, even when we permitted to match the * empty string. Nothing to find here, bail out */ break; } /* we didn't match, quite possibly because the empty match * was not permitted. Skip one character in order to avoid * infinite loop over the same zero-length match. */ start_offset = start_offset + 1; /* FIXME: handle complex sequences like utf8 and newline characters */ last_match_was_empty = FALSE; continue; } else { /* if the output array was too small, truncate the number of captures to RE_MAX_MATCHES */ if (rc == 0) rc = matches_size / 3; log_matcher_pcre_re_feed_backrefs(s, msg, value_handle, matches, rc, value); log_matcher_pcre_re_feed_named_substrings(s, msg, matches, value); if (!new_value) new_value = g_string_sized_new(value_len); /* append non-matching portion */ g_string_append_len(new_value, &value[last_offset], matches[0] - last_offset); /* replacement */ log_template_append_format(replacement, msg, NULL, LTZ_LOCAL, 0, NULL, new_value); last_match_was_empty = (matches[0] == matches[1]); start_offset = last_offset = matches[1]; } } while (self->super.flags & LMF_GLOBAL && start_offset < value_len); if (new_value) { /* append the last literal */ g_string_append_len(new_value, &value[last_offset], value_len - last_offset); if (new_length) *new_length = new_value->len; return g_string_free(new_value, FALSE); } return NULL; } static void log_matcher_pcre_re_free(LogMatcher *s) { LogMatcherPcreRe *self = (LogMatcherPcreRe *) s; pcre_free_study(self->extra); pcre_free(self->pattern); } LogMatcher * log_matcher_pcre_re_new(GlobalConfig *cfg, const LogMatcherOptions *options) { LogMatcherPcreRe *self = g_new0(LogMatcherPcreRe, 1); log_matcher_init(&self->super, options); self->super.compile = log_matcher_pcre_re_compile; self->super.match = log_matcher_pcre_re_match; self->super.replace = log_matcher_pcre_re_replace; self->super.free_fn = log_matcher_pcre_re_free; return &self->super; } typedef LogMatcher *(*LogMatcherConstructFunc)(GlobalConfig *cfg, const LogMatcherOptions *options); struct { const gchar *name; LogMatcherConstructFunc construct; } matcher_types[] = { { "pcre", log_matcher_pcre_re_new }, { "posix", log_matcher_posix_re_new }, { "string", log_matcher_string_new }, { "glob", log_matcher_glob_new }, { NULL, NULL }, }; static LogMatcherConstructFunc log_matcher_lookup_construct(const gchar *type) { gint i; for (i = 0; matcher_types[i].name; i++) { if (strcmp(matcher_types[i].name, type) == 0) return matcher_types[i].construct; } return NULL; } LogMatcher * log_matcher_new(GlobalConfig *cfg, const LogMatcherOptions *options) { LogMatcherConstructFunc construct; construct = log_matcher_lookup_construct(options->type); return construct(cfg, options); } LogMatcher * log_matcher_ref(LogMatcher *s) { s->ref_cnt++; return s; } void log_matcher_unref(LogMatcher *s) { if (--s->ref_cnt == 0) { if (s->free_fn) s->free_fn(s); g_free(s); } } gboolean log_matcher_options_set_type(LogMatcherOptions *options, const gchar *type) { LogMatcherConstructFunc construct; construct = log_matcher_lookup_construct(type); if (!construct) return FALSE; if (options->type) g_free(options->type); options->type = g_strdup(type); return TRUE; } CfgFlagHandler log_matcher_flag_handlers[] = { /* NOTE: underscores are automatically converted to dashes */ { "global", CFH_SET, offsetof(LogMatcherOptions, flags), LMF_GLOBAL }, { "icase", CFH_SET, offsetof(LogMatcherOptions, flags), LMF_ICASE }, { "ignore-case", CFH_SET, offsetof(LogMatcherOptions, flags), LMF_ICASE }, { "newline", CFH_SET, offsetof(LogMatcherOptions, flags), LMF_NEWLINE }, { "unicode", CFH_SET, offsetof(LogMatcherOptions, flags), LMF_UTF8 }, { "utf8", CFH_SET, offsetof(LogMatcherOptions, flags), LMF_UTF8 }, { "store-matches", CFH_SET, offsetof(LogMatcherOptions, flags), LMF_STORE_MATCHES }, { "substring", CFH_SET, offsetof(LogMatcherOptions, flags), LMF_SUBSTRING }, { "prefix", CFH_SET, offsetof(LogMatcherOptions, flags), LMF_PREFIX }, { NULL }, }; gboolean log_matcher_options_process_flag(LogMatcherOptions *self, const gchar *flag) { return cfg_process_flag(log_matcher_flag_handlers, self, flag); } void log_matcher_options_defaults(LogMatcherOptions *options) { options->flags = 0; options->type = NULL; } void log_matcher_options_init(LogMatcherOptions *options, GlobalConfig *cfg) { if (!options->type) { const gchar *default_matcher = "pcre"; if (cfg_is_config_version_older(cfg, 0x0306)) { msg_warning_once("WARNING: syslog-ng changed the default regexp implementation to PCRE starting from " VERSION_3_6 ", please ensure your regexp works with PCRE or please specify type(\"posix\") in filters explicitly"); default_matcher = "posix"; } if (!log_matcher_options_set_type(options, default_matcher)) g_assert_not_reached(); } } void log_matcher_options_destroy(LogMatcherOptions *options) { if (options->type) g_free(options->type); } GQuark log_matcher_error_quark(void) { return g_quark_from_static_string("log-matcher-error-quark"); } syslog-ng-syslog-ng-3.13.2/lib/logmatcher.h000066400000000000000000000077631321171025300205160ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGMATCHER_H_INCLUDED #define LOGMATCHER_H_INCLUDED #include "logmsg/logmsg.h" #include "template/templates.h" #define LOG_MATCHER_ERROR log_template_error_quark() GQuark log_matcher_error_quark(void); enum { /* use global search/replace */ /* use global search/replace */ LMF_GLOBAL = 0x0001, LMF_ICASE = 0x0002, LMF_MATCH_ONLY = 0x0004, /* POSIX + PCRE common flags */ LMF_NEWLINE= 0x0008, LMF_UTF8 = 0x0010, LMF_STORE_MATCHES = 0x0020, LMF_VALID_REGEXP_FLAGS = 0x0037, /* string flags */ LMF_SUBSTRING = 0x0040, LMF_PREFIX = 0x0080, LMF_VALID_STRING_FLAGS = 0x00C7, }; typedef struct _LogMatcherOptions { gint flags; gchar *type; } LogMatcherOptions; typedef struct _LogMatcher LogMatcher; struct _LogMatcher { gint ref_cnt; gint flags; gboolean (*compile)(LogMatcher *s, const gchar *re, GError **error); /* value_len can be -1 to indicate unknown length */ gboolean (*match)(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len); /* value_len can be -1 to indicate unknown length, new_length can be returned as -1 to indicate unknown length */ gchar *(*replace)(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len, LogTemplate *replacement, gssize *new_length); void (*free_fn)(LogMatcher *s); }; static inline gboolean log_matcher_compile(LogMatcher *s, const gchar *re, GError **error) { return s->compile(s, re, error); } static inline gboolean log_matcher_match(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len) { return s->match(s, msg, value_handle, value, value_len); } static inline gchar * log_matcher_replace(LogMatcher *s, LogMessage *msg, gint value_handle, const gchar *value, gssize value_len, LogTemplate *replacement, gssize *new_length) { if (s->replace) return s->replace(s, msg, value_handle, value, value_len, replacement, new_length); return NULL; } static inline void log_matcher_set_flags(LogMatcher *s, gint flags) { s->flags = flags; } static inline gboolean log_matcher_is_replace_supported(LogMatcher *s) { return s->replace != NULL; } LogMatcher *log_matcher_posix_re_new(GlobalConfig *cfg, const LogMatcherOptions *options); LogMatcher *log_matcher_pcre_re_new(GlobalConfig *cfg, const LogMatcherOptions *options); LogMatcher *log_matcher_string_new(GlobalConfig *cfg, const LogMatcherOptions *options); LogMatcher *log_matcher_glob_new(GlobalConfig *cfg, const LogMatcherOptions *options); LogMatcher *log_matcher_new(GlobalConfig *cfg, const LogMatcherOptions *options); LogMatcher *log_matcher_ref(LogMatcher *s); void log_matcher_unref(LogMatcher *s); gboolean log_matcher_options_set_type(LogMatcherOptions *options, const gchar *type); gboolean log_matcher_options_process_flag(LogMatcherOptions *self, const gchar *flag); void log_matcher_options_defaults(LogMatcherOptions *options); void log_matcher_options_init(LogMatcherOptions *options, GlobalConfig *cfg); void log_matcher_options_destroy(LogMatcherOptions *options); #endif syslog-ng-syslog-ng-3.13.2/lib/logmpx.c000066400000000000000000000106331321171025300176600ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logmpx.h" void log_multiplexer_add_next_hop(LogMultiplexer *self, LogPipe *next_hop) { g_ptr_array_add(self->next_hops, next_hop); } static gboolean log_multiplexer_init(LogPipe *s) { LogMultiplexer *self = (LogMultiplexer *) s; gint i; for (i = 0; i < self->next_hops->len; i++) { LogPipe *branch_head = g_ptr_array_index(self->next_hops, i); LogPipe *p; for (p = branch_head; p; p = p->pipe_next) { branch_head->flags |= (p->flags & PIF_BRANCH_PROPERTIES); } if (branch_head->flags & PIF_BRANCH_FALLBACK) { self->fallback_exists = TRUE; } } return TRUE; } static gboolean log_multiplexer_deinit(LogPipe *self) { return TRUE; } static void log_multiplexer_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { LogMultiplexer *self = (LogMultiplexer *) s; gint i; LogPathOptions local_options = *path_options; gboolean matched; gboolean delivered = FALSE; gint fallback; local_options.matched = &matched; if (self->next_hops->len > 1) { log_msg_write_protect(msg); } for (fallback = 0; (fallback == 0) || (fallback == 1 && self->fallback_exists && !delivered); fallback++) { for (i = 0; i < self->next_hops->len; i++) { LogPipe *next_hop = g_ptr_array_index(self->next_hops, i); if (G_UNLIKELY(fallback == 0 && (next_hop->flags & PIF_BRANCH_FALLBACK) != 0)) { continue; } else if (G_UNLIKELY(fallback && (next_hop->flags & PIF_BRANCH_FALLBACK) == 0)) { continue; } matched = TRUE; log_msg_add_ack(msg, &local_options); log_pipe_queue(next_hop, log_msg_ref(msg), &local_options); if (matched) { delivered = TRUE; if (G_UNLIKELY(next_hop->flags & PIF_BRANCH_FINAL)) break; } } } if (self->next_hops->len > 1) { log_msg_write_unprotect(msg); } /* NOTE: non of our multiplexed destinations delivered this message, let's * propagate this result. But only if we don't have a "next". If we do, * that would be responsible for doing the same, for instance if it is a * filter. * * In case where this matters most (e.g. the multiplexer attached to the * source LogPipe), "next" will always be NULL. I am not sure if there's * ever a case, where a LogMpx has both "next" set, and have branches as * well. * * If there's such a case, then from a conceptual point of view, this Mpx * instance should transfer the responsibility for setting "matched" to * the next pipeline element, which is what we do here. */ if (!s->pipe_next && !delivered && path_options->matched) *path_options->matched = FALSE; log_pipe_forward_msg(s, msg, path_options); } static void log_multiplexer_free(LogPipe *s) { LogMultiplexer *self = (LogMultiplexer *) s; g_ptr_array_free(self->next_hops, TRUE); log_pipe_free_method(s); } LogMultiplexer * log_multiplexer_new(GlobalConfig *cfg) { LogMultiplexer *self = g_new0(LogMultiplexer, 1); log_pipe_init_instance(&self->super, cfg); self->super.init = log_multiplexer_init; self->super.deinit = log_multiplexer_deinit; self->super.queue = log_multiplexer_queue; self->super.free_fn = log_multiplexer_free; self->next_hops = g_ptr_array_new(); return self; } syslog-ng-syslog-ng-3.13.2/lib/logmpx.h000066400000000000000000000032521321171025300176640ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGMPX_H_INCLUDED #define LOGMPX_H_INCLUDED #include "logpipe.h" /** * This class encapsulates a fork of the message pipe-line. It receives * messages via its queue() method and forwards them to its list of * next_hops in addition to the standard pipe_next next-hop already provided * by LogPipe. * * This object is used for example for each source to send messages to all * log pipelines that refer to the source. **/ typedef struct _LogMultiplexer { LogPipe super; GPtrArray *next_hops; gboolean fallback_exists; } LogMultiplexer; LogMultiplexer *log_multiplexer_new(GlobalConfig *cfg); void log_multiplexer_add_next_hop(LogMultiplexer *self, LogPipe *next_hop); #endif syslog-ng-syslog-ng-3.13.2/lib/logmsg/000077500000000000000000000000001321171025300174735ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/logmsg/CMakeLists.txt000066400000000000000000000011521321171025300222320ustar00rootroot00000000000000set(LOGMSG_HEADERS logmsg/gsockaddr-serialize.h logmsg/logmsg.h logmsg/logmsg-serialize.h logmsg/logmsg-serialize-fixup.h logmsg/nvtable.h logmsg/nvtable-serialize.h logmsg/nvtable-serialize-endianutils.h logmsg/tags-serialize.h logmsg/timestamp-serialize.h logmsg/tags.h PARENT_SCOPE) set(LOGMSG_SOURCES logmsg/gsockaddr-serialize.c logmsg/logmsg.c logmsg/logmsg-serialize.c logmsg/logmsg-serialize-fixup.c logmsg/nvtable.c logmsg/nvtable-serialize.c logmsg/tags-serialize.c logmsg/timestamp-serialize.c logmsg/tags.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/logmsg/Makefile.am000066400000000000000000000016461321171025300215360ustar00rootroot00000000000000logmsgincludedir = ${pkgincludedir}/logmsg logmsginclude_HEADERS = \ lib/logmsg/gsockaddr-serialize.h \ lib/logmsg/logmsg.h \ lib/logmsg/serialization.h \ lib/logmsg/logmsg-serialize.h \ lib/logmsg/logmsg-serialize-fixup.h \ lib/logmsg/nvtable.h \ lib/logmsg/nvtable-serialize.h \ lib/logmsg/nvtable-serialize-endianutils.h \ lib/logmsg/tags-serialize.h \ lib/logmsg/timestamp-serialize.h \ lib/logmsg/tags.h logmsg_sources = \ lib/logmsg/gsockaddr-serialize.c \ lib/logmsg/logmsg.c \ lib/logmsg/logmsg-serialize.c \ lib/logmsg/logmsg-serialize-fixup.c \ lib/logmsg/nvtable.c \ lib/logmsg/nvtable-serialize.c \ lib/logmsg/tags-serialize.c \ lib/logmsg/timestamp-serialize.c \ lib/logmsg/tags.c include lib/logmsg/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/logmsg/gsockaddr-serialize.c000066400000000000000000000072301321171025300235670ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 2015 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "gsockaddr-serialize.h" #include static gboolean _serialize_ipv4(GSockAddr *addr, SerializeArchive *sa) { struct in_addr ina; ina = g_sockaddr_inet_get_address(addr); return serialize_write_blob(sa, (gchar *) &ina, sizeof(ina)) && serialize_write_uint16(sa, htons(g_sockaddr_get_port(addr))); } #if SYSLOG_NG_ENABLE_IPV6 static gboolean _serialize_ipv6(GSockAddr *addr, SerializeArchive *sa) { struct in6_addr *in6a; in6a = g_sockaddr_inet6_get_address(addr); return serialize_write_blob(sa, (gchar *) in6a, sizeof(*in6a)) && serialize_write_uint16(sa, htons(g_sockaddr_get_port(addr))); } #endif gboolean g_sockaddr_serialize(SerializeArchive *sa, GSockAddr *addr) { if (!addr) { return serialize_write_uint16(sa, 0); } gboolean result = serialize_write_uint16(sa, addr->sa.sa_family); switch (addr->sa.sa_family) { case AF_INET: { result &= _serialize_ipv4(addr, sa); break; } #if SYSLOG_NG_ENABLE_IPV6 case AF_INET6: { result &= _serialize_ipv6(addr, sa); break; } #endif case AF_UNIX: { break; } default: { result = FALSE; break; } } return result; } static gboolean _deserialize_ipv4(SerializeArchive *sa, GSockAddr **addr) { struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; if (!serialize_read_blob(sa, (gchar *) &sin.sin_addr, sizeof(sin.sin_addr)) || !serialize_read_uint16(sa, &sin.sin_port)) return FALSE; *addr = g_sockaddr_inet_new2(&sin); return TRUE; } #if SYSLOG_NG_ENABLE_IPV6 static gboolean _deserialize_ipv6(SerializeArchive *sa, GSockAddr **addr) { gboolean result = FALSE; struct sockaddr_in6 sin6; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; if (serialize_read_blob(sa, (gchar *) &sin6.sin6_addr, sizeof(sin6.sin6_addr)) && serialize_read_uint16(sa, &sin6.sin6_port)) { *addr = g_sockaddr_inet6_new2(&sin6); result = TRUE; } return result; } #endif gboolean g_sockaddr_deserialize(SerializeArchive *sa, GSockAddr **addr) { guint16 family; gboolean result = TRUE; if (!serialize_read_uint16(sa, &family)) return FALSE; switch (family) { case 0: /* special case, no address was stored */ *addr = NULL; break; case AF_INET: { result = _deserialize_ipv4(sa, addr); break; } #if SYSLOG_NG_ENABLE_IPV6 case AF_INET6: { result = _deserialize_ipv6(sa, addr); break; } #endif case AF_UNIX: *addr = g_sockaddr_unix_new(NULL); break; default: result = FALSE; break; } return result; } syslog-ng-syslog-ng-3.13.2/lib/logmsg/gsockaddr-serialize.h000066400000000000000000000024051321171025300235730ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 2015 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef G_SOCKADDR_SERIALIZE_H #define G_SOCKADDR_SERIALIZE_H #include "gsockaddr.h" #include "serialize.h" gboolean g_sockaddr_serialize(SerializeArchive *sa, GSockAddr *addr); gboolean g_sockaddr_deserialize(SerializeArchive *sa, GSockAddr **addr); #endif syslog-ng-syslog-ng-3.13.2/lib/logmsg/logmsg-serialize-fixup.c000066400000000000000000000206301321171025300242460ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2016 Balázs Scheidler * Copyright (c) 2012-2015 Viktor Juhasz * Copyright (c) 2012-2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logmsg-serialize-fixup.h" #include "nvtable-serialize.h" #include /********************************************************************** * This chunk of code fixes up the NVHandle values scattered in a * deserialized NVTable. * * The reason they need fixing is that NVHandles are allocated dynamically * when they are first used in a syslog-ng process. As the serialized * representation of a LogMessage can be read back by another syslog-ng * process, its idea of the name-value pair handle might be different. * * This means that we need to iterate through the struct and change the * handle values. This is not even a simple operation as handles are embedded * in various locations * - in the index table, an array sorted by handle * - as indirect values that refer to other values * - the SDATA handles array that ensures that SDATA values are ordered * the same way they were received. * **********************************************************************/ static gint _index_entry_cmp(const void *a, const void *b) { NVIndexEntry *entry_a = (NVIndexEntry *) a; NVIndexEntry *entry_b = (NVIndexEntry *) b; NVHandle handle_a = entry_a->handle; NVHandle handle_b = entry_b->handle; if (handle_a < handle_b) return -1; else if (handle_a == handle_b) return 0; else return 1; } static void _copy_updated_sdata_handles(LogMessageSerializationState *state) { memcpy(state->msg->sdata, state->updated_sdata_handles, sizeof(state->msg->sdata[0]) * state->msg->num_sdata); } static void _sort_updated_index(LogMessageSerializationState *state) { NVTable *self = state->nvtable; qsort(state->updated_index, self->index_size, sizeof(NVIndexEntry), _index_entry_cmp); } static void _copy_updated_index(LogMessageSerializationState *state) { NVTable *self = state->nvtable; memmove(nv_table_get_index(self), state->updated_index, sizeof(NVIndexEntry) * self->index_size); } static void _fixup_sdata_handle(LogMessageSerializationState *state, NVHandle old_handle, NVHandle new_handle) { LogMessage *msg = state->msg; gint i; if (msg->sdata) { for (i = 0; i < msg->num_sdata; i++) { if (msg->sdata[i] == old_handle) { state->updated_sdata_handles[i] = new_handle; break; } } } } static void _fixup_handle_in_index_entry(LogMessageSerializationState *state, NVIndexEntry *index_entry, NVHandle new_handle) { gint index_slot = index_entry - nv_table_get_index(state->nvtable); NVIndexEntry *new_index_entry = &state->updated_index[index_slot]; new_index_entry->ofs = index_entry->ofs; new_index_entry->handle = new_handle; } static inline gboolean _is_static_entry(NVEntry *entry) { return entry->name_len == 0; } static gboolean _old_handle_has_the_same_name(NVHandle old_handle, NVEntry *entry) { gssize old_handle_name_len = 0; const gchar *old_handle_name = log_msg_get_value_name(old_handle, &old_handle_name_len); if (!old_handle_name) return FALSE; if (old_handle_name_len != entry->name_len) return FALSE; return memcmp(nv_entry_get_name(entry), old_handle_name, old_handle_name_len) == 0; } static NVHandle _allocate_handle_for_entry_name(NVHandle old_handle, NVEntry *entry) { if (_is_static_entry(entry)) return old_handle; if (_old_handle_has_the_same_name(old_handle, entry)) return old_handle; return log_msg_get_value_handle(nv_entry_get_name(entry)); } static NVHandle _allocate_handle_of_referenced_entry(NVTable *self, NVHandle ref_handle) { NVIndexEntry *index_entry; NVEntry *ref_entry = nv_table_get_entry(self, ref_handle, &index_entry); return _allocate_handle_for_entry_name(ref_handle, ref_entry); } static gboolean _is_indirect(NVEntry *entry) { return entry && entry->indirect; } static void _fixup_handle_in_indirect_entry(NVTable *self, NVEntry *entry) { entry->vindirect.handle = _allocate_handle_of_referenced_entry(self, entry->vindirect.handle); } static gboolean _validate_entry(LogMessageSerializationState *state, NVEntry *entry) { NVTable *nvtable = state->nvtable; /* check alignment */ if ((GPOINTER_TO_UINT(entry) & 0x3) != 0) return FALSE; /* entry points above the start of the NVTable */ if (GPOINTER_TO_UINT(entry) < GPOINTER_TO_UINT(nvtable)) return FALSE; /* entry header is inside the allocated NVTable */ if (GPOINTER_TO_UINT(entry) + NV_ENTRY_DIRECT_HDR > GPOINTER_TO_UINT(nvtable) + nvtable->size) return FALSE; /* entry as a whole is inside the allocated NVTable */ if (GPOINTER_TO_UINT(entry) + entry->alloc_len > GPOINTER_TO_UINT(nvtable) + nvtable->size) return FALSE; if (!entry->indirect) { if (entry->alloc_len < NV_ENTRY_DIRECT_HDR + entry->name_len + 1 + entry->vdirect.value_len + 1) return FALSE; } else { if (entry->alloc_len < NV_ENTRY_INDIRECT_HDR + entry->name_len + 1) return FALSE; } return TRUE; } static gboolean _update_entry(LogMessageSerializationState *state, NVEntry *entry) { if ((state->nvtable_flags & NVT_SUPPORTS_UNSET) == 0) { /* if this was serialized with a syslog-ng that didn't support unset, make sure that: * 1) unset is set to FALSE * 2) the rest of the bits are cleared too * * This is needed as earlier syslog-ng versions unfortunately didn't * set the flags to 0, so it might contain garbage. Anything that is * past NVT_SUPPORTS_UNSET however sets these bits to zero to make * adding new flags easier. */ entry->unset = FALSE; entry->__bit_padding = 0; } return TRUE; } static gboolean _fixup_entry(NVHandle old_handle, NVEntry *entry, NVIndexEntry *index_entry, gpointer user_data) { LogMessageSerializationState *state = (LogMessageSerializationState *) user_data; NVTable *self = state->nvtable; NVHandle new_handle; if (!_validate_entry(state, entry) || !_update_entry(state, entry)) { /* this return of TRUE indicates failure, as it terminates the foreach loop */ return TRUE; } new_handle = _allocate_handle_for_entry_name(old_handle, entry); if (new_handle != old_handle) { if (index_entry) _fixup_handle_in_index_entry(state, index_entry, new_handle); if (log_msg_is_handle_sdata(new_handle)) _fixup_sdata_handle(state, old_handle, new_handle); state->handle_changed = TRUE; } if (_is_indirect(entry)) _fixup_handle_in_indirect_entry(self, entry); return FALSE; } gboolean log_msg_fixup_handles_after_deserialization(LogMessageSerializationState *state) { LogMessage *msg = state->msg; NVTable *nvtable = state->nvtable; NVHandle _updated_sdata_handles[msg->num_sdata]; NVIndexEntry _updated_index[nvtable->index_size]; /* NOTE: we are allocating these arrays as auto variables on the stack, so * we can use some stack space here. However, num_sdata is guint8, * index_size is guint16 */ state->updated_sdata_handles = _updated_sdata_handles; state->updated_index = _updated_index; state->handle_changed = FALSE; if (nv_table_foreach_entry(nvtable, _fixup_entry, state)) { /* foreach_entry() returns TRUE if the callback returned failure */ return FALSE; } if (state->handle_changed) { _copy_updated_sdata_handles(state); _sort_updated_index(state); _copy_updated_index(state); } return TRUE; } syslog-ng-syslog-ng-3.13.2/lib/logmsg/logmsg-serialize-fixup.h000066400000000000000000000023001321171025300242450ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * Copyright (c) 2016 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef _LOGMSG_SERIALIZE_FIXUP_H_INCLUDED #define _LOGMSG_SERIALIZE_FIXUP_H_INCLUDED #include "logmsg/serialization.h" gboolean log_msg_fixup_handles_after_deserialization(LogMessageSerializationState *state); #endif syslog-ng-syslog-ng-3.13.2/lib/logmsg/logmsg-serialize.c000066400000000000000000000110201321171025300231060ustar00rootroot00000000000000/* * Copyright (c) 2010-2015 Balabit * Copyright (c) 2015 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logmsg/logmsg-serialize.h" #include "logmsg/logmsg-serialize-fixup.h" #include "logmsg/nvtable-serialize.h" #include "logmsg/gsockaddr-serialize.h" #include "logmsg/timestamp-serialize.h" #include "logmsg/tags-serialize.h" #include "messages.h" #include static gboolean _serialize_message(LogMessageSerializationState *state) { LogMessage *msg = state->msg; SerializeArchive *sa = state->sa; serialize_write_uint8(sa, state->version); serialize_write_uint64(sa, msg->rcptid); g_assert(sizeof(msg->flags) == 4); serialize_write_uint32(sa, msg->flags & ~LF_STATE_MASK); serialize_write_uint16(sa, msg->pri); g_sockaddr_serialize(sa, msg->saddr); timestamp_serialize(sa, msg->timestamps); serialize_write_uint32(sa, msg->host_id); tags_serialize(msg, sa); serialize_write_uint8(sa, msg->initial_parse); serialize_write_uint8(sa, msg->num_matches); serialize_write_uint8(sa, msg->num_sdata); serialize_write_uint8(sa, msg->alloc_sdata); serialize_write_uint32_array(sa, (guint32 *) msg->sdata, msg->num_sdata); nv_table_serialize(state, msg->payload); return TRUE; } gboolean log_msg_serialize(LogMessage *self, SerializeArchive *sa) { LogMessageSerializationState state = { 0 }; state.version = 26; state.msg = self; state.sa = sa; return _serialize_message(&state); } static gboolean _deserialize_sdata(LogMessage *self, SerializeArchive *sa) { if (!serialize_read_uint8(sa, &self->num_sdata)) return FALSE; if (!serialize_read_uint8(sa, &self->alloc_sdata)) return FALSE; self->sdata = (NVHandle *) g_malloc(sizeof(NVHandle)*self->alloc_sdata); serialize_read_uint32_array(sa, (guint32 *) self->sdata, self->num_sdata); return TRUE; } static gboolean _deserialize_message(LogMessageSerializationState *state) { guint8 initial_parse = 0; LogMessage *msg = state->msg; SerializeArchive *sa = state->sa; if (!serialize_read_uint64(sa, &msg->rcptid)) return FALSE; if (!serialize_read_uint32(sa, &msg->flags)) return FALSE; msg->flags |= LF_STATE_MASK; if (!serialize_read_uint16(sa, &msg->pri)) return FALSE; if (!g_sockaddr_deserialize(sa, &msg->saddr)) return FALSE; if (!timestamp_deserialize(sa, msg->timestamps)) return FALSE; if (!serialize_read_uint32(sa, &msg->host_id)) return FALSE; if (!tags_deserialize(msg, sa)) return FALSE; if (!serialize_read_uint8(sa, &initial_parse)) return FALSE; msg->initial_parse=initial_parse; if (!serialize_read_uint8(sa, &msg->num_matches)) return FALSE; if (!_deserialize_sdata(msg, sa)) return FALSE; nv_table_unref(msg->payload); msg->payload = nv_table_deserialize(state); if (!msg->payload) return FALSE; if (!log_msg_fixup_handles_after_deserialization(state)) return FALSE; return TRUE; } static gboolean _check_msg_version(LogMessageSerializationState *state) { if (!serialize_read_uint8(state->sa, &state->version)) return FALSE; if (state->version != 26) { msg_error("Error deserializing log message, unsupported version, " "we only support v26 introduced in " VERSION_3_8 ", " "earlier versions in syslog-ng Premium Editions are not supported", evt_tag_int("version", state->version)); return FALSE; } return TRUE; } gboolean log_msg_deserialize(LogMessage *self, SerializeArchive *sa) { LogMessageSerializationState state = { 0 }; state.sa = sa; state.msg = self; if (!_check_msg_version(&state)) { return FALSE; } return _deserialize_message(&state); } syslog-ng-syslog-ng-3.13.2/lib/logmsg/logmsg-serialize.h000066400000000000000000000023421321171025300231220ustar00rootroot00000000000000/* * Copyright (c) 2010-2015 Balabit * Copyright (c) 2015 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGMSG_SERIALIZE_H #define LOGMSG_SERIALIZE_H #include "serialize.h" gboolean log_msg_deserialize(LogMessage *self, SerializeArchive *sa); gboolean log_msg_serialize(LogMessage *self, SerializeArchive *sa); #endif syslog-ng-syslog-ng-3.13.2/lib/logmsg/logmsg.c000066400000000000000000001571471321171025300211460ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logmsg/logmsg.h" #include "str-utils.h" #include "str-repr/encode.h" #include "messages.h" #include "logpipe.h" #include "timeutils.h" #include "logmsg/nvtable.h" #include "stats/stats-registry.h" #include "stats/stats-cluster-single.h" #include "template/templates.h" #include "tls-support.h" #include "compat/string.h" #include "rcptid.h" #include "template/macros.h" #include "lib/host-id.h" #include "ack_tracker.h" #include #include #include #include #include #include #include /* * Reference/ACK counting for LogMessage structures * * Each LogMessage structure is allocated when received by a LogSource * instance, and then freed once all destinations finish with it. Since a * LogMessage is processed by different threads, reference counting must be * atomic. * * A similar counter is used to track when a given message is considered to * be delivered. In case flow-control is in use, the number of * to-be-expected ACKs are counted in an atomic variable. * * Code is written in a way, that it is explicitly mentioned whether a * function expects a reference (called "consuming" the ref), or whether it * gets a 'borrowed' reference (more common). Also, a function that returns * a LogMessage instance generally returns a reference too. * * Because of these rules, quite a number of refs/unrefs are being made * during the processing of a message, even though they wouldn't cause the * structure to be freed. Considering that ref/unref operations are * expensive atomic operations, these have a considerable overhead. * * The solution we employ in this module, is that we try to exploit the * fact, that each thread is usually working on a single LogMessage * instance, and once it is done with it, it fetches the next one, and so * on. In the LogReader/LogWriter cases, this usage pattern is quite * normal. * * Also, a quite similar usage pattern can be applied to the ACK counter * (the one which tracks how much flow-controlled destinations need to * confirm the deliver of the message). * * The solution implemented here is outlined below (and the same rules are * used for ACKs and REFs): * * - ACKs and REFs are put into the same 32 bit integer value, one half * is used for the ref counter, the other is used for the ACK counter * (see the macros LOGMSG_REFCACHE_ below) * * - The processing of a given message in a given thread is enclosed by * calls to log_msg_refcache_start() / log_msg_refcache_stop() * * - The calls to these functions is optional, if they are not called, * then normal atomic reference counting is performed * * - When refcache_start() is called, the atomic reference count is not * changed by log_msg_ref()/unref(). Rather, a per-thread variable is * used to count the _difference_ to the "would-be" value of the ref counter. * * - When refcache_stop() is called, the atomic reference counter is * updated as a single atomic operation. This means, that if a thread * calls refcache_start() early enough, then the ref/unref operations * performed by the given thread can be completely atomic-op free. * * - There's one catch: if the producer thread (e.g. LogReader), doesn't * add references to a consumer thread (e.g. LogWriter), and the * consumer doesn't use the refcache infrastructure, then the counters * could become negative (simply because the reader's real number of * references is not represented in the refcounter). This is solved by * adding a large-enough number (so called BIAS) to the ref counter in * refcache_start(), which ensures that all possible writers will see a * positive value. This is then substracted in refcache_stop() the * same way as the other references. * * Since we use the same atomic variable to store two things, updating that * counter becomes somewhat more complicated, therefore a g_atomic_int_add() * doesn't suffice. We're using a CAS loop (compare-and-exchange) to do our * stuff, but that shouldn't have that much of an overhead. */ TLS_BLOCK_START { /* message that is being processed by the current thread. Its ack/ref changes are cached */ LogMessage *logmsg_current; /* whether the consumer is flow-controlled, (the producer always is) */ gboolean logmsg_cached_ack_needed; /* has to be signed as these can become negative */ /* number of cached refs by the current thread */ gint logmsg_cached_refs; /* number of cached acks by the current thread */ gint logmsg_cached_acks; /* abort flag in the current thread for acks */ gboolean logmsg_cached_abort; /* suspend flag in the current thread for acks */ gboolean logmsg_cached_suspend; } TLS_BLOCK_END; #define logmsg_current __tls_deref(logmsg_current) #define logmsg_cached_refs __tls_deref(logmsg_cached_refs) #define logmsg_cached_acks __tls_deref(logmsg_cached_acks) #define logmsg_cached_ack_needed __tls_deref(logmsg_cached_ack_needed) #define logmsg_cached_abort __tls_deref(logmsg_cached_abort) #define logmsg_cached_suspend __tls_deref(logmsg_cached_suspend) #define LOGMSG_REFCACHE_SUSPEND_SHIFT 31 /* number of bits to shift to get the SUSPEND flag */ #define LOGMSG_REFCACHE_SUSPEND_MASK 0x80000000 /* bit mask to extract the SUSPEND flag */ #define LOGMSG_REFCACHE_ABORT_SHIFT 30 /* number of bits to shift to get the ABORT flag */ #define LOGMSG_REFCACHE_ABORT_MASK 0x40000000 /* bit mask to extract the ABORT flag */ #define LOGMSG_REFCACHE_ACK_SHIFT 15 /* number of bits to shift to get the ACK counter */ #define LOGMSG_REFCACHE_ACK_MASK 0x3FFF8000 /* bit mask to extract the ACK counter */ #define LOGMSG_REFCACHE_REF_SHIFT 0 /* number of bits to shift to get the REF counter */ #define LOGMSG_REFCACHE_REF_MASK 0x00007FFF /* bit mask to extract the ACK counter */ #define LOGMSG_REFCACHE_BIAS 0x00002000 /* the BIAS we add to the ref counter in refcache_start */ #define LOGMSG_REFCACHE_REF_TO_VALUE(x) (((x) << LOGMSG_REFCACHE_REF_SHIFT) & LOGMSG_REFCACHE_REF_MASK) #define LOGMSG_REFCACHE_ACK_TO_VALUE(x) (((x) << LOGMSG_REFCACHE_ACK_SHIFT) & LOGMSG_REFCACHE_ACK_MASK) #define LOGMSG_REFCACHE_ABORT_TO_VALUE(x) (((x) << LOGMSG_REFCACHE_ABORT_SHIFT) & LOGMSG_REFCACHE_ABORT_MASK) #define LOGMSG_REFCACHE_SUSPEND_TO_VALUE(x) (((x) << LOGMSG_REFCACHE_SUSPEND_SHIFT) & LOGMSG_REFCACHE_SUSPEND_MASK) #define LOGMSG_REFCACHE_VALUE_TO_REF(x) (((x) & LOGMSG_REFCACHE_REF_MASK) >> LOGMSG_REFCACHE_REF_SHIFT) #define LOGMSG_REFCACHE_VALUE_TO_ACK(x) (((x) & LOGMSG_REFCACHE_ACK_MASK) >> LOGMSG_REFCACHE_ACK_SHIFT) #define LOGMSG_REFCACHE_VALUE_TO_ABORT(x) (((x) & LOGMSG_REFCACHE_ABORT_MASK) >> LOGMSG_REFCACHE_ABORT_SHIFT) #define LOGMSG_REFCACHE_VALUE_TO_SUSPEND(x) (((x) & LOGMSG_REFCACHE_SUSPEND_MASK) >> LOGMSG_REFCACHE_SUSPEND_SHIFT) /********************************************************************** * LogMessage **********************************************************************/ static inline gboolean log_msg_chk_flag(const LogMessage *self, gint32 flag) { return self->flags & flag; } static inline void log_msg_set_flag(LogMessage *self, gint32 flag) { self->flags |= flag; } static inline void log_msg_set_host_id(LogMessage *msg) { msg->host_id = host_id_get(); } /* the index matches the value id */ const gchar *builtin_value_names[] = { "HOST", "HOST_FROM", "MESSAGE", "PROGRAM", "PID", "MSGID", "SOURCE", "LEGACY_MSGHDR", NULL, }; static NVHandle match_handles[256]; NVRegistry *logmsg_registry; const char logmsg_sd_prefix[] = ".SDATA."; const gint logmsg_sd_prefix_len = sizeof(logmsg_sd_prefix) - 1; gint logmsg_queue_node_max = 1; /* statistics */ static StatsCounterItem *count_msg_clones; static StatsCounterItem *count_payload_reallocs; static StatsCounterItem *count_sdata_updates; static StatsCounterItem *count_allocated_bytes; static GStaticPrivate priv_macro_value = G_STATIC_PRIVATE_INIT; static inline gboolean log_msg_is_write_protected(const LogMessage *self) { return self->protect_cnt > 0; } void log_msg_write_protect(LogMessage *self) { self->protect_cnt++; } void log_msg_write_unprotect(LogMessage *self) { self->protect_cnt--; } LogMessage * log_msg_make_writable(LogMessage **pself, const LogPathOptions *path_options) { if (log_msg_is_write_protected(*pself)) { LogMessage *new; new = log_msg_clone_cow(*pself, path_options); log_msg_unref(*pself); *pself = new; } return *pself; } static void log_msg_update_sdata_slow(LogMessage *self, NVHandle handle, const gchar *name, gssize name_len) { guint16 alloc_sdata; guint16 prefix_and_block_len; gint i; const gchar *dot; /* this was a structured data element, insert a ref to the sdata array */ stats_counter_inc(count_sdata_updates); if (self->num_sdata == 255) { msg_error("syslog-ng only supports 255 SD elements right now, just drop an email to the mailing list that it was not enough with your use-case so we can increase it"); return; } if (self->alloc_sdata <= self->num_sdata) { alloc_sdata = MAX(self->num_sdata + 1, STRICT_ROUND_TO_NEXT_EIGHT(self->num_sdata)); if (alloc_sdata > 255) alloc_sdata = 255; } else alloc_sdata = self->alloc_sdata; if (log_msg_chk_flag(self, LF_STATE_OWN_SDATA) && self->sdata) { if (self->alloc_sdata < alloc_sdata) { self->sdata = g_realloc(self->sdata, alloc_sdata * sizeof(self->sdata[0])); memset(&self->sdata[self->alloc_sdata], 0, (alloc_sdata - self->alloc_sdata) * sizeof(self->sdata[0])); } } else { NVHandle *sdata; sdata = g_malloc(alloc_sdata * sizeof(self->sdata[0])); if (self->num_sdata) memcpy(sdata, self->sdata, self->num_sdata * sizeof(self->sdata[0])); memset(&sdata[self->num_sdata], 0, sizeof(self->sdata[0]) * (self->alloc_sdata - self->num_sdata)); self->sdata = sdata; log_msg_set_flag(self, LF_STATE_OWN_SDATA); } guint16 old_alloc_sdata = self->alloc_sdata; self->alloc_sdata = alloc_sdata; if (self->sdata) { self->allocated_bytes += ((self->alloc_sdata - old_alloc_sdata) * sizeof(self->sdata[0])); stats_counter_add(count_allocated_bytes, (self->alloc_sdata - old_alloc_sdata) * sizeof(self->sdata[0])); } /* ok, we have our own SDATA array now which has at least one free slot */ if (!self->initial_parse) { dot = memrchr(name, '.', name_len); prefix_and_block_len = dot - name; for (i = self->num_sdata - 1; i >= 0; i--) { gssize sdata_name_len; const gchar *sdata_name; sdata_name_len = 0; sdata_name = log_msg_get_value_name(self->sdata[i], &sdata_name_len); if (sdata_name_len > prefix_and_block_len && strncmp(sdata_name, name, prefix_and_block_len) == 0) { /* ok we have found the last SDATA entry that has the same block */ break; } } i++; } else i = -1; if (i >= 0) { memmove(&self->sdata[i+1], &self->sdata[i], (self->num_sdata - i) * sizeof(self->sdata[0])); self->sdata[i] = handle; } else { self->sdata[self->num_sdata] = handle; } self->num_sdata++; } static inline void log_msg_update_sdata(LogMessage *self, NVHandle handle, const gchar *name, gssize name_len) { guint8 flags; flags = nv_registry_get_handle_flags(logmsg_registry, handle); if (G_UNLIKELY(flags & LM_VF_SDATA)) log_msg_update_sdata_slow(self, handle, name, name_len); } NVHandle log_msg_get_value_handle(const gchar *value_name) { NVHandle handle; handle = nv_registry_alloc_handle(logmsg_registry, value_name); /* check if name starts with sd_prefix and has at least one additional character */ if (strncmp(value_name, logmsg_sd_prefix, logmsg_sd_prefix_len) == 0 && value_name[6]) { nv_registry_set_handle_flags(logmsg_registry, handle, LM_VF_SDATA); } return handle; } gboolean log_msg_is_value_name_valid(const gchar *value) { if (strncmp(value, logmsg_sd_prefix, logmsg_sd_prefix_len) == 0) { const gchar *dot; int dot_found = 0; dot = strchr(value, '.'); while (dot && strlen(dot) > 1) { dot_found++; dot++; dot = strchr(dot, '.'); } return (dot_found >= 3); } else return TRUE; } static void __free_macro_value(void *val) { g_string_free((GString *) val, TRUE); } const gchar * log_msg_get_macro_value(const LogMessage *self, gint id, gssize *value_len) { GString *value; value = g_static_private_get(&priv_macro_value); if (!value) { value = g_string_sized_new(256); g_static_private_set(&priv_macro_value, value, __free_macro_value); } g_string_truncate(value, 0); log_macro_expand_simple(value, id, self); if (value_len) *value_len = value->len; return value->str; } gboolean log_msg_is_handle_macro(NVHandle handle) { guint16 flags; flags = nv_registry_get_handle_flags(logmsg_registry, handle); return !!(flags & LM_VF_MACRO); } gboolean log_msg_is_handle_sdata(NVHandle handle) { guint16 flags; flags = nv_registry_get_handle_flags(logmsg_registry, handle); return !!(flags & LM_VF_SDATA); } gboolean log_msg_is_handle_match(NVHandle handle) { g_assert(match_handles[0] && match_handles[255] && match_handles[0] < match_handles[255]); /* NOTE: match_handles are allocated sequentially in log_msg_registry_init(), * so this simple & fast check is enough */ return (match_handles[0] <= handle && handle <= match_handles[255]); } static void log_msg_init_queue_node(LogMessage *msg, LogMessageQueueNode *node, const LogPathOptions *path_options) { INIT_IV_LIST_HEAD(&node->list); node->ack_needed = path_options->ack_needed; node->flow_control_requested = path_options->flow_control_requested; node->msg = log_msg_ref(msg); log_msg_write_protect(msg); } /* * Allocates a new LogMessageQueueNode instance to be enqueued in a * LogQueue. * * NOTE: Assumed to be runnning in the source thread, and that the same * LogMessage instance is only put into queue from the same thread (e.g. * the related fields are _NOT_ locked). */ LogMessageQueueNode * log_msg_alloc_queue_node(LogMessage *msg, const LogPathOptions *path_options) { LogMessageQueueNode *node; if (msg->cur_node < msg->num_nodes) { node = &msg->nodes[msg->cur_node++]; node->embedded = TRUE; } else { gint nodes = (volatile gint) logmsg_queue_node_max; /* this is a racy update, but it doesn't really hurt if we lose an * update or if we continue with a smaller value in parallel threads * for some time yet, since the smaller number only means that we * pre-allocate somewhat less LogMsgQueueNodes in the message * structure, but will be fine regardless (if we'd overflow the * pre-allocated space, we start allocating nodes dynamically from * heap. */ if (nodes < 32 && nodes <= msg->num_nodes) logmsg_queue_node_max = msg->num_nodes + 1; node = g_slice_new(LogMessageQueueNode); node->embedded = FALSE; } log_msg_init_queue_node(msg, node, path_options); return node; } LogMessageQueueNode * log_msg_alloc_dynamic_queue_node(LogMessage *msg, const LogPathOptions *path_options) { LogMessageQueueNode *node; node = g_slice_new(LogMessageQueueNode); node->embedded = FALSE; log_msg_init_queue_node(msg, node, path_options); return node; } void log_msg_free_queue_node(LogMessageQueueNode *node) { if (!node->embedded) g_slice_free(LogMessageQueueNode, node); } static gboolean _log_name_value_updates(LogMessage *self) { /* we don't log name value updates for internal messages that are * initialized at this point, as that may generate an endless recursion. * log_msg_new_internal() calling log_msg_set_value(), which in turn * generates an internal message, again calling log_msg_set_value() */ return (!self->initial_parse && (self->flags & LF_INTERNAL) == 0); } void log_msg_set_value(LogMessage *self, NVHandle handle, const gchar *value, gssize value_len) { const gchar *name; gssize name_len; gboolean new_entry = FALSE; g_assert(!log_msg_is_write_protected(self)); if (handle == LM_V_NONE) return; name_len = 0; name = log_msg_get_value_name(handle, &name_len); if (_log_name_value_updates(self)) { msg_debug("Setting value", evt_tag_printf("msg", "%p", self), evt_tag_str("name", name), evt_tag_printf("value", "%.*s", (gint) value_len, value)); } if (value_len < 0) value_len = strlen(value); if (!log_msg_chk_flag(self, LF_STATE_OWN_PAYLOAD)) { self->payload = nv_table_clone(self->payload, name_len + value_len + 2); log_msg_set_flag(self, LF_STATE_OWN_PAYLOAD); self->allocated_bytes += self->payload->size; stats_counter_add(count_allocated_bytes, self->payload->size); } /* we need a loop here as a single realloc may not be enough. Might help * if we pass how much bytes we need though. */ while (!nv_table_add_value(self->payload, handle, name, name_len, value, value_len, &new_entry)) { /* error allocating string in payload, reallocate */ guint32 old_size = self->payload->size; if (!nv_table_realloc(self->payload, &self->payload)) { /* can't grow the payload, it has reached the maximum size */ msg_info("Cannot store value for this log message, maximum size has been reached", evt_tag_str("name", name), evt_tag_printf("value", "%.32s%s", value, value_len > 32 ? "..." : "")); break; } guint32 new_size = self->payload->size; self->allocated_bytes += (new_size - old_size); stats_counter_add(count_allocated_bytes, new_size-old_size); stats_counter_inc(count_payload_reallocs); } if (new_entry) log_msg_update_sdata(self, handle, name, name_len); if (handle == LM_V_PROGRAM || handle == LM_V_PID) log_msg_unset_value(self, LM_V_LEGACY_MSGHDR); } void log_msg_unset_value(LogMessage *self, NVHandle handle) { nv_table_unset_value(self->payload, handle); } void log_msg_unset_value_by_name(LogMessage *self, const gchar *name) { log_msg_unset_value(self, log_msg_get_value_handle(name)); } void log_msg_set_value_indirect(LogMessage *self, NVHandle handle, NVHandle ref_handle, guint8 type, guint16 ofs, guint16 len) { const gchar *name; gssize name_len; gboolean new_entry = FALSE; g_assert(!log_msg_is_write_protected(self)); if (handle == LM_V_NONE) return; g_assert(handle >= LM_V_MAX); name_len = 0; name = log_msg_get_value_name(handle, &name_len); if (_log_name_value_updates(self)) { msg_debug("Setting indirect value", evt_tag_printf("msg", "%p", self), evt_tag_str("name", name), evt_tag_int("ref_handle", ref_handle), evt_tag_int("ofs", ofs), evt_tag_int("len", len)); } if (!log_msg_chk_flag(self, LF_STATE_OWN_PAYLOAD)) { self->payload = nv_table_clone(self->payload, name_len + 1); log_msg_set_flag(self, LF_STATE_OWN_PAYLOAD); } NVReferencedSlice referenced_slice = { .handle = ref_handle, .ofs = ofs, .len = len, .type = type }; while (!nv_table_add_value_indirect(self->payload, handle, name, name_len, &referenced_slice, &new_entry)) { /* error allocating string in payload, reallocate */ if (!nv_table_realloc(self->payload, &self->payload)) { /* error growing the payload, skip without storing the value */ msg_info("Cannot store referenced value for this log message, maximum size has been reached", evt_tag_str("name", name), evt_tag_str("ref-name", log_msg_get_value_name(ref_handle, NULL))); break; } stats_counter_inc(count_payload_reallocs); } if (new_entry) log_msg_update_sdata(self, handle, name, name_len); } gboolean log_msg_values_foreach(const LogMessage *self, NVTableForeachFunc func, gpointer user_data) { return nv_table_foreach(self->payload, logmsg_registry, func, user_data); } void log_msg_set_match(LogMessage *self, gint index_, const gchar *value, gssize value_len) { g_assert(index_ < 256); if (index_ >= self->num_matches) self->num_matches = index_ + 1; log_msg_set_value(self, match_handles[index_], value, value_len); } void log_msg_set_match_indirect(LogMessage *self, gint index_, NVHandle ref_handle, guint8 type, guint16 ofs, guint16 len) { g_assert(index_ < 256); log_msg_set_value_indirect(self, match_handles[index_], ref_handle, type, ofs, len); } void log_msg_clear_matches(LogMessage *self) { gint i; for (i = 0; i < self->num_matches; i++) { log_msg_set_value(self, match_handles[i], "", 0); } self->num_matches = 0; } #if GLIB_SIZEOF_LONG != GLIB_SIZEOF_VOID_P #error "The tags bit array assumes that long is the same size as the pointer" #endif #if GLIB_SIZEOF_LONG == 8 #define LOGMSG_TAGS_NDX_SHIFT 6 #define LOGMSG_TAGS_NDX_MASK 0x3F #define LOGMSG_TAGS_BITS 64 #elif GLIB_SIZEOF_LONG == 4 #define LOGMSG_TAGS_NDX_SHIFT 5 #define LOGMSG_TAGS_NDX_MASK 0x1F #define LOGMSG_TAGS_BITS 32 #else #error "Unsupported word length, only 32 or 64 bit platforms are supported" #endif static inline void log_msg_tags_foreach_item(const LogMessage *self, gint base, gulong item, LogMessageTagsForeachFunc callback, gpointer user_data) { gint i; for (i = 0; i < LOGMSG_TAGS_BITS; i++) { if (G_LIKELY(!item)) return; if (item & 1) { LogTagId id = (LogTagId) base + i; callback(self, id, log_tags_get_by_id(id), user_data); } item >>= 1; } } void log_msg_tags_foreach(const LogMessage *self, LogMessageTagsForeachFunc callback, gpointer user_data) { guint i; if (self->num_tags == 0) { log_msg_tags_foreach_item(self, 0, (gulong) self->tags, callback, user_data); } else { for (i = 0; i != self->num_tags; ++i) { log_msg_tags_foreach_item(self, i * LOGMSG_TAGS_BITS, self->tags[i], callback, user_data); } } } static inline void log_msg_set_bit(gulong *tags, gint index_, gboolean value) { if (value) tags[index_ >> LOGMSG_TAGS_NDX_SHIFT] |= ((gulong) (1UL << (index_ & LOGMSG_TAGS_NDX_MASK))); else tags[index_ >> LOGMSG_TAGS_NDX_SHIFT] &= ~((gulong) (1UL << (index_ & LOGMSG_TAGS_NDX_MASK))); } static inline gboolean log_msg_get_bit(gulong *tags, gint index_) { return !!(tags[index_ >> LOGMSG_TAGS_NDX_SHIFT] & ((gulong) (1UL << (index_ & LOGMSG_TAGS_NDX_MASK)))); } void log_msg_set_tag_by_id_onoff(LogMessage *self, LogTagId id, gboolean on) { gulong *old_tags; gint old_num_tags; gboolean inline_tags; g_assert(!log_msg_is_write_protected(self)); if (!log_msg_chk_flag(self, LF_STATE_OWN_TAGS) && self->num_tags) { self->tags = g_memdup(self->tags, sizeof(self->tags[0]) * self->num_tags); } log_msg_set_flag(self, LF_STATE_OWN_TAGS); /* if num_tags is 0, it means that we use inline storage of tags */ inline_tags = self->num_tags == 0; if (inline_tags && id < LOGMSG_TAGS_BITS) { /* store this tag inline */ log_msg_set_bit((gulong *) &self->tags, id, on); } else { /* we can't put this tag inline, either because it is too large, or we don't have the inline space any more */ if ((self->num_tags * LOGMSG_TAGS_BITS) <= id) { if (G_UNLIKELY(8159 < id)) { msg_error("Maximum number of tags reached"); return; } old_num_tags = self->num_tags; self->num_tags = (id / LOGMSG_TAGS_BITS) + 1; old_tags = self->tags; if (old_num_tags) self->tags = g_realloc(self->tags, sizeof(self->tags[0]) * self->num_tags); else self->tags = g_malloc(sizeof(self->tags[0]) * self->num_tags); memset(&self->tags[old_num_tags], 0, (self->num_tags - old_num_tags) * sizeof(self->tags[0])); if (inline_tags) self->tags[0] = (gulong) old_tags; } log_msg_set_bit(self->tags, id, on); } if (on) { log_tags_inc_counter(id); } else { log_tags_dec_counter(id); } } void log_msg_set_tag_by_id(LogMessage *self, LogTagId id) { log_msg_set_tag_by_id_onoff(self, id, TRUE); } void log_msg_set_tag_by_name(LogMessage *self, const gchar *name) { log_msg_set_tag_by_id_onoff(self, log_tags_get_by_name(name), TRUE); } void log_msg_clear_tag_by_id(LogMessage *self, LogTagId id) { log_msg_set_tag_by_id_onoff(self, id, FALSE); } void log_msg_clear_tag_by_name(LogMessage *self, const gchar *name) { log_msg_set_tag_by_id_onoff(self, log_tags_get_by_name(name), FALSE); } gboolean log_msg_is_tag_by_id(LogMessage *self, LogTagId id) { if (G_UNLIKELY(8159 < id)) { msg_error("Invalid tag", evt_tag_int("id", (gint) id)); return FALSE; } if (self->num_tags == 0 && id < LOGMSG_TAGS_BITS) return log_msg_get_bit((gulong *) &self->tags, id); else if (id < self->num_tags * LOGMSG_TAGS_BITS) return log_msg_get_bit(self->tags, id); else return FALSE; } gboolean log_msg_is_tag_by_name(LogMessage *self, const gchar *name) { return log_msg_is_tag_by_id(self, log_tags_get_by_name(name)); } /* structured data elements */ static void log_msg_sdata_append_key_escaped(GString *result, const gchar *sstr, gssize len) { /* The specification does not have any way to escape keys. * The goal is to create syntactically valid structured data fields. */ const guchar *ustr = (const guchar *) sstr; for (gssize i = 0; i < len; i++) { if (!isascii(ustr[i]) || ustr[i] == '=' || ustr[i] == ' ' || ustr[i] == '[' || ustr[i] == ']' || ustr[i] == '"') { gchar hex_code[4]; g_sprintf(hex_code, "%%%02X", ustr[i]); g_string_append(result, hex_code); } else g_string_append_c(result, ustr[i]); } } static void log_msg_sdata_append_escaped(GString *result, const gchar *sstr, gssize len) { gint i; const guchar *ustr = (const guchar *) sstr; for (i = 0; i < len; i++) { if (ustr[i] == '"' || ustr[i] == '\\' || ustr[i] == ']') { g_string_append_c(result, '\\'); g_string_append_c(result, ustr[i]); } else g_string_append_c(result, ustr[i]); } } void log_msg_append_format_sdata(const LogMessage *self, GString *result, guint32 seq_num) { const gchar *value; const gchar *sdata_name, *sdata_elem, *sdata_param, *cur_elem = NULL, *dot; gssize sdata_name_len, sdata_elem_len, sdata_param_len, cur_elem_len = 0, len; gint i; static NVHandle meta_seqid = 0; gssize seqid_length; gboolean has_seq_num = FALSE; const gchar *seqid; if (!meta_seqid) meta_seqid = log_msg_get_value_handle(".SDATA.meta.sequenceId"); seqid = log_msg_get_value(self, meta_seqid, &seqid_length); APPEND_ZERO(seqid, seqid, seqid_length); if (seqid[0]) /* Message stores sequenceId */ has_seq_num = TRUE; else /* Message hasn't sequenceId */ has_seq_num = FALSE; for (i = 0; i < self->num_sdata; i++) { NVHandle handle = self->sdata[i]; guint16 handle_flags; gint sd_id_len; sdata_name_len = 0; sdata_name = log_msg_get_value_name(handle, &sdata_name_len); handle_flags = nv_registry_get_handle_flags(logmsg_registry, handle); value = log_msg_get_value_if_set(self, handle, &len); if (!value) continue; g_assert(handle_flags & LM_VF_SDATA); /* sdata_name always begins with .SDATA. */ g_assert(sdata_name_len > 6); sdata_elem = sdata_name + 7; sd_id_len = (handle_flags >> 8); if (sd_id_len) { dot = sdata_elem + sd_id_len; if (dot - sdata_name != sdata_name_len) { g_assert((dot - sdata_name < sdata_name_len) && *dot == '.'); } else { /* Standalone sdata e.g. [[UserData.updatelist@18372.4]] */ dot = NULL; } } else { dot = memrchr(sdata_elem, '.', sdata_name_len - 7); } if (G_LIKELY(dot)) { sdata_elem_len = dot - sdata_elem; sdata_param = dot + 1; sdata_param_len = sdata_name_len - (dot + 1 - sdata_name); } else { sdata_elem_len = sdata_name_len - 7; if (sdata_elem_len == 0) { sdata_elem = "none"; sdata_elem_len = 4; } sdata_param = ""; sdata_param_len = 0; } if (!cur_elem || sdata_elem_len != cur_elem_len || strncmp(cur_elem, sdata_elem, sdata_elem_len) != 0) { if (cur_elem) { /* close the previous block */ g_string_append_c(result, ']'); } /* the current SD block has changed, emit a start */ g_string_append_c(result, '['); g_string_append_len(result, sdata_elem, sdata_elem_len); /* update cur_elem */ cur_elem = sdata_elem; cur_elem_len = sdata_elem_len; } /* if message hasn't sequenceId and the cur_elem is the meta block Append the sequenceId for the result if seq_num isn't 0 */ if (!has_seq_num && seq_num!=0 && strncmp(sdata_elem,"meta.",5) == 0) { gchar sequence_id[16]; g_snprintf(sequence_id, sizeof(sequence_id), "%d", seq_num); g_string_append_c(result, ' '); g_string_append_len(result,"sequenceId=\"",12); g_string_append_len(result,sequence_id,strlen(sequence_id)); g_string_append_c(result, '"'); has_seq_num = TRUE; } if (sdata_param_len) { if (value) { g_string_append_c(result, ' '); log_msg_sdata_append_key_escaped(result, sdata_param, sdata_param_len); g_string_append(result, "=\""); log_msg_sdata_append_escaped(result, value, len); g_string_append_c(result, '"'); } } } if (cur_elem) { g_string_append_c(result, ']'); } /* There was no meta block and if sequenceId must be added (seq_num!=0) create the whole meta block with sequenceId */ if (!has_seq_num && seq_num!=0) { gchar sequence_id[16]; g_snprintf(sequence_id, sizeof(sequence_id), "%d", seq_num); g_string_append_c(result, '['); g_string_append_len(result,"meta sequenceId=\"",17); g_string_append_len(result,sequence_id,strlen(sequence_id)); g_string_append_len(result, "\"]",2); } } void log_msg_format_sdata(const LogMessage *self, GString *result, guint32 seq_num) { g_string_truncate(result, 0); log_msg_append_format_sdata(self, result, seq_num); } gboolean log_msg_append_tags_callback(const LogMessage *self, LogTagId tag_id, const gchar *name, gpointer user_data) { GString *result = (GString *) ((gpointer *) user_data)[0]; gint original_length = GPOINTER_TO_UINT(((gpointer *) user_data)[1]); g_assert(result); if (result->len > original_length) g_string_append_c(result, ','); str_repr_encode_append(result, name, -1, ","); return TRUE; } void log_msg_print_tags(const LogMessage *self, GString *result) { gpointer args[] = { result, GUINT_TO_POINTER(result->len) }; log_msg_tags_foreach(self, log_msg_append_tags_callback, args); } /** * log_msg_init: * @self: LogMessage instance * @saddr: sender address * * This function initializes a LogMessage instance without allocating it * first. It is used internally by the log_msg_new function. **/ static void log_msg_init(LogMessage *self, GSockAddr *saddr) { GTimeVal tv; /* ref is set to 1, ack is set to 0 */ self->ack_and_ref_and_abort_and_suspended = LOGMSG_REFCACHE_REF_TO_VALUE(1); cached_g_current_time(&tv); self->timestamps[LM_TS_RECVD].tv_sec = tv.tv_sec; self->timestamps[LM_TS_RECVD].tv_usec = tv.tv_usec; self->timestamps[LM_TS_RECVD].zone_offset = get_local_timezone_ofs(self->timestamps[LM_TS_RECVD].tv_sec); self->timestamps[LM_TS_STAMP] = self->timestamps[LM_TS_RECVD]; self->sdata = NULL; self->saddr = g_sockaddr_ref(saddr); self->original = NULL; self->flags |= LF_STATE_OWN_MASK; self->rcptid = rcptid_generate_id(); log_msg_set_host_id(self); } void log_msg_clear(LogMessage *self) { if (log_msg_chk_flag(self, LF_STATE_OWN_PAYLOAD)) nv_table_clear(self->payload); else self->payload = nv_table_new(LM_V_MAX, 16, 256); if (log_msg_chk_flag(self, LF_STATE_OWN_TAGS) && self->tags) { gboolean inline_tags = self->num_tags == 0; if (inline_tags) self->tags = NULL; else memset(self->tags, 0, self->num_tags * sizeof(self->tags[0])); } else self->tags = NULL; self->num_matches = 0; if (!log_msg_chk_flag(self, LF_STATE_OWN_SDATA)) { self->sdata = NULL; self->alloc_sdata = 0; } self->num_sdata = 0; if (log_msg_chk_flag(self, LF_STATE_OWN_SADDR) && self->saddr) { g_sockaddr_unref(self->saddr); } self->saddr = NULL; self->flags |= LF_STATE_OWN_MASK; } static inline LogMessage * log_msg_alloc(gsize payload_size) { LogMessage *msg; gsize payload_space = payload_size ? nv_table_get_alloc_size(LM_V_MAX, 16, payload_size) : 0; gsize alloc_size, payload_ofs = 0; /* NOTE: logmsg_node_max is updated from parallel threads without locking. */ gint nodes = (volatile gint) logmsg_queue_node_max; alloc_size = sizeof(LogMessage) + sizeof(LogMessageQueueNode) * nodes; /* align to 8 boundary */ if (payload_size) { alloc_size = (alloc_size + 7) & ~7; payload_ofs = alloc_size; alloc_size += payload_space; } msg = g_malloc(alloc_size); memset(msg, 0, sizeof(LogMessage)); if (payload_size) msg->payload = nv_table_init_borrowed(((gchar *) msg) + payload_ofs, payload_space, LM_V_MAX); msg->num_nodes = nodes; msg->allocated_bytes = alloc_size + payload_space; stats_counter_add(count_allocated_bytes, msg->allocated_bytes); return msg; } static gboolean _merge_value(NVHandle handle, const gchar *name, const gchar *value, gssize value_len, gpointer user_data) { LogMessage *msg = (LogMessage *) user_data; if (!nv_table_is_value_set(msg->payload, handle)) log_msg_set_value(msg, handle, value, value_len); return FALSE; } void log_msg_merge_context(LogMessage *self, LogMessage **context, gsize context_len) { gint i; for (i = context_len - 1; i >= 0; i--) { LogMessage *msg_to_be_merged = context[i]; log_msg_values_foreach(msg_to_be_merged, _merge_value, self); } } static void log_msg_clone_ack(LogMessage *msg, AckType ack_type) { LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; g_assert(msg->original); path_options.ack_needed = TRUE; log_msg_ack(msg->original, &path_options, ack_type); } /* * log_msg_clone_cow: * * Clone a copy-on-write (cow) copy of a log message. */ LogMessage * log_msg_clone_cow(LogMessage *msg, const LogPathOptions *path_options) { LogMessage *self = log_msg_alloc(0); gsize allocated_bytes = self->allocated_bytes; stats_counter_inc(count_msg_clones); log_msg_write_protect(msg); memcpy(self, msg, sizeof(*msg)); msg->allocated_bytes = allocated_bytes; /* every field _must_ be initialized explicitly if its direct * copying would cause problems (like copying a pointer by value) */ /* reference the original message */ self->original = log_msg_ref(msg); self->ack_and_ref_and_abort_and_suspended = LOGMSG_REFCACHE_REF_TO_VALUE(1) + LOGMSG_REFCACHE_ACK_TO_VALUE( 0) + LOGMSG_REFCACHE_ABORT_TO_VALUE(0); self->cur_node = 0; self->protect_cnt = 0; log_msg_add_ack(self, path_options); if (!path_options->ack_needed) { self->ack_func = NULL; } else { self->ack_func = log_msg_clone_ack; } self->flags &= ~LF_STATE_MASK; if (self->num_tags == 0) self->flags |= LF_STATE_OWN_TAGS; return self; } static gsize _determine_payload_size(gint length, MsgFormatOptions *parse_options) { gsize payload_size; if ((parse_options->flags & LP_STORE_RAW_MESSAGE)) payload_size = length * 4; else payload_size = length * 2; return MAX(payload_size, 256); } /** * log_msg_new: * @msg: message to parse * @length: length of @msg * @saddr: sender address * @flags: parse flags (LP_*) * * This function allocates, parses and returns a new LogMessage instance. **/ LogMessage * log_msg_new(const gchar *msg, gint length, GSockAddr *saddr, MsgFormatOptions *parse_options) { LogMessage *self = log_msg_alloc(_determine_payload_size(length, parse_options)); log_msg_init(self, saddr); if (G_LIKELY(parse_options->format_handler)) { parse_options->format_handler->parse(parse_options, (guchar *) msg, length, self); } else { log_msg_set_value(self, LM_V_MESSAGE, "Error parsing message, format module is not loaded", -1); } return self; } LogMessage * log_msg_new_empty(void) { LogMessage *self = log_msg_alloc(256); log_msg_init(self, NULL); return self; } /* This function creates a new log message that should be considered local */ LogMessage * log_msg_new_local(void) { LogMessage *self = log_msg_new_empty(); self->flags |= LF_LOCAL; return self; } /** * log_msg_new_internal: * @prio: message priority (LOG_*) * @msg: message text * @flags: parse flags (LP_*) * * This function creates a new log message for messages originating * internally to syslog-ng **/ LogMessage * log_msg_new_internal(gint prio, const gchar *msg) { gchar buf[32]; LogMessage *self; g_snprintf(buf, sizeof(buf), "%d", (int) getpid()); self = log_msg_new_local(); self->flags |= LF_INTERNAL; self->initial_parse = TRUE; log_msg_set_value(self, LM_V_PROGRAM, "syslog-ng", 9); log_msg_set_value(self, LM_V_PID, buf, -1); log_msg_set_value(self, LM_V_MESSAGE, msg, -1); self->initial_parse = FALSE; self->pri = prio; return self; } /** * log_msg_new_mark: * * This function returns a new MARK message. MARK messages have the LF_MARK * flag set. **/ LogMessage * log_msg_new_mark(void) { LogMessage *self = log_msg_new_local(); log_msg_set_value(self, LM_V_MESSAGE, "-- MARK --", 10); self->pri = LOG_SYSLOG | LOG_INFO; self->flags |= LF_MARK | LF_INTERNAL; return self; } /** * log_msg_free: * @self: LogMessage instance * * Frees a LogMessage instance. **/ static void log_msg_free(LogMessage *self) { if (log_msg_chk_flag(self, LF_STATE_OWN_PAYLOAD) && self->payload) nv_table_unref(self->payload); if (log_msg_chk_flag(self, LF_STATE_OWN_TAGS) && self->tags && self->num_tags > 0) g_free(self->tags); if (log_msg_chk_flag(self, LF_STATE_OWN_SDATA) && self->sdata) g_free(self->sdata); if (log_msg_chk_flag(self, LF_STATE_OWN_SADDR)) g_sockaddr_unref(self->saddr); if (self->original) log_msg_unref(self->original); stats_counter_sub(count_allocated_bytes, self->allocated_bytes); g_free(self); } /** * log_msg_drop: * @msg: LogMessage instance * @path_options: path specific options * * This function is called whenever a destination driver feels that it is * unable to process this message. It acks and unrefs the message. **/ void log_msg_drop(LogMessage *msg, const LogPathOptions *path_options, AckType ack_type) { log_msg_ack(msg, path_options, ack_type); log_msg_unref(msg); } static AckType _ack_and_ref_and_abort_and_suspend_to_acktype(gint value) { AckType type = AT_PROCESSED; if (IS_SUSPENDFLAG_ON(LOGMSG_REFCACHE_VALUE_TO_SUSPEND(value))) type = AT_SUSPENDED; else if (IS_ABORTFLAG_ON(LOGMSG_REFCACHE_VALUE_TO_ABORT(value))) type = AT_ABORTED; return type; } /*************************************************************************************** * In order to read & understand this code, reading the comment on the top * of this file about ref/ack handling is strongly recommended. ***************************************************************************************/ /* Function to update the combined ACK (with the abort flag) and REF counter. */ static inline gint log_msg_update_ack_and_ref_and_abort_and_suspended(LogMessage *self, gint add_ref, gint add_ack, gint add_abort, gint add_suspend) { gint old_value, new_value; do { new_value = old_value = (volatile gint) self->ack_and_ref_and_abort_and_suspended; new_value = (new_value & ~LOGMSG_REFCACHE_REF_MASK) + LOGMSG_REFCACHE_REF_TO_VALUE( (LOGMSG_REFCACHE_VALUE_TO_REF( old_value) + add_ref)); new_value = (new_value & ~LOGMSG_REFCACHE_ACK_MASK) + LOGMSG_REFCACHE_ACK_TO_VALUE( (LOGMSG_REFCACHE_VALUE_TO_ACK( old_value) + add_ack)); new_value = (new_value & ~LOGMSG_REFCACHE_ABORT_MASK) + LOGMSG_REFCACHE_ABORT_TO_VALUE((LOGMSG_REFCACHE_VALUE_TO_ABORT( old_value) | add_abort)); new_value = (new_value & ~LOGMSG_REFCACHE_SUSPEND_MASK) + LOGMSG_REFCACHE_SUSPEND_TO_VALUE(( LOGMSG_REFCACHE_VALUE_TO_SUSPEND(old_value) | add_suspend)); } while (!g_atomic_int_compare_and_exchange(&self->ack_and_ref_and_abort_and_suspended, old_value, new_value)); return old_value; } /* Function to update the combined ACK (without abort) and REF counter. */ static inline gint log_msg_update_ack_and_ref(LogMessage *self, gint add_ref, gint add_ack) { return log_msg_update_ack_and_ref_and_abort_and_suspended(self, add_ref, add_ack, 0, 0); } /** * log_msg_ref: * @self: LogMessage instance * * Increment reference count of @self and return the new reference. **/ LogMessage * log_msg_ref(LogMessage *self) { gint old_value; if (G_LIKELY(logmsg_current == self)) { /* fastpath, @self is the current message, ref/unref processing is * delayed until log_msg_refcache_stop() is called */ logmsg_cached_refs++; return self; } /* slow path, refcache is not used, do the ordinary way */ old_value = log_msg_update_ack_and_ref(self, 1, 0); g_assert(LOGMSG_REFCACHE_VALUE_TO_REF(old_value) >= 1); return self; } /** * log_msg_unref: * @self: LogMessage instance * * Decrement reference count and free self if the reference count becomes 0. **/ void log_msg_unref(LogMessage *self) { gint old_value; if (G_LIKELY(logmsg_current == self)) { /* fastpath, @self is the current message, ref/unref processing is * delayed until log_msg_refcache_stop() is called */ logmsg_cached_refs--; return; } old_value = log_msg_update_ack_and_ref(self, -1, 0); g_assert(LOGMSG_REFCACHE_VALUE_TO_REF(old_value) >= 1); if (LOGMSG_REFCACHE_VALUE_TO_REF(old_value) == 1) { log_msg_free(self); } } /** * log_msg_add_ack: * @m: LogMessage instance * * This function increments the number of required acknowledges. **/ void log_msg_add_ack(LogMessage *self, const LogPathOptions *path_options) { if (path_options->ack_needed) { if (G_LIKELY(logmsg_current == self)) { /* fastpath, @self is the current message, add_ack/ack processing is * delayed until log_msg_refcache_stop() is called */ logmsg_cached_acks++; logmsg_cached_ack_needed = TRUE; return; } log_msg_update_ack_and_ref(self, 0, 1); } } /** * log_msg_ack: * @msg: LogMessage instance * @path_options: path specific options * @acked: TRUE: positive ack, FALSE: negative ACK * * Indicate that the message was processed successfully and the sender can * queue further messages. **/ void log_msg_ack(LogMessage *self, const LogPathOptions *path_options, AckType ack_type) { gint old_value; if (path_options->ack_needed) { if (G_LIKELY(logmsg_current == self)) { /* fastpath, @self is the current message, add_ack/ack processing is * delayed until log_msg_refcache_stop() is called */ logmsg_cached_acks--; logmsg_cached_abort |= IS_ACK_ABORTED(ack_type); logmsg_cached_suspend |= IS_ACK_SUSPENDED(ack_type); return; } old_value = log_msg_update_ack_and_ref_and_abort_and_suspended(self, 0, -1, IS_ACK_ABORTED(ack_type), IS_ACK_SUSPENDED(ack_type)); if (LOGMSG_REFCACHE_VALUE_TO_ACK(old_value) == 1) { if (ack_type == AT_SUSPENDED) self->ack_func(self, AT_SUSPENDED); else if (ack_type == AT_ABORTED) self->ack_func(self, AT_ABORTED); else self->ack_func(self, _ack_and_ref_and_abort_and_suspend_to_acktype(old_value)); } } } /* * Break out of an acknowledgement chain. The incoming message is * ACKed and a new path options structure is returned that can be used * to send to further consuming pipes. */ const LogPathOptions * log_msg_break_ack(LogMessage *msg, const LogPathOptions *path_options, LogPathOptions *local_options) { /* NOTE: in case the user requested flow control, we can't break the * ACK chain, as that would lead to early acks, that would cause * message loss */ g_assert(!path_options->flow_control_requested); log_msg_ack(msg, path_options, AT_PROCESSED); *local_options = *path_options; local_options->ack_needed = FALSE; return local_options; } /* * Start caching ref/unref/ack/add-ack operations in the current thread for * the message specified by @self. See the comment at the top of this file * for more information. * * This function is to be called by the producer thread (e.g. the one * that generates new messages). You should use * log_msg_refcache_start_consumer() in consumer threads instead. * * This function cannot be called for the same message from multiple * threads. * */ void log_msg_refcache_start_producer(LogMessage *self) { g_assert(logmsg_current == NULL); logmsg_current = self; /* we're the producer of said message, and thus we want to inhibit * freeing/acking it due to our cached refs, add a bias large enough * to cover any possible unrefs/acks of the consumer side */ /* we don't need to be thread-safe here, as a producer has just created this message and no parallel access is yet possible */ self->ack_and_ref_and_abort_and_suspended = (self->ack_and_ref_and_abort_and_suspended & ~LOGMSG_REFCACHE_REF_MASK) + LOGMSG_REFCACHE_REF_TO_VALUE((LOGMSG_REFCACHE_VALUE_TO_REF(self->ack_and_ref_and_abort_and_suspended) + LOGMSG_REFCACHE_BIAS)); self->ack_and_ref_and_abort_and_suspended = (self->ack_and_ref_and_abort_and_suspended & ~LOGMSG_REFCACHE_ACK_MASK) + LOGMSG_REFCACHE_ACK_TO_VALUE((LOGMSG_REFCACHE_VALUE_TO_ACK(self->ack_and_ref_and_abort_and_suspended) + LOGMSG_REFCACHE_BIAS)); logmsg_cached_refs = -LOGMSG_REFCACHE_BIAS; logmsg_cached_acks = -LOGMSG_REFCACHE_BIAS; logmsg_cached_abort = FALSE; logmsg_cached_suspend = FALSE; logmsg_cached_ack_needed = TRUE; } /* * Start caching ref/unref/ack/add-ack operations in the current thread for * the message specified by @self. See the comment at the top of this file * for more information. * * This function is to be called by the consumer threads (e.g. the * ones that consume messages). * * This function can be called from mutliple consumer threads at the * same time, even for the same message. * */ void log_msg_refcache_start_consumer(LogMessage *self, const LogPathOptions *path_options) { g_assert(logmsg_current == NULL); logmsg_current = self; logmsg_cached_ack_needed = path_options->ack_needed; logmsg_cached_refs = 0; logmsg_cached_acks = 0; logmsg_cached_abort = FALSE; logmsg_cached_suspend = FALSE; } /* * Stop caching ref/unref/ack/add-ack operations in the current thread for * the message specified by the log_msg_refcache_start() function. * * See the comment at the top of this file for more information. */ void log_msg_refcache_stop(void) { gint old_value; gint current_cached_acks; gboolean current_cached_abort; gboolean current_cached_suspend; g_assert(logmsg_current != NULL); /* validate that we didn't overflow the counters: * * Both counters must be: * * - at least 1 smaller than the bias, rationale: * * - if we are caching "bias" number of refs, it may happen * that there are bias number of unrefs, potentially running * in consumer threads * * - if the potential unrefs is larger than the bias value, it may * happen that the producer sets the bias (trying to avoid * the freeing of the LogMessage), but still it gets freed. * * - not smaller than the "-bias" value, rationale: * - if we are caching "bias" number of unrefs the same can happen * as with the ref case. * */ g_assert((logmsg_cached_acks < LOGMSG_REFCACHE_BIAS - 1) && (logmsg_cached_acks >= -LOGMSG_REFCACHE_BIAS)); g_assert((logmsg_cached_refs < LOGMSG_REFCACHE_BIAS - 1) && (logmsg_cached_refs >= -LOGMSG_REFCACHE_BIAS)); /* * We fold the differences in ack/ref counts in three stages: * * 1) we take a ref of logmsg_current, this is needed so that the * message is not freed until we return from refcache_stop() * * 2) we add in all the diffs that were accumulated between * refcache_start and refcache_stop. This gets us a final value of the * ack counter, ref must be >= as we took a ref ourselves. * * 3) we call the ack handler if needed, this might change ref counters * recursively (but not ack counters as that already atomically * dropped to zero) * * 4) drop the ref we took in step 1) above * * 4) then we fold in the net ref results of the ack callback and * refcache_stop() combined. This either causes the LogMessage to be * freed (when we were the last), or it stays around because of other * refs. */ /* 1) take ref */ log_msg_ref(logmsg_current); /* 2) fold in ref/ack counter diffs into the atomic value */ current_cached_acks = logmsg_cached_acks; logmsg_cached_acks = 0; current_cached_abort = logmsg_cached_abort; logmsg_cached_abort = FALSE; current_cached_suspend = logmsg_cached_suspend; logmsg_cached_suspend = FALSE; old_value = log_msg_update_ack_and_ref_and_abort_and_suspended(logmsg_current, 0, current_cached_acks, current_cached_abort, current_cached_suspend); if ((LOGMSG_REFCACHE_VALUE_TO_ACK(old_value) == -current_cached_acks) && logmsg_cached_ack_needed) { AckType ack_type_cumulated = _ack_and_ref_and_abort_and_suspend_to_acktype(old_value); if (current_cached_suspend) ack_type_cumulated = AT_SUSPENDED; else if (current_cached_abort) ack_type_cumulated = AT_ABORTED; /* 3) call the ack handler */ logmsg_current->ack_func(logmsg_current, ack_type_cumulated); /* the ack callback may not change the ack counters, it already * dropped to zero atomically, changing that again is an error */ g_assert(logmsg_cached_acks == 0); } /* 4) drop our own ref */ log_msg_unref(logmsg_current); /* 5) fold the combined result of our own ref/unref and ack handler's results */ old_value = log_msg_update_ack_and_ref(logmsg_current, logmsg_cached_refs, 0); if (LOGMSG_REFCACHE_VALUE_TO_REF(old_value) == -logmsg_cached_refs) log_msg_free(logmsg_current); logmsg_cached_refs = 0; logmsg_current = NULL; } void log_msg_registry_init(void) { gint i; logmsg_registry = nv_registry_new(builtin_value_names, NVHANDLE_MAX_VALUE); nv_registry_add_alias(logmsg_registry, LM_V_MESSAGE, "MSG"); nv_registry_add_alias(logmsg_registry, LM_V_MESSAGE, "MSGONLY"); nv_registry_add_alias(logmsg_registry, LM_V_HOST, "FULLHOST"); nv_registry_add_alias(logmsg_registry, LM_V_HOST_FROM, "FULLHOST_FROM"); for (i = 0; macros[i].name; i++) { if (nv_registry_get_handle(logmsg_registry, macros[i].name) == 0) { NVHandle handle; handle = nv_registry_alloc_handle(logmsg_registry, macros[i].name); nv_registry_set_handle_flags(logmsg_registry, handle, (macros[i].id << 8) + LM_VF_MACRO); } } /* register $0 - $255 in order */ for (i = 0; i < 256; i++) { gchar buf[8]; g_snprintf(buf, sizeof(buf), "%d", i); match_handles[i] = nv_registry_alloc_handle(logmsg_registry, buf); } } void log_msg_registry_deinit(void) { nv_registry_free(logmsg_registry); logmsg_registry = NULL; } void log_msg_registry_foreach(GHFunc func, gpointer user_data) { nv_registry_foreach(logmsg_registry, func, user_data); } void log_msg_global_init(void) { log_msg_registry_init(); } void log_msg_stats_global_init(void) { stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_GLOBAL, "msg_clones", NULL ); stats_register_counter(0, &sc_key, SC_TYPE_PROCESSED, &count_msg_clones); stats_cluster_logpipe_key_set(&sc_key, SCS_GLOBAL, "payload_reallocs", NULL ); stats_register_counter(0, &sc_key, SC_TYPE_PROCESSED, &count_payload_reallocs); stats_cluster_logpipe_key_set(&sc_key, SCS_GLOBAL, "sdata_updates", NULL ); stats_register_counter(0, &sc_key, SC_TYPE_PROCESSED, &count_sdata_updates); stats_cluster_single_key_set(&sc_key, SCS_GLOBAL, "msg_allocated_bytes", NULL); stats_register_counter(1, &sc_key, SC_TYPE_SINGLE_VALUE, &count_allocated_bytes); stats_unlock(); } const gchar * log_msg_get_handle_name(NVHandle handle, gssize *length) { return nv_registry_get_handle_name(logmsg_registry, handle, length); } void log_msg_global_deinit(void) { log_msg_registry_deinit(); } gint log_msg_lookup_time_stamp_name(const gchar *name) { if (strcmp(name, "stamp") == 0) return LM_TS_STAMP; else if (strcmp(name, "recvd") == 0) return LM_TS_RECVD; return -1; } gssize log_msg_get_size(LogMessage *self) { return sizeof(LogMessage) + // msg.static fields + self->alloc_sdata * sizeof(self->sdata[0]) + sizeof(GSockAddr) + sizeof (GSockAddrFuncs) + // msg.saddr + msg.saddr.sa_func ((self->num_tags) ? sizeof(self->tags[0]) * self->num_tags : 0) + nv_table_get_memory_consumption(self->payload); // msg.payload (nvtable) } #ifdef __linux__ const gchar * __log_msg_get_value(const LogMessage *self, NVHandle handle, gssize *value_len) __attribute__((alias("log_msg_get_value"))); const gchar * __log_msg_get_value_by_name(const LogMessage *self, const gchar *name, gssize *value_len) __attribute__((alias("log_msg_get_value_by_name"))); void __log_msg_set_value_by_name(LogMessage *self, const gchar *name, const gchar *value, gssize length) __attribute__((alias("log_msg_set_value_by_name"))); #endif syslog-ng-syslog-ng-3.13.2/lib/logmsg/logmsg.h000066400000000000000000000277341321171025300211510ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGMSG_H_INCLUDED #define LOGMSG_H_INCLUDED #include "syslog-ng.h" #include "gsockaddr.h" #include "atomic.h" #include "serialize.h" #include "logstamp.h" #include "logmsg/nvtable.h" #include "msg-format.h" #include "logmsg/tags.h" #include #include #include #include #include typedef enum { AT_UNDEFINED, AT_PROCESSED, AT_ABORTED, AT_SUSPENDED } AckType; #define IS_ACK_ABORTED(x) ((x) == AT_ABORTED ? 1 : 0) #define IS_ABORTFLAG_ON(x) ((x) == 1 ? TRUE : FALSE) #define IS_ACK_SUSPENDED(x) ((x) == AT_SUSPENDED ? 1 : 0) #define IS_SUSPENDFLAG_ON(x) ((x) == 1 ? TRUE : FALSE) #define STRICT_ROUND_TO_NEXT_EIGHT(x) ((x + 8) & ~7) typedef struct _LogPathOptions LogPathOptions; typedef void (*LMAckFunc)(LogMessage *lm, AckType ack_type); #define RE_MAX_MATCHES 256 typedef enum { LM_TS_STAMP = 0, LM_TS_RECVD = 1, LM_TS_MAX } LogMessageTimeStamp; /* builtin values */ enum { LM_V_NONE, LM_V_HOST, LM_V_HOST_FROM, LM_V_MESSAGE, LM_V_PROGRAM, LM_V_PID, LM_V_MSGID, LM_V_SOURCE, LM_V_LEGACY_MSGHDR, /* NOTE: this is used as the number of "statically" allocated elements in * an NVTable. NVTable may impose restrictions on this value (for * instance had to be an even number earlier). So be sure to validate * whether LM_V_MAX would fit NVTable if you add further enums here. */ LM_V_MAX, }; enum { LM_VF_SDATA = 0x0001, LM_VF_MATCH = 0x0002, LM_VF_MACRO = 0x0004, }; enum { /* these flags also matter when the message is serialized */ LF_OLD_UNPARSED = 0x0001, /* message payload is guaranteed to be valid utf8 */ LF_UTF8 = 0x0001, /* message was generated from within syslog-ng, doesn't matter if it came from the internal() source */ LF_INTERNAL = 0x0002, /* message was received on a local transport, e.g. it was generated on the local machine */ LF_LOCAL = 0x0004, /* message is a MARK mode */ LF_MARK = 0x0008, /* state flags that only matter during syslog-ng runtime and never * when a message is serialized */ LF_STATE_MASK = 0xFFF0, LF_STATE_OWN_PAYLOAD = 0x0010, LF_STATE_OWN_SADDR = 0x0020, LF_STATE_OWN_TAGS = 0x0040, LF_STATE_OWN_SDATA = 0x0080, LF_STATE_OWN_MASK = 0x00F0, /* In the log header the hostname shall be printed individually (no group name, no chain hosts)*/ LF_SIMPLE_HOSTNAME = 0x0100, LF_CHAINED_HOSTNAME = 0x00010000, /* NOTE: this flag is now unused. The original intent was to save whether * LEGACY_MSGHDR was saved by the parser code. Now we simply check * whether the length of ${LEGACY_MSGHDR} is non-zero. This used to be a * slow operation (when name-value pairs were stored in a hashtable), now * it is much faster. Also, this makes it possible to reproduce a message * entirely based on name-value pairs. Without this change, even if * LEGACY_MSGHDR was transferred (e.g. ewmm), the other side couldn't * reproduce the original message, as this flag was not transferred. * * The flag remains here for documentation, and also because it is serialized in disk-buffers */ __UNUSED_LF_LEGACY_MSGHDR = 0x00020000, }; typedef struct _LogMessageQueueNode { struct iv_list_head list; LogMessage *msg; gboolean ack_needed:1, embedded:1, flow_control_requested:1; } LogMessageQueueNode; /* NOTE: the members are ordered according to the presumed use frequency. * The structure itself is 2 cachelines, the border is right after the "msg" * member */ struct _LogMessage { /* if you change any of the fields here, be sure to adjust * log_msg_clone_cow() as well to initialize fields properly */ /* ack_and_ref_and_abort_and_suspended is a 32 bit integer that is accessed in an atomic way. * The upper half contains the ACK count (and the abort flag), the lower half * the REF count. It is not a GAtomicCounter as due to ref/ack caching it has * a lot of magic behind its implementation. See the logmsg.c file, around * log_msg_ref/unref. */ /* FIXME: the structure has holes, but right now it's 1 byte short to make * it smaller (it is possible to create a 7 byte contiguos block but 8 * byte alignment is needed. Let's check this with the inline-tags stuff */ gint ack_and_ref_and_abort_and_suspended; AckRecord *ack_record; LMAckFunc ack_func; LogMessage *original; gsize allocated_bytes; /* message parts */ /* the contents of the members below is directly copied into another * LogMessage with pointer values. To change any of the fields please use * log_msg_set_*() functions, which will handle borrowed data members * correctly. */ /* ==== start of directly copied part ==== */ LogStamp timestamps[LM_TS_MAX]; guint32 host_id; gulong *tags; NVHandle *sdata; GSockAddr *saddr; NVTable *payload; guint32 flags; guint16 pri; guint8 initial_parse:1, recursed:1; guint8 num_matches; guint8 num_tags; guint8 alloc_sdata; guint8 num_sdata; /* ==== end of directly copied part ==== */ guint8 num_nodes; guint8 cur_node; guint8 protect_cnt; guint64 rcptid; /* preallocated LogQueueNodes used to insert this message into a LogQueue */ LogMessageQueueNode nodes[0]; /* a preallocated space for the inital NVTable (payload) may follow */ }; extern NVRegistry *logmsg_registry; extern const char logmsg_sd_prefix[]; extern const gint logmsg_sd_prefix_len; extern gint logmsg_node_max; LogMessage *log_msg_ref(LogMessage *m); void log_msg_unref(LogMessage *m); void log_msg_write_protect(LogMessage *m); void log_msg_write_unprotect(LogMessage *m); LogMessage *log_msg_clone_cow(LogMessage *msg, const LogPathOptions *path_options); LogMessage *log_msg_make_writable(LogMessage **pmsg, const LogPathOptions *path_options); gboolean log_msg_write(LogMessage *self, SerializeArchive *sa); gboolean log_msg_read(LogMessage *self, SerializeArchive *sa); /* generic values that encapsulate log message fields, dynamic values and structured data */ NVHandle log_msg_get_value_handle(const gchar *value_name); gboolean log_msg_is_value_name_valid(const gchar *value); gboolean log_msg_is_handle_macro(NVHandle handle); gboolean log_msg_is_handle_sdata(NVHandle handle); gboolean log_msg_is_handle_match(NVHandle handle); static inline gboolean log_msg_is_handle_settable_with_an_indirect_value(NVHandle handle) { return (handle >= LM_V_MAX); } const gchar *log_msg_get_macro_value(const LogMessage *self, gint id, gssize *value_len); static inline const gchar * log_msg_get_value(const LogMessage *self, NVHandle handle, gssize *value_len) { guint16 flags; flags = nv_registry_get_handle_flags(logmsg_registry, handle); if ((flags & LM_VF_MACRO) == 0) return nv_table_get_value(self->payload, handle, value_len); else return log_msg_get_macro_value(self, flags >> 8, value_len); } static inline const gchar * log_msg_get_value_if_set(const LogMessage *self, NVHandle handle, gssize *value_len) { guint16 flags; flags = nv_registry_get_handle_flags(logmsg_registry, handle); if ((flags & LM_VF_MACRO) == 0) return nv_table_get_value_if_set(self->payload, handle, value_len); else return log_msg_get_macro_value(self, flags >> 8, value_len); } static inline const gchar * log_msg_get_value_by_name(const LogMessage *self, const gchar *name, gssize *value_len) { NVHandle handle = log_msg_get_value_handle(name); return log_msg_get_value(self, handle, value_len); } static inline const gchar * log_msg_get_value_name(NVHandle handle, gssize *name_len) { return nv_registry_get_handle_name(logmsg_registry, handle, name_len); } typedef gboolean (*LogMessageTagsForeachFunc)(const LogMessage *self, LogTagId tag_id, const gchar *name, gpointer user_data); void log_msg_set_value(LogMessage *self, NVHandle handle, const gchar *new_value, gssize length); void log_msg_set_value_indirect(LogMessage *self, NVHandle handle, NVHandle ref_handle, guint8 type, guint16 ofs, guint16 len); void log_msg_unset_value(LogMessage *self, NVHandle handle); void log_msg_unset_value_by_name(LogMessage *self, const gchar *name); gboolean log_msg_values_foreach(const LogMessage *self, NVTableForeachFunc func, gpointer user_data); void log_msg_set_match(LogMessage *self, gint index, const gchar *value, gssize value_len); void log_msg_set_match_indirect(LogMessage *self, gint index, NVHandle ref_handle, guint8 type, guint16 ofs, guint16 len); void log_msg_clear_matches(LogMessage *self); static inline void log_msg_set_value_by_name(LogMessage *self, const gchar *name, const gchar *value, gssize length) { NVHandle handle = log_msg_get_value_handle(name); log_msg_set_value(self, handle, value, length); } void log_msg_append_format_sdata(const LogMessage *self, GString *result, guint32 seq_num); void log_msg_format_sdata(const LogMessage *self, GString *result, guint32 seq_num); void log_msg_set_tag_by_id_onoff(LogMessage *self, LogTagId id, gboolean on); void log_msg_set_tag_by_id(LogMessage *self, LogTagId id); void log_msg_set_tag_by_name(LogMessage *self, const gchar *name); void log_msg_clear_tag_by_id(LogMessage *self, LogTagId id); void log_msg_clear_tag_by_name(LogMessage *self, const gchar *name); gboolean log_msg_is_tag_by_id(LogMessage *self, LogTagId id); gboolean log_msg_is_tag_by_name(LogMessage *self, const gchar *name); void log_msg_tags_foreach(const LogMessage *self, LogMessageTagsForeachFunc callback, gpointer user_data); void log_msg_print_tags(const LogMessage *self, GString *result); LogMessageQueueNode *log_msg_alloc_queue_node(LogMessage *msg, const LogPathOptions *path_options); LogMessageQueueNode *log_msg_alloc_dynamic_queue_node(LogMessage *msg, const LogPathOptions *path_options); void log_msg_free_queue_node(LogMessageQueueNode *node); void log_msg_clear(LogMessage *self); void log_msg_merge_context(LogMessage *self, LogMessage **context, gsize context_len); LogMessage *log_msg_new(const gchar *msg, gint length, GSockAddr *saddr, MsgFormatOptions *parse_options); LogMessage *log_msg_new_mark(void); LogMessage *log_msg_new_internal(gint prio, const gchar *msg); LogMessage *log_msg_new_empty(void); LogMessage *log_msg_new_local(void); void log_msg_add_ack(LogMessage *msg, const LogPathOptions *path_options); void log_msg_ack(LogMessage *msg, const LogPathOptions *path_options, AckType ack_type); void log_msg_drop(LogMessage *msg, const LogPathOptions *path_options, AckType ack_type); const LogPathOptions *log_msg_break_ack(LogMessage *msg, const LogPathOptions *path_options, LogPathOptions *local_options); void log_msg_refcache_start_producer(LogMessage *self); void log_msg_refcache_start_consumer(LogMessage *self, const LogPathOptions *path_options); void log_msg_refcache_stop(void); void log_msg_registry_init(void); void log_msg_registry_deinit(void); void log_msg_global_init(void); void log_msg_global_deinit(void); void log_msg_stats_global_init(void); void log_msg_registry_foreach(GHFunc func, gpointer user_data); gint log_msg_lookup_time_stamp_name(const gchar *name); gssize log_msg_get_size(LogMessage *self); #endif syslog-ng-syslog-ng-3.13.2/lib/logmsg/nvtable-serialize-endianutils.h000066400000000000000000000063701321171025300256070ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * Copyright (c) 2012-2015 Viktor Juhasz * Copyright (c) 2012-2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef NVTABLE_SERIALIZE_ENDIANUTILS_H_ #define NVTABLE_SERIALIZE_ENDIANUTILS_H_ static inline guint8 reverse(guint8 b) { b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; b = (b & 0xCC) >> 2 | (b & 0x33) << 2; b = (b & 0xAA) >> 1 | (b & 0x55) << 1; return b; } static inline void nv_table_swap_entry_flags(NVEntry *entry) { entry->flags = reverse(entry->flags); } static inline void nv_entry_swap_bytes(NVEntry *entry) { nv_table_swap_entry_flags(entry); entry->alloc_len = GUINT32_SWAP_LE_BE(entry->alloc_len); if (!entry->indirect) { entry->vdirect.value_len = GUINT32_SWAP_LE_BE(entry->vdirect.value_len); } else { entry->vindirect.handle = GUINT32_SWAP_LE_BE(entry->vindirect.handle); entry->vindirect.ofs = GUINT32_SWAP_LE_BE(entry->vindirect.ofs); entry->vindirect.len = GUINT32_SWAP_LE_BE(entry->vindirect.len); } } static inline void nv_table_dyn_value_swap_bytes(NVIndexEntry* self) { self->handle = GUINT32_SWAP_LE_BE(self->handle); self->ofs = GUINT32_SWAP_LE_BE(self->handle); }; static inline void nv_table_data_swap_bytes(NVTable *self) { NVIndexEntry *index_table; NVEntry *entry; gint i; for (i = 0; i < self->num_static_entries; i++) { entry = nv_table_get_entry_at_ofs(self, self->static_entries[i]); if (!entry) continue; nv_entry_swap_bytes(entry); } index_table = nv_table_get_index(self); for (i = 0; i < self->index_size; i++) { entry = nv_table_get_entry_at_ofs(self, index_table[i].ofs); if (!entry) continue; nv_entry_swap_bytes(entry); } } static inline void nv_table_struct_swap_bytes(NVTable *self) { guint16 i; NVIndexEntry *index_table; self->size = GUINT16_SWAP_LE_BE(self->size); self->used = GUINT16_SWAP_LE_BE(self->used); self->index_size = GUINT16_SWAP_LE_BE(self->index_size); for (i = 0; i < self->num_static_entries; i++) { self->static_entries[i] = GUINT16_SWAP_LE_BE(self->static_entries[i]); } index_table = nv_table_get_index(self); for (i = 0; i < self->index_size; i++) { nv_table_dyn_value_swap_bytes(&index_table[i]); } } #endif /* NVTABLE_SERIALIZE_ENDIANUTILS_H_ */ syslog-ng-syslog-ng-3.13.2/lib/logmsg/nvtable-serialize.c000066400000000000000000000143401321171025300232610ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * Copyright (c) 2012-2015 Viktor Juhasz * Copyright (c) 2012-2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logmsg/nvtable-serialize.h" #include "logmsg/nvtable-serialize-endianutils.h" #include "logmsg/logmsg.h" #include "messages.h" #include #include typedef struct _NVTableMetaData { guint32 magic; guint8 flags; } NVTableMetaData; /********************************************************************** * deserialize an NVTable **********************************************************************/ static gboolean _deserialize_static_entries(SerializeArchive *sa, NVTable *res) { if (!serialize_read_uint32_array(sa, res->static_entries, res->num_static_entries)) return FALSE; return TRUE; } static gboolean _deserialize_dynamic_entries(SerializeArchive *sa, NVTable *res) { NVIndexEntry *index_table; index_table = nv_table_get_index(res); if (!serialize_read_uint32_array(sa, (guint32 *) index_table, res->index_size * 2)) return FALSE; return TRUE; } static gboolean _read_struct(SerializeArchive *sa, NVTable *res) { return _deserialize_static_entries(sa, res) && _deserialize_dynamic_entries(sa, res); } static gboolean _has_to_swap_bytes(guint8 flags) { return !!(flags & NVT_SF_BE) != (G_BYTE_ORDER == G_BIG_ENDIAN); } static inline gboolean _read_magic(SerializeArchive *sa, guint32 *magic) { return serialize_read_uint32(sa, magic); } static inline gboolean _read_flags(SerializeArchive *sa, guint8 *flags) { return serialize_read_uint8(sa, flags); } static inline gboolean _read_metadata(SerializeArchive *sa, NVTableMetaData *meta_data) { if (!_read_magic(sa, &meta_data->magic)) { return FALSE; } if (!_read_flags(sa, &meta_data->flags)) { return FALSE; } if (_has_to_swap_bytes(meta_data->flags)) { meta_data->magic = GUINT32_SWAP_LE_BE(meta_data->magic); } if (memcmp((void *)&meta_data->magic, (const void *)NV_TABLE_MAGIC_V2, 4) != 0) { return FALSE; } return TRUE; } static gboolean _read_header(SerializeArchive *sa, NVTable **nvtable) { NVTable *res = NULL; guint32 size; g_assert(*nvtable == NULL); if (!serialize_read_uint32(sa, &size)) goto error; if (size > NV_TABLE_MAX_BYTES) goto error; res = (NVTable *) g_malloc(size); res->size = size; if (!serialize_read_uint32(sa, &res->used)) goto error; if (!serialize_read_uint16(sa, &res->index_size)) goto error; if (!serialize_read_uint8(sa, &res->num_static_entries)) goto error; /* static entries has to be known by this syslog-ng, if they are over * LM_V_MAX, that means we have no clue how an entry is called, as static * entries don't contain names. If there are less static entries, that * can be ok. */ if (res->num_static_entries > LM_V_MAX) goto error; /* validates self->used and self->index_size value as compared to "size" */ if (!nv_table_alloc_check(res, 0)) goto error; res->borrowed = FALSE; res->ref_cnt = 1; *nvtable = res; return TRUE; error: if (res) g_free(res); return FALSE; } static inline gboolean _read_payload(SerializeArchive *sa, NVTable *res) { return serialize_read_blob(sa, NV_TABLE_ADDR(res, res->size - res->used), res->used); } NVTable * nv_table_deserialize(LogMessageSerializationState *state) { SerializeArchive *sa = state->sa; NVTableMetaData meta_data; NVTable *res = NULL; if (!_read_metadata(sa, &meta_data)) goto error; if (!_read_header(sa, &res)) goto error; state->nvtable_flags = meta_data.flags; state->nvtable = res; if (!_read_struct(sa, res)) goto error; if (!_read_payload(sa, res)) goto error; if (_has_to_swap_bytes(meta_data.flags)) nv_table_data_swap_bytes(res); return res; error: if (res) g_free(res); return NULL; } /********************************************************************** * serialize an NVTable **********************************************************************/ static void _write_struct(SerializeArchive *sa, NVTable *self) { serialize_write_uint32(sa, self->size); serialize_write_uint32(sa, self->used); serialize_write_uint16(sa, self->index_size); serialize_write_uint8(sa, self->num_static_entries); serialize_write_uint32_array(sa, self->static_entries, self->num_static_entries); serialize_write_uint32_array(sa, (guint32 *) nv_table_get_index(self), self->index_size * 2); } static void _write_meta_data(SerializeArchive *sa, NVTableMetaData *meta_data) { serialize_write_uint32(sa, meta_data->magic); serialize_write_uint8(sa, meta_data->flags); } static void _fill_meta_data(NVTable *self, NVTableMetaData *meta_data) { memcpy((void *)&meta_data->magic,(const void *) NV_TABLE_MAGIC_V2, 4); if (G_BYTE_ORDER == G_BIG_ENDIAN) meta_data->flags |= NVT_SF_BE; meta_data->flags |= NVT_SUPPORTS_UNSET; } static void _write_payload(SerializeArchive *sa, NVTable *self) { serialize_write_blob(sa, NV_TABLE_ADDR(self, self->size - self->used), self->used); } gboolean nv_table_serialize(LogMessageSerializationState *state, NVTable *self) { NVTableMetaData meta_data = { 0 }; SerializeArchive *sa = state->sa; _fill_meta_data(self, &meta_data); _write_meta_data(sa, &meta_data); _write_struct(sa, self); _write_payload(sa, self); return TRUE; } syslog-ng-syslog-ng-3.13.2/lib/logmsg/nvtable-serialize.h000066400000000000000000000030311321171025300232610ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * Copyright (c) 2012-2015 Viktor Juhasz * Copyright (c) 2012-2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef _NVTABLE_SERIALIZE_H #define _NVTABLE_SERIALIZE_H #include "logmsg/nvtable.h" #include "logmsg/serialization.h" #define NV_TABLE_MAGIC_V2 "NVT2" #define NVT_SF_BE 0x1 #define NVT_SUPPORTS_UNSET 0x2 NVTable *nv_table_deserialize(LogMessageSerializationState *state); gboolean nv_table_serialize(LogMessageSerializationState *state, NVTable *self); gboolean nv_table_fixup_handles(LogMessageSerializationState *state); #endif syslog-ng-syslog-ng-3.13.2/lib/logmsg/nvtable.c000066400000000000000000000523051321171025300212770ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logmsg/nvtable.h" #include "messages.h" #include #include GStaticMutex nv_registry_lock = G_STATIC_MUTEX_INIT; const gchar *null_string = ""; NVHandle nv_registry_get_handle(NVRegistry *self, const gchar *name) { gpointer p; p = g_hash_table_lookup(self->name_map, name); if (p) return GPOINTER_TO_UINT(p); return 0; } NVHandle nv_registry_alloc_handle(NVRegistry *self, const gchar *name) { gpointer p; NVHandleDesc stored; gsize len; NVHandle res = 0; g_static_mutex_lock(&nv_registry_lock); p = g_hash_table_lookup(self->name_map, name); if (p) { res = GPOINTER_TO_UINT(p); goto exit; } len = strlen(name); if (len == 0) { goto exit; } else if (len > 255) { msg_error("Value names cannot be longer than 255 characters, this value will always expand to the emptry string", evt_tag_str("value", name)); goto exit; } else if (self->names->len >= self->nvhandle_max_value) { msg_error("Hard wired limit of name-value pairs have been reached, all further name-value pair will expand to nothing", evt_tag_printf("limit", "%"G_GUINT32_FORMAT, self->nvhandle_max_value), evt_tag_str("value", name)); goto exit; } /* flags (2 bytes) || length (1 byte) || name (len bytes) || NUL */ /* memory layout: flags || length || name (NUL terminated) */ stored.flags = 0; stored.name_len = len; stored.name = g_strdup(name); g_array_append_val(self->names, stored); g_hash_table_insert(self->name_map, stored.name, GUINT_TO_POINTER(self->names->len)); res = self->names->len; exit: g_static_mutex_unlock(&nv_registry_lock); return res; } /** * nv_registry_add_alias: * @handle: a NV handle to be aliased * @alias: must be a caller allocated string pointing to the alias of "handle" **/ void nv_registry_add_alias(NVRegistry *self, NVHandle handle, const gchar *alias) { g_static_mutex_lock(&nv_registry_lock); g_hash_table_insert(self->name_map, g_strdup(alias), GUINT_TO_POINTER((glong) handle)); g_static_mutex_unlock(&nv_registry_lock); } void nv_registry_set_handle_flags(NVRegistry *self, NVHandle handle, guint16 flags) { NVHandleDesc *stored; if (G_UNLIKELY(!handle)) return; stored = &g_array_index(self->names, NVHandleDesc, handle - 1); stored->flags = flags; } void nv_registry_foreach(NVRegistry *self, GHFunc callback, gpointer user_data) { g_hash_table_foreach(self->name_map, callback, user_data); } NVRegistry * nv_registry_new(const gchar **static_names, guint32 nvhandle_max_value) { NVRegistry *self = g_new0(NVRegistry, 1); gint i; self->nvhandle_max_value = nvhandle_max_value; self->name_map = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); self->names = g_array_new(FALSE, FALSE, sizeof(NVHandleDesc)); for (i = 0; static_names[i]; i++) { nv_registry_alloc_handle(self, static_names[i]); } return self; } void nv_registry_free(NVRegistry *self) { g_array_free(self->names, TRUE); g_hash_table_destroy(self->name_map); g_free(self); } /* return the offset to a newly allocated payload string */ static inline NVEntry * nv_table_alloc_value(NVTable *self, gsize alloc_size) { NVEntry *entry; alloc_size = NV_TABLE_BOUND(alloc_size); /* alloc error, NVTable should be realloced */ if (!nv_table_alloc_check(self, alloc_size)) return NULL; self->used += alloc_size; entry = (NVEntry *) (nv_table_get_top(self) - (self->used)); /* initialize all flags to zero, so we don't need to bump the version for * a compatible change */ entry->flags = 0; entry->alloc_len = alloc_size; entry->indirect = FALSE; entry->referenced = FALSE; entry->unset = FALSE; return entry; } /* we only support single indirection */ const gchar * nv_table_resolve_indirect(NVTable *self, NVEntry *entry, gssize *length) { const gchar *referenced_value; gssize referenced_length; referenced_value = nv_table_get_value(self, entry->vindirect.handle, &referenced_length); if (entry->vindirect.ofs > referenced_length) { if (length) *length = 0; return null_string; } /* here we assume that indirect references are only looked up with * non-zero terminated strings properly handled, thus the caller has * to supply a non-NULL value_len */ g_assert(length != NULL); *length = MIN(entry->vindirect.ofs + entry->vindirect.len, referenced_length) - entry->vindirect.ofs; return referenced_value + entry->vindirect.ofs; } static const inline gchar * nv_table_resolve_entry(NVTable *self, NVEntry *entry, gssize *length) { if (entry->unset) { if (length) *length = 0; return null_string; } else if (!entry->indirect) { if (length) *length = entry->vdirect.value_len; return entry->vdirect.data + entry->name_len + 1; } else return nv_table_resolve_indirect(self, entry, length); } NVEntry * nv_table_get_entry_slow(NVTable *self, NVHandle handle, NVIndexEntry **index_entry) { guint32 ofs; gint l, h, m; NVIndexEntry *index_table = nv_table_get_index(self); guint32 mv; if (!self->index_size) { *index_entry = NULL; return NULL; } /* open-coded binary search */ *index_entry = NULL; l = 0; h = self->index_size - 1; ofs = 0; while (l <= h) { m = (l+h) >> 1; mv = index_table[m].handle; if (mv == handle) { *index_entry = &index_table[m]; ofs = index_table[m].ofs; break; } else if (mv > handle) { h = m - 1; } else { l = m + 1; } } NVEntry *entry = nv_table_get_entry_at_ofs(self, ofs); return entry; } static gboolean nv_table_reserve_table_entry(NVTable *self, NVHandle handle, NVIndexEntry **index_entry) { if (G_UNLIKELY(!(*index_entry) && handle > self->num_static_entries)) { /* this is a dynamic value */ NVIndexEntry *index_table = nv_table_get_index(self);; gint l, h, m, ndx; gboolean found = FALSE; if (!nv_table_alloc_check(self, sizeof(index_table[0]))) return FALSE; l = 0; h = self->index_size - 1; ndx = -1; while (l <= h) { guint16 mv; m = (l+h) >> 1; mv = index_table[m].handle; if (mv == handle) { ndx = m; found = TRUE; break; } else if (mv > handle) { h = m - 1; } else { l = m + 1; } } /* if we find the proper slot we set that, if we don't, we insert a new entry */ if (!found) ndx = l; g_assert(ndx >= 0 && ndx <= self->index_size); if (ndx < self->index_size) { memmove(&index_table[ndx + 1], &index_table[ndx], (self->index_size - ndx) * sizeof(index_table[0])); } *index_entry = &index_table[ndx]; /* we set ofs to zero here, which means that the NVEntry won't be found even if the slot is present in index */ (**index_entry).handle = handle; (**index_entry).ofs = 0; if (!found) self->index_size++; } return TRUE; } static inline void nv_table_set_table_entry(NVTable *self, NVHandle handle, guint32 ofs, NVIndexEntry *index_entry) { if (G_LIKELY(handle <= self->num_static_entries)) { /* this is a statically allocated value, simply store the offset */ self->static_entries[handle-1] = ofs; } else { /* this is a dynamic value */ (*index_entry).handle = handle; (*index_entry).ofs = ofs; } } static gboolean nv_table_make_direct(NVHandle handle, NVEntry *entry, NVIndexEntry *index_entry, gpointer user_data) { NVTable *self = (NVTable *) (((gpointer *) user_data)[0]); NVHandle ref_handle = GPOINTER_TO_UINT(((gpointer *) user_data)[1]); if (entry->indirect && entry->vindirect.handle == ref_handle) { const gchar *value; gssize value_len; value = nv_table_resolve_indirect(self, entry, &value_len); if (!nv_table_add_value(self, handle, entry->vindirect.name, entry->name_len, value, value_len, NULL)) { /* nvtable full, but we can't realloc it ourselves, * propagate this back as a failure of * nv_table_add_value() */ return TRUE; } } return FALSE; } gboolean nv_table_add_value(NVTable *self, NVHandle handle, const gchar *name, gsize name_len, const gchar *value, gsize value_len, gboolean *new_entry) { NVEntry *entry; guint32 ofs; NVIndexEntry *index_entry; if (value_len > NV_TABLE_MAX_BYTES) value_len = NV_TABLE_MAX_BYTES; if (new_entry) *new_entry = FALSE; entry = nv_table_get_entry(self, handle, &index_entry); if (G_UNLIKELY(entry && !entry->indirect && entry->referenced)) { gpointer data[2] = { self, GUINT_TO_POINTER((glong) handle) }; if (nv_table_foreach_entry(self, nv_table_make_direct, data)) { /* we had to stop iteration, which means that we were unable * to allocate enough space for making indirect entries * direct */ return FALSE; } } if (G_UNLIKELY(entry && (((guint) entry->alloc_len)) >= value_len + NV_ENTRY_DIRECT_HDR + name_len + 2)) { gchar *dst; /* this value already exists and the new value fits in the old space */ if (!entry->indirect) { dst = entry->vdirect.data + entry->name_len + 1; entry->vdirect.value_len = value_len; memmove(dst, value, value_len); dst[value_len] = 0; } else { /* this was an indirect entry, convert it */ entry->indirect = 0; entry->vdirect.value_len = value_len; entry->name_len = name_len; memmove(entry->vdirect.data, name, name_len + 1); memmove(entry->vdirect.data + name_len + 1, value, value_len); entry->vdirect.data[entry->name_len + 1 + value_len] = 0; } entry->unset = FALSE; return TRUE; } else if (!entry && new_entry) *new_entry = TRUE; /* check if there's enough free space: size of the struct plus the * size needed for a dynamic table slot */ if (!nv_table_reserve_table_entry(self, handle, &index_entry)) return FALSE; entry = nv_table_alloc_value(self, NV_ENTRY_DIRECT_HDR + name_len + value_len + 2); if (G_UNLIKELY(!entry)) { return FALSE; } ofs = nv_table_get_ofs_for_an_entry(self, entry); entry->vdirect.value_len = value_len; if (handle >= self->num_static_entries) { /* we only store the name for non-builtin values */ entry->name_len = name_len; memmove(entry->vdirect.data, name, name_len + 1); } else entry->name_len = 0; memmove(entry->vdirect.data + entry->name_len + 1, value, value_len); entry->vdirect.data[entry->name_len + 1 + value_len] = 0; nv_table_set_table_entry(self, handle, ofs, index_entry); return TRUE; } void nv_table_unset_value(NVTable *self, NVHandle handle) { NVIndexEntry *index_entry; NVEntry *entry = nv_table_get_entry(self, handle, &index_entry); if (!entry) return; entry->unset = TRUE; /* make sure the actual value is also set to the null_string just in case * this message is serialized and then deserialized by an earlier * syslog-ng version which does not support the unset flag */ if (entry->indirect) { entry->vindirect.ofs = 0; entry->vindirect.len = 0; } else { entry->vdirect.value_len = 0; entry->vdirect.data[entry->name_len + 1] = 0; } } static void nv_table_set_indirect_entry(NVTable *self, NVHandle handle, NVEntry *entry, const gchar *name, gsize name_len, const NVReferencedSlice *referenced_slice) { entry->vindirect.handle = referenced_slice->handle; entry->vindirect.ofs = referenced_slice->ofs; entry->vindirect.len = referenced_slice->len; entry->vindirect.type = referenced_slice->type; if (entry->indirect) return; /* previously a non-indirect entry, convert it */ entry->indirect = 1; if (handle >= self->num_static_entries) { entry->name_len = name_len; memmove(entry->vindirect.name, name, name_len + 1); } else { entry->name_len = 0; } } static gboolean nv_table_copy_referenced_value(NVTable *self, NVEntry *ref_entry, NVHandle handle, const gchar *name, gsize name_len, NVReferencedSlice *ref_slice, gboolean *new_entry) { gssize ref_length; const gchar *ref_value = nv_table_resolve_entry(self, ref_entry, &ref_length); if (ref_slice->ofs > ref_length) { ref_slice->len = 0; ref_slice->ofs = 0; } else { ref_slice->len = MIN(ref_slice->ofs + ref_slice->len, ref_length) - ref_slice->ofs; } return nv_table_add_value(self, handle, name, name_len, ref_value + ref_slice->ofs, ref_slice->len, new_entry); } gboolean nv_table_add_value_indirect(NVTable *self, NVHandle handle, const gchar *name, gsize name_len, NVReferencedSlice *referenced_slice, gboolean *new_entry) { NVEntry *entry, *ref_entry; NVIndexEntry *index_entry; guint32 ofs; if (new_entry) *new_entry = FALSE; ref_entry = nv_table_get_entry(self, referenced_slice->handle, &index_entry); if ((ref_entry && ref_entry->indirect) || handle == referenced_slice->handle) { /* NOTE: uh-oh, the to-be-referenced value is already an indirect * reference, this is not supported, copy the stuff */ return nv_table_copy_referenced_value(self, ref_entry, handle, name, name_len, referenced_slice, new_entry); } entry = nv_table_get_entry(self, handle, &index_entry); if ((!entry && !new_entry && referenced_slice->len == 0) || !ref_entry) { /* we don't store zero length matches unless the caller is * interested in whether a new entry was created. It is used by * the SDATA support code to decide whether a previously * not-present SDATA was set */ return TRUE; } if (entry && !entry->indirect && entry->referenced) { gpointer data[2] = { self, GUINT_TO_POINTER((glong) handle) }; if (!nv_table_foreach_entry(self, nv_table_make_direct, data)) return FALSE; } if (entry && (((guint) entry->alloc_len) >= NV_ENTRY_INDIRECT_HDR + name_len + 1)) { /* this value already exists and the new reference fits in the old space */ nv_table_set_indirect_entry(self, handle, entry, name, name_len, referenced_slice); ref_entry->referenced = TRUE; return TRUE; } else if (!entry && new_entry) { *new_entry = TRUE; } if (!nv_table_reserve_table_entry(self, handle, &index_entry)) return FALSE; entry = nv_table_alloc_value(self, NV_ENTRY_INDIRECT_HDR + name_len + 1); if (!entry) { return FALSE; } ofs = nv_table_get_ofs_for_an_entry(self, entry); nv_table_set_indirect_entry(self, handle, entry, name, name_len, referenced_slice); ref_entry->referenced = TRUE; nv_table_set_table_entry(self, handle, ofs, index_entry); return TRUE; } static gboolean nv_table_call_foreach(NVHandle handle, NVEntry *entry, NVIndexEntry *index_entry, gpointer user_data) { NVTable *self = (NVTable *) ((gpointer *) user_data)[0]; NVRegistry *registry = (NVRegistry *) ((gpointer *) user_data)[1]; NVTableForeachFunc func = ((gpointer *) user_data)[2]; gpointer func_data = ((gpointer *) user_data)[3]; const gchar *value; gssize value_len; if (entry->unset) return FALSE; value = nv_table_resolve_entry(self, entry, &value_len); return func(handle, nv_registry_get_handle_name(registry, handle, NULL), value, value_len, func_data); } gboolean nv_table_foreach(NVTable *self, NVRegistry *registry, NVTableForeachFunc func, gpointer user_data) { gpointer data[4] = { self, registry, func, user_data }; return nv_table_foreach_entry(self, nv_table_call_foreach, data); } gboolean nv_table_foreach_entry(NVTable *self, NVTableForeachEntryFunc func, gpointer user_data) { NVIndexEntry *index_table; NVEntry *entry; gint i; for (i = 0; i < self->num_static_entries; i++) { entry = nv_table_get_entry_at_ofs(self, self->static_entries[i]); if (!entry) continue; if (func(i + 1, entry, NULL, user_data)) return TRUE; } index_table = nv_table_get_index(self); for (i = 0; i < self->index_size; i++) { entry = nv_table_get_entry_at_ofs(self, index_table[i].ofs); if (!entry) continue; if (func(index_table[i].handle, entry, &index_table[i], user_data)) return TRUE; } return FALSE; } void nv_table_clear(NVTable *self) { g_assert(self->ref_cnt == 1); self->used = 0; self->index_size = 0; memset(&self->static_entries[0], 0, self->num_static_entries * sizeof(self->static_entries[0])); } void nv_table_init(NVTable *self, gsize alloc_length, gint num_static_entries) { g_assert(alloc_length <= NV_TABLE_MAX_BYTES); self->size = alloc_length; self->used = 0; self->index_size = 0; self->num_static_entries = num_static_entries; self->ref_cnt = 1; self->borrowed = FALSE; memset(&self->static_entries[0], 0, self->num_static_entries * sizeof(self->static_entries[0])); } NVTable * nv_table_new(gint num_static_entries, gint index_size_hint, gint init_length) { NVTable *self; gsize alloc_length; alloc_length = nv_table_get_alloc_size(num_static_entries, index_size_hint, init_length); self = (NVTable *) g_malloc(alloc_length); nv_table_init(self, alloc_length, num_static_entries); return self; } NVTable * nv_table_init_borrowed(gpointer space, gsize space_len, gint num_static_entries) { NVTable *self = (NVTable *) space; space_len &= ~3; g_assert(space_len > num_static_entries * sizeof(self->static_entries[0]) + sizeof(NVTable)); nv_table_init(self, NV_TABLE_BOUND(space_len), num_static_entries); self->borrowed = TRUE; return self; } /* returns TRUE if successfully realloced, FALSE means that we're unable to grow */ gboolean nv_table_realloc(NVTable *self, NVTable **new) { gsize old_size = self->size; gsize new_size; /* double the size of the current allocation */ new_size = ((gsize) self->size) << 1; if (new_size > NV_TABLE_MAX_BYTES) new_size = NV_TABLE_MAX_BYTES; if (new_size == old_size) return FALSE; if (self->ref_cnt == 1 && !self->borrowed) { *new = self = g_realloc(self, new_size); self->size = new_size; /* move the downwards growing region to the end of the new buffer */ memmove(NV_TABLE_ADDR(self, self->size - self->used), NV_TABLE_ADDR(self, old_size - self->used), self->used); } else { *new = g_malloc(new_size); /* we only copy the header first */ memcpy(*new, self, sizeof(NVTable) + self->num_static_entries * sizeof(self->static_entries[0]) + self->index_size * sizeof(NVIndexEntry)); (*new)->ref_cnt = 1; (*new)->borrowed = FALSE; (*new)->size = new_size; memmove(NV_TABLE_ADDR((*new), (*new)->size - (*new)->used), NV_TABLE_ADDR(self, old_size - self->used), self->used); nv_table_unref(self); } return TRUE; } NVTable * nv_table_ref(NVTable *self) { self->ref_cnt++; return self; } void nv_table_unref(NVTable *self) { if ((--self->ref_cnt == 0) && !self->borrowed) { g_free(self); } } /** * nv_table_clone: * @self: payload to clone * @additional_space: specifies how much additional space is needed in * the newly allocated clone * **/ NVTable * nv_table_clone(NVTable *self, gint additional_space) { NVTable *new; gint new_size; if (nv_table_get_bottom(self) - nv_table_get_ofs_table_top(self) < additional_space) new_size = self->size; else new_size = self->size + (NV_TABLE_BOUND(additional_space)); if (new_size > NV_TABLE_MAX_BYTES) new_size = NV_TABLE_MAX_BYTES; new = g_malloc(new_size); memcpy(new, self, sizeof(NVTable) + self->num_static_entries * sizeof(self->static_entries[0]) + self->index_size * sizeof(NVIndexEntry)); new->size = new_size; new->ref_cnt = 1; new->borrowed = FALSE; memcpy(NV_TABLE_ADDR(new, new->size - new->used), NV_TABLE_ADDR(self, self->size - self->used), self->used); return new; } syslog-ng-syslog-ng-3.13.2/lib/logmsg/nvtable.h000066400000000000000000000312601321171025300213010ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PAYLOAD_H_INCLUDED #define PAYLOAD_H_INCLUDED #include "syslog-ng.h" typedef struct _NVTable NVTable; typedef struct _NVRegistry NVRegistry; typedef struct _NVIndexEntry NVIndexEntry; typedef struct _NVEntry NVEntry; typedef guint32 NVHandle; typedef struct _NVHandleDesc NVHandleDesc; typedef gboolean (*NVTableForeachFunc)(NVHandle handle, const gchar *name, const gchar *value, gssize value_len, gpointer user_data); typedef gboolean (*NVTableForeachEntryFunc)(NVHandle handle, NVEntry *entry, NVIndexEntry *index_entry, gpointer user_data); #define NVHANDLE_MAX_VALUE ((NVHandle)-1) /* NVIndexEntry * this represents an entry in the handle based lookup index, embedded in an NVTable. * * NOTE: * The deserialization code (at least version 26) assumes that this can be * represented by a pair of guint32 instances. It is reading the entire * array back as such. Should you need to change the types here, please * ensure that you also update the nvtable deserialization code. */ struct _NVIndexEntry { NVHandle handle; guint32 ofs; }; struct _NVHandleDesc { gchar *name; guint16 flags; guint8 name_len; }; struct _NVRegistry { /* number of static names that are statically allocated in each payload */ gint num_static_names; GArray *names; GHashTable *name_map; guint32 nvhandle_max_value; }; extern const gchar *null_string; void nv_registry_add_alias(NVRegistry *self, NVHandle handle, const gchar *alias); NVHandle nv_registry_get_handle(NVRegistry *self, const gchar *name); NVHandle nv_registry_alloc_handle(NVRegistry *self, const gchar *name); void nv_registry_set_handle_flags(NVRegistry *self, NVHandle handle, guint16 flags); void nv_registry_foreach(NVRegistry *self, GHFunc callback, gpointer user_data); NVRegistry *nv_registry_new(const gchar **static_names, guint32 nvhandle_max_value); void nv_registry_free(NVRegistry *self); static inline guint16 nv_registry_get_handle_flags(NVRegistry *self, NVHandle handle) { NVHandleDesc *stored; if (G_UNLIKELY(!handle)) return 0; stored = &g_array_index(self->names, NVHandleDesc, handle - 1); return stored->flags; } static inline const gchar * nv_registry_get_handle_name(NVRegistry *self, NVHandle handle, gssize *length) { NVHandleDesc *stored; if (G_UNLIKELY(!handle)) { if (length) *length = 4; return "None"; } if (handle - 1 >= self->names->len) return NULL; stored = &g_array_index(self->names, NVHandleDesc, handle - 1); if (G_LIKELY(length)) *length = stored->name_len; return stored->name; } typedef struct _NVReferencedSlice { NVHandle handle; guint32 ofs; guint32 len; guint8 type; gchar name[0]; } NVReferencedSlice; /* * Contains a name-value pair. */ struct _NVEntry { /* negative offset, counting from string table top, e.g. start of the string is at @top + ofs */ union { struct { /* make sure you don't exceed 8 bits here. So if you want to add new * bits, decrease the size of __bit_padding below */ guint8 indirect:1, referenced:1, unset:1, __bit_padding:5; }; guint8 flags; }; guint8 name_len; guint32 alloc_len; union { struct { guint32 value_len; /* variable data, first the name of this entry, then the value, both are NUL terminated */ gchar data[0]; } vdirect; NVReferencedSlice vindirect; }; }; #define NV_ENTRY_DIRECT_HDR ((gsize) (&((NVEntry *) NULL)->vdirect.data)) #define NV_ENTRY_INDIRECT_HDR (sizeof(NVEntry)) static inline const gchar * nv_entry_get_name(NVEntry *self) { if (self->indirect) return self->vindirect.name; else return self->vdirect.data; } /* * Contains a set of ordered name-value pairs. * * This struct is used to track a set of name-value pairs that make up * a LogMessage structure. The storage layout is as concise as * possible to make it possible to serialize this payload as a single * writev() operation. * * Memory layout: * ============= * * || struct || static value offsets || dynamic value (id, offset) pairs || || stored (name, value) || * * Name value area: * - the name-value area grows down (e.g. lower addresses) from the end of the struct * - name-value pairs are referenced by the offset counting down from the end of the struct * - all NV pairs are positioned at 4 bytes boundary, so 32 bit variables in NVEntry * can be accessed in an aligned manner * * Static value offsets: * - a fixed size of guint32 array, containing 32 bit offsets for statically allocated entries * - the handles for static values have a low value and they match the index in this array * * Dynamic values: * - a dynamically sized NVIndexEntry array (contains ID + offset) * - dynamic values are sorted by the global ID to make handle->entry lookups fast * * Memory allocation * ================= * - the memory used by NVTable is managed by the caller, sometimes it is * allocated inside an existing data structure (we preallocate space * with LogMessage) * * - when the structure needs to grow the instance pointer itself needs to * be changed. In order to avoid doing that in all the API calls, a * separate nv_table_realloc() call is provided. * * - NVTable instances are reference counted, but the reference counts are * not thread safe (and accessing NVTable itself isn't either). When * reallocation is needed and multiple references exist, NVTable clones * itself and leaves the old copy be. * * - It is possible to clone an NVTable, which basically copies the * underlying memory contents. * * Limits * ====== * There might be various assumptions here and there in the code that fields * in this structure should be limited in values. These are as follows. * (the list is not necessarily comprehensive though, so please be careful * when changing types). * - index_size is used to allocate NVIndexEntry arrays on the stack, * so 2^16 * sizeof(NVIndexEntry) is allocated at most (512k). If you * however change this limit, please be careful to audit the * deserialization code. * */ struct _NVTable { /* byte order indication, etc. */ guint32 size; guint32 used; /* this used to be called num_dyn_entries in earlier versions, it matches * the type of the original type, so it is compatible with earlier * versions, but index_size is a more descriptive name */ guint16 index_size; guint8 num_static_entries; guint8 ref_cnt:7, borrowed:1; /* specifies if the memory used by NVTable was borrowed from the container struct */ /* variable data, see memory layout in the comment above */ union { guint32 __dummy_for_alignment; guint32 static_entries[0]; gchar data[0]; }; }; #define NV_TABLE_BOUND(x) (((x) + 0x3) & ~0x3) #define NV_TABLE_ADDR(self, x) ((gchar *) ((self)) + ((gssize)(x))) /* 256MB, this is an artificial limit, but must be less than MAX_GUINT32 as * we want to compare a guint32 to this variable without overflow. */ #define NV_TABLE_MAX_BYTES (256*1024*1024) /* this has to be large enough to hold the NVTable struct above and the * static values */ #define NV_TABLE_MIN_BYTES 128 gboolean nv_table_add_value(NVTable *self, NVHandle handle, const gchar *name, gsize name_len, const gchar *value, gsize value_len, gboolean *new_entry); void nv_table_unset_value(NVTable *self, NVHandle handle); gboolean nv_table_add_value_indirect(NVTable *self, NVHandle handle, const gchar *name, gsize name_len, NVReferencedSlice *referenced_slice, gboolean *new_entry); gboolean nv_table_foreach(NVTable *self, NVRegistry *registry, NVTableForeachFunc func, gpointer user_data); gboolean nv_table_foreach_entry(NVTable *self, NVTableForeachEntryFunc func, gpointer user_data); void nv_table_clear(NVTable *self); NVTable *nv_table_new(gint num_static_values, gint index_size_hint, gint init_length); NVTable *nv_table_init_borrowed(gpointer space, gsize space_len, gint num_static_entries); gboolean nv_table_realloc(NVTable *self, NVTable **new); NVTable *nv_table_clone(NVTable *self, gint additional_space); NVTable *nv_table_ref(NVTable *self); void nv_table_unref(NVTable *self); static inline gsize nv_table_get_alloc_size(gint num_static_entries, gint index_size_hint, gint init_length) { NVTable *self G_GNUC_UNUSED = NULL; gsize size; size = NV_TABLE_BOUND(init_length) + NV_TABLE_BOUND(sizeof(NVTable) + num_static_entries * sizeof(self->static_entries[0]) + index_size_hint * sizeof(NVIndexEntry)); if (size < NV_TABLE_MIN_BYTES) return NV_TABLE_MIN_BYTES; if (size > NV_TABLE_MAX_BYTES) size = NV_TABLE_MAX_BYTES; return size; } static inline gchar * nv_table_get_top(NVTable *self) { return NV_TABLE_ADDR(self, self->size); } static inline gchar * nv_table_get_bottom(NVTable *self) { return nv_table_get_top(self) - self->used; } static inline gchar * nv_table_get_ofs_table_top(NVTable *self) { return (gchar *) &self->data[self->num_static_entries * sizeof(self->static_entries[0]) + self->index_size * sizeof(NVIndexEntry)]; } static inline gboolean nv_table_alloc_check(NVTable *self, gsize alloc_size) { if (nv_table_get_bottom(self) - alloc_size < nv_table_get_ofs_table_top(self)) return FALSE; return TRUE; } /* private declarations for inline functions */ NVEntry *nv_table_get_entry_slow(NVTable *self, NVHandle handle, NVIndexEntry **index_entry); const gchar *nv_table_resolve_indirect(NVTable *self, NVEntry *entry, gssize *len); static inline NVEntry * __nv_table_get_entry(NVTable *self, NVHandle handle, guint16 num_static_entries, NVIndexEntry **index_entry) { guint32 ofs; if (G_UNLIKELY(!handle)) { *index_entry = NULL; return NULL; } if (G_LIKELY(handle <= num_static_entries)) { ofs = self->static_entries[handle - 1]; *index_entry = NULL; if (G_UNLIKELY(!ofs)) return NULL; return (NVEntry *) (nv_table_get_top(self) - ofs); } else { return nv_table_get_entry_slow(self, handle, index_entry); } } static inline NVEntry * nv_table_get_entry(NVTable *self, NVHandle handle, NVIndexEntry **index_entry) { return __nv_table_get_entry(self, handle, self->num_static_entries, index_entry); } static inline gboolean nv_table_is_value_set(NVTable *self, NVHandle handle) { NVIndexEntry *index_entry; return nv_table_get_entry(self, handle, &index_entry) != NULL; } static inline const gchar * nv_table_get_value_if_set(NVTable *self, NVHandle handle, gssize *length) { NVEntry *entry; NVIndexEntry *index_entry; entry = nv_table_get_entry(self, handle, &index_entry); if (!entry || entry->unset) { if (length) *length = 0; return NULL; } if (!entry->indirect) { if (length) *length = entry->vdirect.value_len; return entry->vdirect.data + entry->name_len + 1; } return nv_table_resolve_indirect(self, entry, length); } static inline const gchar * nv_table_get_value(NVTable *self, NVHandle handle, gssize *length) { const gchar *value = nv_table_get_value_if_set(self, handle, length); if (!value) return null_string; return value; } static inline NVIndexEntry * nv_table_get_index(NVTable *self) { return (NVIndexEntry *)&self->static_entries[self->num_static_entries]; } static inline NVEntry * nv_table_get_entry_at_ofs(NVTable *self, guint32 ofs) { if (!ofs) return NULL; return (NVEntry *)(nv_table_get_top(self) - ofs); } static inline guint32 nv_table_get_ofs_for_an_entry(NVTable *self, NVEntry *entry) { return (nv_table_get_top(self) - (gchar *) entry); } static inline gssize nv_table_get_memory_consumption(NVTable *self) { return sizeof(*self)+ self->num_static_entries*sizeof(self->static_entries[0])+ self->used; } #endif syslog-ng-syslog-ng-3.13.2/lib/logmsg/serialization.h000066400000000000000000000026171321171025300225270ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * Copyright (c) 2016 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGMSG_SERIALIZATION_H #define LOGMSG_SERIALIZATION_H #include "serialize.h" #include "logmsg/logmsg.h" typedef struct _LogMessageSerializationState { guint8 version; SerializeArchive *sa; LogMessage *msg; NVTable *nvtable; guint8 nvtable_flags; guint8 handle_changed; NVHandle *updated_sdata_handles; NVIndexEntry *updated_index; } LogMessageSerializationState; #endif syslog-ng-syslog-ng-3.13.2/lib/logmsg/tags-serialize.c000066400000000000000000000037001321171025300225620ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 2015 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "tags-serialize.h" #include "scratch-buffers.h" gboolean tags_deserialize(LogMessage *msg, SerializeArchive *sa) { ScratchBuffersMarker marker; GString *buf = scratch_buffers_alloc_and_mark(&marker); while (1) { if (!serialize_read_string(sa, buf)) return FALSE; if (buf->len == 0) { /* "" , empty string means: last tag */ break; } log_msg_set_tag_by_name(msg, buf->str); } msg->flags |= LF_STATE_OWN_TAGS; scratch_buffers_reclaim_marked(marker); return TRUE; } static gboolean _callback(const LogMessage *msg, LogTagId tag_id, const gchar *name, gpointer user_data) { SerializeArchive *sa = ( SerializeArchive *)user_data; serialize_write_cstring(sa, name, strlen(name)); return TRUE; } gboolean tags_serialize(LogMessage *msg, SerializeArchive *sa) { log_msg_tags_foreach(msg, _callback, (gpointer)sa); return serialize_write_cstring(sa, "", 0); } syslog-ng-syslog-ng-3.13.2/lib/logmsg/tags-serialize.h000066400000000000000000000023601321171025300225700ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 2015 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TAGS_SERIALIZE_H #define TAGS_SERIALIZE_H #include "logmsg/logmsg.h" #include "serialize.h" gboolean tags_deserialize(LogMessage *msg, SerializeArchive *sa); gboolean tags_serialize(LogMessage *msg, SerializeArchive *sa); #endif syslog-ng-syslog-ng-3.13.2/lib/logmsg/tags.c000066400000000000000000000136611321171025300206040ustar00rootroot00000000000000/* * Copyright (c) 2009-2013 Balabit * Copyright (c) 2009 Marton Illes * Copyright (c) 2009-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "tags.h" #include "messages.h" #include "stats/stats-registry.h" typedef struct _LogTag { LogTagId id; gchar *name; StatsCounterItem *counter; } LogTag; static LogTag *log_tags_list = NULL; static GHashTable *log_tags_hash = NULL; static guint32 log_tags_num = 0; static guint32 log_tags_list_size = 4; static GStaticMutex log_tags_lock = G_STATIC_MUTEX_INIT; /* * log_tags_get_by_name * * Lookup a tag id by it's name. If the tag is seen for the first time * the next tag id is assigned and the tag is added to the list. * * The function returns the tag id associated with the name. * * @name: the name of the tag * */ LogTagId log_tags_get_by_name(const gchar *name) { /* If log_tags_hash() is NULL, this unit is already deinitialized but other thread may refer the tag structure. If name is empty, it is an extremal element. In both cases the return value is 0. */ guint id; g_assert(log_tags_hash != NULL); g_static_mutex_lock(&log_tags_lock); id = GPOINTER_TO_UINT(g_hash_table_lookup(log_tags_hash, name)) - 1; if (id == 0xffffffff) { if (log_tags_num < LOG_TAGS_MAX - 1) { id = log_tags_num++; if (id == log_tags_list_size) { log_tags_list_size *= 2; log_tags_list = g_renew(LogTag, log_tags_list, log_tags_list_size); } log_tags_list[id].id = id; log_tags_list[id].name = g_strdup(name); log_tags_list[id].counter = NULL; /* NOTE: stats-level may not be set for calls that happen during * config file parsing, those get fixed up by * log_tags_reinit_stats() below */ stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_TAG, name, NULL ); stats_register_counter(3, &sc_key, SC_TYPE_PROCESSED, &log_tags_list[id].counter); stats_unlock(); g_hash_table_insert(log_tags_hash, log_tags_list[id].name, GUINT_TO_POINTER(log_tags_list[id].id + 1)); } else id = 0; } g_static_mutex_unlock(&log_tags_lock); return id; } /* * log_tag_get_by_id * * Lookup a tag name by it's id. If the id is invalid * NULL is returned, otherwise a gchar * is returned * pointing to the name of the tag. * * The returned pointer should not be freed. * * @id: the tag id to lookup * */ const gchar * log_tags_get_by_id(LogTagId id) { gchar *name = NULL; g_static_mutex_lock(&log_tags_lock); if (id < log_tags_num) name = log_tags_list[id].name; g_static_mutex_unlock(&log_tags_lock); return name; } void log_tags_inc_counter(LogTagId id) { g_static_mutex_lock(&log_tags_lock); if (id < log_tags_num) stats_counter_inc(log_tags_list[id].counter); g_static_mutex_unlock(&log_tags_lock); } void log_tags_dec_counter(LogTagId id) { /* Reader lock because the log_tag_list is not written */ g_static_mutex_lock(&log_tags_lock); if (id < log_tags_num) stats_counter_dec(log_tags_list[id].counter); g_static_mutex_unlock(&log_tags_lock); } /* * NOTE: this is called at cfg_init() time to update the set of counters we * have. If stats-level is decreased, we should unregister everything we * had earlier. If increased we need to register them again. * * log_tags_get_by_name() will also try to register the counter for calls * that are _after_ cfg_init(). Early calls to log_tags_get_by_name() will * not see a proper stats-level() in the global variable here. Those will * get handled by this function. */ void log_tags_reinit_stats(void) { gint id; stats_lock(); for (id = 0; id < log_tags_num; id++) { const gchar *name = log_tags_list[id].name; StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_TAG, name, NULL ); if (stats_check_level(3)) stats_register_counter(3, &sc_key, SC_TYPE_PROCESSED, &log_tags_list[id].counter); else stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &log_tags_list[id].counter); } stats_unlock(); } void log_tags_global_init(void) { /* Necessary only in case of reinitialized tags */ g_static_mutex_lock(&log_tags_lock); log_tags_hash = g_hash_table_new(g_str_hash, g_str_equal); log_tags_list_size = 4; log_tags_num = 0; log_tags_list = g_new0(LogTag, log_tags_list_size); g_static_mutex_unlock(&log_tags_lock); } void log_tags_global_deinit(void) { gint i; g_static_mutex_lock(&log_tags_lock); g_hash_table_destroy(log_tags_hash); stats_lock(); StatsClusterKey sc_key; for (i = 0; i < log_tags_num; i++) { stats_cluster_logpipe_key_set(&sc_key, SCS_TAG, log_tags_list[i].name, NULL ); stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &log_tags_list[i].counter); g_free(log_tags_list[i].name); } stats_unlock(); log_tags_num = 0; g_free(log_tags_list); log_tags_list = NULL; log_tags_hash = NULL; g_static_mutex_unlock(&log_tags_lock); } syslog-ng-syslog-ng-3.13.2/lib/logmsg/tags.h000066400000000000000000000032311321171025300206010ustar00rootroot00000000000000/* * Copyright (c) 2009-2013 Balabit * Copyright (c) 2009 Marton Illes * Copyright (c) 2009-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TAGS_H_INCLUDED #define TAGS_H_INCLUDED #include "syslog-ng.h" typedef guint16 LogTagId; /* this is limited by the LogMessage structure, where a guint8 stores the * number of 32 bit ints, used to store the tags as a bitfield. 256 * 32 = * 8192. */ #if GLIB_SIZEOF_LONG == 4 #define LOG_TAGS_MAX 8192 #else #define LOG_TAGS_MAX 16384 #endif LogTagId log_tags_get_by_name(const gchar *name); const gchar *log_tags_get_by_id(LogTagId id); void log_tags_reinit_stats(void); void log_tags_global_init(void); void log_tags_global_deinit(void); void log_tags_inc_counter(LogTagId id); void log_tags_dec_counter(LogTagId id); #endif syslog-ng-syslog-ng-3.13.2/lib/logmsg/tests/000077500000000000000000000000001321171025300206355ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/logmsg/tests/Makefile.am000066400000000000000000000024261321171025300226750ustar00rootroot00000000000000lib_logmsg_tests_TESTS = \ lib/logmsg/tests/test_logmsg_serialize \ lib/logmsg/tests/test_timestamp_serialize \ lib/logmsg/tests/test_tags check_PROGRAMS += ${lib_logmsg_tests_TESTS} lib_logmsg_tests_test_timestamp_serialize_CFLAGS = $(TEST_CFLAGS) lib_logmsg_tests_test_timestamp_serialize_LDADD = $(TEST_LDADD) lib_logmsg_tests_test_logmsg_serialize_CFLAGS = $(TEST_CFLAGS) lib_logmsg_tests_test_logmsg_serialize_LDADD = $(TEST_LDADD) $(PREOPEN_SYSLOGFORMAT) lib_logmsg_tests_test_tags_CFLAGS = $(TEST_CFLAGS) lib_logmsg_tests_test_tags_LDADD = $(TEST_LDADD) if ENABLE_CRITERION lib_logmsg_tests_TESTS += \ lib/logmsg/tests/test_nvtable \ lib/logmsg/tests/test_gsockaddr_serialize \ lib/logmsg/tests/test_log_message \ lib/logmsg/tests/test_logmsg_ack lib_logmsg_tests_test_nvtable_CFLAGS = $(TEST_CFLAGS) lib_logmsg_tests_test_nvtable_LDADD = $(TEST_LDADD) lib_logmsg_tests_test_gsockaddr_serialize_CFLAGS = $(TEST_CFLAGS) lib_logmsg_tests_test_gsockaddr_serialize_LDADD = $(TEST_LDADD) lib_logmsg_tests_test_log_message_CFLAGS = $(TEST_CFLAGS) lib_logmsg_tests_test_log_message_LDADD = $(TEST_LDADD) lib_logmsg_tests_test_logmsg_ack_LDADD = $(TEST_LDADD) lib_logmsg_tests_test_logmsg_ack_CFLAGS = $(TEST_CFLAGS) endif syslog-ng-syslog-ng-3.13.2/lib/logmsg/tests/test_gsockaddr_serialize.c000066400000000000000000000132721321171025300260550ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2015 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include "apphook.h" #include "logmsg/gsockaddr-serialize.h" #include TestSuite(gsockaddr_serialize, .init = app_startup, .fini = app_shutdown); Test(gsockaddr_serialize, test_empty) { GString *stream = g_string_new(""); SerializeArchive *sa = serialize_string_archive_new(stream); GSockAddr *read_addr = NULL; cr_assert(g_sockaddr_serialize(sa, NULL), "failed to serialize empty GSockAddr"); cr_assert(g_sockaddr_deserialize(sa, &read_addr), "failed to read back empty GSockAddr"); cr_assert_null(read_addr, "deserialized GSockAddr should be empty (NULL)"); serialize_archive_free(sa); g_string_free(stream, TRUE); } Test(gsockaddr_serialize, test_inet) { GSockAddr *addr = g_sockaddr_inet_new("127.0.0.1", 5555); GSockAddr *read_addr = NULL; GString *stream = g_string_new(""); SerializeArchive *sa = serialize_string_archive_new(stream); cr_assert(g_sockaddr_serialize(sa, addr), "failed to serialize inet GSockAddr"); cr_assert(g_sockaddr_deserialize(sa, &read_addr), "failed to read back inet GSockAddr"); cr_assert_arr_eq(g_sockaddr_inet_get_sa(addr), g_sockaddr_inet_get_sa(read_addr), addr->salen); serialize_archive_free(sa); g_string_free(stream, TRUE); g_sockaddr_unref(addr); g_sockaddr_unref(read_addr); } #if SYSLOG_NG_ENABLE_IPV6 Test(gsockaddr_serialize, test_inet6) { GSockAddr *addr = g_sockaddr_inet6_new("::1", 5555); GSockAddr *read_addr = NULL; GString *stream = g_string_new(""); SerializeArchive *sa = serialize_string_archive_new(stream); cr_assert(g_sockaddr_serialize(sa, addr), "failed to serialize inet6 GSockAddr"); cr_assert(g_sockaddr_deserialize(sa, &read_addr), "failed to read back inet6 GSockAddr"); cr_assert_arr_eq(g_sockaddr_inet6_get_sa(addr), g_sockaddr_inet6_get_sa(read_addr), addr->salen); serialize_archive_free(sa); g_string_free(stream, TRUE); g_sockaddr_unref(addr); g_sockaddr_unref(read_addr); } #endif Test(gsockaddr_serialize, test_unix) { GSockAddr *addr = g_sockaddr_unix_new("testpath"); GSockAddr *read_addr = NULL; GString *stream = g_string_new(""); SerializeArchive *sa = serialize_string_archive_new(stream); cr_assert(g_sockaddr_serialize(sa, addr), "failed to serialize unix GSockAddr"); cr_assert(g_sockaddr_deserialize(sa, &read_addr), "failed to read back unix GSockAddr"); serialize_archive_free(sa); g_string_free(stream, TRUE); g_sockaddr_unref(addr); g_sockaddr_unref(read_addr); } Test(gsockaddr_serialize, test_inet_false) { GSockAddr *addr = g_sockaddr_inet_new("127.0.0.1", 5555); GSockAddr *read_addr = NULL; GString *stream = g_string_new(""); SerializeArchive *sa = serialize_string_archive_new(stream); cr_assert(g_sockaddr_serialize(sa, addr), "failed to serialize inet GSockAddr"); g_string_truncate(stream, 0); cr_assert_not(g_sockaddr_deserialize(sa, &read_addr), "SHOULD HAVE FAILED HERE"); serialize_archive_free(sa); sa = serialize_string_archive_new(stream); cr_assert(g_sockaddr_serialize(sa, addr), "failed to serialize inet GSockAddr"); g_string_truncate(stream, 2); cr_assert_not(g_sockaddr_deserialize(sa, &read_addr), "SHOULD BE FAILED_HERE"); serialize_archive_free(sa); g_string_free(stream, TRUE); g_sockaddr_unref(addr); g_sockaddr_unref(read_addr); } #if ENABLE_IPV6 Test(gsockaddr_serialize, test_inet6_false) { GSockAddr *addr = g_sockaddr_inet6_new("::1", 5555); GSockAddr *read_addr = NULL; GString *stream = g_string_new(""); SerializeArchive *sa = serialize_string_archive_new(stream); cr_assert(g_sockaddr_serialize(sa, addr), "failed to serialize inet6 GSockAddr"); g_string_truncate(stream, 0); cr_assert_not(g_sockaddr_deserialize(sa, &read_addr), "SHOULD HAVE FAILED HERE"); serialize_archive_free(sa); sa = serialize_string_archive_new(stream); cr_assert(g_sockaddr_serialize(sa, addr), "failed to serialize inet6 GSockAddr"); g_string_truncate(stream, 2); cr_assert_not(g_sockaddr_deserialize(sa, &read_addr), "SHOULD BE FAILED_HERE"); serialize_archive_free(sa); g_string_free(stream, TRUE); g_sockaddr_unref(addr); g_sockaddr_unref(read_addr); } #endif Test(gsockaddr_serialize, test_bad_family) { GSockAddr *addr = g_sockaddr_inet_new("127.0.0.1", 5555); GSockAddr *read_addr = NULL; guint16 bad_family = 0xFFFF; GString *stream = g_string_new(""); SerializeArchive *sa = serialize_string_archive_new(stream); cr_assert(g_sockaddr_serialize(sa, addr), "failed to serialize GSockAddr"); g_string_overwrite(stream, 0, (const gchar *)&bad_family); cr_assert_not(g_sockaddr_deserialize(sa, &read_addr), "SHOULD HAVE FAILED HERE"); serialize_archive_free(sa); g_string_free(stream, TRUE); g_sockaddr_unref(addr); g_sockaddr_unref(read_addr); } syslog-ng-syslog-ng-3.13.2/lib/logmsg/tests/test_log_message.c000066400000000000000000000432271321171025300243350ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include "msg_parse_lib.h" #include "apphook.h" #include "logpipe.h" #include "rcptid.h" #include "libtest/persist_lib.h" #include #include typedef struct _LogMessageTestParams { LogMessage *message; LogMessage *cloned_message; NVHandle nv_handle; NVHandle sd_handle; const gchar *tag_name; } LogMessageTestParams; static LogMessage * _construct_log_message(void) { const gchar *raw_msg = "foo"; LogMessage *msg; msg = log_msg_new(raw_msg, strlen(raw_msg), NULL, &parse_options); log_msg_set_value(msg, LM_V_HOST, raw_msg, -1); return msg; } static LogMessage * _construct_merge_base_message(void) { LogMessage *msg; msg = log_msg_new_empty(); log_msg_set_value_by_name(msg, "base", "basevalue", -1); log_msg_set_tag_by_name(msg, "basetag"); return msg; } static LogMessage * _construct_merged_message(const gchar *name, const gchar *value) { LogMessage *msg; msg = log_msg_new_empty(); log_msg_set_value_by_name(msg, name, value, -1); log_msg_set_tag_by_name(msg, "mergedtag"); return msg; } static void assert_log_msg_clear_clears_all_properties(LogMessage *message, NVHandle nv_handle, NVHandle sd_handle, const gchar *tag_name) { log_msg_clear(message); cr_assert_str_empty(log_msg_get_value(message, nv_handle, NULL), "Message still contains value after log_msg_clear"); cr_assert_str_empty(log_msg_get_value(message, sd_handle, NULL), "Message still contains sdata value after log_msg_clear"); cr_assert_null(message->saddr, "Message still contains an saddr after log_msg_clear"); cr_assert_not(log_msg_is_tag_by_name(message, tag_name), "Message still contains a valid tag after log_msg_clear"); } static void assert_sdata_value_with_seqnum_equals(LogMessage *msg, guint32 seq_num, const gchar *expected) { GString *result = g_string_sized_new(0); log_msg_append_format_sdata(msg, result, seq_num); cr_assert_str_eq(result->str, expected, "SDATA value does not match, '%s' vs '%s'", expected, result->str); g_string_free(result, TRUE); } static void assert_sdata_value_equals(LogMessage *msg, const gchar *expected) { assert_sdata_value_with_seqnum_equals(msg, 0, expected); } static LogMessageTestParams * log_message_test_params_new(void) { LogMessageTestParams *params = g_new0(LogMessageTestParams, 1); params->tag_name = "tag"; params->message = _construct_log_message(); params->nv_handle = log_msg_get_value_handle("foo"); params->sd_handle = log_msg_get_value_handle(".SDATA.foo.bar"); log_msg_set_value(params->message, params->nv_handle, "value", -1); log_msg_set_value(params->message, params->sd_handle, "value", -1); params->message->saddr = g_sockaddr_inet_new("1.2.3.4", 5050); log_msg_set_tag_by_name(params->message, params->tag_name); return params; } void log_message_test_params_free(LogMessageTestParams *params) { log_msg_unref(params->message); if (params->cloned_message) log_msg_unref(params->cloned_message); g_free(params); } LogMessage * log_message_test_params_clone_message(LogMessageTestParams *params) { LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; params->cloned_message = log_msg_clone_cow(params->message, &path_options); return params->cloned_message; } void setup(void) { app_startup(); init_and_load_syslogformat_module(); } void teardown(void) { deinit_syslogformat_module(); app_shutdown(); } TestSuite(log_message, .init = setup, .fini = teardown); Test(log_message, test_log_message_can_be_created_and_freed) { LogMessage *msg = _construct_log_message(); log_msg_unref(msg); } Test(log_message, test_log_message_can_be_cleared) { LogMessageTestParams *params = log_message_test_params_new(); log_message_test_params_clone_message(params); assert_log_msg_clear_clears_all_properties(params->message, params->nv_handle, params->sd_handle, params->tag_name); assert_log_msg_clear_clears_all_properties(params->cloned_message, params->nv_handle, params->sd_handle, params->tag_name); log_message_test_params_free(params); } Test(log_message, test_rcptid_is_automatically_assigned_to_a_newly_created_log_message) { LogMessage *msg; PersistState *state = clean_and_create_persist_state_for_test("test_values.persist"); rcptid_init(state, TRUE); msg = log_msg_new_empty(); cr_assert_eq(msg->rcptid, 1, "rcptid is not automatically set"); log_msg_unref(msg); commit_and_destroy_persist_state(state); rcptid_deinit(); } Test(log_message, test_log_message_merge_with_empty_context) { LogMessageTestParams *params = log_message_test_params_new(); LogMessage *context[] = {}; log_message_test_params_clone_message(params); log_msg_merge_context(params->message, context, 0); assert_log_messages_equal(params->message, params->cloned_message); log_message_test_params_free(params); } Test(log_message, test_log_message_merge_unset_value) { LogMessage *msg; GPtrArray *context = g_ptr_array_sized_new(0); msg = _construct_merge_base_message(); g_ptr_array_add(context, _construct_merged_message("merged", "mergedvalue")); log_msg_merge_context(msg, (LogMessage **) context->pdata, context->len); assert_log_message_value_by_name(msg, "base", "basevalue"); assert_log_message_value_by_name(msg, "merged", "mergedvalue"); g_ptr_array_foreach(context, (GFunc) log_msg_unref, NULL); g_ptr_array_free(context, TRUE); log_msg_unref(msg); } Test(log_message, test_log_message_merge_doesnt_overwrite_already_set_values) { LogMessage *msg; GPtrArray *context = g_ptr_array_sized_new(0); msg = _construct_merge_base_message(); g_ptr_array_add(context, _construct_merged_message("base", "mergedvalue")); log_msg_merge_context(msg, (LogMessage **) context->pdata, context->len); assert_log_message_value_by_name(msg, "base", "basevalue"); g_ptr_array_foreach(context, (GFunc) log_msg_unref, NULL); g_ptr_array_free(context, TRUE); log_msg_unref(msg); } Test(log_message, test_log_message_merge_merges_the_closest_value_in_the_context) { LogMessage *msg; GPtrArray *context = g_ptr_array_sized_new(0); msg = _construct_merge_base_message(); g_ptr_array_add(context, _construct_merged_message("merged", "mergedvalue1")); g_ptr_array_add(context, _construct_merged_message("merged", "mergedvalue2")); log_msg_merge_context(msg, (LogMessage **) context->pdata, context->len); assert_log_message_value_by_name(msg, "merged", "mergedvalue2"); g_ptr_array_foreach(context, (GFunc) log_msg_unref, NULL); g_ptr_array_free(context, TRUE); log_msg_unref(msg); } Test(log_message, test_log_message_merge_merges_from_all_messages_in_the_context) { LogMessage *msg; GPtrArray *context = g_ptr_array_sized_new(0); msg = _construct_merge_base_message(); g_ptr_array_add(context, _construct_merged_message("merged1", "mergedvalue1")); g_ptr_array_add(context, _construct_merged_message("merged2", "mergedvalue2")); g_ptr_array_add(context, _construct_merged_message("merged3", "mergedvalue3")); log_msg_merge_context(msg, (LogMessage **) context->pdata, context->len); assert_log_message_value_by_name(msg, "merged1", "mergedvalue1"); assert_log_message_value_by_name(msg, "merged2", "mergedvalue2"); assert_log_message_value_by_name(msg, "merged3", "mergedvalue3"); g_ptr_array_foreach(context, (GFunc) log_msg_unref, NULL); g_ptr_array_free(context, TRUE); log_msg_unref(msg); } Test(log_message, test_log_message_merge_leaves_base_tags_intact) { LogMessage *msg; GPtrArray *context = g_ptr_array_sized_new(0); msg = _construct_merge_base_message(); g_ptr_array_add(context, _construct_merged_message("merged1", "mergedvalue1")); log_msg_merge_context(msg, (LogMessage **) context->pdata, context->len); assert_log_message_has_tag(msg, "basetag"); assert_log_message_doesnt_have_tag(msg, "mergedtag"); g_ptr_array_foreach(context, (GFunc) log_msg_unref, NULL); g_ptr_array_free(context, TRUE); log_msg_unref(msg); } Test(log_message, test_log_msg_set_value_indirect_with_self_referencing_handle_results_in_a_nonindirect_value) { LogMessageTestParams *params = log_message_test_params_new(); gssize value_len; log_msg_set_value_indirect(params->message, params->nv_handle, params->nv_handle, 0, 0, 5); cr_assert_str_eq(log_msg_get_value(params->message, params->nv_handle, &value_len), "value", "indirect self-reference value doesn't match"); log_message_test_params_free(params); } Test(log_message, test_log_msg_get_value_with_time_related_macro) { LogMessage *msg; gssize value_len; NVHandle handle; const char *date_value; msg = log_msg_new_empty(); msg->timestamps[LM_TS_STAMP].tv_sec = 1389783444; msg->timestamps[LM_TS_STAMP].zone_offset = 3600; handle = log_msg_get_value_handle("ISODATE"); date_value = log_msg_get_value(msg, handle, &value_len); cr_assert_str_eq(date_value, "2014-01-15T11:57:24+01:00", "ISODATE macro value does not match! value=%s", date_value); log_msg_unref(msg); } Test(log_message, test_local_logmsg_created_with_the_right_flags_and_timestamps) { LogMessage *msg = log_msg_new_local(); gboolean are_equals = log_stamp_eq(&msg->timestamps[LM_TS_STAMP], &msg->timestamps[LM_TS_RECVD]); cr_assert_neq((msg->flags & LF_LOCAL), 0, "LogMessage created by log_msg_new_local() should have LF_LOCAL flag set"); cr_assert(are_equals, "The timestamps in a LogMessage created by log_msg_new_local() should be equals"); } Test(log_message, test_sdata_sanitize_keys) { LogMessage *msg; /* These keys looks strange, but JSON object can be parsed to SDATA, * so the key could contain any character, while the specification * does not declare any way to encode the the keys, just the values. * The goal is to have a syntactically valid syslog message. */ msg = log_msg_new_empty(); log_msg_set_value_by_name(msg, ".SDATA.foo.bar[0]", "value[0]", -1); assert_sdata_value_equals(msg, "[foo bar%5B0%5D=\"value[0\\]\"]"); log_msg_unref(msg); msg = log_msg_new_empty(); log_msg_set_value_by_name(msg, ".SDATA.foo.bácsi", "bácsi", -1); assert_sdata_value_equals(msg, "[foo b%C3%A1csi=\"bácsi\"]"); log_msg_unref(msg); msg = log_msg_new_empty(); log_msg_set_value_by_name(msg, ".SDATA.foo.sp ace", "sp ace", -1); assert_sdata_value_equals(msg, "[foo sp%20ace=\"sp ace\"]"); log_msg_unref(msg); msg = log_msg_new_empty(); log_msg_set_value_by_name(msg, ".SDATA.foo.eq=al", "eq=al", -1); assert_sdata_value_equals(msg, "[foo eq%3Dal=\"eq=al\"]"); log_msg_unref(msg); msg = log_msg_new_empty(); log_msg_set_value_by_name(msg, ".SDATA.foo.quo\"te", "quo\"te", -1); assert_sdata_value_equals(msg, "[foo quo%22te=\"quo\\\"te\"]"); log_msg_unref(msg); } Test(log_message, test_sdata_value_is_updated_by_sdata_name_value_pairs) { LogMessage *msg; msg = log_msg_new_empty(); log_msg_set_value_by_name(msg, ".SDATA.foo.bar1", "value", -1); assert_sdata_value_equals(msg, "[foo bar1=\"value\"]"); log_msg_set_value_by_name(msg, ".SDATA.foo.bar2", "value", -1); assert_sdata_value_equals(msg, "[foo bar1=\"value\" bar2=\"value\"]"); log_msg_set_value_by_name(msg, ".SDATA.foo.bar3", "value", -1); assert_sdata_value_equals(msg, "[foo bar1=\"value\" bar2=\"value\" bar3=\"value\"]"); log_msg_set_value_by_name(msg, ".SDATA.post.value1", "value", -1); assert_sdata_value_equals(msg, "[post value1=\"value\"][foo bar1=\"value\" bar2=\"value\" bar3=\"value\"]"); log_msg_set_value_by_name(msg, ".SDATA.post.value2", "value", -1); assert_sdata_value_equals(msg, "[post value1=\"value\" value2=\"value\"][foo bar1=\"value\" bar2=\"value\" bar3=\"value\"]"); log_msg_unref(msg); } Test(log_message, test_sdata_seqnum_adds_meta_sequence_id) { LogMessage *msg; msg = log_msg_new_empty(); log_msg_set_value_by_name(msg, ".SDATA.foo.bar1", "value", -1); log_msg_set_value_by_name(msg, ".SDATA.foo.bar2", "value", -1); log_msg_set_value_by_name(msg, ".SDATA.foo.bar3", "value", -1); assert_sdata_value_with_seqnum_equals(msg, 5, "[foo bar1=\"value\" bar2=\"value\" bar3=\"value\"][meta sequenceId=\"5\"]"); log_msg_set_value_by_name(msg, ".SDATA.meta.foobar", "value", -1); assert_sdata_value_with_seqnum_equals(msg, 6, "[meta sequenceId=\"6\" foobar=\"value\"][foo bar1=\"value\" bar2=\"value\" bar3=\"value\"]"); log_msg_unref(msg); } Test(log_message, test_sdata_value_omits_unset_values) { LogMessage *msg; msg = log_msg_new_empty(); log_msg_set_value_by_name(msg, ".SDATA.foo.bar1", "value", -1); log_msg_set_value_by_name(msg, ".SDATA.foo.bar2", "value", -1); log_msg_set_value_by_name(msg, ".SDATA.foo.bar3", "value", -1); assert_sdata_value_equals(msg, "[foo bar1=\"value\" bar2=\"value\" bar3=\"value\"]"); log_msg_unset_value_by_name(msg, ".SDATA.foo.bar2"); assert_sdata_value_equals(msg, "[foo bar1=\"value\" bar3=\"value\"]"); log_msg_unset_value_by_name(msg, ".SDATA.foo.bar1"); log_msg_unset_value_by_name(msg, ".SDATA.foo.bar3"); assert_sdata_value_equals(msg, ""); log_msg_unref(msg); } #define DEFUN_KEY_VALUE(name, key, value, size) \ gchar name ## _key[size]; \ gchar name ## _value[size]; \ name ## _key[size-1] = name ## _value[size-1] = 0; \ memset(name ## _key, key, sizeof(name ##_key)-1); \ memset(name ## _value, value, sizeof(name ##_value)-1); \ typedef struct { gssize nvtable_size_old; gssize nvtable_size_new; gssize msg_size_old; gssize msg_size_new; } sizes_t; static sizes_t add_key_value(LogMessage *msg, gchar *key, gchar *value) { sizes_t sizes; sizes.msg_size_old = log_msg_get_size(msg); sizes.nvtable_size_old = nv_table_get_memory_consumption(msg->payload); log_msg_set_value_by_name(msg, key, value, -1); sizes.nvtable_size_new = nv_table_get_memory_consumption(msg->payload); sizes.msg_size_new = log_msg_get_size(msg); return sizes; } static void test_with_sdata(LogMessage *msg, guint32 old_msg_size) { sizes_t sizes; gchar key_format[] = ".SDATA.%02d"; gchar key[] = ".SDATA.**"; gchar value[] = "AAAAAAA"; guint32 single_sdata_kv_size; guint32 sdata_payload_array_size; const char iter_length = 17; for (char i = 0; i < iter_length; i++) { g_sprintf(key, key_format, i); sizes = add_key_value(msg, key, value); single_sdata_kv_size = NV_ENTRY_DIRECT_HDR + NV_TABLE_BOUND(strlen(key)+1 + strlen(value)+1); /* i+1 is stored, but the sdata array size is calculated when adding the i-th */ sdata_payload_array_size = STRICT_ROUND_TO_NEXT_EIGHT(i) * sizeof(msg->sdata[0]); cr_assert_eq(old_msg_size + (i+1) * single_sdata_kv_size + sdata_payload_array_size, sizes.msg_size_new); } } #define SMALL_LENGTH 10 #define LARGE_LENGTH 256 Test(log_message, test_message_size) { LogMessage *msg = log_msg_new_empty(); sizes_t sizes; DEFUN_KEY_VALUE(small, 'C', 'D', SMALL_LENGTH); sizes = add_key_value(msg, small_key, small_value); // (SMALL_LENGTH-1)*'C'+'\0' + (SMALL_LENGTH-1)*'D'+'\0' guint32 entry_size = NV_ENTRY_DIRECT_HDR + NV_TABLE_BOUND(SMALL_LENGTH + SMALL_LENGTH); cr_assert_eq(sizes.nvtable_size_old + entry_size, sizes.nvtable_size_new); cr_assert_eq(sizes.msg_size_old + entry_size, sizes.msg_size_new); // Size increased because of nvtable guint32 msg_size = sizes.msg_size_new; log_msg_set_tag_by_name(msg, "test_tag_storage"); cr_assert(log_msg_is_tag_by_name(msg, "test_tag_storage")); cr_assert_eq(msg_size, log_msg_get_size(msg)); // Tag is not increased until tag id 65 char *tag_name = strdup("00tagname"); // (*8 to convert ot bits) + no need plus 1 bcause we already added one tag: test_tag_storage for (int i = 0; i < GLIB_SIZEOF_LONG*8; i++) { sprintf(tag_name, "%dtagname", i); log_msg_set_tag_by_name(msg, tag_name); } free(tag_name); cr_assert_eq(msg_size + 2*GLIB_SIZEOF_LONG, log_msg_get_size(msg)); DEFUN_KEY_VALUE(big, 'A', 'B', LARGE_LENGTH); sizes = add_key_value(msg, big_key, big_value); // nvtable is expanded entry_size = NV_ENTRY_DIRECT_HDR + NV_TABLE_BOUND(LARGE_LENGTH + LARGE_LENGTH); cr_assert_eq(sizes.nvtable_size_old + entry_size, sizes.nvtable_size_new); // but only increased by the entry cr_assert_eq(sizes.msg_size_old + entry_size, sizes.msg_size_new); // nvtable is doubled test_with_sdata(msg, sizes.msg_size_new); log_msg_unref(msg); } Test(log_message, when_get_indirect_value_with_null_value_len_abort_instead_of_sigsegv, .signal=SIGABRT) { LogMessageTestParams *params = log_message_test_params_new(); NVHandle indirect = log_msg_get_value_handle("INDIRECT"); log_msg_set_value_indirect(params->message, indirect, params->nv_handle, 0, 0, 5); log_msg_get_value(params->message, indirect, NULL); log_message_test_params_free(params); } syslog-ng-syslog-ng-3.13.2/lib/logmsg/tests/test_logmsg_ack.c000066400000000000000000000106271321171025300241540ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logmsg/logmsg.h" #include "apphook.h" #include "logpipe.h" #include #include struct _AckRecord { LogMessage *original; LogPathOptions path_options; gboolean acked; void (*init)(AckRecord *); void (*deinit)(AckRecord *); void (*ack_message)(LogMessage *lm, AckType ack_type); }; static void _init(AckRecord *self) { self->acked = FALSE; log_msg_ref(self->original); log_msg_refcache_start_producer(self->original); log_msg_add_ack(self->original, &self->path_options); log_msg_ref(self->original); log_msg_write_protect(self->original); } static void _deinit(AckRecord *self) { log_msg_drop(self->original, &self->path_options, AT_PROCESSED); log_msg_refcache_stop(); } static void _ack_message(LogMessage *msg, AckType type) { AckRecord *self = msg->ack_record; self->acked = TRUE; } static void ack_record_free(AckRecord *self) { log_msg_unref(self->original); g_free(self); } static AckRecord * ack_record_new(void) { AckRecord *self = g_new0(AckRecord, 1); self->init = _init; self->deinit = _deinit; self->ack_message = _ack_message; self->original = log_msg_new_empty(); self->original->ack_func = self->ack_message; self->original->ack_record = self; self->path_options.ack_needed = TRUE; return self; } static void setup(void) { app_startup(); } static void teardown(void) { app_shutdown(); } static LogMessage * create_clone(LogMessage *msg, LogPathOptions *path_options) { LogMessage *cloned = log_msg_ref(msg); cloned = log_msg_make_writable(&cloned, path_options); log_msg_add_ack(msg, path_options); return cloned; } TestSuite(msg_ack, .init = setup, .fini = teardown); Test(msg_ack, normal_ack) { AckRecord *t = ack_record_new(); t->init(t); t->deinit(t); cr_assert(t->acked); ack_record_free(t); } Test(msg_ack, clone_ack) { AckRecord *t = ack_record_new(); t->init(t); LogMessage *cloned = create_clone(t->original, &t->path_options); log_msg_drop(cloned, &t->path_options, AT_PROCESSED); cr_assert_not(t->acked); t->deinit(t); cr_assert(t->acked); ack_record_free(t); } struct nv_pair { const gchar *name; const gchar *value; }; ParameterizedTestParameters(msg_ack, test_cloned_clone) { static struct nv_pair params[] = { /* This ensures, that the clone message has own payload */ {"test", "value"}, /* Using these parameters the clone message won't has own payload */ {"", ""} }; size_t nb_params = sizeof (params) / sizeof (struct nv_pair); return cr_make_param_array(struct nv_pair, params, nb_params); } /* * This tests that the clone does not break the acknowledgement or the reference counting, * whether the cloned message has own payload or not */ ParameterizedTest(struct nv_pair *param, msg_ack, test_cloned_clone) { AckRecord *t = ack_record_new(); t->init(t); LogMessage *cloned = create_clone(t->original, &t->path_options); log_msg_set_value_by_name(cloned, param->name, param->value, -1); log_msg_write_protect(cloned); LogMessage *cloned_clone1 = create_clone(cloned, &t->path_options); LogMessage *cloned_clone2 = create_clone(cloned, &t->path_options); log_msg_drop(cloned_clone1, &t->path_options, AT_PROCESSED); cr_assert_not(t->acked); log_msg_drop(cloned_clone2, &t->path_options, AT_PROCESSED); cr_assert_not(t->acked); log_msg_drop(cloned, &t->path_options, AT_PROCESSED); cr_assert_not(t->acked); t->deinit(t); cr_assert(t->acked); ack_record_free(t); } syslog-ng-syslog-ng-3.13.2/lib/logmsg/tests/test_logmsg_serialize.c000066400000000000000000000246721321171025300254120ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 2015 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "stopwatch.h" #include "apphook.h" #include "cfg.h" #include "plugin.h" #include "logmsg/logmsg-serialize.h" GlobalConfig *cfg; #define RAW_MSG "<132>1 2006-10-29T01:59:59.156+01:00 mymachine evntslog - - [exampleSDID@0 iut=\"3\" eventSource=\"Application\"] An application event log entry..." #define ERROR_MSG "Failed at %s(%d)", __FILE__, __LINE__ MsgFormatOptions parse_options; unsigned char _serialized_pe_msg[] = { 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x43, 0xfd, 0x0f, 0x00, 0x02, 0x61, 0x60, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x56, 0xa2, 0x1e, 0xb7, 0x00, 0x0e, 0x89, 0x04, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x56, 0xa2, 0x1e, 0xb7, 0x00, 0x0e, 0x89, 0x04, 0x00, 0x00, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x01, 0x94, 0x00, 0x00, 0x01, 0x95, 0x00, 0x00, 0x01, 0x96, 0x00, 0x00, 0x01, 0x97, 0x32, 0x54, 0x56, 0x4e, 0x00, 0x00, 0x00, 0x01, 0xd4, 0x00, 0x00, 0x01, 0x4c, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x93, 0x00, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x94, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x01, 0x95, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x01, 0x96, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x01, 0x97, 0x00, 0x00, 0x00, 0xf8, 0xFC, 0x03, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x61, 0x61, 0x61, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x41, 0x6e, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2e, 0x53, 0x44, 0x41, 0x54, 0x41, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x53, 0x44, 0x49, 0x44, 0x40, 0x30, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x00, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x53, 0x44, 0x41, 0x54, 0x41, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x53, 0x44, 0x49, 0x44, 0x40, 0x30, 0x2e, 0x69, 0x75, 0x74, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x65, 0x76, 0x6e, 0x74, 0x73, 0x6c, 0x6f, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x79, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x53, 0x44, 0x41, 0x54, 0x41, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2e, 0x74, 0x7a, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2e, 0x53, 0x44, 0x41, 0x54, 0x41, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x51, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2e, 0x69, 0x73, 0x53, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x00, 0x30, 0x00, 0x00, 0x00 }; unsigned int _serialized_pe_msg_len = sizeof(_serialized_pe_msg); static void _alloc_dummy_values_to_change_handle_values_accross_restarts(void) { static gint iteration = 1; for (gint i = 0; i < iteration; i++) { gchar dummy_name[32]; g_snprintf(dummy_name, sizeof(dummy_name), "dummy%d", i); nv_registry_alloc_handle(logmsg_registry, dummy_name); } iteration *= 2; } static void _reset_log_msg_registry(void) { log_msg_registry_deinit(); log_msg_registry_init(); _alloc_dummy_values_to_change_handle_values_accross_restarts(); } static void _check_deserialized_message(LogMessage *msg, SerializeArchive *sa) { GString *output = g_string_new(""); LogTemplate *template = log_template_new(cfg, NULL); log_template_compile(template, "${ISODATE}", NULL); cfg->template_options.frac_digits = 3; log_template_append_format(template, msg, &cfg->template_options, LTZ_SEND, 0, NULL, output); assert_string(output->str, "2006-10-29T01:59:59.156+01:00", ERROR_MSG); assert_string(log_msg_get_value(msg, LM_V_HOST, NULL), "mymachine", ERROR_MSG); assert_string(log_msg_get_value(msg, LM_V_PROGRAM, NULL), "evntslog", ERROR_MSG); assert_string(log_msg_get_value(msg, LM_V_MESSAGE, NULL), "An application event log entry...", ERROR_MSG); assert_null(log_msg_get_value_if_set(msg, log_msg_get_value_handle("unset_value"), NULL), ERROR_MSG); assert_string(log_msg_get_value_by_name(msg, ".SDATA.exampleSDID@0.eventSource", NULL), "Application", ERROR_MSG); assert_guint16(msg->pri, 132, ERROR_MSG); log_template_unref(template); g_string_free(output, TRUE); } static LogMessage * _create_message_to_be_serialized(void) { parse_options.flags |= LP_SYSLOG_PROTOCOL; NVHandle test_handle = log_msg_get_value_handle("aaa"); LogMessage *msg = log_msg_new(RAW_MSG, strlen(RAW_MSG), NULL, &parse_options); log_msg_set_value(msg, test_handle, "test_value", -1); NVHandle indirect_handle = log_msg_get_value_handle("indirect_1"); log_msg_set_value_indirect(msg, indirect_handle, test_handle, 0, 5, 3); log_msg_set_value_by_name(msg, "unset_value", "foobar", -1); log_msg_unset_value_by_name(msg, "unset_value"); for (int i = 0; i < 32; i++) { gchar value_name[64]; g_snprintf(value_name, sizeof(value_name), ".SDATA.dynamic.field%d", i); log_msg_set_value_by_name(msg, value_name, "value", -1); g_snprintf(value_name, sizeof(value_name), ".normal.dynamic.field%d", i); log_msg_set_value_by_name(msg, value_name, "value", -1); } return msg; } static SerializeArchive * _serialize_message_for_test(GString *stream) { SerializeArchive *sa = serialize_string_archive_new(stream); LogMessage *msg = _create_message_to_be_serialized(); log_msg_serialize(msg, sa); log_msg_unref(msg); return sa; } static void test_serialize(void) { NVHandle indirect_handle = 0; gssize length = 0; GString *stream = g_string_new(""); SerializeArchive *sa = _serialize_message_for_test(stream); _reset_log_msg_registry(); LogMessage *msg = log_msg_new_empty(); assert_true(log_msg_deserialize(msg, sa), ERROR_MSG); /* we use nv_registry_get_handle() as it will not change the name-value * pair flags, whereas log_msg_get_value_handle() would */ NVHandle sdata_handle = nv_registry_get_handle(logmsg_registry, ".SDATA.exampleSDID@0.eventSource"); assert_true(sdata_handle != 0, "the .SDATA.exampleSDID@0.eventSource handle was not defined during deserialization"); assert_true(log_msg_is_handle_sdata(sdata_handle), "deserialized SDATA name-value pairs have to marked as such"); _check_deserialized_message(msg, sa); indirect_handle = log_msg_get_value_handle("indirect_1"); const gchar *indirect_value = log_msg_get_value(msg, indirect_handle, &length); assert_nstring(indirect_value, length, "val", 3, ERROR_MSG); log_msg_unref(msg); serialize_archive_free(sa); g_string_free(stream, TRUE); } static void test_pe_serialized_message(void) { GString serialized = {0}; serialized.allocated_len = 0; serialized.len = _serialized_pe_msg_len; serialized.str = (gchar *)_serialized_pe_msg; LogMessage *msg = log_msg_new_empty(); SerializeArchive *sa = serialize_string_archive_new(&serialized); _reset_log_msg_registry(); assert_true(log_msg_deserialize(msg, sa), ERROR_MSG); _check_deserialized_message(msg, sa); log_msg_unref(msg); serialize_archive_free(sa); } static void test_serialization_performance(void) { LogMessage *msg = _create_message_to_be_serialized(); GString *stream = g_string_sized_new(512); const int iterations = 100000; SerializeArchive *sa = serialize_string_archive_new(stream); start_stopwatch(); for (int i = 0; i < iterations; i++) { g_string_truncate(stream, 0); log_msg_serialize(msg, sa); } stop_stopwatch_and_display_result(iterations, "serializing %d times took", iterations); serialize_archive_free(sa); log_msg_unref(msg); g_string_free(stream, TRUE); } static void test_deserialization_performance(void) { GString *stream = g_string_sized_new(512); SerializeArchive *sa = _serialize_message_for_test(stream); const int iterations = 100000; LogMessage *msg = log_msg_new_empty(); start_stopwatch(); for (int i = 0; i < iterations; i++) { serialize_string_archive_reset(sa); log_msg_clear(msg); log_msg_deserialize(msg, sa); } stop_stopwatch_and_display_result(iterations, "serializing %d times took", iterations); serialize_archive_free(sa); log_msg_unref(msg); g_string_free(stream, TRUE); } int main(int argc, char **argv) { app_startup(); cfg = cfg_new_snippet(); cfg_load_module(cfg, "syslogformat"); msg_format_options_defaults(&parse_options); msg_format_options_init(&parse_options, cfg); test_serialize(); test_pe_serialized_message(); test_serialization_performance(); test_deserialization_performance(); cfg_free(cfg); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/logmsg/tests/test_nvtable.c000066400000000000000000001040041321171025300234720ustar00rootroot00000000000000/* * Copyright (c) 2009-2016 Balabit * Copyright (c) 2009-2016 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include "logmsg/nvtable.h" #include "apphook.h" #include "logmsg/logmsg.h" #include #include #include #define STATIC_VALUES 16 #define STATIC_HANDLE 1 #define STATIC_NAME "VAL1" #define DYN_HANDLE 17 #define DYN_NAME "VAL17" void assert_nvtable(NVTable *tab, NVHandle handle, gchar *expected_value, gssize expected_length) { const gchar *value; gssize length; value = nv_table_get_value(tab, handle, &length); cr_assert_eq(length, expected_length, "NVTable value mismatch, value=%.*s, expected=%.*s\n", (gint) length, value, (gint) expected_length, expected_value); cr_assert_arr_eq(value, expected_value, expected_length, "NVTable value mismatch, value=%.*s, expected=%.*s\n", (gint) length, value, (gint) expected_length, expected_value); } TestSuite(nvtable, .init = app_startup, .fini = app_shutdown); /* NVRegistry */ /* testcases: * * - static names will have the lowest numbered handles, starting with 1 * - registering the same name will always map to the same handle * - adding an alias and looking up an NV pair by alias should return the same handle * - NV pairs cannot have the zero-length string as a name * - NV pairs cannot have names longer than 255 characters * - no more than predefined number of NV pairs are supported * - */ #define TEST_NVHANDLE_MAX_VALUE 10 Test(nvtable, test_nv_registry) { NVRegistry *reg; gint i, j; NVHandle handle, prev_handle; const gchar *name; gssize len; const gchar *builtins[] = { "BUILTIN1", "BUILTIN2", "BUILTIN3", NULL }; reg = nv_registry_new(builtins, TEST_NVHANDLE_MAX_VALUE); for (i = 0; builtins[i]; i++) { handle = nv_registry_alloc_handle(reg, builtins[i]); cr_assert_eq(handle, (i+1)); name = nv_registry_get_handle_name(reg, handle, &len); cr_assert_str_eq(name, builtins[i]); cr_assert_eq(strlen(name), len); } for (i = 4; i < TEST_NVHANDLE_MAX_VALUE + 1; i++) { gchar dyn_name[16]; g_snprintf(dyn_name, sizeof(dyn_name), "DYN%05d", i); /* try to look up the same name multiple times */ prev_handle = 0; for (j = 0; j < 4; j++) { handle = nv_registry_alloc_handle(reg, dyn_name); g_assert(prev_handle == 0 || (handle == prev_handle)); prev_handle = handle; } name = nv_registry_get_handle_name(reg, handle, &len); g_assert(strcmp(name, dyn_name) == 0); g_assert(strlen(name) == len); g_snprintf(dyn_name, sizeof(dyn_name), "ALIAS%05d", i); nv_registry_add_alias(reg, handle, dyn_name); handle = nv_registry_alloc_handle(reg, dyn_name); g_assert(handle == prev_handle); } for (i = TEST_NVHANDLE_MAX_VALUE; i >= 4; i--) { gchar dyn_name[16]; g_snprintf(dyn_name, sizeof(dyn_name), "DYN%05d", i); /* try to look up the same name multiple times */ prev_handle = 0; for (j = 0; j < 4; j++) { handle = nv_registry_alloc_handle(reg, dyn_name); g_assert(prev_handle == 0 || (handle == prev_handle)); prev_handle = handle; } name = nv_registry_get_handle_name(reg, handle, &len); g_assert(strcmp(name, dyn_name) == 0); g_assert(strlen(name) == len); } handle = nv_registry_alloc_handle(reg, "too-many-values"); cr_assert_eq(handle, 0); nv_registry_free(reg); } /* * - NVTable direct values * - set/get static NV entries * - new NV entry * - entries that fit into the current NVTable * - entries that do not fit into the current NVTable * - overwrite direct NV entry * - value that fits into the current entry * - value that doesn't fit into the current entry, but fits into NVTable * - value that doesn't fit into the current entry and neither to NVTable * - overwrite indirect NV entry: not possible as static entries cannot be indirect * * - set/get dynamic NV entries * - new NV entry * - entries that fit into the current NVTable * - entries that do not fit into the current NVTable * - overwrite direct NV entry * - value that fits into the current entry * - value that doesn't fit into the current entry, but fits into NVTable * - value that doesn't fit into the current entry and neither to NVTable * - overwrite indirect NV entry * - value that fits into the current entry * - value that doesn't fit into the current entry, but fits into NVTable * - value that doesn't fit into the current entry and neither to NVTable */ Test(nvtable, test_nvtable_direct) { NVTable *tab; NVHandle handle; gchar value[1024], name[16]; gboolean success; gint i; guint16 used; for (i = 0; i < sizeof(value); i++) value[i] = 'A' + (i % 26); handle = STATIC_HANDLE; do { g_snprintf(name, sizeof(name), "VAL%d", handle); /*************************************************************/ /* new NV entry */ /*************************************************************/ /* one that fits */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, handle, name, strlen(name), value, 128, NULL); cr_assert(success); assert_nvtable(tab, handle, value, 128); nv_table_unref(tab); /* one that is too large */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, handle, name, strlen(name), value, 512, NULL); cr_assert_not(success); nv_table_unref(tab); /*************************************************************/ /* overwrite NV entry */ /*************************************************************/ /* one that fits, but realloced size wouldn't fit */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 192); success = nv_table_add_value(tab, handle, name, strlen(name), value, 128, NULL); cr_assert(success); used = tab->used; success = nv_table_add_value(tab, handle, name, strlen(name), value, 64, NULL); cr_assert(success); cr_assert_eq(tab->used, used); assert_nvtable(tab, handle, value, 64); nv_table_unref(tab); /* one that is too large for the given entry, but still fits in the NVTable */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, handle, name, strlen(name), value, 64, NULL); cr_assert(success); used = tab->used; success = nv_table_add_value(tab, handle, name, strlen(name), value, 128, NULL); cr_assert(success); cr_assert_gt(tab->used, used); assert_nvtable(tab, handle, value, 128); nv_table_unref(tab); /* one that is too large for the given entry, and also for the NVTable */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, handle, name, strlen(name), value, 64, NULL); cr_assert(success); success = nv_table_add_value(tab, handle, name, strlen(name), value, 512, NULL); cr_assert_not(success); assert_nvtable(tab, handle, value, 64); nv_table_unref(tab); /*************************************************************/ /* overwrite indirect entry */ /*************************************************************/ if (handle > STATIC_VALUES) { /* we can only test this with dynamic entries */ /* setup code: add static and a dynamic-indirect entry */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 192); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); used = tab->used; /* store a direct entry over the indirect one */ success = nv_table_add_value(tab, handle, name, strlen(name), value, 1, NULL); cr_assert(success); cr_assert_eq(tab->used, used); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, handle, value, 1); nv_table_unref(tab); /* setup code: add static and a dynamic-indirect entry */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 64, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 63, 0 }, NULL); cr_assert(success); used = tab->used; /* store a direct entry over the indirect one, we don't fit in the allocated space */ success = nv_table_add_value(tab, handle, name, strlen(name), value, 128, NULL); cr_assert(success); cr_assert_gt(tab->used, used); assert_nvtable(tab, STATIC_HANDLE, value, 64); assert_nvtable(tab, handle, value, 128); nv_table_unref(tab); /* setup code: add static and a dynamic-indirect entry */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 64, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 62, 0 }, NULL); cr_assert(success); used = tab->used; /* store a direct entry over the indirect one, we don't fit in the allocated space */ success = nv_table_add_value(tab, handle, name, strlen(name), value, 256, NULL); cr_assert_not(success); assert_nvtable(tab, STATIC_HANDLE, value, 64); assert_nvtable(tab, handle, value + 1, 62); nv_table_unref(tab); } handle += STATIC_VALUES; } while (handle < 2 * STATIC_VALUES); } /* * - indirect values * - indirect static values are not possible * - set/get dynamic NV entries that refer to direct entries * - new NV entry * - entries that fit into the current NVTable * - entries that do not fit into the current NVTable * - overwrite indirect NV entry * - value always fits to a current NV entry, no other cases * - overwrite direct NV entry * - value that fits into the current entry * - value that doesn't fit into the current entry, but fits into NVTable * - value that doesn't fit into the current entry and neither to NVTable * - set/get dynamic NV entries that refer to indirect entry, they become direct entries * - new NV entry * - entries that fit into the current NVTable * - entries that do not fit into the current NVTable * - overwrite indirect NV entry * - value that fits into the current entry * - value that doesn't fit into the current entry, but fits into NVTable * - value that doesn't fit into the current entry and neither to NVTable * - overwrite direct NV entry * - value that fits into the current entry * - value that doesn't fit into the current entry, but fits into NVTable * - value that doesn't fit into the current entry and neither to NVTable * - set/get dynamic NV entries that refer to a non-existant entry * - */ Test(nvtable, test_nvtable_indirect) { NVTable *tab; NVHandle handle; gchar value[1024], name[16]; gboolean success; gint i; guint16 used; for (i = 0; i < sizeof(value); i++) value[i] = 'A' + (i % 26); handle = DYN_HANDLE+1; g_snprintf(name, sizeof(name), "VAL%d", handle); fprintf(stderr, "Testing indirect values, name: %s, handle: %d\n", name, handle); /*************************************************************/ /*************************************************************/ /* indirect entries that refer to direct entries */ /*************************************************************/ /*************************************************************/ /*************************************************************/ /* new NV entry */ /*************************************************************/ /* one that fits */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 192); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, handle, value + 1, 126); nv_table_unref(tab); /* one that is too large */ /* NOTE: the sizing of the NVTable can easily be broken, it is sized to make it possible to store one direct entry */ tab = nv_table_new(STATIC_VALUES, 0, 138+3); // direct: +3 success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert_not(success); nv_table_unref(tab); /*************************************************************/ /* overwrite NV entry */ /*************************************************************/ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 192); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); used = tab->used; success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 62, 0 }, NULL); cr_assert(success); cr_assert_eq(used, tab->used); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, handle, value + 1, 62); nv_table_unref(tab); /*************************************************************/ /* overwrite direct entry */ /*************************************************************/ /* the new entry fits to the space allocated to the old */ /* setup code: add static and a dynamic-direct entry */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value(tab, handle, name, strlen(name), value, 64, NULL); cr_assert(success); used = tab->used; success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); cr_assert_eq(tab->used, used); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, handle, value + 1, 126); nv_table_unref(tab); /* the new entry will not fit to the space allocated to the old */ /* setup code: add static and a dynamic-direct entry */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value(tab, handle, name, strlen(name), value, 1, NULL); cr_assert(success); used = tab->used; success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); cr_assert_gt(tab->used, used); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, handle, value + 1, 126); nv_table_unref(tab); /* the new entry will not fit to the space allocated to the old and neither to the NVTable */ /* setup code: add static and a dynamic-direct entry */ tab = nv_table_new(STATIC_VALUES, 1, 154+3+4); // direct: +3, indirect: +4 success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value(tab, handle, name, strlen(name), value, 1, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert_not(success); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, handle, value, 1); nv_table_unref(tab); /*************************************************************/ /*************************************************************/ /* indirect entries that refer to indirect entries */ /*************************************************************/ /*************************************************************/ /*************************************************************/ /* new NV entry */ /*************************************************************/ /* one that fits */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, DYN_HANDLE, DYN_NAME, strlen(DYN_NAME), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { DYN_HANDLE, 1, 122, 0 }, NULL); cr_assert(success); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, DYN_HANDLE, value + 1, 126); assert_nvtable(tab, handle, value + 2, 122); nv_table_unref(tab); /* one that is too large */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 192); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, DYN_HANDLE, DYN_NAME, strlen(DYN_NAME), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { DYN_HANDLE, 1, 122, 0 }, NULL); cr_assert_not(success); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, DYN_HANDLE, value + 1, 126); assert_nvtable(tab, handle, "", 0); nv_table_unref(tab); /*************************************************************/ /* overwrite indirect NV entry */ /*************************************************************/ /* we fit to the space of the old */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, DYN_HANDLE, DYN_NAME, strlen(DYN_NAME), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); used = tab->used; success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { DYN_HANDLE, 1, 1, 0 }, NULL); cr_assert(success); cr_assert_eq(tab->used, used); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, DYN_HANDLE, value + 1, 126); assert_nvtable(tab, handle, value + 2, 1); nv_table_unref(tab); /* the new entry will not fit to the space allocated to the old */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, DYN_HANDLE, DYN_NAME, strlen(DYN_NAME), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); used = tab->used; success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { DYN_HANDLE, 1, 16, 0 }, NULL); cr_assert(success); cr_assert_gt(tab->used, used); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, DYN_HANDLE, value + 1, 126); assert_nvtable(tab, handle, value + 2, 16); nv_table_unref(tab); /* one that is too large */ tab = nv_table_new(STATIC_VALUES, 4, 256); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, DYN_HANDLE, DYN_NAME, strlen(DYN_NAME), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); used = tab->used; success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { DYN_HANDLE, 1, 124, 0 }, NULL); cr_assert_not(success); cr_assert_eq(tab->used, used); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, DYN_HANDLE, value + 1, 126); assert_nvtable(tab, handle, value + 1, 126); nv_table_unref(tab); /*************************************************************/ /* overwrite direct NV entry */ /*************************************************************/ /* we fit to the space of the old */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, DYN_HANDLE, DYN_NAME, strlen(DYN_NAME), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); success = nv_table_add_value(tab, handle, name, strlen(name), value, 64, NULL); cr_assert(success); used = tab->used; success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { DYN_HANDLE, 1, 16, 0 }, NULL); cr_assert(success); cr_assert_eq(tab->used, used); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, DYN_HANDLE, value + 1, 126); assert_nvtable(tab, handle, value + 2, 16); nv_table_unref(tab); /* the new entry will not fit to the space allocated to the old */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, DYN_HANDLE, DYN_NAME, strlen(DYN_NAME), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); success = nv_table_add_value(tab, handle, name, strlen(name), value, 16, NULL); cr_assert(success); used = tab->used; success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { DYN_HANDLE, 1, 32, 0 }, NULL); cr_assert(success); cr_assert_gt(tab->used, used); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, DYN_HANDLE, value + 1, 126); assert_nvtable(tab, handle, value + 2, 32); nv_table_unref(tab); /* one that is too large */ tab = nv_table_new(STATIC_VALUES, 4, 256); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, DYN_HANDLE, DYN_NAME, strlen(DYN_NAME), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); success = nv_table_add_value(tab, handle, name, strlen(name), value, 16, NULL); cr_assert(success); used = tab->used; success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { DYN_HANDLE, 1, 124, 0 }, NULL); cr_assert_not(success); cr_assert_eq(tab->used, used); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, DYN_HANDLE, value + 1, 126); assert_nvtable(tab, handle, value, 16); nv_table_unref(tab); /*************************************************************/ /* indirect that refers to non-existant entry */ /*************************************************************/ /* one that fits */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 192); used = tab->used; success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); cr_assert_eq(used, tab->used); assert_nvtable(tab, STATIC_HANDLE, "", 0); assert_nvtable(tab, handle, "", 0); nv_table_unref(tab); } /* * * - other corner cases * - set zero length value in direct value * - add a zero-length value to non-existing entry * - add a zero-length value to an existing entry that is not zero-length * - add a zero-length value to an existing entry that is zero-length * - set zero length value in an indirect value * * - change an entry that is referenced by other entries */ Test(nvtable, test_nvtable_others) { NVTable *tab; NVHandle handle; gchar value[1024], name[16]; gboolean success; gint i; for (i = 0; i < sizeof(value); i++) value[i] = 'A' + (i % 26); handle = DYN_HANDLE+1; g_snprintf(name, sizeof(name), "VAL%d", handle); fprintf(stderr, "Testing other cases, name: %s, handle: %d\n", name, handle); /* one that fits */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 256); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value + 32, 32, NULL); cr_assert(success); assert_nvtable(tab, STATIC_HANDLE, value + 32, 32); assert_nvtable(tab, handle, value + 1, 126); nv_table_unref(tab); /* one that doesn't fit */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 192); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value, 128, NULL); cr_assert(success); success = nv_table_add_value_indirect(tab, handle, name, strlen(name), &(NVReferencedSlice) { STATIC_HANDLE, 1, 126, 0 }, NULL); cr_assert(success); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, 4, value + 32, 32, NULL); cr_assert_not(success); assert_nvtable(tab, STATIC_HANDLE, value, 128); assert_nvtable(tab, handle, value + 1, 126); nv_table_unref(tab); } Test(nvtable, test_nvtable_lookup) { NVTable *tab; NVHandle handle; gchar name[16]; gboolean success; gint i; NVHandle handles[100]; gint x; srand(time(NULL)); for (x = 0; x < 100; x++) { /* test dynamic lookup */ tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 4096); for (i = 0; i < 100; i++) { do { handle = rand() & 0x8FFF; } while (handle == 0); g_snprintf(name, sizeof(name), "VAL%d", handle); success = nv_table_add_value(tab, handle, name, strlen(name), name, strlen(name), NULL); g_assert(success); handles[i] = handle; } for (i = 99; i >= 0; i--) { handle = handles[i]; g_snprintf(name, sizeof(name), "VAL%d", handle); assert_nvtable(tab, handles[i], name, strlen(name)); g_assert(nv_table_is_value_set(tab, handles[i])); } cr_assert_not(nv_table_is_value_set(tab, 0xFE00)); nv_table_unref(tab); } } Test(nvtable, test_nvtable_clone_grows_the_cloned_structure) { NVTable *tab, *tab_clone; gboolean success; tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 64); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, strlen(STATIC_NAME), "value", 5, NULL); cr_assert(success); assert_nvtable(tab, STATIC_HANDLE, "value", 5); tab_clone = nv_table_clone(tab, 64); assert_nvtable(tab_clone, STATIC_HANDLE, "value", 5); cr_assert_lt(tab->size, tab_clone->size); nv_table_unref(tab_clone); nv_table_unref(tab); } Test(nvtable, test_nvtable_clone_cannot_grow_nvtable_larger_than_nvtable_max_bytes) { NVTable *tab, *tab_clone; gboolean success; tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, NV_TABLE_MAX_BYTES - 1024); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, strlen(STATIC_NAME), "value", 5, NULL); cr_assert(success); assert_nvtable(tab, STATIC_HANDLE, "value", 5); tab_clone = nv_table_clone(tab, 2048); assert_nvtable(tab_clone, STATIC_HANDLE, "value", 5); cr_assert_lt(tab->size, tab_clone->size); cr_assert_leq(tab_clone->size, NV_TABLE_MAX_BYTES); nv_table_unref(tab_clone); nv_table_unref(tab); } Test(nvtable, test_nvtable_realloc_doubles_nvtable_size) { NVTable *tab; gboolean success; gsize old_size; tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 1024); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, strlen(STATIC_NAME), "value", 5, NULL); cr_assert(success); assert_nvtable(tab, STATIC_HANDLE, "value", 5); old_size = tab->size; cr_assert(nv_table_realloc(tab, &tab)); cr_assert_geq(tab->size, old_size * 2); assert_nvtable(tab, STATIC_HANDLE, "value", 5); nv_table_unref(tab); } Test(nvtable, test_nvtable_realloc_sets_size_to_nv_table_max_bytes_at_most) { NVTable *tab; gboolean success; gsize old_size; tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, NV_TABLE_MAX_BYTES - 1024); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, strlen(STATIC_NAME), "value", 5, NULL); cr_assert(success); assert_nvtable(tab, STATIC_HANDLE, "value", 5); old_size = tab->size; cr_assert(nv_table_realloc(tab, &tab)); cr_assert_gt(tab->size, old_size); cr_assert_leq(tab->size, NV_TABLE_MAX_BYTES); assert_nvtable(tab, STATIC_HANDLE, "value", 5); nv_table_unref(tab); } Test(nvtable, test_nvtable_realloc_fails_if_size_is_at_maximum) { NVTable *tab; gboolean success; tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, NV_TABLE_MAX_BYTES); success = nv_table_add_value(tab, STATIC_HANDLE, STATIC_NAME, strlen(STATIC_NAME), "value", 5, NULL); cr_assert(success); assert_nvtable(tab, STATIC_HANDLE, "value", 5); cr_assert_not(nv_table_realloc(tab, &tab)); cr_assert_eq(tab->size, NV_TABLE_MAX_BYTES); assert_nvtable(tab, STATIC_HANDLE, "value", 5); nv_table_unref(tab); } Test(nvtable, test_nvtable_realloc_leaves_original_intact_if_there_are_multiple_references) { NVTable *tab_ref1, *tab_ref2; gboolean success; gsize old_size; tab_ref1 = nv_table_new(STATIC_VALUES, STATIC_VALUES, 1024); tab_ref2 = nv_table_ref(tab_ref1); success = nv_table_add_value(tab_ref1, STATIC_HANDLE, STATIC_NAME, strlen(STATIC_NAME), "value", 5, NULL); cr_assert(success); assert_nvtable(tab_ref1, STATIC_HANDLE, "value", 5); assert_nvtable(tab_ref2, STATIC_HANDLE, "value", 5); old_size = tab_ref1->size; cr_assert(nv_table_realloc(tab_ref2, &tab_ref2)); cr_assert_eq(tab_ref1->size, old_size); cr_assert_geq(tab_ref2->size, old_size); assert_nvtable(tab_ref1, STATIC_HANDLE, "value", 5); assert_nvtable(tab_ref2, STATIC_HANDLE, "value", 5); nv_table_unref(tab_ref1); nv_table_unref(tab_ref2); } Test(nvtable, test_nvtable_unset_values) { NVTable *tab; gssize size = 9999; const gchar *value; gboolean success; tab = nv_table_new(STATIC_VALUES, STATIC_VALUES, 1024); value = nv_table_get_value(tab, DYN_HANDLE, &size); cr_assert_not_null(value); cr_assert_eq(value[0], 0); cr_assert_eq(size, 0); size = 1; value = nv_table_get_value_if_set(tab, DYN_HANDLE, &size); cr_assert_null(value); cr_assert_eq(size, 0); success = nv_table_add_value(tab, DYN_HANDLE, DYN_NAME, strlen(DYN_NAME), "foo", 3, NULL); cr_assert(success); size = 1; value = nv_table_get_value_if_set(tab, DYN_HANDLE, &size); cr_assert_not_null(value); cr_assert_arr_eq(value, "foo", 3); cr_assert_eq(size, 3); nv_table_unset_value(tab, DYN_HANDLE); size = 1; value = nv_table_get_value_if_set(tab, DYN_HANDLE, &size); cr_assert_null(value); cr_assert_eq(size, 0); nv_table_unref(tab); } syslog-ng-syslog-ng-3.13.2/lib/logmsg/tests/test_tags.c000066400000000000000000000121431321171025300227770ustar00rootroot00000000000000/* * Copyright (c) 2009-2016 Balabit * Copyright (c) 2009 Marton Illes * Copyright (c) 2009-2016 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "apphook.h" #include "logmsg/logmsg.h" #include "messages.h" #include "filter/filter-tags.h" #include #include #include #include #include gboolean fail = FALSE; gboolean verbose = FALSE; #define NUM_TAGS 8159 #define FILTER_TAGS 100 #define test_fail(fmt, args...) \ do {\ printf(fmt, ##args); \ fail = TRUE; \ } while (0); #define test_msg(fmt, args...) \ do { \ if (verbose) printf(fmt, ##args); \ } while (0); gchar * get_tag_by_id(LogTagId id) { return g_strdup_printf("tags%d", id); } void test_tags(void) { guint i, check; guint id; gchar *name; const gchar *tag_name; for (check = 0; check < 2; check++) for (i = 0; i < NUM_TAGS; i++) { name = get_tag_by_id(i); id = log_tags_get_by_name(name); test_msg("%s tag %s %d\n", check ? "Checking" : "Adding", name, id); if (id != i) test_fail("Invalid tag id %d %s\n", id, name); g_free(name); } for (i = 0; i < NUM_TAGS; i++) { name = get_tag_by_id(i); tag_name = log_tags_get_by_id(i); test_msg("Looking up tag by id %d %s(%s)\n", i, tag_name, name); if (tag_name) { if (!g_str_equal(tag_name, name)) test_fail("Bad tag name for id %d %s (%s)\n", i, tag_name, name); } else test_fail("Error looking up tag by id %d %s\n", i, name); g_free(name); } for (i = NUM_TAGS; i < (NUM_TAGS + 3); i++) { tag_name = log_tags_get_by_id(i); test_msg("Looking up tag by invalid id %d\n", i); if (tag_name) test_fail("Found tag name for invalid id %d %s\n", i, tag_name); } } void test_msg_tags(void) { gchar *name; gint i, set; test_msg("=== LogMessage tests ===\n"); LogMessage *msg = log_msg_new_empty(); for (set = 1; set != -1; set--) { for (i = NUM_TAGS; i > -1; i--) { name = get_tag_by_id(i); if (set) log_msg_set_tag_by_name(msg, name); else log_msg_clear_tag_by_name(msg, name); test_msg("%s tag %d %s\n", set ? "Setting" : "Clearing", i, name); if (set ^ log_msg_is_tag_by_id(msg, i)) test_fail("Tag is %sset now (by id) %d\n", set ? "not " : "", i); g_free(name); } } log_msg_unref(msg); msg = log_msg_new_empty(); for (set = 1; set != -1; set--) { for (i = 0; i < NUM_TAGS; i++) { name = get_tag_by_id(i); if (set) log_msg_set_tag_by_name(msg, name); else log_msg_clear_tag_by_name(msg, name); test_msg("%s tag %d %s\n", set ? "Setting" : "Clearing", i, name); if (set ^ log_msg_is_tag_by_id(msg, i)) test_fail("Tag is %sset now (by id) %d\n", set ? "not " : "", i); if (set && i < sizeof(gulong) * 8 && msg->num_tags != 0) test_fail("Small IDs are set which should be stored in-line but num_tags is non-zero"); g_free(name); } } log_msg_unref(msg); } void test_filters(gboolean not) { LogMessage *msg = log_msg_new_empty(); FilterExprNode *f = filter_tags_new(NULL); guint i; GList *l = NULL; test_msg("=== filter tests %s===\n", not ? "not " : ""); for (i = 1; i < FILTER_TAGS; i += 3) l = g_list_prepend(l, get_tag_by_id(i)); filter_tags_add(f, l); f->comp = not; for (i = 0; i < FILTER_TAGS; i++) { test_msg("Testing filter, message has tag %d\n", i); log_msg_set_tag_by_id(msg, i); if (((i % 3 == 1) ^ filter_expr_eval(f, msg)) ^ not) test_fail("Failed to match message by tag %d\n", i); test_msg("Testing filter, message no tag\n"); log_msg_clear_tag_by_id(msg, i); if (filter_expr_eval(f, msg) ^ not) test_fail("Failed to match message with no tags\n"); } filter_expr_unref(f); log_msg_unref(msg); } int main(int argc, char *argv[]) { app_startup(); if (argc > 1) verbose = TRUE; msg_init(TRUE); test_tags(); test_msg_tags(); test_filters(FALSE); test_filters(TRUE); app_shutdown(); return (fail ? 1 : 0); } syslog-ng-syslog-ng-3.13.2/lib/logmsg/tests/test_timestamp_serialize.c000066400000000000000000000063741321171025300261240ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 2015 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "apphook.h" #include "logmsg/logmsg.h" #include "logmsg/timestamp-serialize.h" #define PREPARE_TEST LogStamp input_timestamps[LM_TS_MAX]; \ LogStamp output_timestamps[LM_TS_MAX]; \ GString *stream = g_string_new(""); \ input_timestamps[LM_TS_STAMP].tv_sec = 1; \ input_timestamps[LM_TS_STAMP].tv_usec = 2; \ input_timestamps[LM_TS_STAMP].zone_offset = 3; \ input_timestamps[LM_TS_RECVD].tv_sec = 4; \ input_timestamps[LM_TS_RECVD].tv_usec = 5; \ input_timestamps[LM_TS_RECVD].zone_offset = 6; \ SerializeArchive *sa = serialize_string_archive_new(stream); #define CLEAN_TEST serialize_archive_free(sa); \ g_string_free(stream, TRUE); static void test_normal_working(void) { PREPARE_TEST assert_true(timestamp_serialize(sa, input_timestamps), "Failed to serialize timestamps"); assert_true(timestamp_deserialize(sa, output_timestamps), "Failed to deserialize timestamps"); assert_nstring((const gchar *)input_timestamps, sizeof(input_timestamps), (const gchar *)output_timestamps, sizeof(output_timestamps), "The serialized and the deserialized timestamps are not equal"); CLEAN_TEST } static void test_derializing_injured_timestamp(void) { PREPARE_TEST assert_true(timestamp_serialize(sa, input_timestamps), "Failed to serialize timestamps"); g_string_truncate(stream, 0); assert_false(timestamp_deserialize(sa, output_timestamps), "Should be failed"); serialize_archive_free(sa); sa = serialize_string_archive_new(stream); assert_true(timestamp_serialize(sa, input_timestamps), "Failed to serialize timestamps"); g_string_truncate(stream, sizeof(guint64)); assert_false(timestamp_deserialize(sa, output_timestamps), "Should be failed"); serialize_archive_free(sa); sa = serialize_string_archive_new(stream); assert_true(timestamp_serialize(sa, input_timestamps), "Failed to serialize timestamps"); g_string_truncate(stream, sizeof(guint64) + sizeof(guint32)); assert_false(timestamp_deserialize(sa, output_timestamps), "Should be failed"); CLEAN_TEST } int main(int argc, char **argv) { app_startup(); test_normal_working(); start_grabbing_messages(); test_derializing_injured_timestamp(); stop_grabbing_messages(); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/logmsg/timestamp-serialize.c000066400000000000000000000043341321171025300236330ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 2015 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "timestamp-serialize.h" static gboolean _write_log_stamp(SerializeArchive *sa, LogStamp *stamp) { return serialize_write_uint64(sa, stamp->tv_sec) && serialize_write_uint32(sa, stamp->tv_usec) && serialize_write_uint32(sa, stamp->zone_offset); } static gboolean _read_log_stamp(SerializeArchive *sa, LogStamp *stamp) { guint64 val64; guint32 val; if (!serialize_read_uint64(sa, &val64)) return FALSE; stamp->tv_sec = (gint64) val64; if (!serialize_read_uint32(sa, &val)) return FALSE; stamp->tv_usec = val; if (!serialize_read_uint32(sa, &val)) return FALSE; stamp->zone_offset = (gint) val; return TRUE; } gboolean timestamp_serialize(SerializeArchive *sa, LogStamp *timestamps) { LogStamp additional_timestamp; return _write_log_stamp(sa, ×tamps[LM_TS_STAMP]) && _write_log_stamp(sa, ×tamps[LM_TS_RECVD]) && _write_log_stamp(sa, &additional_timestamp); } gboolean timestamp_deserialize(SerializeArchive *sa, LogStamp *timestamps) { LogStamp additional_timestamp = {0}; return _read_log_stamp(sa, ×tamps[LM_TS_STAMP]) && _read_log_stamp(sa, ×tamps[LM_TS_RECVD]) && _read_log_stamp(sa, &additional_timestamp); } syslog-ng-syslog-ng-3.13.2/lib/logmsg/timestamp-serialize.h000066400000000000000000000024201321171025300236320ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 2015 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TIMESTAMP_SERIALIZE_H #define TIMESTAMP_SERIALIZE_H #include "logmsg/logmsg.h" #include "serialize.h" gboolean timestamp_serialize(SerializeArchive *sa, LogStamp *timestamps); gboolean timestamp_deserialize(SerializeArchive *sa, LogStamp *timestamps); #endif syslog-ng-syslog-ng-3.13.2/lib/logpipe.c000066400000000000000000000061061321171025300200110ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logpipe.h" #include "cfg-tree.h" gboolean (*pipe_single_step_hook)(LogPipe *pipe, LogMessage *msg, const LogPathOptions *path_options); EVTTAG * log_pipe_location_tag(LogPipe *pipe) { return log_expr_node_location_tag(pipe->expr_node); } void log_pipe_init_instance(LogPipe *self, GlobalConfig *cfg) { g_atomic_counter_set(&self->ref_cnt, 1); self->cfg = cfg; self->pipe_next = NULL; self->persist_name = NULL; self->plugin_name = NULL; /* NOTE: queue == NULL means that this pipe simply forwards the * message along the pipeline, e.g. like it has called * log_msg_forward_msg. Since this is a common case, it is better * inlined (than to use an indirect call) for performance. */ self->queue = NULL; self->free_fn = log_pipe_free_method; } LogPipe * log_pipe_new(GlobalConfig *cfg) { LogPipe *self = g_new0(LogPipe, 1); log_pipe_init_instance(self, cfg); return self; } void log_pipe_free_method(LogPipe *self) { ; } LogPipe * log_pipe_ref(LogPipe *self) { g_assert(!self || g_atomic_counter_get(&self->ref_cnt) > 0); if (self) { g_atomic_counter_inc(&self->ref_cnt); } return self; } static void _free(LogPipe *self) { if (self->free_fn) self->free_fn(self); g_free(self->plugin_name); g_free(self); } void log_pipe_unref(LogPipe *self) { g_assert(!self || g_atomic_counter_get(&self->ref_cnt)); if (self && (g_atomic_counter_dec_and_test(&self->ref_cnt))) { _free(self); } } void log_pipe_forward_notify(LogPipe *self, gint notify_code, gpointer user_data) { log_pipe_notify(self->pipe_next, notify_code, user_data); } void log_pipe_set_persist_name(LogPipe *self, const gchar *persist_name) { g_free((gpointer)self->persist_name); self->persist_name = persist_name; } const gchar * log_pipe_get_persist_name(const LogPipe *self) { return (self->generate_persist_name != NULL) ? self->generate_persist_name(self) : self->persist_name; } #ifdef __linux__ void __log_pipe_forward_msg(LogPipe *self, LogMessage *msg, const LogPathOptions *path_options) __attribute__((alias("log_pipe_forward_msg"))); #endif syslog-ng-syslog-ng-3.13.2/lib/logpipe.h000066400000000000000000000304671321171025300200250ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPIPE_H_INCLUDED #define LOGPIPE_H_INCLUDED #include "syslog-ng.h" #include "logmsg/logmsg.h" #include "cfg.h" #include "atomic.h" #include "messages.h" /* notify code values */ #define NC_CLOSE 1 #define NC_READ_ERROR 2 #define NC_WRITE_ERROR 3 #define NC_FILE_MOVED 4 #define NC_FILE_EOF 5 #define NC_REOPEN_REQUIRED 6 /* indicates that the LogPipe was initialized */ #define PIF_INITIALIZED 0x0001 /* indicates that this LogPipe got cloned into the tree already */ #define PIF_INLINED 0x0002 /* log statement flags that are copied to the head of a branch */ #define PIF_BRANCH_FINAL 0x0004 #define PIF_BRANCH_FALLBACK 0x0008 #define PIF_BRANCH_PROPERTIES (PIF_BRANCH_FINAL + PIF_BRANCH_FALLBACK) /* branch starting with this pipe wants hard flow control */ #define PIF_HARD_FLOW_CONTROL 0x0010 /* this pipe is a source for messages, it is not meant to be used to * forward messages, syslog-ng will only use these pipes for the * left-hand side of the processing graph, e.g. no other pipes may be * sending messages to these pipes and these are expected to generate * messages "automatically". */ #define PIF_SOURCE 0x0020 /* private flags range, to be used by other LogPipe instances for their own purposes */ #define PIF_PRIVATE(x) ((x) << 16) /** * * Processing pipeline * * Within syslog-ng, the user configuration is converted into a tree-like * structure. It's node in this tree is a LogPipe object responsible for * queueing message towards the destination. Each node is free to * drop/transform the message it receives. * * The center.c module contains code that transforms the configuration * into the log processing tree. Each log statement in user configuration * becomes a linked list of pipes, then each source, referenced by the * is piped into the newly created pipe. * * Something like this: * * log statement: * mpx | filter | parser | dest1 | dest2 | dest3 * * source1 -> log statement1 * |-> log statement2 * * E.g. each source is sending to each log path it was referenced from. Each * item in the log path is a pipe, which receives messages and forwards it * at its discretion. Filters are pipes too, which lose data. Destinations * are piping their output to the next element on the pipeline. This * basically means that the pipeline is a wired representation of the user * configuration without having to loop through configuration data. * * Reference counting * * The pipes do not reference each other through their pipe_next member, * simply because there'd be too much reference loops to care about. * Instead pipe_next is a borrowed reference, which is assumed to be valid * as long as the configuration is not freed. * * Flow control * * Flow control is the mechanism used to control the message rate between * input/output sides of syslog-ng in order to avoid message loss. If the * two sides were independent, the input side could well receive messages * at a much higher rate than the destination is able to cope with. * * This is implemented by allocating a per-source window (similar to a TCP * window), which can be "filled" by the source without the danger of * output queue overflow. Also, whenever a message is processed by the * destination it invokes an ACK, which in turn increments the window size. * * This basically boils down to the following: * * the source is free to receive as much messages as fits into its window * * whenever the destination has processed a message, this is signalled * to freeing up a lot in its window * * if the message is full, the source is suspended, no further messages * are received. * * This controls the message rate but doesn't completely ruin throughput, * as the source has some space without being suspended, as suspension and * resuming action takes considerable amount of time (mostly latency, but * CPU is certainly also used). * * There are currently two forms of flow control: * * hard flow control * * soft flow control * * The first is the form of flow control present in earlier syslog-ng * versions and was renamed as "hard" in order to differentiate from the * other form. Hard means that the source is completely suspended until * the destination indeed processed a message. If the network is down, * the disk is full, the source will not accept messages. * * Soft flow control was introduced when syslog-ng became threaded and the * earlier priority based behaviour couldn't be mimiced any other way. * Soft flow control cannot be configured, it is automatically used by * file destinations if "hard" flow control is not enabled by the user. * Soft flow control means that flow is only controlled as long as the * destination is writable, if an error occurs (disk full, etc) messages * get dropped on the floor. But as long as the destination is writable, * the destination rate controls the source rate as well. * * The behaviour in non-threaded syslog-ng was, that destinations were * prioritized over sources, and whenever a destination was writable, * sources were implicitly suspended. This is not easily implementable by * threads and ivykis, thus this alternative mechanism was created. * * Please note that soft-flow-control is a somewhat stronger guarantee * than the earlier behaviour, therefore it is currently only used for * destination files. * * Plugin overrides * * Various methods can be overridden by external objects within * LogPipe and derived classes. The aim of this functionality to * make it possible to attach new functions to a LogPipe at runtime. * * For example, it'd make sense to implement the "suppress" * functionality as such plugin, which is currently implemented in * LogWriter, and in case a non-LogWriter destination would need it, * then a separate implementation would be needed. * * The way to override a method by an external object is as follows: * * - it should save the current value of the method address (for * example "queue" for the queue method), and the associated * user_data pointer (queue_data in this case) * * - it should change the pointer pointing to the relevant method to * its own code (e.g. change "queue" in LogPipe) **/ struct _LogPathOptions { /* an acknowledgement is "passed" to this path, an ACK is still * needed to close the window slot. This was called "flow-control" * and meant both of these things: the user requested * flags(flow-control), _AND_ an acknowledgement was needed. With * the latest change, the one below specifies the user option, * while the "ack is still needed" condition is stored in * ack_needed. */ gboolean ack_needed; /* The user has requested flow-control on this processing path, * which means that the destination should invoke log_msg_ack() * after it has completed processing it (e.g. after sending to the * actual destination, possibly after confirmation if the transport * supports that). If flow-control is not requested, destinations * are permitted to call log_msg_ack() early (e.g. at queue time). * * This is initially FALSE and can be set to TRUE anywhere _before_ * the destination driver, which will actually carry out the * required action. */ gboolean flow_control_requested; gboolean *matched; }; #define LOG_PATH_OPTIONS_INIT { TRUE, FALSE, NULL } struct _LogPipe { GAtomicCounter ref_cnt; gint32 flags; GlobalConfig *cfg; LogExprNode *expr_node; LogPipe *pipe_next; StatsCounterItem *discarded_messages; const gchar *persist_name; /* user_data pointer of the "queue" method in case it is overridden by a plugin, see the explanation in the comment on the top. */ gpointer queue_data; void (*queue)(LogPipe *self, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data); gchar *plugin_name; gboolean (*init)(LogPipe *self); gboolean (*deinit)(LogPipe *self); const gchar *(*generate_persist_name)(const LogPipe *self); /* clone this pipe when used in multiple locations in the processing * pipe-line. If it contains state, it should behave as if it was * the same instance, otherwise it can be a copy. */ LogPipe *(*clone)(LogPipe *self); void (*free_fn)(LogPipe *self); void (*notify)(LogPipe *self, gint notify_code, gpointer user_data); }; extern gboolean (*pipe_single_step_hook)(LogPipe *pipe, LogMessage *msg, const LogPathOptions *path_options); LogPipe *log_pipe_ref(LogPipe *self); void log_pipe_unref(LogPipe *self); LogPipe *log_pipe_new(GlobalConfig *cfg); void log_pipe_init_instance(LogPipe *self, GlobalConfig *cfg); void log_pipe_forward_notify(LogPipe *self, gint notify_code, gpointer user_data); EVTTAG *log_pipe_location_tag(LogPipe *pipe); static inline GlobalConfig * log_pipe_get_config(LogPipe *s) { return s->cfg; } static inline void log_pipe_set_config(LogPipe *s, GlobalConfig *cfg) { s->cfg = cfg; } static inline void log_pipe_reset_config(LogPipe *s) { log_pipe_set_config(s, NULL); } static inline gboolean log_pipe_init(LogPipe *s) { if (!(s->flags & PIF_INITIALIZED)) { if (!s->init || s->init(s)) { s->flags |= PIF_INITIALIZED; return TRUE; } return FALSE; } return TRUE; } static inline gboolean log_pipe_deinit(LogPipe *s) { if ((s->flags & PIF_INITIALIZED)) { if (!s->deinit || s->deinit(s)) { s->flags &= ~PIF_INITIALIZED; return TRUE; } return FALSE; } return TRUE; } static inline void log_pipe_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options); static inline void log_pipe_forward_msg(LogPipe *self, LogMessage *msg, const LogPathOptions *path_options) { if (self->pipe_next) { log_pipe_queue(self->pipe_next, msg, path_options); } else { log_msg_drop(msg, path_options, AT_PROCESSED); } } static inline void log_pipe_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options) { g_assert((s->flags & PIF_INITIALIZED) != 0); if (G_UNLIKELY(pipe_single_step_hook)) { if (!pipe_single_step_hook(s, msg, path_options)) { log_msg_drop(msg, path_options, AT_PROCESSED); return; } } if (G_UNLIKELY(s->flags & (PIF_HARD_FLOW_CONTROL))) { LogPathOptions local_path_options = *path_options; local_path_options.flow_control_requested = 1; path_options = &local_path_options; if (G_UNLIKELY(debug_flag)) { msg_debug("Requesting flow control", log_pipe_location_tag(s)); } } if (s->queue) { s->queue(s, msg, path_options, s->queue_data); } else { log_pipe_forward_msg(s, msg, path_options); } } static inline LogPipe * log_pipe_clone(LogPipe *self) { if (self->clone) return self->clone(self); return NULL; } static inline void log_pipe_notify(LogPipe *s, gint notify_code, gpointer user_data) { if (s->notify) s->notify(s, notify_code, user_data); } static inline void log_pipe_append(LogPipe *s, LogPipe *next) { s->pipe_next = next; } void log_pipe_set_persist_name(LogPipe *self, const gchar *persist_name); const gchar * log_pipe_get_persist_name(const LogPipe *self); void log_pipe_free_method(LogPipe *s); #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/000077500000000000000000000000001321171025300200505ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/logproto/CMakeLists.txt000066400000000000000000000017671321171025300226230ustar00rootroot00000000000000set(LOGPROTO_HEADERS logproto/logproto-client.h logproto/logproto-server.h logproto/logproto-buffered-server.h logproto/logproto-dgram-server.h logproto/logproto-framed-client.h logproto/logproto-framed-server.h logproto/logproto-text-client.h logproto/logproto-text-server.h logproto/logproto-indented-multiline-server.h logproto/logproto-regexp-multiline-server.h logproto/logproto-record-server.h logproto/logproto-builtins.h logproto/logproto.h PARENT_SCOPE) set(LOGPROTO_SOURCES logproto/logproto-client.c logproto/logproto-server.c logproto/logproto-buffered-server.c logproto/logproto-dgram-server.c logproto/logproto-framed-client.c logproto/logproto-framed-server.c logproto/logproto-text-client.c logproto/logproto-text-server.c logproto/logproto-indented-multiline-server.c logproto/logproto-regexp-multiline-server.c logproto/logproto-record-server.c logproto/logproto-builtins.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/logproto/Makefile.am000066400000000000000000000023251321171025300221060ustar00rootroot00000000000000logprotoincludedir = ${pkgincludedir}/logproto logprotoinclude_HEADERS = \ lib/logproto/logproto-client.h \ lib/logproto/logproto-server.h \ lib/logproto/logproto-buffered-server.h \ lib/logproto/logproto-dgram-server.h \ lib/logproto/logproto-framed-client.h \ lib/logproto/logproto-framed-server.h \ lib/logproto/logproto-text-client.h \ lib/logproto/logproto-text-server.h \ lib/logproto/logproto-indented-multiline-server.h \ lib/logproto/logproto-regexp-multiline-server.h \ lib/logproto/logproto-multiline-server.h \ lib/logproto/logproto-record-server.h \ lib/logproto/logproto-builtins.h \ lib/logproto/logproto.h logproto_sources = \ lib/logproto/logproto-client.c \ lib/logproto/logproto-server.c \ lib/logproto/logproto-buffered-server.c \ lib/logproto/logproto-dgram-server.c \ lib/logproto/logproto-framed-client.c \ lib/logproto/logproto-framed-server.c \ lib/logproto/logproto-text-client.c \ lib/logproto/logproto-text-server.c \ lib/logproto/logproto-indented-multiline-server.c \ lib/logproto/logproto-regexp-multiline-server.c \ lib/logproto/logproto-multiline-server.c \ lib/logproto/logproto-record-server.c \ lib/logproto/logproto-builtins.c include lib/logproto/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-buffered-server.c000066400000000000000000000745771321171025300251710ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto-buffered-server.h" #include "messages.h" #include "serialize.h" #include "compat/string.h" #include #include #include #include typedef struct _BufferedServerBookmarkData { PersistEntryHandle persist_handle; gint32 pending_buffer_pos; gint64 pending_raw_stream_pos; gint32 pending_raw_buffer_size; } BufferedServerBookmarkData; LogProtoBufferedServerState * log_proto_buffered_server_get_state(LogProtoBufferedServer *self) { if (self->persist_state) { g_assert(self->persist_handle != 0); return persist_state_map_entry(self->persist_state, self->persist_handle); } if (G_UNLIKELY(!self->state1)) { self->state1 = g_new0(LogProtoBufferedServerState, 1); } return self->state1; } void log_proto_buffered_server_put_state(LogProtoBufferedServer *self) { if (self->persist_state && self->persist_handle) persist_state_unmap_entry(self->persist_state, self->persist_handle); } static gboolean log_proto_buffered_server_convert_from_raw(LogProtoBufferedServer *self, const guchar *raw_buffer, gsize raw_buffer_len) { /* some data was read */ gsize avail_in = raw_buffer_len; gsize avail_out; gchar *out; gint ret = -1; gboolean success = FALSE; LogProtoBufferedServerState *state = log_proto_buffered_server_get_state(self); do { avail_out = state->buffer_size - state->pending_buffer_end; out = (gchar *) self->buffer + state->pending_buffer_end; ret = g_iconv(self->convert, (gchar **) &raw_buffer, &avail_in, (gchar **) &out, &avail_out); if (ret == (gsize) -1) { switch (errno) { case EINVAL: if (self->stream_based) { /* Incomplete text, do not report an error, rather try to read again */ state->pending_buffer_end = state->buffer_size - avail_out; if (avail_in > 0) { if (avail_in > sizeof(state->raw_buffer_leftover)) { msg_error("Invalid byte sequence, the remaining raw buffer is larger than the supported leftover size", evt_tag_str("encoding", self->super.options->encoding), evt_tag_int("avail_in", avail_in), evt_tag_int("leftover_size", sizeof(state->raw_buffer_leftover))); goto error; } memcpy(state->raw_buffer_leftover, raw_buffer, avail_in); state->raw_buffer_leftover_size = avail_in; state->raw_buffer_size -= avail_in; msg_trace("Leftover characters remained after conversion, delaying message until another chunk arrives", evt_tag_str("encoding", self->super.options->encoding), evt_tag_int("avail_in", avail_in)); goto success; } } else { msg_error("Byte sequence too short, cannot convert an individual frame in its entirety", evt_tag_str("encoding", self->super.options->encoding), evt_tag_int("avail_in", avail_in)); goto error; } break; case E2BIG: state->pending_buffer_end = state->buffer_size - avail_out; /* extend the buffer */ if (state->buffer_size < self->super.options->max_buffer_size) { state->buffer_size *= 2; if (state->buffer_size > self->super.options->max_buffer_size) state->buffer_size = self->super.options->max_buffer_size; self->buffer = g_realloc(self->buffer, state->buffer_size); /* recalculate the out pointer, and add what we have now */ ret = -1; } else { msg_error("Incoming byte stream requires a too large conversion buffer, probably invalid character sequence", evt_tag_str("encoding", self->super.options->encoding), evt_tag_printf("buffer", "%.*s", (gint) state->pending_buffer_end, self->buffer)); goto error; } break; case EILSEQ: default: msg_notice("Invalid byte sequence or other error while converting input, skipping character", evt_tag_str("encoding", self->super.options->encoding), evt_tag_printf("char", "0x%02x", *(guchar *) raw_buffer)); goto error; } } else { state->pending_buffer_end = state->buffer_size - avail_out; } } while (avail_in > 0); success: success = TRUE; error: log_proto_buffered_server_put_state(self); return success; } static void log_proto_buffered_server_apply_state(LogProtoBufferedServer *self, PersistEntryHandle handle, const gchar *persist_name) { struct stat st; gint64 ofs = 0; LogProtoBufferedServerState *state; gint fd; fd = self->super.transport->fd; self->persist_handle = handle; if (fstat(fd, &st) < 0) return; state = log_proto_buffered_server_get_state(self); if (!self->buffer) { self->buffer = g_malloc(state->buffer_size); } state->pending_buffer_end = 0; if (state->file_inode && state->file_inode == st.st_ino && state->file_size <= st.st_size && state->raw_stream_pos <= st.st_size) { ofs = state->raw_stream_pos; lseek(fd, ofs, SEEK_SET); } else { if (state->file_inode) { /* the stored state does not match the current file */ msg_notice("The current log file has a mismatching size/inode information, restarting from the beginning", evt_tag_str("state", persist_name), evt_tag_int("stored_inode", state->file_inode), evt_tag_int("cur_file_inode", st.st_ino), evt_tag_int("stored_size", state->file_size), evt_tag_int("cur_file_size", st.st_size), evt_tag_int("raw_stream_pos", state->raw_stream_pos)); } goto error; } if (state->raw_buffer_size) { gssize rc; guchar *raw_buffer; if (!self->super.options->encoding) { /* no conversion, we read directly into our buffer */ if (state->raw_buffer_size > state->buffer_size) { msg_notice("Invalid LogProtoBufferedServerState.raw_buffer_size, larger than buffer_size and no encoding is set, restarting from the beginning", evt_tag_str("state", persist_name), evt_tag_int("raw_buffer_size", state->raw_buffer_size), evt_tag_int("buffer_size", state->buffer_size), evt_tag_int("init_buffer_size", self->super.options->init_buffer_size)); goto error; } raw_buffer = self->buffer; } else { if (state->raw_buffer_size > self->super.options->max_buffer_size) { msg_notice("Invalid LogProtoBufferedServerState.raw_buffer_size, larger than max_buffer_size, restarting from the beginning", evt_tag_str("state", persist_name), evt_tag_int("raw_buffer_size", state->raw_buffer_size), evt_tag_int("init_buffer_size", self->super.options->init_buffer_size), evt_tag_int("max_buffer_size", self->super.options->max_buffer_size)); goto error; } raw_buffer = g_alloca(state->raw_buffer_size); } rc = log_transport_read(self->super.transport, raw_buffer, state->raw_buffer_size, NULL); if (rc != state->raw_buffer_size) { msg_notice("Error re-reading buffer contents of the file to be continued, restarting from the beginning", evt_tag_str("state", persist_name)); goto error; } state->pending_buffer_end = 0; if (self->super.options->encoding) { if (!log_proto_buffered_server_convert_from_raw(self, raw_buffer, rc)) { msg_notice("Error re-converting buffer contents of the file to be continued, restarting from the beginning", evt_tag_str("state", persist_name)); goto error; } } else { state->pending_buffer_end += rc; } if (state->buffer_pos > state->pending_buffer_end) { msg_notice("Converted buffer contents is smaller than the current buffer position, starting from the beginning of the buffer, some lines may be duplicated", evt_tag_str("state", persist_name)); state->buffer_pos = state->pending_buffer_pos = 0; } self->fetch_state = LPBSF_FETCHING_FROM_BUFFER; } else { /* although we do have buffer position information, but the * complete contents of the buffer is already processed, instead * of reading and then dropping it, position the file after the * indicated block */ state->raw_stream_pos += state->raw_buffer_size; ofs = state->raw_stream_pos; state->raw_buffer_size = 0; state->buffer_pos = state->pending_buffer_end = 0; lseek(fd, state->raw_stream_pos, SEEK_SET); } goto exit; error: ofs = 0; state->buffer_pos = 0; state->pending_buffer_end = 0; state->__deprecated_buffer_cached_eol = 0; state->raw_stream_pos = 0; state->raw_buffer_size = 0; state->raw_buffer_leftover_size = 0; lseek(fd, 0, SEEK_SET); exit: state->file_inode = st.st_ino; state->file_size = st.st_size; state->raw_stream_pos = ofs; state->pending_buffer_pos = state->buffer_pos; state->pending_raw_stream_pos = state->raw_stream_pos; state->pending_raw_buffer_size = state->raw_buffer_size; state->__deprecated_buffer_cached_eol = 0; state = NULL; log_proto_buffered_server_put_state(self); } static PersistEntryHandle log_proto_buffered_server_alloc_state(LogProtoBufferedServer *self, PersistState *persist_state, const gchar *persist_name) { LogProtoBufferedServerState *state; PersistEntryHandle handle; handle = persist_state_alloc_entry(persist_state, persist_name, sizeof(LogProtoBufferedServerState)); if (handle) { state = persist_state_map_entry(persist_state, handle); state->header.version = 0; state->header.big_endian = (G_BYTE_ORDER == G_BIG_ENDIAN); persist_state_unmap_entry(persist_state, handle); } return handle; } static gboolean log_proto_buffered_server_convert_state(LogProtoBufferedServer *self, guint8 persist_version, gpointer old_state, gsize old_state_size, LogProtoBufferedServerState *state) { if (persist_version <= 2) { state->header.version = 0; state->file_inode = 0; state->raw_stream_pos = strtoll((gchar *) old_state, NULL, 10); state->file_size = 0; return TRUE; } else if (persist_version == 3) { SerializeArchive *archive; guint32 read_length; gint64 cur_size; gint64 cur_inode; gint64 cur_pos; guint16 version; gchar *buffer; gsize buffer_len; cur_inode = -1; cur_pos = 0; cur_size = 0; version = 0; archive = serialize_buffer_archive_new(old_state, old_state_size); /* NOTE: the v23 conversion code adds an extra length field which we * need to read out. */ g_assert(serialize_read_uint32(archive, &read_length) && read_length == old_state_size - sizeof(read_length)); /* original v3 format starts here */ if (!serialize_read_uint16(archive, &version) || version != 0) { msg_error("Internal error restoring log reader state, stored data has incorrect version", evt_tag_int("version", version)); goto error_converting_v3; } if (!serialize_read_uint64(archive, (guint64 *) &cur_pos) || !serialize_read_uint64(archive, (guint64 *) &cur_inode) || !serialize_read_uint64(archive, (guint64 *) &cur_size)) { msg_error("Internal error restoring information about the current file position, restarting from the beginning"); goto error_converting_v3; } if (!serialize_read_uint16(archive, &version) || version != 0) { msg_error("Internal error, protocol state has incorrect version", evt_tag_int("version", version)); goto error_converting_v3; } if (!serialize_read_cstring(archive, &buffer, &buffer_len)) { msg_error("Internal error, error reading buffer contents", evt_tag_int("version", version)); goto error_converting_v3; } if (!self->buffer || state->buffer_size < buffer_len) { gsize buffer_size = MAX(self->super.options->init_buffer_size, buffer_len); self->buffer = g_realloc(self->buffer, buffer_size); } serialize_archive_free(archive); memcpy(self->buffer, buffer, buffer_len); state->buffer_pos = 0; state->pending_buffer_end = buffer_len; g_free(buffer); state->header.version = 0; state->file_inode = cur_inode; state->raw_stream_pos = cur_pos; state->file_size = cur_size; return TRUE; error_converting_v3: serialize_archive_free(archive); } return FALSE; } gboolean log_proto_buffered_server_restart_with_state(LogProtoServer *s, PersistState *persist_state, const gchar *persist_name) { LogProtoBufferedServer *self = (LogProtoBufferedServer *) s; guint8 persist_version; PersistEntryHandle old_state_handle; gpointer old_state; gsize old_state_size; PersistEntryHandle new_state_handle = 0; gpointer new_state = NULL; gboolean success; self->persist_state = persist_state; old_state_handle = persist_state_lookup_entry(persist_state, persist_name, &old_state_size, &persist_version); if (!old_state_handle) { new_state_handle = log_proto_buffered_server_alloc_state(self, persist_state, persist_name); if (!new_state_handle) goto fallback_non_persistent; log_proto_buffered_server_apply_state(self, new_state_handle, persist_name); return TRUE; } if (persist_version < 4) { new_state_handle = log_proto_buffered_server_alloc_state(self, persist_state, persist_name); if (!new_state_handle) goto fallback_non_persistent; old_state = persist_state_map_entry(persist_state, old_state_handle); new_state = persist_state_map_entry(persist_state, new_state_handle); success = log_proto_buffered_server_convert_state(self, persist_version, old_state, old_state_size, new_state); persist_state_unmap_entry(persist_state, old_state_handle); persist_state_unmap_entry(persist_state, new_state_handle); /* we're using the newly allocated state structure regardless if * conversion succeeded. If the conversion went wrong then * new_state is still in its freshly initialized form since the * convert function will not touch the state in the error * branches. */ log_proto_buffered_server_apply_state(self, new_state_handle, persist_name); return success; } else if (persist_version == 4) { LogProtoBufferedServerState *state; old_state = persist_state_map_entry(persist_state, old_state_handle); state = old_state; if ((state->header.big_endian && G_BYTE_ORDER == G_LITTLE_ENDIAN) || (!state->header.big_endian && G_BYTE_ORDER == G_BIG_ENDIAN)) { /* byte order conversion in order to avoid the hassle with scattered byte order conversions in the code */ state->header.big_endian = !state->header.big_endian; state->buffer_pos = GUINT32_SWAP_LE_BE(state->buffer_pos); state->pending_buffer_pos = GUINT32_SWAP_LE_BE(state->pending_buffer_pos); state->pending_buffer_end = GUINT32_SWAP_LE_BE(state->pending_buffer_end); state->buffer_size = GUINT32_SWAP_LE_BE(state->buffer_size); state->raw_stream_pos = GUINT64_SWAP_LE_BE(state->raw_stream_pos); state->raw_buffer_size = GUINT32_SWAP_LE_BE(state->raw_buffer_size); state->pending_raw_stream_pos = GUINT64_SWAP_LE_BE(state->pending_raw_stream_pos); state->pending_raw_buffer_size = GUINT32_SWAP_LE_BE(state->pending_raw_buffer_size); state->file_size = GUINT64_SWAP_LE_BE(state->file_size); state->file_inode = GUINT64_SWAP_LE_BE(state->file_inode); } if (state->header.version > 0) { msg_error("Internal error restoring log reader state, stored data is too new", evt_tag_int("version", state->header.version)); goto error; } persist_state_unmap_entry(persist_state, old_state_handle); log_proto_buffered_server_apply_state(self, old_state_handle, persist_name); return TRUE; } else { msg_error("Internal error restoring log reader state, stored data is too new", evt_tag_int("version", persist_version)); goto error; } return TRUE; fallback_non_persistent: new_state = g_new0(LogProtoBufferedServerState, 1); error: if (!new_state) { new_state_handle = log_proto_buffered_server_alloc_state(self, persist_state, persist_name); if (!new_state_handle) goto fallback_non_persistent; new_state = persist_state_map_entry(persist_state, new_state_handle); } if (new_state) { LogProtoBufferedServerState *state = new_state; /* error happened, restart the file from the beginning */ state->raw_stream_pos = 0; state->file_inode = 0; state->file_size = 0; if (new_state_handle) log_proto_buffered_server_apply_state(self, new_state_handle, persist_name); else self->state1 = new_state; } if (new_state_handle) { persist_state_unmap_entry(persist_state, new_state_handle); } return FALSE; } gboolean log_proto_buffered_server_prepare(LogProtoServer *s, GIOCondition *cond) { LogProtoBufferedServer *self = (LogProtoBufferedServer *) s; *cond = self->super.transport->cond; /* if there's no pending I/O in the transport layer, then we want to do a read */ if (*cond == 0) *cond = G_IO_IN; return FALSE; } static gint log_proto_buffered_server_read_data_method(LogProtoBufferedServer *self, guchar *buf, gsize len, LogTransportAuxData *aux) { return log_transport_read(self->super.transport, buf, len, aux); } static gboolean log_proto_buffered_server_fetch_from_buffer(LogProtoBufferedServer *self, const guchar **msg, gsize *msg_len, LogTransportAuxData *aux) { gsize buffer_bytes; const guchar *buffer_start; LogProtoBufferedServerState *state = log_proto_buffered_server_get_state(self); gboolean success = FALSE; buffer_start = self->buffer + state->pending_buffer_pos; buffer_bytes = state->pending_buffer_end - state->pending_buffer_pos; if (buffer_bytes == 0) { /* if buffer_bytes is zero bytes, it means that we completely * processed our buffer without having a fraction of a line still * there. It is important to reset * pending_buffer_pos/pending_buffer_end to zero as the caller assumes * that if we return no message from the buffer, then buffer_pos is * _zero_. */ if (G_UNLIKELY(self->pos_tracking)) { state->pending_raw_stream_pos += state->pending_raw_buffer_size; state->pending_raw_buffer_size = 0; } state->pending_buffer_pos = state->pending_buffer_end = 0; goto exit; } success = self->fetch_from_buffer(self, buffer_start, buffer_bytes, msg, msg_len); if (aux) log_transport_aux_data_copy(aux, &self->buffer_aux); exit: log_proto_buffered_server_put_state(self); return success; } static inline void log_proto_buffered_server_allocate_buffer(LogProtoBufferedServer *self, LogProtoBufferedServerState *state) { state->buffer_size = self->super.options->init_buffer_size; self->buffer = g_malloc(state->buffer_size); } static inline gint log_proto_buffered_server_read_data(LogProtoBufferedServer *self, gpointer buffer, gsize count) { gint rc; log_transport_aux_data_reinit(&self->buffer_aux); rc = self->read_data(self, buffer, count, &self->buffer_aux); return rc; } static GIOStatus log_proto_buffered_server_fetch_into_buffer(LogProtoBufferedServer *self) { guchar *raw_buffer = NULL; gint avail; gint rc; LogProtoBufferedServerState *state = log_proto_buffered_server_get_state(self); GIOStatus result = G_IO_STATUS_NORMAL; if (G_UNLIKELY(!self->buffer)) log_proto_buffered_server_allocate_buffer(self, state); if (self->convert == (GIConv) -1) { /* no conversion, we read directly into our buffer */ raw_buffer = self->buffer + state->pending_buffer_end; avail = state->buffer_size - state->pending_buffer_end; } else { /* if conversion is needed, we first read into an on-stack * buffer, and then convert it into our internal buffer */ raw_buffer = g_alloca(self->super.options->init_buffer_size + state->raw_buffer_leftover_size); memcpy(raw_buffer, state->raw_buffer_leftover, state->raw_buffer_leftover_size); avail = self->super.options->init_buffer_size; } if (avail == 0) goto exit; rc = log_proto_buffered_server_read_data(self, raw_buffer + state->raw_buffer_leftover_size, avail); if (rc < 0) { if (errno == EAGAIN) { /* ok we don't have any more data to read, return to main poll loop */ result = G_IO_STATUS_AGAIN; } else { /* an error occurred while reading */ msg_error("I/O error occurred while reading", evt_tag_int(EVT_TAG_FD, self->super.transport->fd), evt_tag_errno(EVT_TAG_OSERROR, errno)); result = G_IO_STATUS_ERROR; } } else if (rc == 0) { /* EOF read */ msg_verbose("EOF occurred while reading", evt_tag_int(EVT_TAG_FD, self->super.transport->fd)); if (state->raw_buffer_leftover_size > 0) { msg_error("EOF read on a channel with leftovers from previous character conversion, dropping input"); state->pending_buffer_pos = state->pending_buffer_end = 0; } result = G_IO_STATUS_EOF; } else { state->pending_raw_buffer_size += rc; rc += state->raw_buffer_leftover_size; state->raw_buffer_leftover_size = 0; if (self->convert == (GIConv) -1) { state->pending_buffer_end += rc; } else if (!log_proto_buffered_server_convert_from_raw(self, raw_buffer, rc)) { result = G_IO_STATUS_ERROR; } } exit: log_proto_buffered_server_put_state(self); return result; } static LogProtoStatus _convert_io_status_to_log_proto_status(GIOStatus io_status) { if (io_status == G_IO_STATUS_EOF) return LPS_EOF; else if (io_status == G_IO_STATUS_ERROR) return LPS_ERROR; g_assert_not_reached(); } static void _buffered_server_update_pos(LogProtoServer *s) { LogProtoBufferedServer *self = (LogProtoBufferedServer *) s; LogProtoBufferedServerState *state = log_proto_buffered_server_get_state(self); if (state->pending_buffer_pos == state->pending_buffer_end) { state->pending_buffer_end = 0; state->pending_buffer_pos = 0; if (self->pos_tracking) { state->pending_raw_stream_pos += state->pending_raw_buffer_size; state->pending_raw_buffer_size = 0; } } log_proto_buffered_server_put_state(self); } static void _buffered_server_bookmark_save(Bookmark *bookmark) { BufferedServerBookmarkData *bookmark_data = (BufferedServerBookmarkData *)(&bookmark->container); LogProtoBufferedServerState *state = persist_state_map_entry(bookmark->persist_state, bookmark_data->persist_handle); state->buffer_pos = bookmark_data->pending_buffer_pos; state->raw_stream_pos = bookmark_data->pending_raw_stream_pos; state->raw_buffer_size = bookmark_data->pending_raw_buffer_size; msg_trace("Last message got confirmed", evt_tag_int("raw_stream_pos", state->raw_stream_pos), evt_tag_int("raw_buffer_len", state->raw_buffer_size), evt_tag_int("buffer_pos", state->buffer_pos), evt_tag_int("buffer_end", state->pending_buffer_end)); persist_state_unmap_entry(bookmark->persist_state, bookmark_data->persist_handle); } static void _buffered_server_bookmark_fill(LogProtoBufferedServer *self, Bookmark *bookmark) { LogProtoBufferedServerState *state = log_proto_buffered_server_get_state(self); BufferedServerBookmarkData *data = (BufferedServerBookmarkData *)(&bookmark->container); data->pending_buffer_pos = state->pending_buffer_pos; data->pending_raw_stream_pos = state->pending_raw_stream_pos; data->pending_raw_buffer_size = state->pending_raw_buffer_size; data->persist_handle = self->persist_handle; bookmark->save = _buffered_server_bookmark_save; log_proto_buffered_server_put_state(self); } /** * Returns: TRUE to indicate success, FALSE otherwise. The returned * msg can be NULL even if no failure occurred. **/ static LogProtoStatus log_proto_buffered_server_fetch(LogProtoServer *s, const guchar **msg, gsize *msg_len, gboolean *may_read, LogTransportAuxData *aux, Bookmark *bookmark) { LogProtoBufferedServer *self = (LogProtoBufferedServer *) s; LogProtoStatus result = LPS_SUCCESS; while (1) { if (self->fetch_state == LPBSF_FETCHING_FROM_BUFFER) { if (log_proto_buffered_server_fetch_from_buffer(self, msg, msg_len, aux)) goto exit; if (log_proto_buffered_server_is_input_closed(self)) { result = _convert_io_status_to_log_proto_status(self->io_status); goto exit; } else { self->fetch_state = LPBSF_FETCHING_FROM_INPUT; } } else if (self->fetch_state == LPBSF_FETCHING_FROM_INPUT) { GIOStatus io_status; if (!(*may_read)) goto exit; io_status = log_proto_buffered_server_fetch_into_buffer(self); switch (io_status) { case G_IO_STATUS_NORMAL: if (self->no_multi_read) *may_read = FALSE; break; case G_IO_STATUS_AGAIN: goto exit; case G_IO_STATUS_ERROR: case G_IO_STATUS_EOF: self->io_status = io_status; break; default: g_assert_not_reached(); } self->fetch_state = LPBSF_FETCHING_FROM_BUFFER; } } exit: /* result contains our result, but once an error happens, the error condition remains persistent */ if (result != LPS_SUCCESS) self->super.status = result; else { if (bookmark && *msg) { _buffered_server_bookmark_fill(self, bookmark); _buffered_server_update_pos(&self->super); } } return result; } static gboolean log_proto_buffered_server_is_position_tracked(LogProtoServer *s) { LogProtoBufferedServer *self = (LogProtoBufferedServer *) s; return self->pos_tracking; } gboolean log_proto_buffered_server_validate_options_method(LogProtoServer *s) { LogProtoBufferedServer *self = (LogProtoBufferedServer *) s; if (self->super.options->encoding && self->convert == (GIConv) -1) { msg_error("Unknown character set name specified", evt_tag_str("encoding", self->super.options->encoding)); return FALSE; } return log_proto_server_validate_options_method(s); } void log_proto_buffered_server_free_method(LogProtoServer *s) { LogProtoBufferedServer *self = (LogProtoBufferedServer *) s; log_transport_aux_data_destroy(&self->buffer_aux); g_free(self->buffer); if (self->state1) { g_free(self->state1); } if (self->convert != (GIConv) -1) g_iconv_close(self->convert); log_proto_server_free_method(s); } void log_proto_buffered_server_init(LogProtoBufferedServer *self, LogTransport *transport, const LogProtoServerOptions *options) { log_proto_server_init(&self->super, transport, options); self->super.prepare = log_proto_buffered_server_prepare; self->super.fetch = log_proto_buffered_server_fetch; self->super.free_fn = log_proto_buffered_server_free_method; self->super.transport = transport; self->super.restart_with_state = log_proto_buffered_server_restart_with_state; self->super.is_position_tracked = log_proto_buffered_server_is_position_tracked; self->super.validate_options = log_proto_buffered_server_validate_options_method; self->convert = (GIConv) -1; self->read_data = log_proto_buffered_server_read_data_method; self->io_status = G_IO_STATUS_NORMAL; if (options->encoding) self->convert = g_iconv_open("utf-8", options->encoding); else self->convert = (GIConv) -1; self->stream_based = TRUE; self->pos_tracking = options->position_tracking_enabled; } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-buffered-server.h000066400000000000000000000076551321171025300251670ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_BUFFERED_SERVER_H_INCLUDED #define LOGPROTO_BUFFERED_SERVER_H_INCLUDED #include "logproto-server.h" #include "persistable-state-header.h" enum { LPBSF_FETCHING_FROM_INPUT, LPBSF_FETCHING_FROM_BUFFER, }; typedef struct _LogProtoBufferedServerState { /* NOTE: that if you add/remove structure members you have to update * the byte order swap code in LogProtoFileReader for mulit-byte * members. */ PersistableStateHeader header; guint8 raw_buffer_leftover_size; guint8 __padding1[1]; guint32 buffer_pos; guint32 pending_buffer_end; guint32 buffer_size; guint32 __deprecated_buffer_cached_eol; guint32 pending_buffer_pos; /* the stream position where we converted out current buffer from (offset in file) */ gint64 raw_stream_pos; gint64 pending_raw_stream_pos; /* the size of raw data (measured in bytes) that got converted from raw_stream_pos into our buffer */ gint32 raw_buffer_size; gint32 pending_raw_buffer_size; guchar raw_buffer_leftover[8]; gint64 file_size; gint64 file_inode; } LogProtoBufferedServerState; typedef struct _LogProtoBufferedServer LogProtoBufferedServer; struct _LogProtoBufferedServer { LogProtoServer super; gboolean (*fetch_from_buffer)(LogProtoBufferedServer *self, const guchar *buffer_start, gsize buffer_bytes, const guchar **msg, gsize *msg_len); gint (*read_data)(LogProtoBufferedServer *self, guchar *buf, gsize len, LogTransportAuxData *aux); gboolean /* track & record the position in the input, to be used for file * position tracking. It's not always on as it's expensive when * an encoding is specified and the last record in the input is * not complete. */ pos_tracking:1, /* specifies that the input is a stream of bytes, size of chunks * read split the input randomly. Non-stream based stuff is udp * or fixed-size records read from a file. */ stream_based:1, no_multi_read:1; gint fetch_state; GIOStatus io_status; LogProtoBufferedServerState *state1; PersistState *persist_state; PersistEntryHandle persist_handle; GIConv convert; guchar *buffer; /* auxiliary data (e.g. GSockAddr, other transport related meta * data) associated with the already buffered data */ LogTransportAuxData buffer_aux; }; static inline gboolean log_proto_buffered_server_is_input_closed(LogProtoBufferedServer *self) { return self->io_status != G_IO_STATUS_NORMAL; } gboolean log_proto_buffered_server_prepare(LogProtoServer *s, GIOCondition *cond); LogProtoBufferedServerState *log_proto_buffered_server_get_state(LogProtoBufferedServer *self); void log_proto_buffered_server_put_state(LogProtoBufferedServer *self); /* LogProtoBufferedServer */ gboolean log_proto_buffered_server_validate_options_method(LogProtoServer *s); void log_proto_buffered_server_init(LogProtoBufferedServer *self, LogTransport *transport, const LogProtoServerOptions *options); void log_proto_buffered_server_free_method(LogProtoServer *s); #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-builtins.c000066400000000000000000000045011321171025300237100ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto-dgram-server.h" #include "logproto-text-client.h" #include "logproto-text-server.h" #include "logproto-indented-multiline-server.h" #include "logproto-framed-client.h" #include "logproto-framed-server.h" #include "plugin.h" #include "plugin-types.h" /* This module defines various core-implemented LogProto implementations as * plugins, so that modules may find them, dynamically based on their plugin * name */ DEFINE_LOG_PROTO_SERVER(log_proto_dgram); DEFINE_LOG_PROTO_CLIENT(log_proto_text); DEFINE_LOG_PROTO_SERVER(log_proto_text); DEFINE_LOG_PROTO_SERVER(log_proto_indented_multiline); DEFINE_LOG_PROTO_CLIENT(log_proto_framed); DEFINE_LOG_PROTO_SERVER(log_proto_framed); static Plugin framed_server_plugins[] = { /* there's no separate client side for the 'dgram' transport */ LOG_PROTO_CLIENT_PLUGIN(log_proto_text, "dgram"), LOG_PROTO_SERVER_PLUGIN(log_proto_dgram, "dgram"), LOG_PROTO_CLIENT_PLUGIN(log_proto_text, "text"), LOG_PROTO_SERVER_PLUGIN(log_proto_text, "text"), LOG_PROTO_SERVER_PLUGIN(log_proto_indented_multiline, "indented-multiline"), LOG_PROTO_CLIENT_PLUGIN(log_proto_framed, "framed"), LOG_PROTO_SERVER_PLUGIN(log_proto_framed, "framed"), }; void log_proto_register_builtin_plugins(PluginContext *context) { plugin_register(context, framed_server_plugins, G_N_ELEMENTS(framed_server_plugins)); } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-builtins.h000066400000000000000000000022201321171025300237110ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_PLUGINS_H_INCLUDED #define LOGPROTO_PLUGINS_H_INCLUDED #include "cfg.h" void log_proto_register_builtin_plugins(PluginContext *context); #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-client.c000066400000000000000000000042431321171025300233400ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto-client.h" #include "messages.h" #include "cfg.h" #include "plugin.h" #include "plugin-types.h" gboolean log_proto_client_validate_options_method(LogProtoClient *s) { return TRUE; } void log_proto_client_free_method(LogProtoClient *s) { log_transport_free(s->transport); } void log_proto_client_free(LogProtoClient *s) { if (s->free_fn) s->free_fn(s); g_free(s); } void log_proto_client_init(LogProtoClient *self, LogTransport *transport, const LogProtoClientOptions *options) { self->validate_options = log_proto_client_validate_options_method; self->free_fn = log_proto_client_free_method; self->options = options; self->transport = transport; } void log_proto_client_options_defaults(LogProtoClientOptions *options) { } void log_proto_client_options_init(LogProtoClientOptions *options, GlobalConfig *cfg) { } void log_proto_client_options_destroy(LogProtoClientOptions *options) { } LogProtoClientFactory * log_proto_client_get_factory(PluginContext *context, const gchar *name) { Plugin *plugin; plugin = plugin_find(context, LL_CONTEXT_CLIENT_PROTO, name); if (plugin && plugin->construct) return plugin->construct(plugin); return NULL; } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-client.h000066400000000000000000000130041321171025300233400ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_CLIENT_H_INCLUDED #define LOGPROTO_CLIENT_H_INCLUDED #include "logproto.h" #include "persist-state.h" typedef struct _LogProtoClient LogProtoClient; #define LOG_PROTO_CLIENT_OPTIONS_SIZE 32 typedef struct _LogProtoClientOptions { } LogProtoClientOptions; typedef union _LogProtoClientOptionsStorage { LogProtoClientOptions super; gchar __padding[LOG_PROTO_CLIENT_OPTIONS_SIZE]; } LogProtoClientOptionsStorage; typedef void (*LogProtoClientAckCallback)(gint num_msg_acked, gpointer user_data); typedef void (*LogProtoClientRewindCallback)(gpointer user_data); typedef struct { LogProtoClientAckCallback ack_callback; LogProtoClientRewindCallback rewind_callback; gpointer user_data; } LogProtoClientFlowControlFuncs; void log_proto_client_options_defaults(LogProtoClientOptions *options); void log_proto_client_options_init(LogProtoClientOptions *options, GlobalConfig *cfg); void log_proto_client_options_destroy(LogProtoClientOptions *options); struct _LogProtoClient { LogProtoStatus status; const LogProtoClientOptions *options; LogTransport *transport; /* FIXME: rename to something else */ gboolean (*prepare)(LogProtoClient *s, gint *fd, GIOCondition *cond); LogProtoStatus (*post)(LogProtoClient *s, guchar *msg, gsize msg_len, gboolean *consumed); LogProtoStatus (*flush)(LogProtoClient *s); gboolean (*validate_options)(LogProtoClient *s); void (*free_fn)(LogProtoClient *s); LogProtoClientFlowControlFuncs flow_control_funcs; }; static inline void log_proto_client_set_client_flow_control(LogProtoClient *self, LogProtoClientFlowControlFuncs *flow_control_funcs) { self->flow_control_funcs.ack_callback = flow_control_funcs->ack_callback; self->flow_control_funcs.rewind_callback = flow_control_funcs->rewind_callback; self->flow_control_funcs.user_data = flow_control_funcs->user_data; } static inline void log_proto_client_msg_ack(LogProtoClient *self, gint num_msg_acked) { if (self->flow_control_funcs.ack_callback) self->flow_control_funcs.ack_callback(num_msg_acked, self->flow_control_funcs.user_data); } static inline void log_proto_client_msg_rewind(LogProtoClient *self) { if (self->flow_control_funcs.rewind_callback) self->flow_control_funcs.rewind_callback(self->flow_control_funcs.user_data); } static inline gboolean log_proto_client_validate_options(LogProtoClient *self) { return self->validate_options(self); } static inline gboolean log_proto_client_prepare(LogProtoClient *s, gint *fd, GIOCondition *cond) { return s->prepare(s, fd, cond); } static inline LogProtoStatus log_proto_client_flush(LogProtoClient *s) { if (s->flush) return s->flush(s); else return LPS_SUCCESS; } static inline LogProtoStatus log_proto_client_post(LogProtoClient *s, guchar *msg, gsize msg_len, gboolean *consumed) { return s->post(s, msg, msg_len, consumed); } static inline gint log_proto_client_get_fd(LogProtoClient *s) { /* FIXME: Layering violation */ return s->transport->fd; } static inline void log_proto_client_reset_error(LogProtoClient *s) { s->status = LPS_SUCCESS; } gboolean log_proto_client_validate_options(LogProtoClient *self); void log_proto_client_init(LogProtoClient *s, LogTransport *transport, const LogProtoClientOptions *options); void log_proto_client_free(LogProtoClient *s); void log_proto_client_free_method(LogProtoClient *s); #define DEFINE_LOG_PROTO_CLIENT(prefix) \ static gpointer \ prefix ## _client_plugin_construct(Plugin *self) \ { \ static LogProtoClientFactory proto = { \ .construct = prefix ## _client_new, \ }; \ return &proto; \ } #define LOG_PROTO_CLIENT_PLUGIN(prefix, __name) \ { \ .type = LL_CONTEXT_CLIENT_PROTO, \ .name = __name, \ .construct = prefix ## _client_plugin_construct, \ } typedef struct _LogProtoClientFactory LogProtoClientFactory; struct _LogProtoClientFactory { LogProtoClient *(*construct)(LogTransport *transport, const LogProtoClientOptions *options); }; static inline LogProtoClient * log_proto_client_factory_construct(LogProtoClientFactory *self, LogTransport *transport, const LogProtoClientOptions *options) { return self->construct(transport, options); } LogProtoClientFactory *log_proto_client_get_factory(PluginContext *context, const gchar *name); #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-dgram-server.c000066400000000000000000000042461321171025300244630ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto-dgram-server.h" #include "logproto-buffered-server.h" /* proto that reads the input in datagrams (e.g. the underlying transport * determines record sizes, such as UDP) */ typedef struct _LogProtoDGramServer LogProtoDGramServer; struct _LogProtoDGramServer { LogProtoBufferedServer super; }; static gboolean log_proto_dgram_server_fetch_from_buffer(LogProtoBufferedServer *s, const guchar *buffer_start, gsize buffer_bytes, const guchar **msg, gsize *msg_len) { LogProtoBufferedServerState *state = log_proto_buffered_server_get_state(s); /* * we are set to packet terminating mode */ *msg = buffer_start; *msg_len = buffer_bytes; state->pending_buffer_pos = state->pending_buffer_end; log_proto_buffered_server_put_state(s); return TRUE; } LogProtoServer * log_proto_dgram_server_new(LogTransport *transport, const LogProtoServerOptions *options) { LogProtoDGramServer *self = g_new0(LogProtoDGramServer, 1); log_proto_buffered_server_init(&self->super, transport, options); self->super.fetch_from_buffer = log_proto_dgram_server_fetch_from_buffer; self->super.stream_based = FALSE; return &self->super.super; } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-dgram-server.h000066400000000000000000000025541321171025300244700ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_DGRAM_SERVER_H_INCLUDED #define LOGPROTO_DGRAM_SERVER_H_INCLUDED #include "logproto-server.h" /* * LogProtoDGramServer * * This class reads input as datagrams, each datagram is a separate * message, regardless of embedded EOL/NUL characters. */ LogProtoServer *log_proto_dgram_server_new(LogTransport *transport, const LogProtoServerOptions *options); #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-framed-client.c000066400000000000000000000055051321171025300245760ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto-framed-client.h" #include "logproto-text-client.h" #include "messages.h" #define LPFCS_FRAME_SEND 0 #define LPFCS_MESSAGE_SEND 1 typedef struct _LogProtoFramedClient { LogProtoTextClient super; guchar frame_hdr_buf[9]; } LogProtoFramedClient; static LogProtoStatus log_proto_framed_client_post(LogProtoClient *s, guchar *msg, gsize msg_len, gboolean *consumed) { LogProtoFramedClient *self = (LogProtoFramedClient *) s; gint frame_hdr_len; gint rc; if (msg_len > 9999999) { static const guchar *warn_msg; if (warn_msg != msg) { msg_warning("Error, message length too large for framed protocol, truncated", evt_tag_int("length", msg_len)); warn_msg = msg; } msg_len = 9999999; } rc = LPS_SUCCESS; while (rc == LPS_SUCCESS && !(*consumed) && self->super.partial == NULL) { switch (self->super.state) { case LPFCS_FRAME_SEND: frame_hdr_len = g_snprintf((gchar *) self->frame_hdr_buf, sizeof(self->frame_hdr_buf), "%" G_GSIZE_FORMAT" ", msg_len); rc = log_proto_text_client_submit_write(s, self->frame_hdr_buf, frame_hdr_len, NULL, LPFCS_MESSAGE_SEND); break; case LPFCS_MESSAGE_SEND: *consumed = TRUE; rc = log_proto_text_client_submit_write(s, msg, msg_len, (GDestroyNotify) g_free, LPFCS_FRAME_SEND); break; default: g_assert_not_reached(); } } return rc; } LogProtoClient * log_proto_framed_client_new(LogTransport *transport, const LogProtoClientOptions *options) { LogProtoFramedClient *self = g_new0(LogProtoFramedClient, 1); log_proto_text_client_init(&self->super, transport, options); self->super.super.post = log_proto_framed_client_post; self->super.state = LPFCS_FRAME_SEND; return &self->super.super; } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-framed-client.h000066400000000000000000000023401321171025300245750ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_FRAMED_CLIENT_H_INCLUDED #define LOGPROTO_FRAMED_CLIENT_H_INCLUDED #include "logproto-client.h" /* framed */ LogProtoClient *log_proto_framed_client_new(LogTransport *transport, const LogProtoClientOptions *options); #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-framed-server.c000066400000000000000000000220721321171025300246240ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto-framed-server.h" #include "messages.h" #include #include #include #define LPFSS_FRAME_READ 0 #define LPFSS_MESSAGE_READ 1 #define LPFS_FRAME_BUFFER 10 typedef struct _LogProtoFramedServer { LogProtoServer super; gint state; guchar *buffer; guint32 buffer_size, buffer_pos, buffer_end; guint32 frame_len; gboolean half_message_in_buffer; } LogProtoFramedServer; static gboolean log_proto_framed_server_prepare(LogProtoServer *s, GIOCondition *cond) { LogProtoFramedServer *self = (LogProtoFramedServer *) s; *cond = self->super.transport->cond; /* there is a half message in our buffer so try to wait */ if (!self->half_message_in_buffer) { if (self->buffer_pos != self->buffer_end) { /* we have a full message in our buffer so parse it without reading new data from the transport layer */ return TRUE; } } /* if there's no pending I/O in the transport layer, then we want to do a read */ if (*cond == 0) *cond = G_IO_IN; return FALSE; } static LogProtoStatus log_proto_framed_server_fetch_data(LogProtoFramedServer *self, gboolean *may_read, LogTransportAuxData *aux) { gint rc; if (self->buffer_pos == self->buffer_end) self->buffer_pos = self->buffer_end = 0; if (self->buffer_size == self->buffer_end) { /* no more space in the buffer, we can't fetch further data. Move the * things we already have to the beginning of the buffer to make * space. */ memmove(self->buffer, &self->buffer[self->buffer_pos], self->buffer_end - self->buffer_pos); self->buffer_end = self->buffer_end - self->buffer_pos; self->buffer_pos = 0; } if (!(*may_read)) return LPS_SUCCESS; rc = log_transport_read(self->super.transport, &self->buffer[self->buffer_end], self->buffer_size - self->buffer_end, aux); if (rc < 0) { if (errno != EAGAIN) { msg_error("Error reading RFC5428 style framed data", evt_tag_int("fd", self->super.transport->fd), evt_tag_errno("error", errno)); return LPS_ERROR; } else { /* we need more data to parse this message but the data is not available yet */ self->half_message_in_buffer = TRUE; } } else if (rc == 0) { msg_verbose("EOF occurred while reading", evt_tag_int(EVT_TAG_FD, self->super.transport->fd)); return LPS_EOF; } else { self->buffer_end += rc; } return LPS_SUCCESS; } static gboolean log_proto_framed_server_extract_frame_length(LogProtoFramedServer *self, gboolean *need_more_data) { gint i; *need_more_data = TRUE; self->frame_len = 0; for (i = self->buffer_pos; i < self->buffer_end; i++) { if (isdigit(self->buffer[i]) && (i - self->buffer_pos < 10)) { self->frame_len = self->frame_len * 10 + (self->buffer[i] - '0'); } else if (self->buffer[i] == ' ') { *need_more_data = FALSE; self->buffer_pos = i + 1; return TRUE; } else { msg_error("Invalid frame header", evt_tag_printf("header", "%.*s", (gint) (i - self->buffer_pos), &self->buffer[self->buffer_pos])); return FALSE; } } /* couldn't extract frame header, no error but need more data */ return TRUE; } static LogProtoStatus log_proto_framed_server_fetch(LogProtoServer *s, const guchar **msg, gsize *msg_len, gboolean *may_read, LogTransportAuxData *aux, Bookmark *bookmark) { LogProtoFramedServer *self = (LogProtoFramedServer *) s; LogProtoStatus status; gboolean try_read, need_more_data; if (G_UNLIKELY(!self->buffer)) { self->buffer_size = self->super.options->init_buffer_size; self->buffer = g_malloc(self->buffer_size); } switch (self->state) { case LPFSS_FRAME_READ: try_read = TRUE; read_frame: if (!log_proto_framed_server_extract_frame_length(self, &need_more_data)) { /* invalid frame header */ log_transport_aux_data_reinit(aux); return LPS_ERROR; } if (need_more_data && try_read) { status = log_proto_framed_server_fetch_data(self, may_read, aux); if (status != LPS_SUCCESS) { log_transport_aux_data_reinit(aux); return status; } try_read = FALSE; goto read_frame; } if (!need_more_data) { self->state = LPFSS_MESSAGE_READ; if (self->frame_len > self->super.options->max_msg_size) { msg_error("Incoming frame larger than log_msg_size()", evt_tag_int("log_msg_size", self->super.options->max_msg_size), evt_tag_int("frame_length", self->frame_len)); log_transport_aux_data_reinit(aux); return LPS_ERROR; } if (self->buffer_size < self->super.options->max_buffer_size && self->frame_len > self->buffer_size - self->buffer_pos) { /* a larger buffer would have prevented moving of data, grow * the buffer up to max_buffer_size */ self->buffer_size = 16 * (self->frame_len + LPFS_FRAME_BUFFER); if (self->buffer_size > self->super.options->max_buffer_size) self->buffer_size = self->super.options->max_buffer_size; self->buffer = g_realloc(self->buffer, self->buffer_size); msg_debug("Resizing input buffer", evt_tag_int("new_size", self->buffer_size)); } if (self->buffer_pos + self->frame_len > self->buffer_size) { /* message would be too large to fit into the buffer at * buffer_pos, we need to move data to the beginning of * the buffer to make space, and once we are at it, move * to the beginning to make space for the maximum number * of messages before the next shift */ memmove(self->buffer, &self->buffer[self->buffer_pos], self->buffer_end - self->buffer_pos); self->buffer_end = self->buffer_end - self->buffer_pos; self->buffer_pos = 0; } goto read_message; } break; case LPFSS_MESSAGE_READ: try_read = TRUE; read_message: /* NOTE: here we can assume that the complete message fits into * the buffer because of the checks/move operation in the * LPFSS_FRAME_READ state */ if (self->buffer_end - self->buffer_pos >= self->frame_len) { /* ok, we already have the complete message */ *msg = &self->buffer[self->buffer_pos]; *msg_len = self->frame_len; self->buffer_pos += self->frame_len; self->state = LPFSS_FRAME_READ; /* we have the full message here so reset the half message flag */ self->half_message_in_buffer = FALSE; return LPS_SUCCESS; } if (try_read) { status = log_proto_framed_server_fetch_data(self, may_read, aux); if (status != LPS_SUCCESS) { log_transport_aux_data_reinit(aux); return status; } try_read = FALSE; goto read_message; } break; default: break; } return LPS_SUCCESS; } static void log_proto_framed_server_free(LogProtoServer *s) { LogProtoFramedServer *self = (LogProtoFramedServer *) s; g_free(self->buffer); log_proto_server_free_method(s); } LogProtoServer * log_proto_framed_server_new(LogTransport *transport, const LogProtoServerOptions *options) { LogProtoFramedServer *self = g_new0(LogProtoFramedServer, 1); log_proto_server_init(&self->super, transport, options); self->super.prepare = log_proto_framed_server_prepare; self->super.fetch = log_proto_framed_server_fetch; self->super.free_fn = log_proto_framed_server_free; self->half_message_in_buffer = FALSE; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-framed-server.h000066400000000000000000000023231321171025300246260ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_FRAMED_SERVER_H_INCLUDED #define LOGPROTO_FRAMED_SERVER_H_INCLUDED #include "logproto-server.h" LogProtoServer *log_proto_framed_server_new(LogTransport *transport, const LogProtoServerOptions *options); #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-indented-multiline-server.c000066400000000000000000000061531321171025300271620ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "logproto-indented-multiline-server.h" #include "messages.h" static inline gboolean log_proto_indented_multiline_is_continuation(guchar first_char) { return (first_char == ' ' || first_char == '\t'); } static gint log_proto_indented_multiline_accumulate_line(LogProtoTextServer *s, const guchar *msg, gsize msg_len, gssize consumed_len) { /* NOTES: * * msg * points to the beginning of the line _repeatedly_, e.g. as * long as we return the we couldn't extract a message. * * msg_len * This is getting longer and longer as lines get accumulated * in the message. * * consumed_len * Is the length of the message starting with "msg" that was already * consumed by this function. In practice this points to the EOL * character of the last consumed line. * */ /* let's check if the current line is a continuation line or not */ if (consumed_len >= 0 && msg_len > consumed_len + 1) { guchar first_character_of_the_current_line = msg[consumed_len + 1]; if (log_proto_indented_multiline_is_continuation(first_character_of_the_current_line)) { return LPT_CONSUME_LINE | LPT_WAITING; } else { return LPT_REWIND_LINE | LPT_EXTRACTED; } } return LPT_CONSUME_LINE | LPT_WAITING; } void log_proto_indented_multiline_server_init(LogProtoIMultiLineServer *self, LogTransport *transport, const LogProtoServerOptions *options) { log_proto_text_server_init(&self->super, transport, options); self->super.accumulate_line = log_proto_indented_multiline_accumulate_line; } LogProtoServer * log_proto_indented_multiline_server_new(LogTransport *transport, const LogProtoServerOptions *options) { LogProtoIMultiLineServer *self = g_new0(LogProtoIMultiLineServer, 1); log_proto_indented_multiline_server_init(self, transport, options); return &self->super.super.super; } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-indented-multiline-server.h000066400000000000000000000037341321171025300271710ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_INDENTED_MULTILINE_SERVER_INCLUDED #define LOGPROTO_INDENTED_MULTILINE_SERVER_INCLUDED #include "logproto-text-server.h" typedef struct _LogProtoIMultiLineServer LogProtoIMultiLineServer; struct _LogProtoIMultiLineServer { LogProtoTextServer super; }; /* LogProtoIMultiLineServer * * This class processes indented multiline text files/streams. Each * record consists of one line that starts with non-whitespace, with * zero or more lines starting with whitespace. A record is terminated * when we reach a line that starts with non-whitespace, or EOF. */ LogProtoServer *log_proto_indented_multiline_server_new(LogTransport *transport, const LogProtoServerOptions *options); void log_proto_indented_multiline_server_init(LogProtoIMultiLineServer *self, LogTransport *transport, const LogProtoServerOptions *options); #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-multiline-server.c000066400000000000000000000073571321171025300254010ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto/logproto-multiline-server.h" #include "logproto/logproto-regexp-multiline-server.h" #include "logproto/logproto-indented-multiline-server.h" /* * This is basically a factory that takes multi-line related options and * constructs the appropriate LogProtoServer instance. */ LogProtoServer * log_proto_multiline_server_new(LogTransport *transport, const LogProtoMultiLineServerOptions *options) { switch (options->mode) { case MLM_INDENTED: return log_proto_indented_multiline_server_new(transport, &options->super); case MLM_PREFIX_GARBAGE: return log_proto_prefix_garbage_multiline_server_new(transport, &options->super, options->prefix, options->garbage); case MLM_PREFIX_SUFFIX: return log_proto_prefix_suffix_multiline_server_new(transport, &options->super, options->prefix, options->garbage); case MLM_NONE: return log_proto_text_server_new(transport, &options->super); } g_assert_not_reached(); } gboolean log_proto_multi_line_server_options_set_mode(LogProtoMultiLineServerOptions *options, const gchar *mode) { if (strcasecmp(mode, "indented") == 0) options->mode = MLM_INDENTED; else if (strcasecmp(mode, "regexp") == 0) options->mode = MLM_PREFIX_GARBAGE; else if (strcasecmp(mode, "prefix-garbage") == 0) options->mode = MLM_PREFIX_GARBAGE; else if (strcasecmp(mode, "prefix-suffix") == 0) options->mode = MLM_PREFIX_SUFFIX; else if (strcasecmp(mode, "none") == 0) options->mode = MLM_NONE; else return FALSE; return TRUE; } gboolean log_proto_multi_line_server_options_set_prefix(LogProtoMultiLineServerOptions *options, const gchar *prefix_regexp, GError **error) { options->prefix = multi_line_regexp_compile(prefix_regexp, error); return options->prefix != NULL; } gboolean log_proto_multi_line_server_options_set_garbage(LogProtoMultiLineServerOptions *options, const gchar *garbage_regexp, GError **error) { options->garbage = multi_line_regexp_compile(garbage_regexp, error); return options->garbage != NULL; } void log_proto_multi_line_server_options_defaults(LogProtoMultiLineServerOptions *options) { options->mode = MLM_NONE; } void log_proto_multi_line_server_options_init(LogProtoMultiLineServerOptions *options) { } void log_proto_multi_line_server_options_destroy(LogProtoMultiLineServerOptions *options) { multi_line_regexp_free(options->prefix); multi_line_regexp_free(options->garbage); } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-multiline-server.h000066400000000000000000000043171321171025300253770ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_MULTILINE_SERVER_INCLUDED #define LOGPROTO_MULTILINE_SERVER_INCLUDED #include "logproto/logproto-regexp-multiline-server.h" enum { MLM_NONE, MLM_INDENTED, MLM_PREFIX_GARBAGE, MLM_PREFIX_SUFFIX, }; typedef struct _LogProtoMultiLineServerOptions { LogProtoServerOptions super; gint mode; MultiLineRegexp *prefix; MultiLineRegexp *garbage; } LogProtoMultiLineServerOptions; LogProtoServer * log_proto_multiline_server_new(LogTransport *transport, const LogProtoMultiLineServerOptions *options); gboolean log_proto_multi_line_server_options_set_mode(LogProtoMultiLineServerOptions *options, const gchar *mode); gboolean log_proto_multi_line_server_options_set_prefix(LogProtoMultiLineServerOptions *options, const gchar *prefix_regexp, GError **error); gboolean log_proto_multi_line_server_options_set_garbage(LogProtoMultiLineServerOptions *options, const gchar *garbage_regexp, GError **error); void log_proto_multi_line_server_options_defaults(LogProtoMultiLineServerOptions *options); void log_proto_multi_line_server_options_init(LogProtoMultiLineServerOptions *options); void log_proto_multi_line_server_options_destroy(LogProtoMultiLineServerOptions *options); #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-record-server.c000066400000000000000000000115451321171025300246470ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto-record-server.h" #include "logproto-buffered-server.h" #include "messages.h" #include /* proto that reads the stream in even sized chunks */ typedef struct _LogProtoRecordServer LogProtoRecordServer; struct _LogProtoRecordServer { LogProtoBufferedServer super; gint record_size; }; static gboolean log_proto_record_server_validate_options(LogProtoServer *s) { LogProtoRecordServer *self = (LogProtoRecordServer *) s; if (s->options->max_buffer_size < self->record_size) { msg_error("Buffer is too small to hold the number of bytes required for a record, please make sure log-msg-size() is greater than equal to record-size", evt_tag_int("record_size", self->record_size), evt_tag_int("max_buffer_size", s->options->max_buffer_size)); return FALSE; } return log_proto_buffered_server_validate_options_method(s); } static gint log_proto_record_server_read_data(LogProtoBufferedServer *s, guchar *buf, gsize len, LogTransportAuxData *aux) { LogProtoRecordServer *self = (LogProtoRecordServer *) s; gint rc; /* assert that we have enough space in the buffer to read record_size bytes */ g_assert(len >= self->record_size); len = self->record_size; rc = log_transport_read(self->super.super.transport, buf, len, aux); if (rc > 0 && rc != self->record_size) { msg_error("Record size was set, and couldn't read enough bytes", evt_tag_int(EVT_TAG_FD, self->super.super.transport->fd), evt_tag_int("record_size", self->record_size), evt_tag_int("read", rc)); errno = EIO; return -1; } return rc; } static void log_proto_record_server_init(LogProtoRecordServer *self, LogTransport *transport, const LogProtoServerOptions *options, gint record_size) { log_proto_buffered_server_init(&self->super, transport, options); self->super.super.validate_options = log_proto_record_server_validate_options; self->super.read_data = log_proto_record_server_read_data; self->super.stream_based = FALSE; self->record_size = record_size; } static gboolean log_proto_binary_record_server_fetch_from_buffer(LogProtoBufferedServer *s, const guchar *buffer_start, gsize buffer_bytes, const guchar **msg, gsize *msg_len) { LogProtoBufferedServerState *state = log_proto_buffered_server_get_state(s); *msg_len = buffer_bytes; state->pending_buffer_pos = state->pending_buffer_end; *msg = buffer_start; log_proto_buffered_server_put_state(s); return TRUE; } LogProtoServer * log_proto_binary_record_server_new(LogTransport *transport, const LogProtoServerOptions *options, gint record_size) { LogProtoRecordServer *self = g_new0(LogProtoRecordServer, 1); log_proto_record_server_init(self, transport, options, record_size); self->super.fetch_from_buffer = log_proto_binary_record_server_fetch_from_buffer; return &self->super.super; } static gboolean log_proto_padded_record_server_fetch_from_buffer(LogProtoBufferedServer *s, const guchar *buffer_start, gsize buffer_bytes, const guchar **msg, gsize *msg_len) { LogProtoBufferedServerState *state = log_proto_buffered_server_get_state(s); const guchar *eol; eol = find_eom(buffer_start, buffer_bytes); *msg_len = (eol ? eol - buffer_start : buffer_bytes); state->pending_buffer_pos = state->pending_buffer_end; *msg = buffer_start; log_proto_buffered_server_put_state(s); return TRUE; } LogProtoServer * log_proto_padded_record_server_new(LogTransport *transport, const LogProtoServerOptions *options, gint record_size) { LogProtoRecordServer *self = g_new0(LogProtoRecordServer, 1); log_proto_record_server_init(self, transport, options, record_size); self->super.fetch_from_buffer = log_proto_padded_record_server_fetch_from_buffer; return &self->super.super; } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-record-server.h000066400000000000000000000033001321171025300246420ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_RECORD_SERVER_H_INCLUDED #define LOGPROTO_RECORD_SERVER_H_INCLUDED #include "logproto-server.h" /* * LogProtoBinaryRecordServer * * This class reads input in equally sized chunks. The message is the * whole record, regardless of embedded NUL/NL characters. */ LogProtoServer *log_proto_binary_record_server_new(LogTransport *transport, const LogProtoServerOptions *options, gint record_size); /* * LogProtoPaddedRecordServer * * This class reads input in equally sized chunks. The message lasts * until the first EOL/NUL character within the chunk. */ LogProtoServer *log_proto_padded_record_server_new(LogTransport *transport, const LogProtoServerOptions *options, gint record_size); #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-regexp-multiline-server.c000066400000000000000000000204121321171025300266540ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "logproto-regexp-multiline-server.h" #include "messages.h" #include "compat/pcre.h" #include struct _MultiLineRegexp { pcre *pattern; pcre_extra *extra; }; MultiLineRegexp * multi_line_regexp_compile(const gchar *regexp, GError **error) { MultiLineRegexp *self = g_new0(MultiLineRegexp, 1); gint optflags = 0; gint rc; const gchar *errptr; gint erroffset; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* complile the regexp */ self->pattern = pcre_compile2(regexp, 0, &rc, &errptr, &erroffset, NULL); if (!self->pattern) { g_set_error(error, 0, 0, "Error while compiling multi-line regexp as a PCRE expression, error=%s, error_at=%d", errptr, erroffset); goto error; } #ifdef PCRE_STUDY_JIT_COMPILE optflags = PCRE_STUDY_JIT_COMPILE; #endif /* optimize regexp */ self->extra = pcre_study(self->pattern, optflags, &errptr); if (errptr != NULL) { g_set_error(error, 0, 0, "Error while studying multi-line regexp, error=%s", errptr); goto error; } return self; error: if (self->pattern) pcre_free(self->pattern); g_free(self); return NULL; } void multi_line_regexp_free(MultiLineRegexp *self) { if (self) { if (self->pattern) pcre_free(self->pattern); if (self->extra) pcre_free_study(self->extra); g_free(self); } } struct _LogProtoREMultiLineServer { LogProtoTextServer super; /* these are borrowed */ MultiLineRegexp *prefix; MultiLineRegexp *garbage; gint (*get_offset_of_garbage)(LogProtoREMultiLineServer *self, const guchar *line, gsize line_len); }; static int _find_regexp(MultiLineRegexp *re, const guchar *str, gsize len, gint *matches, gint matches_num) { gint rc; if (!re) return -1; rc = pcre_exec(re->pattern, re->extra, (const gchar *) str, len, 0, 0, matches, matches_num * 3); return rc; } static gboolean _regexp_matches(MultiLineRegexp *re, const guchar *str, gsize len) { gint match[3]; if (_find_regexp(re, str, len, match, 1) < 0) return FALSE; return match[0] >= 0; } gint log_proto_prefix_garbage_multiline_get_offset_of_garbage(LogProtoREMultiLineServer *self, const guchar *line, gsize line_len) { gint match[3]; if (_find_regexp(self->garbage, line, line_len, match, 1) < 0) return -1; return match[0]; }; gint log_proto_prefix_suffix_multiline_get_offset_of_garbage(LogProtoREMultiLineServer *self, const guchar *line, gsize line_len) { gint match[3]; if (_find_regexp(self->garbage, line, line_len, match, 1) < 0) return -1; return match[1]; }; static gint _accumulate_initial_line(LogProtoREMultiLineServer *self, const guchar *line, gsize line_len, gssize consumed_len) { gint offset_of_garbage = self->get_offset_of_garbage(self, line, line_len); if (offset_of_garbage >= 0) return LPT_CONSUME_PARTIALLY(line_len - offset_of_garbage) | LPT_EXTRACTED; else return LPT_CONSUME_LINE | LPT_WAITING; } static gint _accumulate_continuation_line(LogProtoREMultiLineServer *self, const guchar *line, gsize line_len, gssize consumed_len) { gint offset_of_garbage = self->get_offset_of_garbage(self, line, line_len); if (offset_of_garbage >= 0) return LPT_CONSUME_PARTIALLY(line_len - offset_of_garbage) | LPT_EXTRACTED; else if (_regexp_matches(self->prefix, line, line_len)) return LPT_REWIND_LINE | LPT_EXTRACTED; else return LPT_CONSUME_LINE | LPT_WAITING; } static gint log_proto_regexp_multiline_accumulate_line(LogProtoTextServer *s, const guchar *msg, gsize msg_len, gssize consumed_len) { LogProtoREMultiLineServer *self = (LogProtoREMultiLineServer *) s; gboolean initial_line; /* NOTES: * * msg * points to the beginning of the line _repeatedly_, e.g. as * long as we return the we couldn't extract a message. * * msg_len * This is getting longer and longer as lines get accumulated * in the message. * * consumed_len * Is the length of the message starting with "msg" that was already * consumed by this function. In practice this points to the EOL * character of the last consumed line. * */ initial_line = (consumed_len < 0) || (msg_len <= consumed_len + 1); if (initial_line) { return _accumulate_initial_line(self, msg, msg_len, consumed_len); } else { const guchar *start_of_the_current_line = &msg[consumed_len + 1]; gint length_of_the_current_line = msg_len - (start_of_the_current_line - msg); return _accumulate_continuation_line(self, start_of_the_current_line, length_of_the_current_line, consumed_len); } } static gboolean log_proto_regexp_multi_line_server_validate_options(LogProtoServer *s) { LogProtoREMultiLineServer *self = (LogProtoREMultiLineServer *) s; if (!self->prefix && !self->garbage) { msg_error("To follow files in multi-line-mode() 'regexp', 'prefix-garbage', 'prefix-suffix', " "please also specifiy regexps using the multi-line-prefix/garbage options"); return FALSE; } return log_proto_text_server_validate_options_method(s); } void log_proto_regexp_multiline_server_init(LogProtoREMultiLineServer *self, LogTransport *transport, const LogProtoServerOptions *options, MultiLineRegexp *prefix, MultiLineRegexp *garbage_or_suffix) { log_proto_text_server_init(&self->super, transport, options); self->super.super.super.validate_options = log_proto_regexp_multi_line_server_validate_options; self->super.accumulate_line = log_proto_regexp_multiline_accumulate_line; self->prefix = prefix; self->garbage = garbage_or_suffix; } LogProtoServer * log_proto_prefix_garbage_multiline_server_new(LogTransport *transport, const LogProtoServerOptions *options, MultiLineRegexp *prefix, MultiLineRegexp *garbage) { LogProtoREMultiLineServer *self = g_new0(LogProtoREMultiLineServer, 1); log_proto_regexp_multiline_server_init(self, transport, options, prefix, garbage); self->get_offset_of_garbage = log_proto_prefix_garbage_multiline_get_offset_of_garbage; return &self->super.super.super; } LogProtoServer * log_proto_prefix_suffix_multiline_server_new(LogTransport *transport, const LogProtoServerOptions *options, MultiLineRegexp *prefix, MultiLineRegexp *suffix) { LogProtoREMultiLineServer *self = g_new0(LogProtoREMultiLineServer, 1); log_proto_regexp_multiline_server_init(self, transport, options, prefix, suffix); self->get_offset_of_garbage = log_proto_prefix_suffix_multiline_get_offset_of_garbage; return &self->super.super.super; } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-regexp-multiline-server.h000066400000000000000000000053131321171025300266640ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_REGEXP_MULTILINE_SERVER_INCLUDED #define LOGPROTO_REGEXP_MULTILINE_SERVER_INCLUDED #include "logproto-text-server.h" typedef struct _MultiLineRegexp MultiLineRegexp; typedef struct _LogProtoREMultiLineServer LogProtoREMultiLineServer; MultiLineRegexp *multi_line_regexp_compile(const gchar *regexp, GError **error); void multi_line_regexp_free(MultiLineRegexp *self); /* LogProtoREMultiLineServer * * This class processes indented multiline text files/streams. Each * record consists of one line that starts with non-whitespace, with * zero or more lines starting with whitespace. A record is terminated * when we reach a line that starts with non-whitespace, or EOF. */ LogProtoServer *log_proto_prefix_garbage_multiline_server_new(LogTransport *transport, const LogProtoServerOptions *options, MultiLineRegexp *prefix, MultiLineRegexp *garbage); void log_proto_regexp_multiline_server_init(LogProtoREMultiLineServer *self, LogTransport *transport, const LogProtoServerOptions *options, MultiLineRegexp *prefix, MultiLineRegexp *garbage); LogProtoServer *log_proto_prefix_suffix_multiline_server_new(LogTransport *transport, const LogProtoServerOptions *options, MultiLineRegexp *prefix, MultiLineRegexp *suffix); #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-server.c000066400000000000000000000131351321171025300233700ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto-server.h" #include "messages.h" #include "cfg.h" #include "plugin.h" #include "plugin-types.h" /** * Find the character terminating the buffer. * * NOTE: when looking for the end-of-message here, it either needs to be * terminated via NUL or via NL, when terminating via NL we have to make * sure that there's no NUL left in the message. This function iterates over * the input data and returns a pointer to the first occurence of NL or NUL. * * It uses an algorithm similar to what there's in libc memchr/strchr. * * NOTE: find_eom is not static as it is used by a unit test program. **/ const guchar * find_eom(const guchar *s, gsize n) { const guchar *char_ptr; const gulong *longword_ptr; gulong longword, magic_bits, charmask; gchar c; c = '\n'; /* align input to long boundary */ for (char_ptr = s; n > 0 && ((gulong) char_ptr & (sizeof(longword) - 1)) != 0; ++char_ptr, n--) { if (*char_ptr == c || *char_ptr == '\0') return char_ptr; } longword_ptr = (gulong *) char_ptr; #if GLIB_SIZEOF_LONG == 8 magic_bits = 0x7efefefefefefeffL; #elif GLIB_SIZEOF_LONG == 4 magic_bits = 0x7efefeffL; #else #error "unknown architecture" #endif memset(&charmask, c, sizeof(charmask)); while (n > sizeof(longword)) { longword = *longword_ptr++; if ((((longword + magic_bits) ^ ~longword) & ~magic_bits) != 0 || ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask)) & ~magic_bits) != 0) { gint i; char_ptr = (const guchar *) (longword_ptr - 1); for (i = 0; i < sizeof(longword); i++) { if (*char_ptr == c || *char_ptr == '\0') return char_ptr; char_ptr++; } } n -= sizeof(longword); } char_ptr = (const guchar *) longword_ptr; while (n-- > 0) { if (*char_ptr == c || *char_ptr == '\0') return char_ptr; ++char_ptr; } return NULL; } gboolean log_proto_server_validate_options_method(LogProtoServer *s) { return TRUE; } void log_proto_server_free_method(LogProtoServer *s) { log_transport_free(s->transport); } void log_proto_server_free(LogProtoServer *s) { if (s->free_fn) s->free_fn(s); g_free(s); } void log_proto_server_init(LogProtoServer *self, LogTransport *transport, const LogProtoServerOptions *options) { self->validate_options = log_proto_server_validate_options_method; self->free_fn = log_proto_server_free_method; self->options = options; self->transport = transport; } gboolean log_proto_server_options_set_encoding(LogProtoServerOptions *self, const gchar *encoding) { GIConv convert; g_free(self->encoding); self->encoding = g_strdup(encoding); /* validate encoding */ convert = g_iconv_open("utf-8", encoding); if (convert == (GIConv) -1) return FALSE; g_iconv_close(convert); return TRUE; } void log_proto_server_options_defaults(LogProtoServerOptions *options) { memset(options, 0, sizeof(*options)); options->max_msg_size = -1; options->init_buffer_size = -1; options->max_buffer_size = -1; options->position_tracking_enabled = FALSE; } void log_proto_server_options_init(LogProtoServerOptions *options, GlobalConfig *cfg) { if (options->initialized) return; if (options->max_msg_size == -1) { options->max_msg_size = cfg->log_msg_size; } if (options->max_buffer_size == -1) { if (options->encoding) { /* Based on the implementation of LogProtoTextServer, the buffer is yielded as a complete message when max_msg_size is reached and there is no EOM in the buffer. In worst case, the buffer contains max_msg_size - 1 bytes before the next fetch, which can be 6 times max_msg_size due to the utf8 conversion. And additional space is required because of the possible leftover bytes. */ options->max_buffer_size = 8 * options->max_msg_size; } else options->max_buffer_size = options->max_msg_size; } if (options->init_buffer_size == -1) options->init_buffer_size = MIN(options->max_msg_size, options->max_buffer_size); options->initialized = TRUE; } void log_proto_server_options_destroy(LogProtoServerOptions *options) { g_free(options->encoding); if (options->destroy) options->destroy(options); options->initialized = FALSE; } LogProtoServerFactory * log_proto_server_get_factory(PluginContext *context, const gchar *name) { Plugin *plugin; plugin = plugin_find(context, LL_CONTEXT_SERVER_PROTO, name); if (plugin && plugin->construct) return plugin->construct(plugin); return NULL; } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-server.h000066400000000000000000000132221321171025300233720ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_SERVER_H_INCLUDED #define LOGPROTO_SERVER_H_INCLUDED #include "logproto.h" #include "persist-state.h" #include "transport/transport-aux-data.h" #include "bookmark.h" typedef struct _LogProtoServer LogProtoServer; typedef struct _LogProtoServerOptions LogProtoServerOptions; #define LOG_PROTO_SERVER_OPTIONS_SIZE 128 struct _LogProtoServerOptions { void (*destroy)(LogProtoServerOptions *self); gboolean initialized; gchar *encoding; /* maximum message length in bytes */ gint max_msg_size; gint max_buffer_size; gint init_buffer_size; gboolean position_tracking_enabled; }; typedef union LogProtoServerOptionsStorage { LogProtoServerOptions super; gchar __padding[LOG_PROTO_SERVER_OPTIONS_SIZE]; } LogProtoServerOptionsStorage; gboolean log_proto_server_options_validate(const LogProtoServerOptions *options); gboolean log_proto_server_options_set_encoding(LogProtoServerOptions *s, const gchar *encoding); void log_proto_server_options_defaults(LogProtoServerOptions *options); void log_proto_server_options_init(LogProtoServerOptions *options, GlobalConfig *cfg); void log_proto_server_options_destroy(LogProtoServerOptions *options); struct _LogProtoServer { LogProtoStatus status; const LogProtoServerOptions *options; LogTransport *transport; /* FIXME: rename to something else */ gboolean (*is_position_tracked)(LogProtoServer *s); gboolean (*prepare)(LogProtoServer *s, GIOCondition *cond); gboolean (*restart_with_state)(LogProtoServer *s, PersistState *state, const gchar *persist_name); LogProtoStatus (*fetch)(LogProtoServer *s, const guchar **msg, gsize *msg_len, gboolean *may_read, LogTransportAuxData *aux, Bookmark *bookmark); gboolean (*validate_options)(LogProtoServer *s); void (*free_fn)(LogProtoServer *s); }; static inline gboolean log_proto_server_validate_options(LogProtoServer *self) { return self->validate_options(self); } static inline void log_proto_server_set_options(LogProtoServer *self, const LogProtoServerOptions *options) { self->options = options; } static inline gboolean log_proto_server_prepare(LogProtoServer *s, GIOCondition *cond) { return s->prepare(s, cond); } static inline gboolean log_proto_server_restart_with_state(LogProtoServer *s, PersistState *state, const gchar *persist_name) { if (s->restart_with_state) return s->restart_with_state(s, state, persist_name); return FALSE; } static inline LogProtoStatus log_proto_server_fetch(LogProtoServer *s, const guchar **msg, gsize *msg_len, gboolean *may_read, LogTransportAuxData *aux, Bookmark *bookmark) { if (s->status == LPS_SUCCESS) return s->fetch(s, msg, msg_len, may_read, aux, bookmark); return s->status; } static inline gint log_proto_server_get_fd(LogProtoServer *s) { /* FIXME: Layering violation, as transport may not be fd based at all. * But LogReader assumes it is. */ return s->transport->fd; } static inline void log_proto_server_reset_error(LogProtoServer *s) { s->status = LPS_SUCCESS; } static inline gboolean log_proto_server_is_position_tracked(LogProtoServer *s) { if (s->is_position_tracked) return s->is_position_tracked(s); return FALSE; } gboolean log_proto_server_validate_options_method(LogProtoServer *s); void log_proto_server_init(LogProtoServer *s, LogTransport *transport, const LogProtoServerOptions *options); void log_proto_server_free_method(LogProtoServer *s); void log_proto_server_free(LogProtoServer *s); #define DEFINE_LOG_PROTO_SERVER(prefix) \ static gpointer \ prefix ## _server_plugin_construct(Plugin *self) \ { \ static LogProtoServerFactory proto = { \ .construct = prefix ## _server_new, \ }; \ return &proto; \ } #define LOG_PROTO_SERVER_PLUGIN(prefix, __name) \ { \ .type = LL_CONTEXT_SERVER_PROTO, \ .name = __name, \ .construct = prefix ## _server_plugin_construct, \ } typedef struct _LogProtoServerFactory LogProtoServerFactory; struct _LogProtoServerFactory { LogProtoServer *(*construct)(LogTransport *transport, const LogProtoServerOptions *options); }; static inline LogProtoServer * log_proto_server_factory_construct(LogProtoServerFactory *self, LogTransport *transport, const LogProtoServerOptions *options) { return self->construct(transport, options); } LogProtoServerFactory *log_proto_server_get_factory(PluginContext *context, const gchar *name); const guchar *find_eom(const guchar *s, gsize n); #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-text-client.c000066400000000000000000000133231321171025300243210ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto-text-client.h" #include "messages.h" #include static gboolean log_proto_text_client_prepare(LogProtoClient *s, gint *fd, GIOCondition *cond) { LogProtoTextClient *self = (LogProtoTextClient *) s; *fd = self->super.transport->fd; *cond = self->super.transport->cond; /* if there's no pending I/O in the transport layer, then we want to do a write */ if (*cond == 0) *cond = G_IO_OUT; return self->partial != NULL; } static LogProtoStatus log_proto_text_client_flush(LogProtoClient *s) { LogProtoTextClient *self = (LogProtoTextClient *) s; gint rc; /* attempt to flush previously buffered data */ if (self->partial) { gint len = self->partial_len - self->partial_pos; rc = log_transport_write(self->super.transport, &self->partial[self->partial_pos], len); if (rc < 0) { if (errno != EAGAIN && errno != EINTR) { msg_error("I/O error occurred while writing", evt_tag_int("fd", self->super.transport->fd), evt_tag_errno(EVT_TAG_OSERROR, errno)); return LPS_ERROR; } return LPS_SUCCESS; } else if (rc != len) { self->partial_pos += rc; return LPS_SUCCESS; } else { if (self->partial_free) self->partial_free(self->partial); self->partial = NULL; if (self->next_state >= 0) { self->state = self->next_state; self->next_state = -1; } log_proto_client_msg_ack(&self->super, 1); /* NOTE: we return here to give a chance to the framed protocol to send the frame header. */ return LPS_SUCCESS; } } return LPS_SUCCESS; } LogProtoStatus log_proto_text_client_submit_write(LogProtoClient *s, guchar *msg, gsize msg_len, GDestroyNotify msg_free, gint next_state) { LogProtoTextClient *self = (LogProtoTextClient *) s; g_assert(self->partial == NULL); self->partial = msg; self->partial_len = msg_len; self->partial_pos = 0; self->partial_free = msg_free; self->next_state = next_state; return log_proto_text_client_flush(s); } /* * log_proto_text_client_post: * @msg: formatted log message to send (this might be consumed by this function) * @msg_len: length of @msg * @consumed: pointer to a gboolean that gets set if the message was consumed by this function * @error: error information, if any * * This function posts a message to the log transport, performing buffering * of partially sent data if needed. The return value indicates whether we * successfully sent this message, or if it should be resent by the caller. **/ static LogProtoStatus log_proto_text_client_post(LogProtoClient *s, guchar *msg, gsize msg_len, gboolean *consumed) { LogProtoTextClient *self = (LogProtoTextClient *) s; gint rc; /* try to flush already buffered data */ *consumed = FALSE; rc = log_proto_text_client_flush(s); if (rc == LPS_ERROR) { /* log_proto_flush() already logs in the case of an error */ return rc; } if (self->partial) { /* NOTE: the partial buffer has not been emptied yet even with the * flush above, we shouldn't attempt to write again. * * Otherwise: with the framed protocol this could case the frame * header to be split, and interleaved with message payload, as in: * * First bytes of frame header || payload || tail of frame header. * * This obviously would cause the framing to break. Also libssl * returns an error in this case, which is how this was discovered. */ return rc; } *consumed = TRUE; return log_proto_text_client_submit_write(s, msg, msg_len, (GDestroyNotify) g_free, -1); } void log_proto_text_client_free(LogProtoClient *s) { LogProtoTextClient *self = (LogProtoTextClient *)s; if (self->partial_free) self->partial_free(self->partial); self->partial = NULL; log_proto_client_free_method(s); }; void log_proto_text_client_init(LogProtoTextClient *self, LogTransport *transport, const LogProtoClientOptions *options) { log_proto_client_init(&self->super, transport, options); self->super.prepare = log_proto_text_client_prepare; self->super.flush = log_proto_text_client_flush; self->super.post = log_proto_text_client_post; self->super.free_fn = log_proto_text_client_free; self->super.transport = transport; self->next_state = -1; } LogProtoClient * log_proto_text_client_new(LogTransport *transport, const LogProtoClientOptions *options) { LogProtoTextClient *self = g_new0(LogProtoTextClient, 1); log_proto_text_client_init(self, transport, options); return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-text-client.h000066400000000000000000000033351321171025300243300ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_TEXT_CLIENT_H_INCLUDED #define LOGPROTO_TEXT_CLIENT_H_INCLUDED #include "logproto-client.h" typedef struct _LogProtoTextClient { LogProtoClient super; gint state, next_state; guchar *partial; GDestroyNotify partial_free; gsize partial_len, partial_pos; } LogProtoTextClient; LogProtoStatus log_proto_text_client_submit_write(LogProtoClient *s, guchar *msg, gsize msg_len, GDestroyNotify msg_free, gint next_state); void log_proto_text_client_init(LogProtoTextClient *self, LogTransport *transport, const LogProtoClientOptions *options); LogProtoClient *log_proto_text_client_new(LogTransport *transport, const LogProtoClientOptions *options); #define log_proto_text_client_free_method log_proto_client_free_method #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-text-server.c000066400000000000000000000345711321171025300243610ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto-text-server.h" #include "messages.h" #include /* * log_proto_get_fixed_encoding_scale: * * This function returns the number of bytes of a single character in the * encoding specified by the @encoding parameter, provided it is listed in * the limited set hard-wired in the fixed_encodings array above. * * syslog-ng sometimes needs to calculate the size of the original, raw data * that relates to its already utf8 converted input buffer. For that the * slow solution is to actually perform the utf8 -> raw conversion, however * since we don't really need the actual conversion, just the size of the * data in bytes we can be faster than that by multiplying the number of * input characters with the size of the character in the known * fixed-length-encodings in the list above. * * This function returns 0 if the encoding is not known, in which case the * slow path is to be executed. */ gint log_proto_get_char_size_for_fixed_encoding(const gchar *encoding) { static struct { const gchar *prefix; gint scale; } fixed_encodings[] = { { "ascii", 1 }, { "us-ascii", 1 }, { "iso-8859", 1 }, { "iso8859", 1 }, { "latin", 1 }, { "ucs2", 2 }, { "ucs-2", 2 }, { "ucs4", 4 }, { "ucs-4", 4 }, { "koi", 1 }, { "unicode", 2 }, { "windows", 1 }, { "wchar_t", sizeof(wchar_t) }, { NULL, 0 } }; gint scale = 0; gint i; for (i = 0; fixed_encodings[i].prefix; i++) { if (strncasecmp(encoding, fixed_encodings[i].prefix, strlen(fixed_encodings[i].prefix)) == 0) { scale = fixed_encodings[i].scale; break; } } return scale; } static gboolean log_proto_text_server_prepare(LogProtoServer *s, GIOCondition *cond) { LogProtoTextServer *self = (LogProtoTextServer *) s; gboolean avail; if (log_proto_buffered_server_prepare(s, cond)) { return TRUE; } avail = (self->cached_eol_pos != 0); return avail; } static void log_proto_text_server_maybe_realloc_reverse_buffer(LogProtoTextServer *self, gsize buffer_length) { if (self->reverse_buffer_len >= buffer_length) return; /* we free and malloc, since we never need the data still in reverse buffer */ g_free(self->reverse_buffer); self->reverse_buffer_len = buffer_length; self->reverse_buffer = g_malloc(buffer_length); } /* * returns the number of bytes that represent the UTF8 encoding buffer * in the original encoding that the user specified. * * NOTE: this is slow, but we only call this for the remainder of our * buffer (e.g. the partial line at the end of our last chunk of read * data). Also, this is only invoked if the file uses an encoding. */ static gsize log_proto_text_server_get_raw_size_of_buffer(LogProtoTextServer *self, const guchar *buffer, gsize buffer_len) { gchar *out; const guchar *in; gsize avail_out, avail_in; gint ret; if (self->reverse_convert == ((GIConv) -1) && !self->convert_scale) { /* try to speed up raw size calculation by recognizing the most * prominent character encodings and in the case the encoding * uses fixed size characters set that in self->convert_scale, * which in turn will speed up the reversal of the UTF8 buffer * size to raw buffer sizes. */ self->convert_scale = log_proto_get_char_size_for_fixed_encoding(self->super.super.options->encoding); if (self->convert_scale == 0) { /* this encoding is not known, do the conversion for real :( */ self->reverse_convert = g_iconv_open(self->super.super.options->encoding, "utf-8"); } } if (self->convert_scale) return g_utf8_strlen((gchar *) buffer, buffer_len) * self->convert_scale; /* Multiplied by 6, because 1 character can be maximum 6 bytes in UTF-8 encoding */ log_proto_text_server_maybe_realloc_reverse_buffer(self, buffer_len * 6); avail_out = self->reverse_buffer_len; out = self->reverse_buffer; avail_in = buffer_len; in = buffer; ret = g_iconv(self->reverse_convert, (gchar **) &in, &avail_in, &out, &avail_out); if (ret == (gsize) -1) { /* oops, we cannot reverse that we ourselves converted to UTF-8, * this is simply impossible, but never say never */ msg_error("Internal error, couldn't reverse the internal UTF8 string to the original encoding", evt_tag_printf("buffer", "%.*s", (gint) buffer_len, buffer)); return 0; } else { return self->reverse_buffer_len - avail_out; } } static gint log_proto_text_server_accumulate_line_method(LogProtoTextServer *self, const guchar *msg, gsize msg_len, gssize consumed_len) { return LPT_CONSUME_LINE | LPT_EXTRACTED; } static void log_proto_text_server_split_buffer(LogProtoTextServer *self, LogProtoBufferedServerState *state, const guchar *buffer_start, gsize buffer_bytes) { gsize raw_split_size; /* buffer is not full, but no EOL is present, move partial line * to the beginning of the buffer to make space for new data. */ memmove(self->super.buffer, buffer_start, buffer_bytes); state->pending_buffer_pos = 0; state->pending_buffer_end = buffer_bytes; if (G_UNLIKELY(self->super.pos_tracking)) { /* NOTE: we modify the current file position _after_ updating buffer_pos, since if we crash right here, at least we won't lose data on the next restart, but rather we duplicate some data */ if (self->super.super.options->encoding) raw_split_size = log_proto_text_server_get_raw_size_of_buffer(self, buffer_start, buffer_bytes); else raw_split_size = buffer_bytes; state->pending_raw_stream_pos += (gint64) (state->pending_raw_buffer_size - raw_split_size); state->pending_raw_buffer_size = raw_split_size; msg_trace("Buffer split", evt_tag_int("raw_split_size", raw_split_size), evt_tag_int("buffer_bytes", buffer_bytes)); } } static gboolean log_proto_text_server_try_extract(LogProtoTextServer *self, LogProtoBufferedServerState *state, const guchar *buffer_start, gsize buffer_bytes, const guchar *eol, const guchar **msg, gsize *msg_len) { gint verdict; guint32 next_line_pos; guint32 next_eol_pos = 0; next_line_pos = eol + 1 - self->super.buffer; if (state->pending_buffer_end != next_line_pos) { const guchar *eom; /* we have some more data in the buffer, check if we have a * subsequent EOL there. It indicates whether we need to * read further data, or the buffer already contains a * complete line */ eom = find_eom(self->super.buffer + next_line_pos, state->pending_buffer_end - next_line_pos); if (eom) next_eol_pos = eom - self->super.buffer; } *msg_len = eol - buffer_start; *msg = buffer_start; verdict = log_proto_text_server_accumulate_line(self, *msg, *msg_len, self->consumed_len); if (verdict & LPT_EXTRACTED) { if (verdict & LPT_CONSUME_LINE) { gint drop_length = (verdict & LPT_CONSUME_PARTIAL_AMOUNT_MASK) >> LPT_CONSUME_PARTIAL_AMOUNT_SHIFT; state->pending_buffer_pos = next_line_pos; self->cached_eol_pos = next_eol_pos; if (drop_length) *msg_len -= drop_length; } else if (verdict & LPT_REWIND_LINE) { if (self->consumed_len >= 0) *msg_len = self->consumed_len; else *msg_len = 0; state->pending_buffer_pos = (buffer_start + self->consumed_len + 1) - self->super.buffer; self->cached_eol_pos = eol - self->super.buffer; } else g_assert_not_reached(); self->consumed_len = -1; } else if (verdict & LPT_WAITING) { *msg = NULL; *msg_len = 0; if (verdict & LPT_CONSUME_LINE) { self->cached_eol_pos = next_eol_pos; self->consumed_len = eol - buffer_start; } else { /* when we are waiting for another line, the current one * can't be rewinded, so LPT_REWIND_LINE is not valid */ g_assert_not_reached(); } return FALSE; } else g_assert_not_reached(); return TRUE; } static gboolean log_proto_text_server_extract(LogProtoTextServer *self, LogProtoBufferedServerState *state, const guchar *buffer_start, gsize buffer_bytes, const guchar *eol, const guchar **msg, gsize *msg_len) { do { if (log_proto_text_server_try_extract(self, state, buffer_start, buffer_bytes, eol, msg, msg_len)) return TRUE; eol = self->super.buffer + self->cached_eol_pos; } while (self->cached_eol_pos > 0); return FALSE; } static void log_proto_text_server_remove_trailing_newline(const guchar **msg, gsize *msg_len) { const guchar *msg_start = (*msg); const guchar *msg_end = msg_start + (*msg_len); /* msg_end points at the newline character. A \r or \0 may precede * this which should be removed from the message body */ while ((msg_end > msg_start) && (msg_end[-1] == '\r' || msg_end[-1] == '\n' || msg_end[-1] == 0)) msg_end--; *msg_len = msg_end - msg_start; } static inline void log_proto_text_server_yield_whole_buffer_as_message(LogProtoTextServer *self, LogProtoBufferedServerState *state, const guchar *buffer_start, gsize buffer_bytes, const guchar **msg, gsize *msg_len) { /* no EOL, our buffer is full, no way to move forward, return * everything we have in our buffer. */ *msg = buffer_start; *msg_len = buffer_bytes; self->consumed_len = -1; state->pending_buffer_pos = (*msg) + (*msg_len) - self->super.buffer; } static inline const guchar * log_proto_text_server_locate_next_eol(LogProtoTextServer *self, LogProtoBufferedServerState *state, const guchar *buffer_start, gsize buffer_bytes) { const guchar *eol; if (self->cached_eol_pos) { /* previous invocation was nice enough to save a cached EOL * pointer, no need to look it up again */ eol = self->super.buffer + self->cached_eol_pos; self->cached_eol_pos = 0; } else { eol = find_eom(buffer_start + self->consumed_len + 1, buffer_bytes - self->consumed_len - 1); } return eol; } static gboolean log_proto_text_server_message_size_too_large(LogProtoTextServer *self, gsize buffer_bytes) { return buffer_bytes >= self->super.super.options->max_msg_size; } /** * log_proto_text_server_fetch_from_buffer: * @self: LogReader instance * @saddr: socket address to be assigned to new messages (consumed!) * @flush: whether to flush the input buffer * @msg_counter: the number of messages processed in the current poll iteration * * Returns TRUE if a message was found in the buffer, FALSE if we need to read again. **/ static gboolean log_proto_text_server_fetch_from_buffer(LogProtoBufferedServer *s, const guchar *buffer_start, gsize buffer_bytes, const guchar **msg, gsize *msg_len) { LogProtoTextServer *self = (LogProtoTextServer *) s; LogProtoBufferedServerState *state = log_proto_buffered_server_get_state(&self->super); gboolean result = FALSE; const guchar *eol = log_proto_text_server_locate_next_eol(self, state, buffer_start, buffer_bytes); if (!eol) { if (log_proto_text_server_message_size_too_large(self, buffer_bytes) || log_proto_buffered_server_is_input_closed(&self->super)) { log_proto_text_server_yield_whole_buffer_as_message(self, state, buffer_start, buffer_bytes, msg, msg_len); } else { log_proto_text_server_split_buffer(self, state, buffer_start, buffer_bytes); goto exit; } } else if (!log_proto_text_server_extract(self, state, buffer_start, buffer_bytes, eol, msg, msg_len)) { if (log_proto_text_server_message_size_too_large(self, buffer_bytes)) { log_proto_text_server_yield_whole_buffer_as_message(self, state, buffer_start, buffer_bytes, msg, msg_len); } else { log_proto_text_server_split_buffer(self, state, buffer_start, buffer_bytes); goto exit; } } log_proto_text_server_remove_trailing_newline(msg, msg_len); result = TRUE; exit: log_proto_buffered_server_put_state(&self->super); return result; } static void log_proto_text_server_free(LogProtoServer *s) { LogProtoTextServer *self = (LogProtoTextServer *) s; if (self->reverse_convert != (GIConv) -1) g_iconv_close(self->reverse_convert); g_free(self->reverse_buffer); log_proto_buffered_server_free_method(&self->super.super); } void log_proto_text_server_init(LogProtoTextServer *self, LogTransport *transport, const LogProtoServerOptions *options) { log_proto_buffered_server_init(&self->super, transport, options); self->super.super.prepare = log_proto_text_server_prepare; self->super.super.free_fn = log_proto_text_server_free; self->super.fetch_from_buffer = log_proto_text_server_fetch_from_buffer; self->accumulate_line = log_proto_text_server_accumulate_line_method; self->super.stream_based = TRUE; self->reverse_convert = (GIConv) -1; self->consumed_len = -1; } LogProtoServer * log_proto_text_server_new(LogTransport *transport, const LogProtoServerOptions *options) { LogProtoTextServer *self = g_new0(LogProtoTextServer, 1); log_proto_text_server_init(self, transport, options); return &self->super.super; } syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto-text-server.h000066400000000000000000000054151321171025300243610ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_TEXT_SERVER_INCLUDED #define LOGPROTO_TEXT_SERVER_INCLUDED #include "logproto-buffered-server.h" enum { LPT_EXTRACTED = 0x0001, LPT_WAITING = 0x0002, LPT_CONSUME_LINE = 0x0010, LPT_REWIND_LINE = 0x0020, }; #define LPT_CONSUME_PARTIAL_AMOUNT_SHIFT 8 #define LPT_CONSUME_PARTIAL_AMOUNT_MASK ~0xFF #define LPT_CONSUME_PARTIALLY(drop_length) (LPT_CONSUME_LINE | ((drop_length) << LPT_CONSUME_PARTIAL_AMOUNT_SHIFT)) typedef struct _LogProtoTextServer LogProtoTextServer; struct _LogProtoTextServer { LogProtoBufferedServer super; gint (*accumulate_line)(LogProtoTextServer *self, const guchar *msg, gsize msg_len, gssize consumed_len); GIConv reverse_convert; gchar *reverse_buffer; gsize reverse_buffer_len; gint convert_scale; gint32 consumed_len; gint32 cached_eol_pos; }; /* LogProtoTextServer * * This class processes text files/streams. Each record is terminated via an EOL character. */ LogProtoServer *log_proto_text_server_new(LogTransport *transport, const LogProtoServerOptions *options); void log_proto_text_server_init(LogProtoTextServer *self, LogTransport *transport, const LogProtoServerOptions *options); static inline gint log_proto_text_server_accumulate_line(LogProtoTextServer *self, const guchar *msg, gsize msg_len, gssize consumed_len) { return self->accumulate_line(self, msg, msg_len, consumed_len); } gint log_proto_get_char_size_for_fixed_encoding(const gchar *encoding); static inline gboolean log_proto_text_server_validate_options_method(LogProtoServer *s) { return log_proto_buffered_server_validate_options_method(s); } #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/logproto.h000066400000000000000000000022341321171025300220670ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPROTO_H_INCLUDED #define LOGPROTO_H_INCLUDED #include "transport/logtransport.h" typedef enum { LPS_SUCCESS, LPS_ERROR, LPS_EOF, } LogProtoStatus; #endif syslog-ng-syslog-ng-3.13.2/lib/logproto/tests/000077500000000000000000000000001321171025300212125ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/logproto/tests/Makefile.am000066400000000000000000000020361321171025300232470ustar00rootroot00000000000000lib_logproto_tests_TESTS = \ lib/logproto/tests/test_logproto \ lib/logproto/tests/test_findeom check_PROGRAMS += ${lib_logproto_tests_TESTS} lib_logproto_tests_test_logproto_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/logproto/tests lib_logproto_tests_test_logproto_LDADD = $(TEST_LDADD) lib_logproto_tests_test_logproto_SOURCES = \ lib/logproto/tests/test_logproto.c \ lib/logproto/tests/test_logproto.h \ lib/logproto/tests/test-server-options.c \ lib/logproto/tests/test-record-server.c \ lib/logproto/tests/test-text-server.c \ lib/logproto/tests/test-dgram-server.c \ lib/logproto/tests/test-framed-server.c \ lib/logproto/tests/test-indented-multiline-server.c \ lib/logproto/tests/test-regexp-multiline-server.c lib_logproto_tests_test_findeom_CFLAGS = \ $(TEST_CFLAGS) \ -I${top_srcdir}/libtest lib_logproto_tests_test_findeom_LDADD = \ ${top_builddir}/lib/libsyslog-ng.la \ ${top_builddir}/libtest/libsyslog-ng-test.a lib_logproto_tests_test_findeom_SOURCES = \ lib/logproto/tests/test_findeom.c syslog-ng-syslog-ng-3.13.2/lib/logproto/tests/test-dgram-server.c000066400000000000000000000162531321171025300247400ustar00rootroot00000000000000/* * Copyright (c) 2012-2013 Balabit * Copyright (c) 2012-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "mock-transport.h" #include "proto_lib.h" #include "msg_parse_lib.h" #include "logproto/logproto-dgram-server.h" /**************************************************************************************** * LogProtoDGramServer ****************************************************************************************/ static void test_log_proto_dgram_server_no_encoding(void) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; proto = log_proto_dgram_server_new( log_transport_mock_endless_records_new( "0123456789ABCDEF0123456789ABCDEF", -1, "01234567\n", -1, "01234567\0", 9, /* utf8 */ "árvíztűrőtükörfúrógép\n\n", 32, /* iso-8859-2 */ "\xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |árvíztűrőtükörfú| */ "\x72\xf3\x67\xe9\x70\n", -1, /* |rógép| */ /* ucs4 */ "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\x72", 32, /* |...z...t...ű...r| */ "01234", 5, LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "0123456789ABCDEF0123456789ABCDEF", -1); assert_proto_server_fetch(proto, "01234567\n", -1); assert_proto_server_fetch(proto, "01234567\0", 9); /* no encoding: utf8 remains utf8 */ assert_proto_server_fetch(proto, "árvíztűrőtükörfúrógép\n\n", -1); /* no encoding: iso-8859-2 remains iso-8859-2 */ assert_proto_server_fetch(proto, "\xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |.rv.zt.r.t.k.rf.| */ "\x72\xf3\x67\xe9\x70\n", /* |r.g.p| */ -1); /* no encoding, ucs4 becomes a string with embedded NULs */ assert_proto_server_fetch(proto, "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\x72", 32); /* |...z...t...ű...r| */ assert_proto_server_fetch(proto, "01234", -1); log_proto_server_free(proto); } static void test_log_proto_dgram_server_ucs4(void) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; log_proto_server_options_set_encoding(&proto_server_options, "ucs-4"); proto = log_proto_dgram_server_new( log_transport_mock_endless_records_new( /* ucs4, terminated by record size */ "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\x72", 32, /* |...z...t...ű...r| */ /* ucs4, terminated by ucs4 encododed NL at the end */ "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\n", 32, /* |...z...t...ű| */ LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "árvíztűr", -1); assert_proto_server_fetch(proto, "árvíztű\n", -1); log_proto_server_free(proto); } static void test_log_proto_dgram_server_invalid_ucs4(void) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; log_proto_server_options_set_encoding(&proto_server_options, "ucs-4"); proto = log_proto_dgram_server_new( /* 31 bytes record size */ log_transport_mock_endless_records_new( /* invalid ucs4, trailing zeroes at the end */ "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00", 31, /* |...z...t...ű...r| */ LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch_failure(proto, LPS_ERROR, "Byte sequence too short, cannot convert an individual frame in its entirety"); log_proto_server_free(proto); } static void test_log_proto_dgram_server_iso_8859_2(void) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; log_proto_server_options_set_encoding(&proto_server_options, "iso-8859-2"); proto = log_proto_dgram_server_new( log_transport_mock_endless_records_new( /* iso-8859-2, deliberately contains * accented chars so utf8 representation * becomes longer than the record size */ "\xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |árvíztűrőtükörfú| */ "\x72\xf3\x67\xe9\x70\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9", -1, /* |rógépééééééééééé| */ LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "árvíztűrőtükörfúrógépééééééééééé", -1); assert_proto_server_fetch_ignored_eof(proto); log_proto_server_free(proto); } static void test_log_proto_dgram_server_eof_handling(void) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; proto = log_proto_dgram_server_new( log_transport_mock_endless_records_new( /* no eol before EOF */ "01234567", -1, LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "01234567", -1); assert_proto_server_fetch_ignored_eof(proto); assert_proto_server_fetch_ignored_eof(proto); assert_proto_server_fetch_ignored_eof(proto); log_proto_server_free(proto); } void test_log_proto_dgram_server(void) { PROTO_TESTCASE(test_log_proto_dgram_server_no_encoding); PROTO_TESTCASE(test_log_proto_dgram_server_ucs4); PROTO_TESTCASE(test_log_proto_dgram_server_invalid_ucs4); PROTO_TESTCASE(test_log_proto_dgram_server_iso_8859_2); PROTO_TESTCASE(test_log_proto_dgram_server_eof_handling); } syslog-ng-syslog-ng-3.13.2/lib/logproto/tests/test-framed-server.c000066400000000000000000000201421321171025300250740ustar00rootroot00000000000000/* * Copyright (c) 2012-2013 Balabit * Copyright (c) 2012-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "mock-transport.h" #include "proto_lib.h" #include "msg_parse_lib.h" #include "logproto/logproto-framed-server.h" #include /**************************************************************************************** * LogProtoFramedServer ****************************************************************************************/ static void test_log_proto_framed_server_simple_messages(void) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; proto = log_proto_framed_server_new( log_transport_mock_stream_new( "32 0123456789ABCDEF0123456789ABCDEF", -1, "10 01234567\n\n", -1, "10 01234567\0\0", 13, /* utf8 */ "30 árvíztűrőtükörfúrógép", -1, /* iso-8859-2 */ "21 \xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |árvíztűrőtükörfú| */ "\x72\xf3\x67\xe9\x70", -1, /* |rógép| */ /* ucs4 */ "32 \x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\x72", 35, /* |...z...t...ű...r| */ LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "0123456789ABCDEF0123456789ABCDEF", -1); assert_proto_server_fetch(proto, "01234567\n\n", -1); assert_proto_server_fetch(proto, "01234567\0\0", 10); assert_proto_server_fetch(proto, "árvíztűrőtükörfúrógép", -1); assert_proto_server_fetch(proto, "\xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |.rv.zt.r.t.k.rf.| */ "\x72\xf3\x67\xe9\x70", -1); /* |r.g.p| */ assert_proto_server_fetch(proto, "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\x72", 32); /* |...z...t...q...r| */ assert_proto_server_fetch_failure(proto, LPS_EOF, NULL); log_proto_server_free(proto); } static void test_log_proto_framed_server_io_error(void) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; proto = log_proto_framed_server_new( log_transport_mock_stream_new( "32 0123456789ABCDEF0123456789ABCDEF", -1, LTM_INJECT_ERROR(EIO), LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "0123456789ABCDEF0123456789ABCDEF", -1); assert_proto_server_fetch_failure(proto, LPS_ERROR, "Error reading RFC5428 style framed data"); log_proto_server_free(proto); } static void test_log_proto_framed_server_invalid_header(void) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; proto = log_proto_framed_server_new( log_transport_mock_stream_new( "1q 0123456789ABCDEF0123456789ABCDEF", -1, LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch_failure(proto, LPS_ERROR, "Invalid frame header"); log_proto_server_free(proto); } static void test_log_proto_framed_server_too_long_line(void) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; proto = log_proto_framed_server_new( log_transport_mock_stream_new( "48 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF", -1, LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch_failure(proto, LPS_ERROR, "Incoming frame larger than log_msg_size()"); log_proto_server_free(proto); } static void test_log_proto_framed_server_message_exceeds_buffer(void) { LogProtoServer *proto; /* should cause the buffer to be extended, shifted, as the first message * resizes the buffer to 16+10 == 26 bytes. */ proto_server_options.max_msg_size = 32; proto = log_proto_framed_server_new( log_transport_mock_records_new( "16 0123456789ABCDE\n16 0123456789ABCDE\n", -1, LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "0123456789ABCDE\n", -1); assert_proto_server_fetch(proto, "0123456789ABCDE\n", -1); log_proto_server_free(proto); } static void test_log_proto_framed_server_buffer_shift_before_fetch(void) { LogProtoServer *proto; /* this testcase fills the initially 10 byte buffer with data, which * causes a shift in log_proto_framed_server_fetch() */ proto_server_options.max_msg_size = 32; proto_server_options.init_buffer_size = 10; proto_server_options.max_buffer_size = 10; proto = log_proto_framed_server_new( log_transport_mock_records_new( "7 012345\n4", 10, " 123\n", -1, LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "012345\n", -1); assert_proto_server_fetch(proto, "123\n", -1); log_proto_server_free(proto); } static void test_log_proto_framed_server_buffer_shift_to_make_space_for_a_frame(void) { LogProtoServer *proto; /* this testcase fills the initially 10 byte buffer with data, which * causes a shift in log_proto_framed_server_fetch() */ proto_server_options.max_msg_size = 32; proto_server_options.init_buffer_size = 10; proto_server_options.max_buffer_size = 10; proto = log_proto_framed_server_new( log_transport_mock_records_new( "6 01234\n4 ", 10, "123\n", -1, LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "01234\n", -1); assert_proto_server_fetch(proto, "123\n", -1); log_proto_server_free(proto); } static void test_log_proto_framed_server_multi_read(void) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; proto = log_proto_framed_server_new( log_transport_mock_records_new( "7 foobar\n", -1, /* no EOL, proto implementation would read another chunk */ "6 fooba", -1, LTM_INJECT_ERROR(EIO), LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "foobar\n", -1); /* with multi-read, we get the injected failure at the 2nd fetch */ assert_proto_server_fetch_failure(proto, LPS_ERROR, "Error reading RFC5428 style framed data"); log_proto_server_free(proto); /* NOTE: LPBS_NOMREAD is not implemented for framed protocol */ } void test_log_proto_framed_server(void) { PROTO_TESTCASE(test_log_proto_framed_server_simple_messages); PROTO_TESTCASE(test_log_proto_framed_server_io_error); PROTO_TESTCASE(test_log_proto_framed_server_invalid_header); PROTO_TESTCASE(test_log_proto_framed_server_too_long_line); PROTO_TESTCASE(test_log_proto_framed_server_message_exceeds_buffer); PROTO_TESTCASE(test_log_proto_framed_server_buffer_shift_before_fetch); PROTO_TESTCASE(test_log_proto_framed_server_buffer_shift_to_make_space_for_a_frame); PROTO_TESTCASE(test_log_proto_framed_server_multi_read); } syslog-ng-syslog-ng-3.13.2/lib/logproto/tests/test-indented-multiline-server.c000066400000000000000000000105751321171025300274410ustar00rootroot00000000000000/* * Copyright (c) 2012-2013 Balabit * Copyright (c) 2012-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "mock-transport.h" #include "proto_lib.h" #include "msg_parse_lib.h" #include "logproto/logproto-indented-multiline-server.h" /**************************************************************************************** * LogProtoIMultiLineServer ****************************************************************************************/ static void test_proper_multiline(gboolean input_is_stream) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; proto = log_proto_indented_multiline_server_new( /* 32 bytes max line length */ (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "0\n" " 1=2\n" " 3=4\n" "newline\n", -1, LTM_PADDING, LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "0\n" " 1=2\n" " 3=4", -1); log_proto_server_free(proto); } static void test_line_without_continuation(gboolean input_is_stream) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; proto = log_proto_indented_multiline_server_new( /* 32 bytes max line length */ (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new) ( "01234567\n", -1, "01234567\n", -1, "newline\n", -1, LTM_PADDING, LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "01234567", -1); assert_proto_server_fetch(proto, "01234567", -1); log_proto_server_free(proto); } static void test_input_starts_with_continuation(gboolean input_is_stream) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; proto = log_proto_indented_multiline_server_new( /* 32 bytes max line length */ (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new) ( " 01234567\n", -1, "01234567\n", -1, "newline\n", -1, LTM_PADDING, LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, " 01234567", -1); assert_proto_server_fetch(proto, "01234567", -1); log_proto_server_free(proto); } static void test_multiline_at_eof(gboolean input_is_stream) { LogProtoServer *proto; proto_server_options.max_msg_size = 32; proto = log_proto_indented_multiline_server_new( /* 32 bytes max line length */ (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new) ( "01234567\n", -1, " 01234567\n", -1, " end\n", -1, LTM_EOF), get_inited_proto_server_options()); assert_proto_server_fetch(proto, "01234567\n" " 01234567\n" " end", -1); assert_proto_server_fetch_failure(proto, LPS_EOF, NULL); log_proto_server_free(proto); } void test_log_proto_indented_multiline_server(void) { PROTO_TESTCASE(test_proper_multiline, FALSE); PROTO_TESTCASE(test_proper_multiline, TRUE); PROTO_TESTCASE(test_line_without_continuation, FALSE); PROTO_TESTCASE(test_input_starts_with_continuation, TRUE); PROTO_TESTCASE(test_multiline_at_eof, FALSE); PROTO_TESTCASE(test_multiline_at_eof, TRUE); } syslog-ng-syslog-ng-3.13.2/lib/logproto/tests/test-record-server.c000066400000000000000000000215341321171025300251220ustar00rootroot00000000000000/* * Copyright (c) 2012-2013 Balabit * Copyright (c) 2012-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "mock-transport.h" #include "proto_lib.h" #include "msg_parse_lib.h" #include "logproto/logproto-record-server.h" /**************************************************************************************** * LogProtoRecordServer ****************************************************************************************/ static void test_log_proto_binary_record_server_no_encoding(void) { LogProtoServer *proto; proto = log_proto_binary_record_server_new( log_transport_mock_records_new( "0123456789ABCDEF0123456789ABCDEF", -1, "01234567\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", -1, "01234567\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 32, /* utf8 */ "árvíztűrőtükörfúrógép\n\n", 32, /* iso-8859-2 */ "\xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |árvíztűrőtükörfú| */ "\x72\xf3\x67\xe9\x70\n\n\n\n\n\n\n\n\n\n\n", -1, /* |rógép| */ /* ucs4 */ "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\x72", 32, /* |...z...t...ű...r| */ "01234", 5, LTM_EOF), get_inited_proto_server_options(), 32); assert_proto_server_fetch(proto, "0123456789ABCDEF0123456789ABCDEF", -1); assert_proto_server_fetch(proto, "01234567\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", -1); assert_proto_server_fetch(proto, "01234567\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 32); assert_proto_server_fetch(proto, "árvíztűrőtükörfúrógép\n\n", -1); assert_proto_server_fetch(proto, "\xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |.rv.zt.r.t.k.rf.| */ "\x72\xf3\x67\xe9\x70\n\n\n\n\n\n\n\n\n\n\n", -1); /* |r.g.p| */ assert_proto_server_fetch(proto, "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\x72", 32); /* |...z...t...q...r| */ assert_proto_server_fetch_failure(proto, LPS_ERROR, "Record size was set, and couldn't read enough bytes"); log_proto_server_free(proto); } static void test_log_proto_padded_record_server_no_encoding(void) { LogProtoServer *proto; proto = log_proto_padded_record_server_new( log_transport_mock_records_new( "0123456789ABCDEF0123456789ABCDEF", -1, "01234567\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", -1, "01234567\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 32, /* utf8 */ "árvíztűrőtükörfúrógép\n\n", 32, /* iso-8859-2 */ "\xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |árvíztűrőtükörfú| */ "\x72\xf3\x67\xe9\x70\n\n\n\n\n\n\n\n\n\n\n", -1, /* |rógép| */ /* ucs4 */ "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\x72", 32, /* |...z...t...ű...r| */ "01234", 5, LTM_EOF), get_inited_proto_server_options(), 32); assert_proto_server_fetch(proto, "0123456789ABCDEF0123456789ABCDEF", -1); assert_proto_server_fetch(proto, "01234567", -1); assert_proto_server_fetch(proto, "01234567", -1); /* no encoding: utf8 remains utf8 */ assert_proto_server_fetch(proto, "árvíztűrőtükörfúrógép", -1); /* no encoding: iso-8859-2 remains iso-8859-2 */ assert_proto_server_fetch(proto, "\xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |.rv.zt.r.t.k.rf.| */ "\x72\xf3\x67\xe9\x70", /* |r.g.p| */ -1); /* no encoding, ucs4 becomes an empty string as it starts with a zero byte */ assert_proto_server_fetch(proto, "", -1); assert_proto_server_fetch_failure(proto, LPS_ERROR, "Record size was set, and couldn't read enough bytes"); log_proto_server_free(proto); } static void test_log_proto_padded_record_server_ucs4(void) { LogProtoServer *proto; log_proto_server_options_set_encoding(&proto_server_options, "ucs-4"); proto = log_proto_padded_record_server_new( log_transport_mock_records_new( /* ucs4, terminated by record size */ "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\x72", 32, /* |...z...t...ű...r| */ /* ucs4, terminated by ucs4 encododed NL at the end */ "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\n", 32, /* |...z...t...ű| */ "01234", 5, LTM_EOF), get_inited_proto_server_options(), 32); assert_proto_server_fetch(proto, "árvíztűr", -1); assert_proto_server_fetch(proto, "árvíztű", -1); assert_proto_server_fetch_failure(proto, LPS_ERROR, "Record size was set, and couldn't read enough bytes"); log_proto_server_free(proto); } static void test_log_proto_padded_record_server_invalid_ucs4(void) { LogProtoServer *proto; log_proto_server_options_set_encoding(&proto_server_options, "ucs-4"); proto = log_proto_padded_record_server_new( /* 31 bytes record size */ log_transport_mock_records_new( /* invalid ucs4, trailing zeroes at the end */ "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00", 31, /* |...z...t...ű...r| */ LTM_EOF), get_inited_proto_server_options(), 31); assert_proto_server_fetch_failure(proto, LPS_ERROR, "Byte sequence too short, cannot convert an individual frame in its entirety"); log_proto_server_free(proto); } static void test_log_proto_padded_record_server_iso_8859_2(void) { LogProtoServer *proto; log_proto_server_options_set_encoding(&proto_server_options, "iso-8859-2"); proto = log_proto_padded_record_server_new( /* 32 bytes record size */ log_transport_mock_records_new( /* iso-8859-2, deliberately contains * accented chars so utf8 representation * becomes longer than the record size */ "\xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |árvíztűrőtükörfú| */ "\x72\xf3\x67\xe9\x70\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9", -1, /* |rógépééééééééééé| */ LTM_EOF), get_inited_proto_server_options(), 32); assert_proto_server_fetch(proto, "árvíztűrőtükörfúrógépééééééééééé", -1); assert_proto_server_fetch_failure(proto, LPS_EOF, NULL); log_proto_server_free(proto); } void test_log_proto_record_server(void) { /* binary records are only tested in no-encoding mode, as there's only one * differing code-path that is used in LPRS_BINARY mode */ PROTO_TESTCASE(test_log_proto_binary_record_server_no_encoding); PROTO_TESTCASE(test_log_proto_padded_record_server_no_encoding); PROTO_TESTCASE(test_log_proto_padded_record_server_ucs4); PROTO_TESTCASE(test_log_proto_padded_record_server_invalid_ucs4); PROTO_TESTCASE(test_log_proto_padded_record_server_iso_8859_2); } syslog-ng-syslog-ng-3.13.2/lib/logproto/tests/test-regexp-multiline-server.c000066400000000000000000000175601321171025300271420ustar00rootroot00000000000000/* * Copyright (c) 2013-2014 Balabit * Copyright (c) 2013-2014 Balázs Scheidler * Copyright (c) 2014 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "mock-transport.h" #include "proto_lib.h" #include "msg_parse_lib.h" #include "logproto/logproto-regexp-multiline-server.h" /**************************************************************************************** * LogProtoREMultiLineServer ****************************************************************************************/ static void test_lines_separated_with_prefix(gboolean input_is_stream) { LogProtoServer *proto; MultiLineRegexp *re; proto = log_proto_prefix_garbage_multiline_server_new( /* 32 bytes max line length, which means that the complete * multi-line block plus one additional line must fit into 32 * bytes. */ (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "Foo First Line\n" "Foo Second Line\n" "Foo Third Line\n" "Foo Multiline\n" "multi\n" "Foo final\n", -1, LTM_PADDING, LTM_EOF), get_inited_proto_server_options(), re = multi_line_regexp_compile("^Foo", NULL), NULL); assert_proto_server_fetch(proto, "Foo First Line", -1); assert_proto_server_fetch(proto, "Foo Second Line", -1); assert_proto_server_fetch(proto, "Foo Third Line", -1); assert_proto_server_fetch(proto, "Foo Multiline\nmulti", -1); log_proto_server_free(proto); log_proto_server_options_destroy(&proto_server_options); multi_line_regexp_free(re); } static void test_lines_separated_with_prefix_and_garbage(gboolean input_is_stream) { LogProtoServer *proto; MultiLineRegexp *re1, *re2; proto = log_proto_prefix_garbage_multiline_server_new( /* 32 bytes max line length, which means that the complete * multi-line block plus one additional line must fit into 32 * bytes. */ (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "Foo First Line Bar\n" "Foo Second Line Bar\n" "Foo Third Line Bar\n" "Foo Multiline\n" "multi Bar\n" "Foo final\n", -1, LTM_PADDING, LTM_EOF), get_inited_proto_server_options(), re1 = multi_line_regexp_compile("^Foo", NULL), re2 = multi_line_regexp_compile(" Bar$", NULL)); assert_proto_server_fetch(proto, "Foo First Line", -1); assert_proto_server_fetch(proto, "Foo Second Line", -1); assert_proto_server_fetch(proto, "Foo Third Line", -1); assert_proto_server_fetch(proto, "Foo Multiline\nmulti", -1); log_proto_server_free(proto); log_proto_server_options_destroy(&proto_server_options); multi_line_regexp_free(re1); multi_line_regexp_free(re2); } static void test_lines_separated_with_prefix_and_suffix(gboolean input_is_stream) { LogProtoServer *proto; MultiLineRegexp *re1, *re2; proto = log_proto_prefix_suffix_multiline_server_new( /* 32 bytes max line length, which means that the complete * multi-line block plus one additional line must fit into 32 * bytes. */ (0 && input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "prefix first suffix garbage\n" "prefix multi\n" "suffix garbage\n" "prefix final\n", -1, LTM_PADDING, LTM_EOF), get_inited_proto_server_options(), re1 = multi_line_regexp_compile("^prefix", NULL), re2 = multi_line_regexp_compile("suffix", NULL)); assert_proto_server_fetch(proto, "prefix first suffix", -1); assert_proto_server_fetch(proto, "prefix multi\nsuffix", -1); log_proto_server_free(proto); log_proto_server_options_destroy(&proto_server_options); multi_line_regexp_free(re1); multi_line_regexp_free(re2); }; static void test_lines_separated_with_garbage(gboolean input_is_stream) { LogProtoServer *proto; MultiLineRegexp *re; proto = log_proto_prefix_garbage_multiline_server_new( /* 32 bytes max line length, which means that the complete * multi-line block plus one additional line must fit into 32 * bytes. */ (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "Foo First Line Bar\n" "Foo Second Line Bar\n" "Foo Third Line Bar\n" "Foo Multiline\n" "multi Bar\n" "Foo final\n", -1, LTM_PADDING, LTM_EOF), get_inited_proto_server_options(), NULL, re = multi_line_regexp_compile(" Bar$", NULL)); assert_proto_server_fetch(proto, "Foo First Line", -1); assert_proto_server_fetch(proto, "Foo Second Line", -1); assert_proto_server_fetch(proto, "Foo Third Line", -1); assert_proto_server_fetch(proto, "Foo Multiline\nmulti", -1); log_proto_server_free(proto); log_proto_server_options_destroy(&proto_server_options); multi_line_regexp_free(re); } static void test_first_line_without_prefix(gboolean input_is_stream) { LogProtoServer *proto; MultiLineRegexp *re; proto = log_proto_prefix_garbage_multiline_server_new( /* 32 bytes max line length, which means that the complete * multi-line block plus one additional line must fit into 32 * bytes. */ (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "First Line\n" "Foo Second Line\n" "Foo Third Line\n" "Foo Multiline\n" "multi\n" "Foo final\n", -1, LTM_PADDING, LTM_EOF), get_inited_proto_server_options(), re = multi_line_regexp_compile("^Foo", NULL), NULL); assert_proto_server_fetch(proto, "First Line", -1); assert_proto_server_fetch(proto, "Foo Second Line", -1); assert_proto_server_fetch(proto, "Foo Third Line", -1); assert_proto_server_fetch(proto, "Foo Multiline\nmulti", -1); log_proto_server_free(proto); log_proto_server_options_destroy(&proto_server_options); multi_line_regexp_free(re); } void test_log_proto_regexp_multiline_server(void) { PROTO_TESTCASE(test_lines_separated_with_prefix, FALSE); PROTO_TESTCASE(test_lines_separated_with_prefix, TRUE); PROTO_TESTCASE(test_lines_separated_with_prefix_and_garbage, FALSE); PROTO_TESTCASE(test_lines_separated_with_prefix_and_garbage, TRUE); PROTO_TESTCASE(test_lines_separated_with_prefix_and_suffix, FALSE); PROTO_TESTCASE(test_lines_separated_with_prefix_and_suffix, TRUE); PROTO_TESTCASE(test_lines_separated_with_garbage, FALSE); PROTO_TESTCASE(test_lines_separated_with_garbage, TRUE); PROTO_TESTCASE(test_first_line_without_prefix, FALSE); PROTO_TESTCASE(test_first_line_without_prefix, TRUE); } syslog-ng-syslog-ng-3.13.2/lib/logproto/tests/test-server-options.c000066400000000000000000000060131321171025300253320ustar00rootroot00000000000000/* * Copyright (c) 2012-2013 Balabit * Copyright (c) 2012-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "mock-transport.h" #include "proto_lib.h" #include "msg_parse_lib.h" static void test_log_proto_server_options_limits(void) { LogProtoServerOptions opts; log_proto_server_options_defaults(&opts); log_proto_server_options_init(&opts, configuration); assert_true(opts.max_msg_size > 0, "LogProtoServerOptions.max_msg_size is not initialized properly, max_msg_size=%d", opts.max_msg_size); assert_true(opts.init_buffer_size > 0, "LogProtoServerOptions.init_buffer_size is not initialized properly, init_buffer_size=%d", opts.init_buffer_size); assert_true(opts.max_buffer_size > 0, "LogProtoServerOptions.max_buffer_size is not initialized properly, max_buffer_size=%d", opts.max_buffer_size); log_proto_server_options_destroy(&opts); } static void test_log_proto_server_options_valid_encoding(void) { LogProtoServerOptions opts; log_proto_server_options_defaults(&opts); /* check that encoding can be set and error is properly returned */ log_proto_server_options_set_encoding(&opts, "utf-8"); assert_string(opts.encoding, "utf-8", "LogProtoServerOptions.encoding was not properly set"); log_proto_server_options_destroy(&opts); } static void test_log_proto_server_options_invalid_encoding(void) { LogProtoServerOptions opts; gboolean success; log_proto_server_options_defaults(&opts); success = log_proto_server_options_set_encoding(&opts, "never-ever-is-going-to-be-such-an-encoding"); assert_string(opts.encoding, "never-ever-is-going-to-be-such-an-encoding", "LogProtoServerOptions.encoding was not properly set"); log_proto_server_options_init(&opts, configuration); assert_false(success, "Successfully set a bogus encoding, which is insane"); log_proto_server_options_destroy(&opts); } /* abstract LogProtoServer methods */ void test_log_proto_server_options(void) { PROTO_TESTCASE(test_log_proto_server_options_limits); PROTO_TESTCASE(test_log_proto_server_options_valid_encoding); PROTO_TESTCASE(test_log_proto_server_options_invalid_encoding); } syslog-ng-syslog-ng-3.13.2/lib/logproto/tests/test-text-server.c000066400000000000000000000472451321171025300246370ustar00rootroot00000000000000/* * Copyright (c) 2012-2013 Balabit * Copyright (c) 2012-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "mock-transport.h" #include "proto_lib.h" #include "msg_parse_lib.h" #include "logproto/logproto-text-server.h" #include /**************************************************************************************** * LogProtoTextServer ****************************************************************************************/ LogProtoServer * construct_test_proto(LogTransport *transport) { proto_server_options.max_msg_size = 32; return log_proto_text_server_new(transport, get_inited_proto_server_options()); } static void test_log_proto_text_server_no_encoding(gboolean input_is_stream) { LogProtoServer *proto; proto = construct_test_proto( /* 32 bytes max line length */ (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "01234567\n" /* line too long */ "0123456789ABCDEF0123456789ABCDEF01234567\n" /* utf8 */ "árvíztűrőtükörfúrógép\n" /* iso-8859-2 */ "\xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |árvíztűrőtükörfú| */ "\x72\xf3\x67\xe9\x70\n", /* |rógép| */ -1, /* NUL terminated line */ "01234567\0" "01234567\0\n" "01234567\n\0" "01234567\r\n\0", 40, "01234567\r\n" /* no eol before EOF */ "01234567", -1, LTM_EOF)); assert_proto_server_fetch(proto, "01234567", -1); /* input split due to an oversized input line */ assert_proto_server_fetch(proto, "0123456789ABCDEF0123456789ABCDEF", -1); assert_proto_server_fetch(proto, "01234567", -1); assert_proto_server_fetch(proto, "árvíztűrőtükörfúrógép", -1); assert_proto_server_fetch(proto, "\xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |árvíztűrőtükörfú| */ "\x72\xf3\x67\xe9\x70", /* |rógép| */ -1); assert_proto_server_fetch(proto, "01234567", -1); assert_proto_server_fetch(proto, "01234567", -1); assert_proto_server_fetch(proto, "", -1); assert_proto_server_fetch(proto, "01234567", -1); assert_proto_server_fetch(proto, "", -1); assert_proto_server_fetch(proto, "01234567", -1); assert_proto_server_fetch(proto, "", -1); assert_proto_server_fetch(proto, "01234567", -1); assert_proto_server_fetch(proto, "01234567", -1); log_proto_server_free(proto); } static void test_log_proto_text_server_no_eol_before_eof(void) { LogProtoServer *proto; proto = construct_test_proto( log_transport_mock_stream_new( /* no eol before EOF */ "01234567", -1, LTM_EOF)); assert_proto_server_fetch(proto, "01234567", -1); assert_proto_server_fetch_failure(proto, LPS_EOF, NULL); log_proto_server_free(proto); } static void test_log_proto_text_server_eol_before_eof(void) { LogProtoServer *proto; proto = construct_test_proto( log_transport_mock_records_new( /* eol before EOF */ "01234\n567\n890\n", -1, LTM_INJECT_ERROR(EIO), LTM_EOF)); assert_proto_server_fetch(proto, "01234", -1); assert_proto_server_fetch(proto, "567", -1); assert_proto_server_fetch(proto, "890", -1); assert_proto_server_fetch_failure(proto, LPS_ERROR, NULL); log_proto_server_free(proto); } static void test_log_proto_text_server_io_error_before_eof(void) { LogProtoServer *proto; proto = construct_test_proto( log_transport_mock_stream_new( "01234567", -1, LTM_INJECT_ERROR(EIO), LTM_EOF)); assert_proto_server_fetch(proto, "01234567", -1); assert_proto_server_fetch_failure(proto, LPS_ERROR, NULL); log_proto_server_free(proto); } static void test_log_proto_text_server_partial_chars_before_eof(void) { LogProtoServer *proto; log_proto_server_options_set_encoding(&proto_server_options, "utf-8"); proto = construct_test_proto( log_transport_mock_stream_new( /* utf8 */ "\xc3", -1, LTM_EOF)); assert_true(log_proto_server_validate_options(proto), "validate_options() returned failure but it should have succeeded"); assert_proto_server_fetch_failure(proto, LPS_EOF, "EOF read on a channel with leftovers from previous character conversion, dropping input"); log_proto_server_free(proto); } static void test_log_proto_text_server_not_fixed_encoding(void) { LogProtoServer *proto; log_proto_server_options_set_encoding(&proto_server_options, "utf-8"); /* to test whether a non-easily-reversable charset works too */ proto = construct_test_proto( log_transport_mock_stream_new( /* utf8 */ "árvíztűrőtükörfúrógép\n", -1, LTM_EOF)); assert_true(log_proto_server_validate_options(proto), "validate_options() returned failure but it should have succeeded"); assert_proto_server_fetch(proto, "árvíztűrőtükörfúrógép", -1); assert_proto_server_fetch_failure(proto, LPS_EOF, NULL); log_proto_server_free(proto); } static void test_log_proto_text_server_ucs4(void) { LogProtoServer *proto; log_proto_server_options_set_encoding(&proto_server_options, "ucs-4"); proto = construct_test_proto( log_transport_mock_stream_new( /* ucs4 */ "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\x72" /* |...z...t...ű...r| */ "\x00\x00\x01\x51\x00\x00\x00\x74\x00\x00\x00\xfc\x00\x00\x00\x6b" /* |...Q...t.......k| */ "\x00\x00\x00\xf6\x00\x00\x00\x72\x00\x00\x00\x66\x00\x00\x00\xfa" /* |.......r...f....| */ "\x00\x00\x00\x72\x00\x00\x00\xf3\x00\x00\x00\x67\x00\x00\x00\xe9" /* |...r.......g....| */ "\x00\x00\x00\x70\x00\x00\x00\x0a", 88, /* |...p....| */ LTM_EOF)); assert_true(log_proto_server_validate_options(proto), "validate_options() returned failure but it should have succeeded"); assert_proto_server_fetch(proto, "árvíztűrőtükörfúrógép", -1); assert_proto_server_fetch_failure(proto, LPS_EOF, NULL); log_proto_server_free(proto); } static void test_log_proto_text_server_iso8859_2(void) { LogProtoServer *proto; log_proto_server_options_set_encoding(&proto_server_options, "iso-8859-2"); proto = construct_test_proto( log_transport_mock_stream_new( /* iso-8859-2 */ "\xe1\x72\x76\xed\x7a\x74\xfb\x72\xf5\x74\xfc\x6b\xf6\x72\x66\xfa" /* |árvíztűrőtükörfú| */ "\x72\xf3\x67\xe9\x70\n", -1, /* |rógép| */ LTM_EOF)); assert_true(log_proto_server_validate_options(proto), "validate_options() returned failure but it should have succeeded"); assert_proto_server_fetch(proto, "árvíztűrőtükörfúrógép", -1); assert_proto_server_fetch_failure(proto, LPS_EOF, NULL); log_proto_server_free(proto); } static void test_log_proto_text_server_invalid_encoding(void) { LogProtoServer *proto; gboolean success; log_proto_server_options_set_encoding(&proto_server_options, "never-ever-is-going-to-be-such-an-encoding"); proto = construct_test_proto( log_transport_mock_stream_new( "", -1, LTM_EOF)); start_grabbing_messages(); success = log_proto_server_validate_options(proto); assert_grabbed_messages_contain("Unknown character set name specified; encoding='never-ever-is-going-to-be-such-an-encoding'", "message about unknown charset missing"); assert_false(success, "validate_options() returned success but it should have failed"); log_proto_server_free(proto); } static void test_log_proto_text_server_multi_read(void) { LogProtoServer *proto; proto = construct_test_proto( log_transport_mock_records_new( "foobar\n", -1, /* no EOL, proto implementation would read another chunk */ "foobaz", -1, LTM_INJECT_ERROR(EIO), LTM_EOF)); assert_proto_server_fetch(proto, "foobar", -1); assert_proto_server_fetch(proto, "foobaz", -1); assert_proto_server_fetch_failure(proto, LPS_ERROR, NULL); log_proto_server_free(proto); } static void test_log_proto_text_server_multi_read_not_allowed(void) { /* FIXME: */ #if 0 LogProtoServer *proto; proto = construct_test_proto( log_transport_mock_records_new( "foobar\n", -1, /* no EOL, proto implementation would read another chunk */ "foobaz", -1, LTM_INJECT_ERROR(EIO), LTM_EOF)); ((LogProtoBufferedServer *) proto)->no_multi_read = TRUE; assert_proto_server_fetch_single_read(proto, "foobar", -1); /* because of EAGAIN */ assert_proto_server_fetch_single_read(proto, NULL, -1); /* because of NOMREAD, partial lines are returned as empty */ assert_proto_server_fetch_single_read(proto, NULL, -1); /* because of EAGAIN */ assert_proto_server_fetch_single_read(proto, NULL, -1); /* error was detected by this time, partial line is returned before the error */ assert_proto_server_fetch_single_read(proto, "foobaz", -1); /* finally the error is returned too */ assert_proto_server_fetch_failure(proto, LPS_ERROR, NULL); log_proto_server_free(proto); #endif } LogProtoServer * construct_test_proto_with_accumulator(gint (*accumulator)(LogProtoTextServer *, const guchar *, gsize, gssize), LogTransport *transport) { LogProtoServer *proto = construct_test_proto(transport); ((LogProtoTextServer *) proto)->accumulate_line = accumulator; return proto; } static gint accumulate_seq; static gint accumulator_delay_lines(LogProtoTextServer *self, const guchar *msg, gsize msg_len, gssize consumed_len) { accumulate_seq++; if ((accumulate_seq % 2) == 0) return LPT_REWIND_LINE | LPT_EXTRACTED; else return LPT_CONSUME_LINE | LPT_WAITING; } static void test_log_proto_text_server_is_not_fetching_input_as_long_as_there_is_an_eol_in_buffer(void) { LogProtoServer *proto; accumulate_seq = 0; proto = construct_test_proto_with_accumulator( accumulator_delay_lines, log_transport_mock_records_new( /* should the LogProto instance read ahead, it gets an * EIO error */ "foo\n" "bar\n" "baz\n" "booz\n", -1, LTM_INJECT_ERROR(EIO), LTM_EOF)); assert_proto_server_fetch(proto, "foo", -1); assert_proto_server_fetch(proto, "bar", -1); assert_proto_server_fetch(proto, "baz", -1); assert_proto_server_fetch(proto, "booz", -1); assert_proto_server_fetch_failure(proto, LPS_ERROR, NULL); log_proto_server_free(proto); } static gint accumulator_assert_that_lines_are_starting_with_sequence_number(LogProtoTextServer *self, const guchar *msg, gsize msg_len, gssize consumed_len) { assert_true((msg[0] - '0') == accumulate_seq, "accumulate_line: Message doesn't start with sequence number, msg=%.*s, seq=%d", msg_len, msg, accumulate_seq); assert_gint(consumed_len, -1, "Initial invocation of the accumulator expects -1 as consumed_len"); accumulate_seq++; return LPT_CONSUME_LINE | LPT_EXTRACTED; } static void test_log_proto_text_server_accumulate_line_is_called_for_each_line(gboolean input_is_stream) { LogProtoServer *proto; accumulate_seq = 0; proto = construct_test_proto_with_accumulator( accumulator_assert_that_lines_are_starting_with_sequence_number, /* 32 bytes max line length */ (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "0 line\n" "1 line\n" "2 line\n" "3 line\n", -1, LTM_PADDING, LTM_EOF)); assert_proto_server_fetch(proto, "0 line", -1); assert_proto_server_fetch(proto, "1 line", -1); assert_proto_server_fetch(proto, "2 line", -1); assert_proto_server_fetch(proto, "3 line", -1); log_proto_server_free(proto); } static gint accumulator_extract_pairs(LogProtoTextServer *self, const guchar *msg, gsize msg_len, gssize consumed_len) { accumulate_seq++; if ((accumulate_seq % 2) == 0) return LPT_CONSUME_LINE | LPT_EXTRACTED; else return LPT_CONSUME_LINE | LPT_WAITING; } static void test_log_proto_text_server_accumulate_line_can_consume_lines_without_returning_them(gboolean input_is_stream) { LogProtoServer *proto; accumulate_seq = 0; proto = construct_test_proto_with_accumulator( accumulator_extract_pairs, (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "0 line\n" "1 line\n" "2 line\n" "3 line\n", -1, LTM_PADDING, LTM_EOF)); assert_proto_server_fetch(proto, "0 line\n1 line", -1); assert_proto_server_fetch(proto, "2 line\n3 line", -1); log_proto_server_free(proto); } static gint accumulator_join_continuation_lines(LogProtoTextServer *self, const guchar *msg, gsize msg_len, gssize consumed_len) { if (consumed_len >= 0 && msg_len > consumed_len + 1) { gchar first_char = msg[consumed_len + 1]; if (first_char == ' ') return LPT_CONSUME_LINE | LPT_WAITING; else return LPT_REWIND_LINE | LPT_EXTRACTED; } else { return LPT_CONSUME_LINE | LPT_WAITING; } } static void test_log_proto_text_server_accumulate_line_can_rewind_lines_if_uninteresting(gboolean input_is_stream) { LogProtoServer *proto; accumulate_seq = 0; proto = construct_test_proto_with_accumulator( accumulator_join_continuation_lines, (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "0 line\n" " line\n" "2 line\n" " line\n" "3 end\n", -1, LTM_PADDING, LTM_EOF)); assert_proto_server_fetch(proto, "0 line\n line", -1); assert_proto_server_fetch(proto, "2 line\n line", -1); log_proto_server_free(proto); } static void test_log_proto_text_server_accumulation_terminated_if_input_is_closed(gboolean input_is_stream) { LogProtoServer *proto; accumulate_seq = 0; proto = construct_test_proto_with_accumulator( accumulator_join_continuation_lines, (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "0 line\n" " line\n" "1 line\n", -1, LTM_EOF)); assert_proto_server_fetch(proto, "0 line\n line", -1); assert_proto_server_fetch(proto, "1 line", -1); log_proto_server_free(proto); } static void test_log_proto_text_server_accumulation_terminated_if_buffer_full(gboolean input_is_stream) { LogProtoServer *proto; accumulate_seq = 0; proto = construct_test_proto_with_accumulator( accumulator_join_continuation_lines, (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "0123456789abcdef\n" " 0123456789abcdef\n" " continuation\n", -1, LTM_EOF)); assert_proto_server_fetch(proto, "0123456789abcdef\n 0123456789abcd", -1); assert_proto_server_fetch(proto, "ef\n continuation", -1); log_proto_server_free(proto); } static gint accumulator_rewind_initial(LogProtoTextServer *self, const guchar *msg, gsize msg_len, gssize consumed_len) { accumulate_seq++; if (accumulate_seq == 1) return LPT_REWIND_LINE | LPT_EXTRACTED; return LPT_CONSUME_LINE | LPT_EXTRACTED; } static void test_log_proto_text_server_rewinding_the_initial_line_results_in_an_empty_message(gboolean input_is_stream) { LogProtoServer *proto; accumulate_seq = 0; proto = construct_test_proto_with_accumulator( accumulator_rewind_initial, (input_is_stream ? log_transport_mock_stream_new : log_transport_mock_records_new)( "0 line\n" "1 line\n" "2 line\n", -1, LTM_PADDING, LTM_EOF)); assert_proto_server_fetch(proto, "", -1); assert_proto_server_fetch(proto, "0 line", -1); assert_proto_server_fetch(proto, "1 line", -1); assert_proto_server_fetch(proto, "2 line", -1); log_proto_server_free(proto); } void test_log_proto_text_server(void) { PROTO_TESTCASE(test_log_proto_text_server_no_encoding, FALSE); PROTO_TESTCASE(test_log_proto_text_server_no_encoding, TRUE); PROTO_TESTCASE(test_log_proto_text_server_no_eol_before_eof); PROTO_TESTCASE(test_log_proto_text_server_eol_before_eof); PROTO_TESTCASE(test_log_proto_text_server_io_error_before_eof); PROTO_TESTCASE(test_log_proto_text_server_partial_chars_before_eof); PROTO_TESTCASE(test_log_proto_text_server_not_fixed_encoding); PROTO_TESTCASE(test_log_proto_text_server_ucs4); PROTO_TESTCASE(test_log_proto_text_server_iso8859_2); PROTO_TESTCASE(test_log_proto_text_server_invalid_encoding); PROTO_TESTCASE(test_log_proto_text_server_multi_read); PROTO_TESTCASE(test_log_proto_text_server_multi_read_not_allowed); PROTO_TESTCASE(test_log_proto_text_server_is_not_fetching_input_as_long_as_there_is_an_eol_in_buffer); PROTO_TESTCASE(test_log_proto_text_server_accumulation_terminated_if_input_is_closed, FALSE); PROTO_TESTCASE(test_log_proto_text_server_accumulation_terminated_if_input_is_closed, TRUE); PROTO_TESTCASE(test_log_proto_text_server_accumulation_terminated_if_buffer_full, TRUE); PROTO_TESTCASE(test_log_proto_text_server_accumulation_terminated_if_buffer_full, FALSE); PROTO_TESTCASE(test_log_proto_text_server_rewinding_the_initial_line_results_in_an_empty_message, FALSE); PROTO_TESTCASE(test_log_proto_text_server_rewinding_the_initial_line_results_in_an_empty_message, TRUE); PROTO_TESTCASE(test_log_proto_text_server_accumulate_line_is_called_for_each_line, FALSE); PROTO_TESTCASE(test_log_proto_text_server_accumulate_line_is_called_for_each_line, TRUE); PROTO_TESTCASE(test_log_proto_text_server_accumulate_line_can_consume_lines_without_returning_them, TRUE); PROTO_TESTCASE(test_log_proto_text_server_accumulate_line_can_consume_lines_without_returning_them, FALSE); PROTO_TESTCASE(test_log_proto_text_server_accumulate_line_can_rewind_lines_if_uninteresting, TRUE); PROTO_TESTCASE(test_log_proto_text_server_accumulate_line_can_rewind_lines_if_uninteresting, FALSE); } syslog-ng-syslog-ng-3.13.2/lib/logproto/tests/test_findeom.c000066400000000000000000000073041321171025300240420ustar00rootroot00000000000000/* * Copyright (c) 2008-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto/logproto-server.h" #include "logmsg/logmsg.h" #include static void testcase(const gchar *msg_, gsize msg_len, gint eom_ofs) { const guchar *eom; const guchar *msg = (const guchar *) msg_; eom = find_eom((guchar *) msg, msg_len); if (eom_ofs == -1 && eom != NULL) { fprintf(stderr, "EOM returned is not NULL, which was expected. eom_ofs=%d, eom=%s\n", eom_ofs, eom); exit(1); } if (eom_ofs == -1) return; if (eom - msg != eom_ofs) { fprintf(stderr, "EOM is at wrong location. msg=%s, eom_ofs=%d, eom=%s\n", msg, eom_ofs, eom); exit(1); } } int main(void) { testcase("a\nb\nc\n", 6, 1); testcase("ab\nb\nc\n", 7, 2); testcase("abc\nb\nc\n", 8, 3); testcase("abcd\nb\nc\n", 9, 4); testcase("abcde\nb\nc\n", 10, 5); testcase("abcdef\nb\nc\n", 11, 6); testcase("abcdefg\nb\nc\n", 12, 7); testcase("abcdefgh\nb\nc\n", 13, 8); testcase("abcdefghi\nb\nc\n", 14, 9); testcase("abcdefghij\nb\nc\n", 15, 10); testcase("abcdefghijk\nb\nc\n", 16, 11); testcase("abcdefghijkl\nb\nc\n", 17, 12); testcase("abcdefghijklm\nb\nc\n", 18, 13); testcase("abcdefghijklmn\nb\nc\n", 19, 14); testcase("abcdefghijklmno\nb\nc\n", 20, 15); testcase("abcdefghijklmnop\nb\nc\n", 21, 16); testcase("abcdefghijklmnopq\nb\nc\n", 22, 17); testcase("abcdefghijklmnopqr\nb\nc\n", 23, 18); testcase("abcdefghijklmnopqrs\nb\nc\n", 24, 19); testcase("abcdefghijklmnopqrst\nb\nc\n", 25, 20); testcase("abcdefghijklmnopqrstu\nb\nc\n", 26, 21); testcase("abcdefghijklmnopqrstuv\nb\nc\n", 27, 22); testcase("abcdefghijklmnopqrstuvw\nb\nc\n", 28, 23); testcase("abcdefghijklmnopqrstuvwx\nb\nc\n", 29, 24); testcase("abcdefghijklmnopqrstuvwxy\nb\nc\n", 30, 25); testcase("abcdefghijklmnopqrstuvwxyz\nb\nc\n", 31, 26); testcase("a", 1, -1); testcase("ab", 2, -1); testcase("abc", 3, -1); testcase("abcd", 4, -1); testcase("abcde", 5, -1); testcase("abcdef", 6, -1); testcase("abcdefg", 7, -1); testcase("abcdefgh", 8, -1); testcase("abcdefghi", 9, -1); testcase("abcdefghij", 10, -1); testcase("abcdefghijk", 11, -1); testcase("abcdefghijkl", 12, -1); testcase("abcdefghijklm", 13, -1); testcase("abcdefghijklmn", 14, -1); testcase("abcdefghijklmno", 15, -1); testcase("abcdefghijklmnop", 16, -1); testcase("abcdefghijklmnopq", 17, -1); testcase("abcdefghijklmnopqr", 18, -1); testcase("abcdefghijklmnopqrs", 19, -1); testcase("abcdefghijklmnopqrst", 20, -1); testcase("abcdefghijklmnopqrstu", 21, -1); testcase("abcdefghijklmnopqrstuv", 22, -1); testcase("abcdefghijklmnopqrstuvw", 23, -1); testcase("abcdefghijklmnopqrstuvwx", 24, -1); testcase("abcdefghijklmnopqrstuvwxy", 25, -1); testcase("abcdefghijklmnopqrstuvwxyz", 26, -1); return 0; } syslog-ng-syslog-ng-3.13.2/lib/logproto/tests/test_logproto.c000066400000000000000000000071771321171025300242760ustar00rootroot00000000000000/* * Copyright (c) 2012-2013 Balabit * Copyright (c) 2012-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "test_logproto.h" #include "mock-transport.h" #include "proto_lib.h" #include "msg_parse_lib.h" #include "logproto/logproto-text-server.h" #include "logproto/logproto-framed-server.h" #include "logproto/logproto-dgram-server.h" #include "logproto/logproto-record-server.h" #include "apphook.h" static void test_log_proto_base(void) { LogProtoServer *proto; assert_gint(log_proto_get_char_size_for_fixed_encoding("iso-8859-2"), 1, NULL); assert_gint(log_proto_get_char_size_for_fixed_encoding("ucs-4"), 4, NULL); log_proto_server_options_set_encoding(&proto_server_options, "ucs-4"); proto = log_proto_binary_record_server_new( log_transport_mock_records_new( /* ucs4, terminated by record size */ "\x00\x00\x00\xe1\x00\x00\x00\x72\x00\x00\x00\x76\x00\x00\x00\xed" /* |...á...r...v...í| */ "\x00\x00\x00\x7a\x00\x00\x00\x74\x00\x00\x01\x71\x00\x00\x00\x72", 32, /* |...z...t...ű...r| */ LTM_EOF), get_inited_proto_server_options(), 32); /* check if error state is not forgotten unless reset_error is called */ proto->status = LPS_ERROR; assert_proto_server_status(proto, proto->status , LPS_ERROR); assert_proto_server_fetch_failure(proto, LPS_ERROR, NULL); log_proto_server_reset_error(proto); assert_proto_server_fetch(proto, "árvíztűr", -1); assert_proto_server_status(proto, proto->status, LPS_SUCCESS); log_proto_server_free(proto); log_proto_server_options_destroy(&proto_server_options); } static void test_log_proto(void) { /* * Things that are yet to be done: * * log_proto_text_server_new * - apply-state/restart_with_state * - questions: maybe move this to a separate LogProtoFileReader? * - apply state: * - same file, continued: same inode, size grown, * - truncated file: same inode, size smaller * - file starts over, all state data is reset! * - buffer: * - no encoding * - encoding: utf8, ucs4, koi8r * - state version: v1, v2, v3, v4 * - queued * - saddr caching * * log_proto_text_client_new * log_proto_file_writer_new * log_proto_framed_client_new */ test_log_proto_server_options(); test_log_proto_base(); test_log_proto_record_server(); test_log_proto_text_server(); test_log_proto_indented_multiline_server(); test_log_proto_regexp_multiline_server(); test_log_proto_dgram_server(); test_log_proto_framed_server(); } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { app_startup(); init_proto_tests(); test_log_proto(); deinit_proto_tests(); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/logproto/tests/test_logproto.h000066400000000000000000000025531321171025300242740ustar00rootroot00000000000000/* * Copyright (c) 2012-2013 Balabit * Copyright (c) 2012-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TEST_LOGPROTO_H_INCLUDED #define TEST_LOGPROTO_H_INCLUDED void test_log_proto_server_options(void); void test_log_proto_record_server(void); void test_log_proto_text_server(void); void test_log_proto_indented_multiline_server(void); void test_log_proto_regexp_multiline_server(void); void test_log_proto_dgram_server(void); void test_log_proto_framed_server(void); #endif syslog-ng-syslog-ng-3.13.2/lib/logqueue-fifo.c000066400000000000000000000453761321171025300211350ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logqueue.h" #include "logpipe.h" #include "messages.h" #include "serialize.h" #include "stats/stats-registry.h" #include "mainloop-worker.h" #include #include #include #include #include #include const QueueType log_queue_fifo_type = "FIFO"; /* * LogFifo is a scalable first-in-first-output queue implementation, that: * * - has a per-thread, unlocked input queue where threads can put their items * * - has a locked wait-queue where items go once the per-thread input * would be overflown or if the input thread goes to sleep (e.g. one * lock acquisition per a longer period) * * - has an unlocked output queue where items from the wait queue go, once * it becomes depleted. * * This means that items flow in this sequence from one list to the next: * * input queue (per-thread) -> wait queue (locked) -> output queue (single-threaded) * * Fastpath is: * - input threads putting elements on their per-thread queue (lockless) * - output threads removing elements from the output queue (lockless) * * Slowpath: * - input queue is overflown (or the input thread goes to sleep), wait * queue mutex is grabbed, all elements are put to the wait queue. * * - output queue is depleted, wait queue mutex is grabbed, all elements * on the wait queue is put to the output queue * * Threading assumptions: * - the head of the queue is only manipulated from the output thread * - the tail of the queue is only manipulated from the input threads * */ typedef struct _LogQueueFifo { LogQueue super; /* scalable qoverflow implementation */ struct iv_list_head qoverflow_output; struct iv_list_head qoverflow_wait; gint qoverflow_wait_len; gint qoverflow_output_len; gint qoverflow_size; /* in number of elements */ struct iv_list_head qbacklog; /* entries that were sent but not acked yet */ gint qbacklog_len; struct { struct iv_list_head items; WorkerBatchCallback cb; guint16 len; guint16 finish_cb_registered; } qoverflow_input[0]; } LogQueueFifo; /* NOTE: this is inherently racy. If the LogQueue->lock is taken, then the * race is limited to the changes in qoverflow_output queue changes. * * In the output thread, this means that this can get race-free. In the * input thread, the qoverflow_output can change because of a * log_queue_fifo_push_head() or log_queue_fifo_rewind_backlog(). * */ static void iv_list_update_msg_size(LogQueueFifo *self, struct iv_list_head *head) { LogMessage *msg; struct iv_list_head *ilh, *ilh2; iv_list_for_each_safe(ilh, ilh2, head) { msg = iv_list_entry(ilh, LogMessageQueueNode, list)->msg; stats_counter_add(self->super.memory_usage, log_msg_get_size(msg)); } } static gint64 log_queue_fifo_get_length(LogQueue *s) { LogQueueFifo *self = (LogQueueFifo *) s; return self->qoverflow_wait_len + self->qoverflow_output_len; } gboolean log_queue_fifo_is_empty_racy(LogQueue *s) { LogQueueFifo *self = (LogQueueFifo *) s; gboolean has_message_in_queue = FALSE; g_static_mutex_lock(&self->super.lock); if (log_queue_fifo_get_length(s) > 0) { has_message_in_queue = TRUE; } else { gint i; for (i = 0; i < log_queue_max_threads && !has_message_in_queue; i++) { has_message_in_queue |= self->qoverflow_input[i].finish_cb_registered; } } g_static_mutex_unlock(&self->super.lock); return !has_message_in_queue; } /* NOTE: this is inherently racy, can only be called if log processing is suspended (e.g. reload time) */ static gboolean log_queue_fifo_keep_on_reload(LogQueue *s) { LogQueueFifo *self = (LogQueueFifo *) s; return log_queue_fifo_get_length(s) > 0 || self->qbacklog_len > 0; } /* move items from the per-thread input queue to the lock-protected "wait" queue */ static void log_queue_fifo_move_input_unlocked(LogQueueFifo *self, gint thread_id) { gint queue_len; /* since we're in the input thread, queue_len will be racy. It can * increase due to log_queue_fifo_push_head() and can also decrease as * items are removed from the output queue using log_queue_pop_head(). * * The only reason we're using it here is to check for qoverflow * overflows, however the only side-effect of the race (if lost) is that * we would lose a couple of message too many or add some more messages to * qoverflow than permitted by the user. Since if flow-control is used, * the fifo size should be sized larger than the potential window sizes, * otherwise we can lose messages anyway, this is not deemed a cost to * justify proper locking in this case. */ queue_len = log_queue_fifo_get_length(&self->super); if (queue_len + self->qoverflow_input[thread_id].len > self->qoverflow_size) { /* slow path, the input thread's queue would overflow the queue, let's drop some messages */ LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; gint i; gint n; /* NOTE: MAX is needed here to ensure that the lost race on queue_len * doesn't result in n < 0 */ n = self->qoverflow_input[thread_id].len - MAX(0, (self->qoverflow_size - queue_len)); for (i = 0; i < n; i++) { LogMessageQueueNode *node = iv_list_entry(self->qoverflow_input[thread_id].items.next, LogMessageQueueNode, list); LogMessage *msg = node->msg; iv_list_del(&node->list); self->qoverflow_input[thread_id].len--; path_options.ack_needed = node->ack_needed; path_options.flow_control_requested = node->flow_control_requested; stats_counter_inc(self->super.dropped_messages); log_msg_free_queue_node(node); if (path_options.flow_control_requested) log_msg_drop(msg, &path_options, AT_SUSPENDED); else log_msg_drop(msg, &path_options, AT_PROCESSED); } msg_debug("Destination queue full, dropping messages", evt_tag_int("queue_len", queue_len), evt_tag_int("log_fifo_size", self->qoverflow_size), evt_tag_int("count", n), evt_tag_str("persist_name", self->super.persist_name)); } stats_counter_add(self->super.queued_messages, self->qoverflow_input[thread_id].len); iv_list_update_msg_size(self, &self->qoverflow_input[thread_id].items); iv_list_splice_tail_init(&self->qoverflow_input[thread_id].items, &self->qoverflow_wait); self->qoverflow_wait_len += self->qoverflow_input[thread_id].len; self->qoverflow_input[thread_id].len = 0; } /* move items from the per-thread input queue to the lock-protected * "wait" queue, but grabbing locks first. This is registered as a * callback to be called when the input worker thread finishes its * job. */ static gpointer log_queue_fifo_move_input(gpointer user_data) { LogQueueFifo *self = (LogQueueFifo *) user_data; gint thread_id; thread_id = main_loop_worker_get_thread_id(); g_assert(thread_id >= 0); g_static_mutex_lock(&self->super.lock); log_queue_fifo_move_input_unlocked(self, thread_id); log_queue_push_notify(&self->super); g_static_mutex_unlock(&self->super.lock); self->qoverflow_input[thread_id].finish_cb_registered = FALSE; log_queue_unref(&self->super); return NULL; } /** * Assumed to be called from one of the input threads. If the thread_id * cannot be determined, the item is put directly in the wait queue. * * Puts the message to the queue, and logs an error if it caused the * queue to be full. * * It attempts to put the item to the per-thread input queue. * * NOTE: It consumes the reference passed by the caller. **/ static void log_queue_fifo_push_tail(LogQueue *s, LogMessage *msg, const LogPathOptions *path_options) { LogQueueFifo *self = (LogQueueFifo *) s; gint thread_id; LogMessageQueueNode *node; thread_id = main_loop_worker_get_thread_id(); g_assert(thread_id < 0 || log_queue_max_threads > thread_id); /* NOTE: we don't use high-water marks for now, as log_fetch_limit * limits the number of items placed on the per-thread input queue * anyway, and any sane number decreased the performance measurably. * * This means that per-thread input queues contain _all_ items that * a single poll iteration produces. And once the reader is finished * (either because the input is depleted or because of * log_fetch_limit / window_size) the whole bunch is propagated to * the "wait" queue. */ if (thread_id >= 0) { /* fastpath, use per-thread input FIFOs */ if (!self->qoverflow_input[thread_id].finish_cb_registered) { /* this is the first item in the input FIFO, register a finish * callback to make sure it gets moved to the wait_queue if the * input thread finishes * One reference should be held, while the callback is registered * avoiding use-after-free situation */ main_loop_worker_register_batch_callback(&self->qoverflow_input[thread_id].cb); self->qoverflow_input[thread_id].finish_cb_registered = TRUE; log_queue_ref(&self->super); } node = log_msg_alloc_queue_node(msg, path_options); iv_list_add_tail(&node->list, &self->qoverflow_input[thread_id].items); self->qoverflow_input[thread_id].len++; log_msg_unref(msg); return; } /* slow path, put the pending item and the whole input queue to the wait_queue */ g_static_mutex_lock(&self->super.lock); if (thread_id >= 0) log_queue_fifo_move_input_unlocked(self, thread_id); if (log_queue_fifo_get_length(s) < self->qoverflow_size) { node = log_msg_alloc_queue_node(msg, path_options); iv_list_add_tail(&node->list, &self->qoverflow_wait); self->qoverflow_wait_len++; log_queue_push_notify(&self->super); stats_counter_inc(self->super.queued_messages); stats_counter_add(self->super.memory_usage, log_msg_get_size(msg)); g_static_mutex_unlock(&self->super.lock); log_msg_unref(msg); } else { stats_counter_inc(self->super.dropped_messages); g_static_mutex_unlock(&self->super.lock); if (path_options->flow_control_requested) log_msg_drop(msg, path_options, AT_SUSPENDED); else log_msg_drop(msg, path_options, AT_PROCESSED); msg_debug("Destination queue full, dropping message", evt_tag_int("queue_len", log_queue_fifo_get_length(&self->super)), evt_tag_int("log_fifo_size", self->qoverflow_size), evt_tag_str("persist_name", self->super.persist_name)); } return; } /* * Put an item back to the front of the queue. * * This is assumed to be called only from the output thread. * * NOTE: It consumes the reference passed by the caller. */ static void log_queue_fifo_push_head(LogQueue *s, LogMessage *msg, const LogPathOptions *path_options) { LogQueueFifo *self = (LogQueueFifo *) s; LogMessageQueueNode *node; /* we don't check limits when putting items "in-front", as it * normally happens when we start processing an item, but at the end * can't deliver it. No checks, no drops either. */ node = log_msg_alloc_dynamic_queue_node(msg, path_options); iv_list_add(&node->list, &self->qoverflow_output); self->qoverflow_output_len++; log_msg_unref(msg); stats_counter_inc(self->super.queued_messages); stats_counter_add(self->super.memory_usage, log_msg_get_size(msg)); } /* * Can only run from the output thread. * * NOTE: this returns a reference which the caller must take care to free. */ static LogMessage * log_queue_fifo_pop_head(LogQueue *s, LogPathOptions *path_options) { LogQueueFifo *self = (LogQueueFifo *) s; LogMessageQueueNode *node; LogMessage *msg = NULL; if (self->qoverflow_output_len == 0) { /* slow path, output queue is empty, get some elements from the wait queue */ g_static_mutex_lock(&self->super.lock); iv_list_splice_tail_init(&self->qoverflow_wait, &self->qoverflow_output); self->qoverflow_output_len = self->qoverflow_wait_len; self->qoverflow_wait_len = 0; g_static_mutex_unlock(&self->super.lock); } if (self->qoverflow_output_len > 0) { node = iv_list_entry(self->qoverflow_output.next, LogMessageQueueNode, list); msg = node->msg; path_options->ack_needed = node->ack_needed; self->qoverflow_output_len--; if (!self->super.use_backlog) { iv_list_del(&node->list); log_msg_free_queue_node(node); } else { iv_list_del_init(&node->list); } } else { /* no items either on the wait queue nor the output queue. * * NOTE: the input queues may contain items even in this case, * however we don't touch them here, they'll be migrated to the * wait_queue once the input threads finish their processing (or * the high watermark is reached). Also, they are unlocked, so * no way to touch them safely. */ return NULL; } stats_counter_dec(self->super.queued_messages); stats_counter_sub(self->super.memory_usage, log_msg_get_size(msg)); if (self->super.use_backlog) { log_msg_ref(msg); iv_list_add_tail(&node->list, &self->qbacklog); self->qbacklog_len++; } return msg; } /* * Can only run from the output thread. */ static void log_queue_fifo_ack_backlog(LogQueue *s, gint rewind_count) { LogQueueFifo *self = (LogQueueFifo *) s; LogMessage *msg; LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; gint pos; for (pos = 0; pos < rewind_count && self->qbacklog_len > 0; pos++) { LogMessageQueueNode *node; node = iv_list_entry(self->qbacklog.next, LogMessageQueueNode, list); msg = node->msg; iv_list_del(&node->list); self->qbacklog_len--; path_options.ack_needed = node->ack_needed; log_msg_ack(msg, &path_options, AT_PROCESSED); log_msg_free_queue_node(node); log_msg_unref(msg); } } /* * log_queue_rewind_backlog_all: * * Move items on our backlog back to our qoverflow queue. Please note that this * function does not really care about qoverflow size, it has to put the backlog * somewhere. The backlog is emptied as that will be filled if we send the * items again. * * NOTE: this is assumed to be called from the output thread. */ static void log_queue_fifo_rewind_backlog_all(LogQueue *s) { LogQueueFifo *self = (LogQueueFifo *) s; iv_list_splice_tail_init(&self->qbacklog, &self->qoverflow_output); iv_list_update_msg_size(self, &self->qbacklog); self->qoverflow_output_len += self->qbacklog_len; stats_counter_add(self->super.queued_messages, self->qbacklog_len); self->qbacklog_len = 0; } static void log_queue_fifo_rewind_backlog(LogQueue *s, guint rewind_count) { LogQueueFifo *self = (LogQueueFifo *) s; guint pos; if (rewind_count > self->qbacklog_len) rewind_count = self->qbacklog_len; for (pos = 0; pos < rewind_count; pos++) { LogMessageQueueNode *node = iv_list_entry(self->qbacklog.prev, LogMessageQueueNode, list); /* * Because the message go to the backlog only in case of pop_head * and pop_head add ack and ref when it pushes the message into the backlog * The rewind must decrease the ack and ref too */ iv_list_del_init(&node->list); iv_list_add(&node->list, &self->qoverflow_output); self->qbacklog_len--; self->qoverflow_output_len++; stats_counter_inc(self->super.queued_messages); stats_counter_add(self->super.memory_usage, log_msg_get_size(node->msg)); } } static void log_queue_fifo_free_queue(struct iv_list_head *q) { while (!iv_list_empty(q)) { LogMessageQueueNode *node; LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; LogMessage *msg; node = iv_list_entry(q->next, LogMessageQueueNode, list); iv_list_del(&node->list); path_options.ack_needed = node->ack_needed; msg = node->msg; log_msg_free_queue_node(node); log_msg_ack(msg, &path_options, AT_ABORTED); log_msg_unref(msg); } } static void log_queue_fifo_free(LogQueue *s) { LogQueueFifo *self = (LogQueueFifo *) s; gint i; for (i = 0; i < log_queue_max_threads; i++) { g_assert(self->qoverflow_input[i].finish_cb_registered == FALSE); log_queue_fifo_free_queue(&self->qoverflow_input[i].items); } log_queue_fifo_free_queue(&self->qoverflow_wait); log_queue_fifo_free_queue(&self->qoverflow_output); log_queue_fifo_free_queue(&self->qbacklog); log_queue_free_method(s); } LogQueue * log_queue_fifo_new(gint qoverflow_size, const gchar *persist_name) { LogQueueFifo *self; gint i; self = g_malloc0(sizeof(LogQueueFifo) + log_queue_max_threads * sizeof(self->qoverflow_input[0])); log_queue_init_instance(&self->super, persist_name); self->super.type = log_queue_fifo_type; self->super.use_backlog = FALSE; self->super.get_length = log_queue_fifo_get_length; self->super.is_empty_racy = log_queue_fifo_is_empty_racy; self->super.keep_on_reload = log_queue_fifo_keep_on_reload; self->super.push_tail = log_queue_fifo_push_tail; self->super.push_head = log_queue_fifo_push_head; self->super.pop_head = log_queue_fifo_pop_head; self->super.ack_backlog = log_queue_fifo_ack_backlog; self->super.rewind_backlog = log_queue_fifo_rewind_backlog; self->super.rewind_backlog_all = log_queue_fifo_rewind_backlog_all; self->super.free_fn = log_queue_fifo_free; for (i = 0; i < log_queue_max_threads; i++) { INIT_IV_LIST_HEAD(&self->qoverflow_input[i].items); worker_batch_callback_init(&self->qoverflow_input[i].cb); self->qoverflow_input[i].cb.func = log_queue_fifo_move_input; self->qoverflow_input[i].cb.user_data = self; } INIT_IV_LIST_HEAD(&self->qoverflow_wait); INIT_IV_LIST_HEAD(&self->qoverflow_output); INIT_IV_LIST_HEAD(&self->qbacklog); self->qoverflow_size = qoverflow_size; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/logqueue-fifo.h000066400000000000000000000022351321171025300211250ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGQUEUE_FIFO_H_INCLUDED #define LOGQUEUE_FIFO_H_INCLUDED #include "logqueue.h" LogQueue *log_queue_fifo_new(gint qoverflow_size, const gchar *persist_name); #endif syslog-ng-syslog-ng-3.13.2/lib/logqueue.c000066400000000000000000000152431321171025300202020ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logqueue.h" #include "stats/stats-registry.h" #include "messages.h" gint log_queue_max_threads = 0; /* * When this is called, it is assumed that the output thread is currently * not running (since this is the function that wakes it up), thus we can * access the length of the output queue without acquiring a lock. Memory * barriers are covered by the use of the self->lock mutex, since * push_notify is registered under the protection of self->lock and after * that the length of the output queue will not change (since parallel_push * is only registered if it has less than enough items). * * NOTE: self->lock must have been acquired before calling this function. */ void log_queue_push_notify(LogQueue *self) { if (self->parallel_push_notify) { /* make sure the callback can call log_queue_check_items() again */ GDestroyNotify destroy = self->parallel_push_data_destroy; gpointer user_data = self->parallel_push_data; LogQueuePushNotifyFunc func = self->parallel_push_notify; self->parallel_push_data = NULL; self->parallel_push_data_destroy = NULL; self->parallel_push_notify = NULL; g_static_mutex_unlock(&self->lock); func(user_data); if (destroy && user_data) destroy(user_data); g_static_mutex_lock(&self->lock); } } void log_queue_reset_parallel_push(LogQueue *self) { g_static_mutex_lock(&self->lock); self->parallel_push_notify = NULL; self->parallel_push_data = NULL; g_static_mutex_unlock(&self->lock); } void log_queue_set_parallel_push(LogQueue *self, LogQueuePushNotifyFunc parallel_push_notify, gpointer user_data, GDestroyNotify user_data_destroy) { g_static_mutex_lock(&self->lock); self->parallel_push_notify = parallel_push_notify; self->parallel_push_data = user_data; self->parallel_push_data_destroy = user_data_destroy; g_static_mutex_unlock(&self->lock); } /* * * @batch_items: the number of items processed in a batch (e.g. the number of items the consumer is preferred to process at a single invocation) * @partial_batch: true is returned if some elements (but less than batch_items) are already buffered * @timeout: the number of milliseconds that the consumer needs to wait before we can possibly proceed */ gboolean log_queue_check_items(LogQueue *self, gint *timeout, LogQueuePushNotifyFunc parallel_push_notify, gpointer user_data, GDestroyNotify user_data_destroy) { gint64 num_elements; g_static_mutex_lock(&self->lock); /* drop reference to the previous callback/userdata */ if (self->parallel_push_data && self->parallel_push_data_destroy) self->parallel_push_data_destroy(self->parallel_push_data); num_elements = log_queue_get_length(self); if (num_elements == 0) { self->parallel_push_notify = parallel_push_notify; self->parallel_push_data = user_data; self->parallel_push_data_destroy = user_data_destroy; g_static_mutex_unlock(&self->lock); return FALSE; } /* consume the user_data reference as we won't use the callback */ if (user_data && user_data_destroy) user_data_destroy(user_data); self->parallel_push_notify = NULL; self->parallel_push_data = NULL; g_static_mutex_unlock(&self->lock); /* recalculate buckets, throttle is only running in the output thread, no need to lock it. */ if (self->throttle > 0) { gint64 diff; gint new_buckets; GTimeVal now; g_get_current_time(&now); /* throttling is enabled, calculate new buckets */ if (self->last_throttle_check.tv_sec != 0) { diff = g_time_val_diff(&now, &self->last_throttle_check); } else { diff = 0; self->last_throttle_check = now; } new_buckets = (self->throttle * diff) / G_USEC_PER_SEC; if (new_buckets) { /* if new_buckets is zero, we don't save the current time as * last_throttle_check. The reason is that new_buckets could be * rounded to zero when only a minimal interval passes between * poll iterations. */ self->throttle_buckets = MIN(self->throttle, self->throttle_buckets + new_buckets); self->last_throttle_check = now; } if (num_elements && self->throttle_buckets == 0) { if (timeout) { /* we are unable to send because of throttling, make sure that we * wake up when the rate limits lets us send at least 1 message */ *timeout = (1000 / self->throttle) + 1; msg_debug("Throttling output", evt_tag_int("wait", *timeout)); } return FALSE; } } return TRUE; } void log_queue_set_counters(LogQueue *self, StatsCounterItem *queued_messages, StatsCounterItem *dropped_messages, StatsCounterItem *memory_usage) { self->queued_messages = queued_messages; self->dropped_messages = dropped_messages; self->memory_usage = memory_usage; stats_counter_set(self->memory_usage, self->memory_usage_qout_initial_value + self->memory_usage_overflow_initial_value); stats_counter_set(self->queued_messages, log_queue_get_length(self)); } void log_queue_init_instance(LogQueue *self, const gchar *persist_name) { g_atomic_counter_set(&self->ref_cnt, 1); self->free_fn = log_queue_free_method; self->persist_name = persist_name ? g_strdup(persist_name) : NULL; g_static_mutex_init(&self->lock); } void log_queue_free_method(LogQueue *self) { g_static_mutex_free(&self->lock); g_free(self->persist_name); g_free(self); } void log_queue_set_max_threads(gint max_threads) { log_queue_max_threads = max_threads; } syslog-ng-syslog-ng-3.13.2/lib/logqueue.h000066400000000000000000000127151321171025300202100ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGQUEUE_H_INCLUDED #define LOGQUEUE_H_INCLUDED #include "logmsg/logmsg.h" #include "stats/stats-registry.h" extern gint log_queue_max_threads; typedef void (*LogQueuePushNotifyFunc)(gpointer user_data); typedef struct _LogQueue LogQueue; typedef char *QueueType; struct _LogQueue { QueueType type; GAtomicCounter ref_cnt; gboolean use_backlog; gint throttle; gint throttle_buckets; GTimeVal last_throttle_check; gchar *persist_name; StatsCounterItem *queued_messages; StatsCounterItem *dropped_messages; StatsCounterItem *memory_usage; gssize memory_usage_qout_initial_value; gssize memory_usage_overflow_initial_value; GStaticMutex lock; LogQueuePushNotifyFunc parallel_push_notify; gpointer parallel_push_data; GDestroyNotify parallel_push_data_destroy; /* queue management */ gboolean (*keep_on_reload)(LogQueue *self); gint64 (*get_length)(LogQueue *self); gboolean (*is_empty_racy)(LogQueue *self); void (*push_tail)(LogQueue *self, LogMessage *msg, const LogPathOptions *path_options); void (*push_head)(LogQueue *self, LogMessage *msg, const LogPathOptions *path_options); LogMessage *(*pop_head)(LogQueue *self, LogPathOptions *path_options); void (*ack_backlog)(LogQueue *self, gint n); void (*rewind_backlog)(LogQueue *self, guint rewind_count); void (*rewind_backlog_all)(LogQueue *self); void (*free_fn)(LogQueue *self); }; static inline gboolean log_queue_keep_on_reload(LogQueue *self) { if (self->keep_on_reload) return self->keep_on_reload(self); return TRUE; } static inline gint64 log_queue_get_length(LogQueue *self) { return self->get_length(self); } static inline gboolean log_queue_is_empty_racy(LogQueue *self) { if (self->is_empty_racy) return self->is_empty_racy(self); else return (self->get_length(self) == 0); } static inline void log_queue_push_tail(LogQueue *self, LogMessage *msg, const LogPathOptions *path_options) { self->push_tail(self, msg, path_options); } static inline void log_queue_push_head(LogQueue *self, LogMessage *msg, const LogPathOptions *path_options) { self->push_head(self, msg, path_options); } static inline LogMessage * log_queue_pop_head(LogQueue *self, LogPathOptions *path_options) { LogMessage *msg = NULL; if (self->throttle && self->throttle_buckets == 0) return NULL; msg = self->pop_head(self, path_options); if (msg && self->throttle_buckets > 0) self->throttle_buckets--; return msg; } static inline LogMessage * log_queue_pop_head_ignore_throttle(LogQueue *self, LogPathOptions *path_options) { return self->pop_head(self, path_options); } static inline void log_queue_rewind_backlog(LogQueue *self, guint rewind_count) { if (!self->use_backlog) return; self->rewind_backlog(self, rewind_count); } static inline void log_queue_rewind_backlog_all(LogQueue *self) { if (!self->use_backlog) return; self->rewind_backlog_all(self); } static inline void log_queue_ack_backlog(LogQueue *self, guint rewind_count) { if (!self->use_backlog) return; self->ack_backlog(self, rewind_count); } static inline LogQueue * log_queue_ref(LogQueue *self) { g_assert(!self || g_atomic_counter_get(&self->ref_cnt) > 0); if (self) { g_atomic_counter_inc(&self->ref_cnt); } return self; } static inline void log_queue_unref(LogQueue *self) { g_assert(!self || g_atomic_counter_get(&self->ref_cnt) > 0); if (self && g_atomic_counter_dec_and_test(&self->ref_cnt)) { if (self->free_fn) self->free_fn(self); } } static inline void log_queue_set_throttle(LogQueue *self, gint throttle) { self->throttle = throttle; self->throttle_buckets = throttle; } static inline void log_queue_set_use_backlog(LogQueue *self, gboolean use_backlog) { if (self) self->use_backlog = use_backlog; } void log_queue_push_notify(LogQueue *self); void log_queue_reset_parallel_push(LogQueue *self); void log_queue_set_parallel_push(LogQueue *self, LogQueuePushNotifyFunc parallel_push_notify, gpointer user_data, GDestroyNotify user_data_destroy); gboolean log_queue_check_items(LogQueue *self, gint *timeout, LogQueuePushNotifyFunc parallel_push_notify, gpointer user_data, GDestroyNotify user_data_destroy); void log_queue_set_counters(LogQueue *self, StatsCounterItem *queued_messages, StatsCounterItem *dropped_messages, StatsCounterItem *memory_usage); void log_queue_init_instance(LogQueue *self, const gchar *persist_name); void log_queue_free_method(LogQueue *self); void log_queue_set_max_threads(gint max_threads); #endif syslog-ng-syslog-ng-3.13.2/lib/logreader.c000066400000000000000000000447301321171025300203230ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logreader.h" #include "mainloop-io-worker.h" #include "mainloop-call.h" #include "ack_tracker.h" #include "scratch-buffers.h" #include struct _LogReader { LogSource super; LogProtoServer *proto; gboolean immediate_check; LogPipe *control; LogReaderOptions *options; PollEvents *poll_events; GSockAddr *peer_addr; /* NOTE: these used to be LogReaderWatch members, which were merged into * LogReader with the multi-thread refactorization */ struct iv_task restart_task; struct iv_event schedule_wakeup; MainLoopIOWorkerJob io_job; gboolean watches_running:1, suspended:1; gint notify_code; /* proto & poll_events pending to be applied. As long as the previous * processing is being done, we can't replace these in self->proto and * self->poll_events, they get applied to the production ones as soon as * the previous work is finished */ gboolean pending_proto_present; GCond *pending_proto_cond; GStaticMutex pending_proto_lock; LogProtoServer *pending_proto; PollEvents *pending_poll_events; }; static gboolean log_reader_fetch_log(LogReader *self); static void log_reader_stop_watches(LogReader *self); static void log_reader_update_watches(LogReader *self); static void log_reader_apply_proto_and_poll_events(LogReader *self, LogProtoServer *proto, PollEvents *poll_events) { if (self->proto) log_proto_server_free(self->proto); if (self->poll_events) poll_events_free(self->poll_events); self->proto = proto; self->poll_events = poll_events; } static void log_reader_work_perform(void *s) { LogReader *self = (LogReader *) s; self->notify_code = log_reader_fetch_log(self); } static void log_reader_work_finished(void *s) { LogReader *self = (LogReader *) s; if (self->pending_proto_present) { /* pending proto is only set in the main thread, so no need to * lock it before coming here. After we're syncing with the * log_writer_reopen() call, quite possibly coming from a * non-main thread. */ g_static_mutex_lock(&self->pending_proto_lock); log_reader_apply_proto_and_poll_events(self, self->pending_proto, self->pending_poll_events); self->pending_proto = NULL; self->pending_poll_events = NULL; self->pending_proto_present = FALSE; g_cond_signal(self->pending_proto_cond); g_static_mutex_unlock(&self->pending_proto_lock); } if (self->notify_code) { gint notify_code = self->notify_code; self->notify_code = 0; log_pipe_notify(self->control, notify_code, self); } if (self->super.super.flags & PIF_INITIALIZED) { /* reenable polling the source assuming that we're still in * business (e.g. the reader hasn't been uninitialized) */ log_proto_server_reset_error(self->proto); log_reader_update_watches(self); } log_pipe_unref(&self->super.super); } static void log_reader_wakeup_triggered(gpointer s) { LogReader *self = (LogReader *) s; if (!self->io_job.working && self->suspended) { /* NOTE: by the time working is set to FALSE we're over an * update_watches call. So it is called either here (when * work_finished has done its work) or from work_finished above. The * two are not racing as both run in the main thread */ log_reader_update_watches(self); } } /* NOTE: may be running in the destination's thread, thus proper locking must be used */ static void log_reader_wakeup(LogSource *s) { LogReader *self = (LogReader *) s; /* * We might get called even after this LogReader has been * deinitialized, in which case we must not do anything (since the * iv_event triggered here is not registered). * * This happens when log_writer_deinit() flushes its output queue * after the reader which produced the message has already been * deinited. Since init/deinit calls are made in the main thread, no * locking is needed. * */ if (self->super.super.flags & PIF_INITIALIZED) iv_event_post(&self->schedule_wakeup); } static void log_reader_io_process_input(gpointer s) { LogReader *self = (LogReader *) s; log_reader_stop_watches(self); log_pipe_ref(&self->super.super); if ((self->options->flags & LR_THREADED)) { main_loop_io_worker_job_submit(&self->io_job); } else { /* Checking main_loop_io_worker_job_quit() helps to speed up the * reload process. If reload/shutdown is requested we shouldn't do * anything here, outstanding messages will be processed by the new * configuration. * * Our current understanding is that it doesn't prevent race * conditions of any kind. */ if (!main_loop_worker_job_quit()) { log_reader_work_perform(s); log_reader_work_finished(s); } } } static void log_reader_init_watches(LogReader *self) { IV_TASK_INIT(&self->restart_task); self->restart_task.cookie = self; self->restart_task.handler = log_reader_io_process_input; IV_EVENT_INIT(&self->schedule_wakeup); self->schedule_wakeup.cookie = self; self->schedule_wakeup.handler = log_reader_wakeup_triggered; main_loop_io_worker_job_init(&self->io_job); self->io_job.user_data = self; self->io_job.work = (void (*)(void *)) log_reader_work_perform; self->io_job.completion = (void (*)(void *)) log_reader_work_finished; } static void log_reader_stop_watches(LogReader *self) { if (self->watches_running) { poll_events_stop_watches(self->poll_events); if (iv_task_registered(&self->restart_task)) iv_task_unregister(&self->restart_task); self->watches_running = FALSE; } } static void log_reader_start_watches_if_stopped(LogReader *self) { if (!self->watches_running) { poll_events_start_watches(self->poll_events); self->watches_running = TRUE; } } static gboolean log_reader_is_opened(LogReader *self) { return self->proto && self->poll_events; } static void log_reader_suspend_until_awoken(LogReader *self) { self->immediate_check = FALSE; poll_events_suspend_watches(self->poll_events); self->suspended = TRUE; } static void log_reader_force_check_in_next_poll(LogReader *self) { self->immediate_check = FALSE; poll_events_suspend_watches(self->poll_events); self->suspended = FALSE; if (!iv_task_registered(&self->restart_task)) { iv_task_register(&self->restart_task); } } static void log_reader_update_watches(LogReader *self) { GIOCondition cond; gboolean free_to_send; gboolean line_is_ready_in_buffer; main_loop_assert_main_thread(); if (!log_reader_is_opened(self)) return; log_reader_start_watches_if_stopped(self); free_to_send = log_source_free_to_send(&self->super); if (!free_to_send) { log_reader_suspend_until_awoken(self); return; } line_is_ready_in_buffer = log_proto_server_prepare(self->proto, &cond); if (self->immediate_check || line_is_ready_in_buffer) { log_reader_force_check_in_next_poll(self); return; } poll_events_update_watches(self->poll_events, cond); } static void _add_aux_nvpair(const gchar *name, const gchar *value, gsize value_len, gpointer user_data) { LogMessage *msg = (LogMessage *) user_data; log_msg_set_value_by_name(msg, name, value, value_len);; } static gboolean log_reader_handle_line(LogReader *self, const guchar *line, gint length, LogTransportAuxData *aux) { LogMessage *m; msg_debug("Incoming log entry", evt_tag_printf("line", "%.*s", length, line)); /* use the current time to get the time zone offset */ m = log_msg_new((gchar *) line, length, aux->peer_addr ? : self->peer_addr, &self->options->parse_options); log_msg_refcache_start_producer(m); log_transport_aux_data_foreach(aux, _add_aux_nvpair, m); log_source_post(&self->super, m); log_msg_refcache_stop(); return log_source_free_to_send(&self->super); } /* returns: notify_code (NC_XXXX) or 0 for success */ static gint log_reader_fetch_log(LogReader *self) { gint msg_count = 0; gboolean may_read = TRUE; LogTransportAuxData aux; /* NOTE: this loop is here to decrease the load on the main loop, we try * to fetch a couple of messages in a single run (but only up to * fetch_limit). */ log_transport_aux_data_init(&aux); while (msg_count < self->options->fetch_limit && !main_loop_worker_job_quit()) { Bookmark *bookmark; const guchar *msg; gsize msg_len; LogProtoStatus status; msg = NULL; /* NOTE: may_read is used to implement multi-read checking. It * is initialized to TRUE to indicate that the protocol is * allowed to issue a read(). If multi-read is disallowed in the * protocol, it resets may_read to FALSE after the first read was issued. */ log_transport_aux_data_reinit(&aux); bookmark = ack_tracker_request_bookmark(self->super.ack_tracker); status = log_proto_server_fetch(self->proto, &msg, &msg_len, &may_read, &aux, bookmark); switch (status) { case LPS_EOF: g_sockaddr_unref(aux.peer_addr); return NC_CLOSE; case LPS_ERROR: g_sockaddr_unref(aux.peer_addr); return NC_READ_ERROR; case LPS_SUCCESS: break; default: g_assert_not_reached(); break; } if (!msg) { /* no more messages for now */ break; } if (msg_len > 0 || (self->options->flags & LR_EMPTY_LINES)) { msg_count++; ScratchBuffersMarker mark; scratch_buffers_mark(&mark); if (!log_reader_handle_line(self, msg, msg_len, &aux)) { scratch_buffers_reclaim_marked(mark); /* window is full, don't generate further messages */ break; } scratch_buffers_reclaim_marked(mark); } } log_transport_aux_data_destroy(&aux); if (msg_count == self->options->fetch_limit) self->immediate_check = TRUE; return 0; } static gboolean log_reader_init(LogPipe *s) { LogReader *self = (LogReader *) s; if (!log_source_init(s)) return FALSE; if (!log_proto_server_validate_options(self->proto)) return FALSE; if (!self->options->parse_options.format_handler) { msg_error("Unknown format plugin specified", evt_tag_str("format", self->options->parse_options.format)); return FALSE; } poll_events_set_callback(self->poll_events, log_reader_io_process_input, self); log_reader_update_watches(self); iv_event_register(&self->schedule_wakeup); return TRUE; } static gboolean log_reader_deinit(LogPipe *s) { LogReader *self = (LogReader *) s; main_loop_assert_main_thread(); iv_event_unregister(&self->schedule_wakeup); log_reader_stop_watches(self); if (!log_source_deinit(s)) return FALSE; return TRUE; } static void log_reader_free(LogPipe *s) { LogReader *self = (LogReader *) s; if (self->proto) { log_proto_server_free(self->proto); self->proto = NULL; } if (self->poll_events) poll_events_free(self->poll_events); log_pipe_unref(self->control); g_sockaddr_unref(self->peer_addr); g_static_mutex_free(&self->pending_proto_lock); g_cond_free(self->pending_proto_cond); log_source_free(s); } void log_reader_set_options(LogReader *s, LogPipe *control, LogReaderOptions *options, const gchar *stats_id, const gchar *stats_instance) { LogReader *self = (LogReader *) s; /* log_reader_reopen() needs to be called prior to set_options. This is * an ugly hack, but at least it is more explicitly than what used to be * here, which silently ignored if self->proto was NULL. */ g_assert(self->proto != NULL); gboolean pos_tracked = log_proto_server_is_position_tracked(self->proto); log_source_set_options(&self->super, &options->super, stats_id, stats_instance, (options->flags & LR_THREADED), pos_tracked, control->expr_node); log_pipe_unref(self->control); log_pipe_ref(control); self->control = control; self->options = options; log_proto_server_set_options(self->proto, &self->options->proto_options.super); } /* run in the main thread in reaction to a log_reader_reopen to change * the source LogProtoServer instance. It needs to be ran in the main * thread as it reregisters the watches associated with the main * thread. */ void log_reader_reopen_deferred(gpointer s) { gpointer *args = (gpointer *) s; LogReader *self = args[0]; LogProtoServer *proto = args[1]; PollEvents *poll_events = args[2]; if (self->io_job.working) { self->pending_proto = proto; self->pending_poll_events = poll_events; self->pending_proto_present = TRUE; return; } log_reader_stop_watches(self); log_reader_apply_proto_and_poll_events(self, proto, poll_events); log_reader_update_watches(self); } void log_reader_reopen(LogReader *self, LogProtoServer *proto, PollEvents *poll_events) { gpointer args[] = { self, proto, poll_events }; main_loop_call((MainLoopTaskFunc) log_reader_reopen_deferred, args, TRUE); if (!main_loop_is_main_thread()) { g_static_mutex_lock(&self->pending_proto_lock); while (self->pending_proto_present) { g_cond_wait(self->pending_proto_cond, g_static_mutex_get_mutex(&self->pending_proto_lock)); } g_static_mutex_unlock(&self->pending_proto_lock); } } void log_reader_set_peer_addr(LogReader *s, GSockAddr *peer_addr) { LogReader *self = (LogReader *) s; g_sockaddr_unref(self->peer_addr); self->peer_addr = g_sockaddr_ref(peer_addr); } LogReader * log_reader_new(GlobalConfig *cfg) { LogReader *self = g_new0(LogReader, 1); log_source_init_instance(&self->super, cfg); self->super.super.init = log_reader_init; self->super.super.deinit = log_reader_deinit; self->super.super.free_fn = log_reader_free; self->super.wakeup = log_reader_wakeup; self->immediate_check = FALSE; log_reader_init_watches(self); g_static_mutex_init(&self->pending_proto_lock); self->pending_proto_cond = g_cond_new(); return self; } void log_reader_set_immediate_check(LogReader *s) { LogReader *self = (LogReader *) s; self->immediate_check = TRUE; } void log_reader_options_defaults(LogReaderOptions *options) { log_source_options_defaults(&options->super); log_proto_server_options_defaults(&options->proto_options.super); msg_format_options_defaults(&options->parse_options); options->fetch_limit = 10; } /* * NOTE: _init needs to be idempotent when called multiple times w/o invoking _destroy * * Rationale: * - init is called from driver init (e.g. affile_sd_init), * - destroy is called from driver free method (e.g. affile_sd_free, NOT affile_sd_deinit) * * The reason: * - when initializing the reloaded configuration fails for some reason, * we have to fall back to the old configuration, thus we cannot dump * the information stored in the Options structure at deinit time, but * have to recover it when the old configuration is initialized. * * For the reasons above, init and destroy behave the following way: * * - init is idempotent, it can be called multiple times without leaking * memory, and without loss of information * - destroy is only called once, when the options are indeed to be destroyed * * Also important to note is that when init is called multiple times, the * GlobalConfig reference is the same, this means that it is enough to * remember whether init was called already and return w/o doing anything in * that case, which is actually how idempotency is implemented here. */ void log_reader_options_init(LogReaderOptions *options, GlobalConfig *cfg, const gchar *group_name) { if (options->initialized) return; log_source_options_init(&options->super, cfg, group_name); log_proto_server_options_init(&options->proto_options.super, cfg); msg_format_options_init(&options->parse_options, cfg); if (options->check_hostname == -1) options->check_hostname = cfg->check_hostname; if (options->check_hostname) { options->parse_options.flags |= LP_CHECK_HOSTNAME; } if (!options->super.keep_timestamp) { options->parse_options.flags |= LP_NO_PARSE_DATE; } if (options->parse_options.default_pri == 0xFFFF) { if (options->flags & LR_KERNEL) options->parse_options.default_pri = LOG_KERN | LOG_NOTICE; else options->parse_options.default_pri = LOG_USER | LOG_NOTICE; } if (options->proto_options.super.encoding) options->parse_options.flags |= LP_ASSUME_UTF8; if (cfg->threaded) options->flags |= LR_THREADED; options->initialized = TRUE; } void log_reader_options_destroy(LogReaderOptions *options) { log_source_options_destroy(&options->super); log_proto_server_options_destroy(&options->proto_options.super); msg_format_options_destroy(&options->parse_options); options->initialized = FALSE; } CfgFlagHandler log_reader_flag_handlers[] = { /* NOTE: underscores are automatically converted to dashes */ /* LogReaderOptions */ { "kernel", CFH_SET, offsetof(LogReaderOptions, flags), LR_KERNEL }, { "empty-lines", CFH_SET, offsetof(LogReaderOptions, flags), LR_EMPTY_LINES }, { "threaded", CFH_SET, offsetof(LogReaderOptions, flags), LR_THREADED }, { NULL }, }; gboolean log_reader_options_process_flag(LogReaderOptions *options, gchar *flag) { if (!msg_format_options_process_flag(&options->parse_options, flag)) return cfg_process_flag(log_reader_flag_handlers, options, flag); return TRUE; } syslog-ng-syslog-ng-3.13.2/lib/logreader.h000066400000000000000000000047501321171025300203260ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGREADER_H_INCLUDED #define LOGREADER_H_INCLUDED #include "logsource.h" #include "logproto/logproto-server.h" #include "poll-events.h" #include "timeutils.h" /* flags */ #define LR_KERNEL 0x0002 #define LR_EMPTY_LINES 0x0004 #define LR_THREADED 0x0040 /* options */ typedef struct _LogReaderOptions { gboolean initialized; LogSourceOptions super; MsgFormatOptions parse_options; LogProtoServerOptionsStorage proto_options; guint32 flags; gint fetch_limit; const gchar *group_name; gboolean check_hostname; } LogReaderOptions; typedef struct _LogReader LogReader; void log_reader_set_options(LogReader *s, LogPipe *control, LogReaderOptions *options, const gchar *stats_id, const gchar *stats_instance); void log_reader_set_follow_filename(LogReader *self, const gchar *follow_filename); void log_reader_set_peer_addr(LogReader *s, GSockAddr *peer_addr); void log_reader_set_immediate_check(LogReader *s); void log_reader_reopen(LogReader *s, LogProtoServer *proto, PollEvents *poll_events); LogReader *log_reader_new(GlobalConfig *cfg); void log_reader_options_defaults(LogReaderOptions *options); void log_reader_options_init(LogReaderOptions *options, GlobalConfig *cfg, const gchar *group_name); void log_reader_options_destroy(LogReaderOptions *options); gint log_reader_options_lookup_flag(const gchar *flag); void log_reader_options_set_tags(LogReaderOptions *options, GList *tags); gboolean log_reader_options_process_flag(LogReaderOptions *options, gchar *flag); #endif syslog-ng-syslog-ng-3.13.2/lib/logsource.c000066400000000000000000000405741321171025300203630ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logsource.h" #include "messages.h" #include "host-resolve.h" #include "timeutils.h" #include "stats/stats-registry.h" #include "stats/stats-syslog.h" #include "logmsg/tags.h" #include "ack_tracker.h" #include gboolean accurate_nanosleep = FALSE; void log_source_wakeup(LogSource *self) { if (self->wakeup) self->wakeup(self); msg_debug("Source has been resumed", log_pipe_location_tag(&self->super)); } static inline void _flow_control_window_size_adjust(LogSource *self, guint32 window_size_increment) { guint32 old_window_size; window_size_increment += g_atomic_counter_get(&self->suspended_window_size); old_window_size = g_atomic_counter_exchange_and_add(&self->window_size, window_size_increment); g_atomic_counter_set(&self->suspended_window_size, 0); if (old_window_size == 0) log_source_wakeup(self); } static void _flow_control_rate_adjust(LogSource *self) { guint32 cur_ack_count, last_ack_count; /* NOTE: this is racy. msg_ack may be executing in different writer * threads. I don't want to lock, all we need is an approximate value of * the ACK rate of the last couple of seconds. */ #ifdef SYSLOG_NG_HAVE_CLOCK_GETTIME if (accurate_nanosleep && self->threaded) { cur_ack_count = ++self->ack_count; if ((cur_ack_count & 0x3FFF) == 0) { struct timespec now; glong diff; /* do this every once in a while, once in 16k messages should be fine */ last_ack_count = self->last_ack_count; /* make sure that we have at least 16k messages to measure the rate * for. Because of the race we may have last_ack_count == * cur_ack_count if another thread already measured the same span */ if (last_ack_count < cur_ack_count - 16383) { clock_gettime(CLOCK_MONOTONIC, &now); if (now.tv_sec > self->last_ack_rate_time.tv_sec + 6) { /* last check was too far apart, this means the rate is quite slow. turn off sleeping. */ self->window_full_sleep_nsec = 0; self->last_ack_rate_time = now; } else { /* ok, we seem to have a close enough measurement, this means * we do have a high rate. Calculate how much we should sleep * in case the window gets full */ diff = timespec_diff_nsec(&now, &self->last_ack_rate_time); self->window_full_sleep_nsec = (diff / (cur_ack_count - last_ack_count)); if (self->window_full_sleep_nsec > 1e6) { /* in case we'd be waiting for 1msec for another free slot in the window, let's go to background instead */ self->window_full_sleep_nsec = 0; } else { /* otherwise let's wait for about 8 message to be emptied before going back to the loop, but clamp the maximum time to 0.1msec */ self->window_full_sleep_nsec <<= 3; if (self->window_full_sleep_nsec > 1e5) self->window_full_sleep_nsec = 1e5; } self->last_ack_count = cur_ack_count; self->last_ack_rate_time = now; } } } } #endif } void log_source_flow_control_adjust(LogSource *self, guint32 window_size_increment) { _flow_control_window_size_adjust(self, window_size_increment); _flow_control_rate_adjust(self); } /** * log_source_msg_ack: * * This is running in the same thread as the _destination_, thus care must * be taken when manipulating the LogSource data structure. **/ static void log_source_msg_ack(LogMessage *msg, AckType ack_type) { AckTracker *ack_tracker = msg->ack_record->tracker; ack_tracker_manage_msg_ack(ack_tracker, msg, ack_type); } void log_source_flow_control_suspend(LogSource *self) { msg_debug("Source has been suspended", log_pipe_location_tag(&self->super)); g_atomic_counter_set(&self->suspended_window_size, g_atomic_counter_get(&self->window_size)); g_atomic_counter_set(&self->window_size, 0); _flow_control_rate_adjust(self); } void log_source_mangle_hostname(LogSource *self, LogMessage *msg) { const gchar *resolved_name; gsize resolved_name_len; const gchar *orig_host; resolved_name = resolve_sockaddr_to_hostname(&resolved_name_len, msg->saddr, &self->options->host_resolve_options); log_msg_set_value(msg, LM_V_HOST_FROM, resolved_name, resolved_name_len); orig_host = log_msg_get_value(msg, LM_V_HOST, NULL); if (!self->options->keep_hostname || !orig_host || !orig_host[0]) { gchar host[256]; gint host_len = -1; if (G_UNLIKELY(self->options->chain_hostnames)) { msg->flags |= LF_CHAINED_HOSTNAME; if (msg->flags & LF_SIMPLE_HOSTNAME) { /* local without group name */ host_len = g_snprintf(host, sizeof(host), "%s", resolved_name); } else if (msg->flags & LF_LOCAL) { /* local */ host_len = g_snprintf(host, sizeof(host), "%s@%s", self->options->group_name, resolved_name); } else if (!orig_host || !orig_host[0]) { /* remote && no hostname */ host_len = g_snprintf(host, sizeof(host), "%s/%s", resolved_name, resolved_name); } else { /* everything else, append source hostname */ if (orig_host && orig_host[0]) host_len = g_snprintf(host, sizeof(host), "%s/%s", orig_host, resolved_name); else { strncpy(host, resolved_name, sizeof(host)); /* just in case it is not zero terminated */ host[255] = 0; } } if (host_len >= sizeof(host)) host_len = sizeof(host) - 1; log_msg_set_value(msg, LM_V_HOST, host, host_len); } else { log_msg_set_value(msg, LM_V_HOST, resolved_name, resolved_name_len); } } } gboolean log_source_init(LogPipe *s) { LogSource *self = (LogSource *) s; stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, self->options->stats_source | SCS_SOURCE, self->stats_id, self->stats_instance); stats_register_counter(self->options->stats_level, &sc_key, SC_TYPE_PROCESSED, &self->recvd_messages); stats_register_counter(self->options->stats_level, &sc_key, SC_TYPE_STAMP, &self->last_message_seen); stats_unlock(); return TRUE; } gboolean log_source_deinit(LogPipe *s) { LogSource *self = (LogSource *) s; stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, self->options->stats_source | SCS_SOURCE, self->stats_id, self->stats_instance); stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &self->recvd_messages); stats_unregister_counter(&sc_key, SC_TYPE_STAMP, &self->last_message_seen); stats_unlock(); return TRUE; } void log_source_post(LogSource *self, LogMessage *msg) { LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; gint old_window_size; ack_tracker_track_msg(self->ack_tracker, msg); /* NOTE: we start by enabling flow-control, thus we need an acknowledgement */ path_options.ack_needed = TRUE; log_msg_ref(msg); log_msg_add_ack(msg, &path_options); msg->ack_func = log_source_msg_ack; old_window_size = g_atomic_counter_exchange_and_add(&self->window_size, -1); if (G_UNLIKELY(old_window_size == 1)) msg_debug("Source has been suspended", log_pipe_location_tag(&self->super)); /* * NOTE: this assertion validates that the source is not overflowing its * own flow-control window size, decreased above, by the atomic statement. * * If the _old_ value is zero, that means that the decrement operation * above has decreased the value to -1. */ g_assert(old_window_size > 0); log_pipe_queue(&self->super, msg, &path_options); } static gboolean _invoke_mangle_callbacks(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options) { LogSource *self = (LogSource *) s; GList *next_item = g_list_first(self->options->source_queue_callbacks); while(next_item) { if(next_item->data) { if(!((mangle_callback) (next_item->data))(log_pipe_get_config(s),msg,self)) { log_msg_drop(msg, path_options, AT_PROCESSED); return FALSE; } } next_item = next_item->next; } return TRUE; } static void log_source_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { LogSource *self = (LogSource *) s; gint i; msg_set_context(msg); if (!self->options->keep_timestamp) msg->timestamps[LM_TS_STAMP] = msg->timestamps[LM_TS_RECVD]; g_assert(msg->timestamps[LM_TS_STAMP].zone_offset != -1); /* $HOST setup */ log_source_mangle_hostname(self, msg); /* $PROGRAM override */ if (self->options->program_override) { if (self->options->program_override_len < 0) self->options->program_override_len = strlen(self->options->program_override); log_msg_set_value(msg, LM_V_PROGRAM, self->options->program_override, self->options->program_override_len); } /* $HOST override */ if (self->options->host_override) { if (self->options->host_override_len < 0) self->options->host_override_len = strlen(self->options->host_override); log_msg_set_value(msg, LM_V_HOST, self->options->host_override, self->options->host_override_len); } /* source specific tags */ if (self->options->tags) { for (i = 0; i < self->options->tags->len; i++) { log_msg_set_tag_by_id(msg, g_array_index(self->options->tags, LogTagId, i)); } } log_msg_set_tag_by_id(msg, self->options->source_group_tag); /* stats counters */ if (stats_check_level(2)) { stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_HOST | SCS_SOURCE, NULL, log_msg_get_value(msg, LM_V_HOST, NULL) ); stats_register_and_increment_dynamic_counter(2, &sc_key, msg->timestamps[LM_TS_RECVD].tv_sec); if (stats_check_level(3)) { stats_cluster_logpipe_key_set(&sc_key, SCS_SENDER | SCS_SOURCE, NULL, log_msg_get_value(msg, LM_V_HOST_FROM, NULL) ); stats_register_and_increment_dynamic_counter(3, &sc_key, msg->timestamps[LM_TS_RECVD].tv_sec); stats_cluster_logpipe_key_set(&sc_key, SCS_PROGRAM | SCS_SOURCE, NULL, log_msg_get_value(msg, LM_V_PROGRAM, NULL) ); stats_register_and_increment_dynamic_counter(3, &sc_key, msg->timestamps[LM_TS_RECVD].tv_sec); } stats_unlock(); } stats_syslog_process_message_pri(msg->pri); /* message setup finished, send it out */ if (!_invoke_mangle_callbacks(s, msg, path_options)) return; stats_counter_inc(self->recvd_messages); stats_counter_set(self->last_message_seen, msg->timestamps[LM_TS_RECVD].tv_sec); log_pipe_forward_msg(s, msg, path_options); msg_set_context(NULL); if (accurate_nanosleep && self->threaded && self->window_full_sleep_nsec > 0 && !log_source_free_to_send(self)) { struct timespec ts; /* wait one 0.1msec in the hope that the buffer clears up */ ts.tv_sec = 0; ts.tv_nsec = self->window_full_sleep_nsec; nanosleep(&ts, NULL); } } static inline void _create_ack_tracker_if_not_exists(LogSource *self, gboolean pos_tracked) { if (!self->ack_tracker) { if (pos_tracked) self->ack_tracker = late_ack_tracker_new(self); else self->ack_tracker = early_ack_tracker_new(self); } } void log_source_set_options(LogSource *self, LogSourceOptions *options, const gchar *stats_id, const gchar *stats_instance, gboolean threaded, gboolean pos_tracked, LogExprNode *expr_node) { /* NOTE: we don't adjust window_size even in case it was changed in the * configuration and we received a SIGHUP. This means that opened * connections will not have their window_size changed. */ if (g_atomic_counter_get(&self->window_size) == -1) g_atomic_counter_set(&self->window_size, options->init_window_size); self->options = options; if (self->stats_id) g_free(self->stats_id); self->stats_id = stats_id ? g_strdup(stats_id) : NULL; if (self->stats_instance) g_free(self->stats_instance); self->stats_instance = stats_instance ? g_strdup(stats_instance): NULL; self->threaded = threaded; self->pos_tracked = pos_tracked; self->super.expr_node = expr_node; _create_ack_tracker_if_not_exists(self, pos_tracked); } void log_source_init_instance(LogSource *self, GlobalConfig *cfg) { log_pipe_init_instance(&self->super, cfg); self->super.queue = log_source_queue; self->super.free_fn = log_source_free; self->super.init = log_source_init; self->super.deinit = log_source_deinit; g_atomic_counter_set(&self->window_size, -1); self->ack_tracker = NULL; } void log_source_free(LogPipe *s) { LogSource *self = (LogSource *) s; g_free(self->stats_id); g_free(self->stats_instance); log_pipe_free_method(s); ack_tracker_free(self->ack_tracker); } void log_source_options_defaults(LogSourceOptions *options) { options->init_window_size = 100; options->keep_hostname = -1; options->chain_hostnames = -1; options->keep_timestamp = -1; options->program_override_len = -1; options->host_override_len = -1; options->tags = NULL; options->read_old_records = TRUE; host_resolve_options_defaults(&options->host_resolve_options); } /* NOTE: _init needs to be idempotent when called multiple times w/o invoking _destroy */ void log_source_options_init(LogSourceOptions *options, GlobalConfig *cfg, const gchar *group_name) { gchar *source_group_name; options->source_queue_callbacks = cfg->source_mangle_callback_list; if (options->keep_hostname == -1) options->keep_hostname = cfg->keep_hostname; if (options->chain_hostnames == -1) options->chain_hostnames = cfg->chain_hostnames; if (options->keep_timestamp == -1) options->keep_timestamp = cfg->keep_timestamp; options->group_name = group_name; source_group_name = g_strdup_printf(".source.%s", group_name); options->source_group_tag = log_tags_get_by_name(source_group_name); g_free(source_group_name); host_resolve_options_init(&options->host_resolve_options, &cfg->host_resolve_options); } void log_source_options_destroy(LogSourceOptions *options) { host_resolve_options_destroy(&options->host_resolve_options); if (options->program_override) g_free(options->program_override); if (options->host_override) g_free(options->host_override); if (options->tags) { g_array_free(options->tags, TRUE); options->tags = NULL; } } void log_source_options_set_tags(LogSourceOptions *options, GList *tags) { LogTagId id; if (!options->tags) options->tags = g_array_new(FALSE, FALSE, sizeof(LogTagId)); while (tags) { id = log_tags_get_by_name((gchar *) tags->data); g_array_append_val(options->tags, id); g_free(tags->data); tags = g_list_delete_link(tags, tags); } } void log_source_global_init(void) { accurate_nanosleep = check_nanosleep(); if (!accurate_nanosleep) { msg_debug("nanosleep() is not accurate enough to introduce minor stalls on the reader side, multi-threaded performance may be affected"); } } syslog-ng-syslog-ng-3.13.2/lib/logsource.h000066400000000000000000000071221321171025300203600ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGSOURCE_H_INCLUDED #define LOGSOURCE_H_INCLUDED #include "logpipe.h" #include "stats/stats-registry.h" typedef struct _LogSourceOptions { gint init_window_size; const gchar *group_name; gboolean keep_timestamp; gboolean keep_hostname; gboolean chain_hostnames; HostResolveOptions host_resolve_options; gchar *program_override; gint program_override_len; gchar *host_override; gint host_override_len; LogTagId source_group_tag; gboolean read_old_records; GArray *tags; GList *source_queue_callbacks; gint stats_level; gint stats_source; } LogSourceOptions; typedef struct _LogSource LogSource; /** * LogSource: * * This structure encapsulates an object which generates messages without * defining how those messages are accepted by peers. The most prominent * derived class is LogReader which is an extended RFC3164 capable syslog * message processor used everywhere. **/ struct _LogSource { LogPipe super; LogSourceOptions *options; gboolean threaded; gboolean pos_tracked; gchar *stats_id; gchar *stats_instance; GAtomicCounter window_size; GAtomicCounter suspended_window_size; StatsCounterItem *last_message_seen; StatsCounterItem *recvd_messages; guint32 last_ack_count; guint32 ack_count; glong window_full_sleep_nsec; struct timespec last_ack_rate_time; AckTracker *ack_tracker; void (*wakeup)(LogSource *s); }; static inline gboolean log_source_free_to_send(LogSource *self) { return g_atomic_counter_get(&self->window_size) > 0; } static inline gint log_source_get_init_window_size(LogSource *self) { return self->options->init_window_size; } gboolean log_source_init(LogPipe *s); gboolean log_source_deinit(LogPipe *s); void log_source_post(LogSource *self, LogMessage *msg); void log_source_set_options(LogSource *self, LogSourceOptions *options, const gchar *stats_id, const gchar *stats_instance, gboolean threaded, gboolean pos_tracked, LogExprNode *expr_node); void log_source_mangle_hostname(LogSource *self, LogMessage *msg); void log_source_init_instance(LogSource *self, GlobalConfig *cfg); void log_source_options_defaults(LogSourceOptions *options); void log_source_options_init(LogSourceOptions *options, GlobalConfig *cfg, const gchar *group_name); void log_source_options_destroy(LogSourceOptions *options); void log_source_options_set_tags(LogSourceOptions *options, GList *tags); void log_source_free(LogPipe *s); void log_source_wakeup(LogSource *self); void log_source_flow_control_adjust(LogSource *self, guint32 window_size_increment); void log_source_flow_control_suspend(LogSource *self); void log_source_global_init(void); #endif syslog-ng-syslog-ng-3.13.2/lib/logstamp.c000066400000000000000000000115341321171025300202010ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logstamp.h" #include "messages.h" #include "timeutils.h" #include "str-format.h" static void log_stamp_append_frac_digits(const LogStamp *stamp, GString *target, gint frac_digits) { glong usecs; usecs = stamp->tv_usec % 1000000; if (frac_digits > 0) { gulong x; g_string_append_c(target, '.'); for (x = 100000; frac_digits && x; x = x / 10) { g_string_append_c(target, (usecs / x) + '0'); usecs = usecs % x; frac_digits--; } } } /** * log_stamp_format: * @stamp: Timestamp to format * @target: Target storage for formatted timestamp * @ts_format: Specifies basic timestamp format (TS_FMT_BSD, TS_FMT_ISO) * @zone_offset: Specifies custom zone offset if @tz_convert == TZ_CNV_CUSTOM * * Emits the formatted version of @stamp into @target as specified by * @ts_format and @tz_convert. **/ void log_stamp_append_format(const LogStamp *stamp, GString *target, gint ts_format, glong zone_offset, gint frac_digits) { glong target_zone_offset = 0; struct tm *tm, tm_storage; char buf[8]; time_t t; if (zone_offset != -1) target_zone_offset = zone_offset; else target_zone_offset = stamp->zone_offset; t = stamp->tv_sec + target_zone_offset; cached_gmtime(&t, &tm_storage); tm = &tm_storage; switch (ts_format) { case TS_FMT_BSD: g_string_append(target, month_names_abbrev[tm->tm_mon]); g_string_append_c(target, ' '); format_uint32_padded(target, 2, ' ', 10, tm->tm_mday); g_string_append_c(target, ' '); format_uint32_padded(target, 2, '0', 10, tm->tm_hour); g_string_append_c(target, ':'); format_uint32_padded(target, 2, '0', 10, tm->tm_min); g_string_append_c(target, ':'); format_uint32_padded(target, 2, '0', 10, tm->tm_sec); log_stamp_append_frac_digits(stamp, target, frac_digits); break; case TS_FMT_ISO: format_uint32_padded(target, 0, 0, 10, tm->tm_year + 1900); g_string_append_c(target, '-'); format_uint32_padded(target, 2, '0', 10, tm->tm_mon + 1); g_string_append_c(target, '-'); format_uint32_padded(target, 2, '0', 10, tm->tm_mday); g_string_append_c(target, 'T'); format_uint32_padded(target, 2, '0', 10, tm->tm_hour); g_string_append_c(target, ':'); format_uint32_padded(target, 2, '0', 10, tm->tm_min); g_string_append_c(target, ':'); format_uint32_padded(target, 2, '0', 10, tm->tm_sec); log_stamp_append_frac_digits(stamp, target, frac_digits); format_zone_info(buf, sizeof(buf), target_zone_offset); g_string_append(target, buf); break; case TS_FMT_FULL: format_uint32_padded(target, 0, 0, 10, tm->tm_year + 1900); g_string_append_c(target, ' '); g_string_append(target, month_names_abbrev[tm->tm_mon]); g_string_append_c(target, ' '); format_uint32_padded(target, 2, ' ', 10, tm->tm_mday); g_string_append_c(target, ' '); format_uint32_padded(target, 2, '0', 10, tm->tm_hour); g_string_append_c(target, ':'); format_uint32_padded(target, 2, '0', 10, tm->tm_min); g_string_append_c(target, ':'); format_uint32_padded(target, 2, '0', 10, tm->tm_sec); log_stamp_append_frac_digits(stamp, target, frac_digits); break; case TS_FMT_UNIX: format_uint32_padded(target, 0, 0, 10, (int) stamp->tv_sec); log_stamp_append_frac_digits(stamp, target, frac_digits); break; default: g_assert_not_reached(); break; } } void log_stamp_format(LogStamp *stamp, GString *target, gint ts_format, glong zone_offset, gint frac_digits) { g_string_truncate(target, 0); log_stamp_append_format(stamp, target, ts_format, zone_offset, frac_digits); } gboolean log_stamp_eq(const LogStamp *a, const LogStamp *b) { return a->tv_sec == b->tv_sec && a->tv_usec == b->tv_usec && a->zone_offset == b->zone_offset; } syslog-ng-syslog-ng-3.13.2/lib/logstamp.h000066400000000000000000000033731321171025300202100ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGSTAMP_H_INCLUDED #define LOGSTAMP_H_INCLUDED #include "syslog-ng.h" /* timestamp formats */ #define TS_FMT_BSD 0 #define TS_FMT_ISO 1 #define TS_FMT_FULL 2 #define TS_FMT_UNIX 3 typedef struct _LogStamp { time_t tv_sec; guint32 tv_usec; /* zone offset in seconds, add this to UTC to get the time in local */ gint32 zone_offset; } LogStamp; static inline gboolean log_stamp_is_timezone_set(const LogStamp *self) { return self->zone_offset != -1; } void log_stamp_format(LogStamp *stamp, GString *target, gint ts_format, glong zone_offset, gint frac_digits); void log_stamp_append_format(const LogStamp *stamp, GString *target, gint ts_format, glong zone_offset, gint frac_digits); gboolean log_stamp_eq(const LogStamp *a, const LogStamp *b); #endif syslog-ng-syslog-ng-3.13.2/lib/logthrdestdrv.c000066400000000000000000000336541321171025300212550ustar00rootroot00000000000000/* * Copyright (c) 2013, 2014 Balabit * Copyright (c) 2013, 2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stats/stats-cluster-logpipe.h" #include "logthrdestdrv.h" #include "seqnum.h" #define MAX_RETRIES_OF_FAILED_INSERT_DEFAULT 3 static gchar * log_threaded_dest_driver_format_seqnum_for_persist(LogThrDestDriver *self) { static gchar persist_name[256]; g_snprintf(persist_name, sizeof(persist_name), "%s.seqnum", self->super.super.super.generate_persist_name((const LogPipe *)self)); return persist_name; } static void log_threaded_dest_driver_suspend(LogThrDestDriver *self) { iv_validate_now(); self->timer_reopen.expires = iv_now; self->timer_reopen.expires.tv_sec += self->time_reopen; iv_timer_register(&self->timer_reopen); } static void log_threaded_dest_driver_message_became_available_in_the_queue(gpointer user_data) { LogThrDestDriver *self = (LogThrDestDriver *) user_data; if (!self->under_termination) iv_event_post(&self->wake_up_event); } static void log_threaded_dest_driver_wake_up(gpointer data) { LogThrDestDriver *self = (LogThrDestDriver *)data; if (!iv_task_registered(&self->do_work)) { iv_task_register(&self->do_work); } } static void log_threaded_dest_driver_start_watches(LogThrDestDriver *self) { iv_task_register(&self->do_work); } static void log_threaded_dest_driver_stop_watches(LogThrDestDriver *self) { if (iv_task_registered(&self->do_work)) { iv_task_unregister(&self->do_work); } if (iv_timer_registered(&self->timer_reopen)) { iv_timer_unregister(&self->timer_reopen); } if (iv_timer_registered(&self->timer_throttle)) { iv_timer_unregister(&self->timer_throttle); } } static void log_threaded_dest_driver_shutdown(gpointer data) { LogThrDestDriver *self = (LogThrDestDriver *)data; log_threaded_dest_driver_stop_watches(self); iv_quit(); } static void __connect(LogThrDestDriver *self) { self->worker.connected = TRUE; if (self->worker.connect) { self->worker.connected = self->worker.connect(self); } if (!self->worker.connected) { log_queue_reset_parallel_push(self->queue); log_threaded_dest_driver_suspend(self); } else { log_threaded_dest_driver_start_watches(self); } } static void __disconnect(LogThrDestDriver *self) { if (self->worker.disconnect) { self->worker.disconnect(self); } self->worker.connected = FALSE; } static void _disconnect_and_suspend(LogThrDestDriver *self) { self->suspended = TRUE; __disconnect(self); log_queue_reset_parallel_push(self->queue); log_threaded_dest_driver_suspend(self); } static void log_threaded_dest_driver_do_insert(LogThrDestDriver *self) { LogMessage *msg; worker_insert_result_t result; LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; while (G_LIKELY(!self->under_termination) && !self->suspended && (msg = log_queue_pop_head(self->queue, &path_options)) != NULL) { msg_set_context(msg); log_msg_refcache_start_consumer(msg, &path_options); result = self->worker.insert(self, msg); switch (result) { case WORKER_INSERT_RESULT_DROP: msg_error("Message dropped while sending message to destinaton", evt_tag_str("driver", self->super.super.id)); log_threaded_dest_driver_message_drop(self, msg); _disconnect_and_suspend(self); break; case WORKER_INSERT_RESULT_ERROR: self->retries.counter++; if (self->retries.counter >= self->retries.max) { if (self->messages.retry_over) self->messages.retry_over(self, msg); msg_error("Multiple failures while sending message to destination, message dropped", evt_tag_str("driver", self->super.super.id), evt_tag_int("number_of_retries", self->retries.max)); log_threaded_dest_driver_message_drop(self, msg); } else { log_threaded_dest_driver_message_rewind(self, msg); _disconnect_and_suspend(self); } break; case WORKER_INSERT_RESULT_NOT_CONNECTED: log_threaded_dest_driver_message_rewind(self, msg); _disconnect_and_suspend(self); break; case WORKER_INSERT_RESULT_REWIND: log_threaded_dest_driver_message_rewind(self, msg); break; case WORKER_INSERT_RESULT_SUCCESS: stats_counter_inc(self->written_messages); log_threaded_dest_driver_message_accept(self, msg); break; default: break; } msg_set_context(NULL); log_msg_refcache_stop(); } if (!self->suspended) { if (self->worker.worker_message_queue_empty) { self->worker.worker_message_queue_empty(self); } } } static void log_threaded_dest_driver_do_work(gpointer data) { LogThrDestDriver *self = (LogThrDestDriver *)data; gint timeout_msec = 0; self->suspended = FALSE; main_loop_worker_run_gc(); log_threaded_dest_driver_stop_watches(self); if (!self->worker.connected) { __connect(self); } else if (log_queue_check_items(self->queue, &timeout_msec, log_threaded_dest_driver_message_became_available_in_the_queue, self, NULL)) { log_threaded_dest_driver_do_insert(self); if (!self->suspended) log_threaded_dest_driver_start_watches(self); } else if (timeout_msec != 0) { log_queue_reset_parallel_push(self->queue); iv_validate_now(); self->timer_throttle.expires = iv_now; timespec_add_msec(&self->timer_throttle.expires, timeout_msec); iv_timer_register(&self->timer_throttle); } } static void log_threaded_dest_driver_init_watches(LogThrDestDriver *self) { IV_EVENT_INIT(&self->wake_up_event); self->wake_up_event.cookie = self; self->wake_up_event.handler = log_threaded_dest_driver_wake_up; iv_event_register(&self->wake_up_event); IV_EVENT_INIT(&self->shutdown_event); self->shutdown_event.cookie = self; self->shutdown_event.handler = log_threaded_dest_driver_shutdown; iv_event_register(&self->shutdown_event); IV_TIMER_INIT(&self->timer_reopen); self->timer_reopen.cookie = self; self->timer_reopen.handler = log_threaded_dest_driver_do_work; IV_TIMER_INIT(&self->timer_throttle); self->timer_throttle.cookie = self; self->timer_throttle.handler = log_threaded_dest_driver_do_work; IV_TASK_INIT(&self->do_work); self->do_work.cookie = self; self->do_work.handler = log_threaded_dest_driver_do_work; } static void log_threaded_dest_driver_worker_thread_main(gpointer arg) { LogThrDestDriver *self = (LogThrDestDriver *)arg; iv_init(); msg_debug("Worker thread started", evt_tag_str("driver", self->super.super.id)); log_queue_set_use_backlog(self->queue, TRUE); log_threaded_dest_driver_init_watches(self); log_threaded_dest_driver_start_watches(self); if (self->worker.thread_init) self->worker.thread_init(self); iv_main(); __disconnect(self); if (self->worker.thread_deinit) self->worker.thread_deinit(self); msg_debug("Worker thread finished", evt_tag_str("driver", self->super.super.id)); iv_deinit(); } static void log_threaded_dest_driver_stop_thread(gpointer s) { LogThrDestDriver *self = (LogThrDestDriver *) s; self->under_termination = TRUE; iv_event_post(&self->shutdown_event); } static void log_threaded_dest_driver_start_thread(LogThrDestDriver *self) { main_loop_create_worker_thread(log_threaded_dest_driver_worker_thread_main, log_threaded_dest_driver_stop_thread, self, &self->worker_options); } static void _update_memory_usage_counter_when_fifo_is_used(LogThrDestDriver *self) { if (!g_strcmp0(self->queue->type, "FIFO") && self->memory_usage) { LogPipe *_pipe = &self->super.super.super; load_counter_from_persistent_storage(log_pipe_get_config(_pipe), self->memory_usage); } } gboolean log_threaded_dest_driver_start(LogPipe *s) { LogThrDestDriver *self = (LogThrDestDriver *)s; GlobalConfig *cfg = log_pipe_get_config(s); if (cfg && self->time_reopen == -1) self->time_reopen = cfg->time_reopen; self->queue = log_dest_driver_acquire_queue( &self->super, self->super.super.super.generate_persist_name((const LogPipe *)self)); if (self->queue == NULL) { return FALSE; } stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key,self->stats_source | SCS_DESTINATION, self->super.super.id, self->format.stats_instance(self)); stats_register_counter(0, &sc_key, SC_TYPE_QUEUED, &self->queued_messages); stats_register_counter(0, &sc_key, SC_TYPE_DROPPED, &self->dropped_messages); stats_register_counter(0, &sc_key, SC_TYPE_PROCESSED, &self->processed_messages); stats_register_counter_and_index(1, &sc_key, SC_TYPE_MEMORY_USAGE, &self->memory_usage); stats_register_counter(1, &sc_key, SC_TYPE_WRITTEN, &self->written_messages); stats_unlock(); log_queue_set_counters(self->queue, self->queued_messages, self->dropped_messages, self->memory_usage); _update_memory_usage_counter_when_fifo_is_used(self); self->seq_num = GPOINTER_TO_INT(cfg_persist_config_fetch(cfg, log_threaded_dest_driver_format_seqnum_for_persist(self))); if (!self->seq_num) init_sequence_number(&self->seq_num); log_threaded_dest_driver_start_thread(self); return TRUE; } gboolean log_threaded_dest_driver_deinit_method(LogPipe *s) { LogThrDestDriver *self = (LogThrDestDriver *)s; log_queue_reset_parallel_push(self->queue); log_queue_set_counters(self->queue, NULL, NULL, NULL); cfg_persist_config_add(log_pipe_get_config(s), log_threaded_dest_driver_format_seqnum_for_persist(self), GINT_TO_POINTER(self->seq_num), NULL, FALSE); save_counter_to_persistent_storage(log_pipe_get_config(s), self->memory_usage); stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, self->stats_source | SCS_DESTINATION, self->super.super.id, self->format.stats_instance(self)); stats_unregister_counter(&sc_key, SC_TYPE_QUEUED, &self->queued_messages); stats_unregister_counter(&sc_key, SC_TYPE_DROPPED, &self->dropped_messages); stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &self->processed_messages); stats_unregister_counter(&sc_key, SC_TYPE_WRITTEN, &self->written_messages); stats_unregister_counter(&sc_key, SC_TYPE_MEMORY_USAGE, &self->memory_usage); stats_unlock(); if (!log_dest_driver_deinit_method(s)) return FALSE; return TRUE; } void log_threaded_dest_driver_free(LogPipe *s) { LogThrDestDriver *self = (LogThrDestDriver *)s; log_dest_driver_free((LogPipe *)self); } static void log_threaded_dest_driver_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { LogThrDestDriver *self = (LogThrDestDriver *)s; LogPathOptions local_options; if (!path_options->flow_control_requested) path_options = log_msg_break_ack(msg, path_options, &local_options); if (self->queue_method) self->queue_method(self); log_msg_add_ack(msg, path_options); log_queue_push_tail(self->queue, log_msg_ref(msg), path_options); stats_counter_inc(self->processed_messages); log_dest_driver_queue_method(s, msg, path_options, user_data); } void log_threaded_dest_driver_init_instance(LogThrDestDriver *self, GlobalConfig *cfg) { log_dest_driver_init_instance(&self->super, cfg); self->worker_options.is_output_thread = TRUE; self->super.super.super.init = log_threaded_dest_driver_start; self->super.super.super.deinit = log_threaded_dest_driver_deinit_method; self->super.super.super.queue = log_threaded_dest_driver_queue; self->super.super.super.free_fn = log_threaded_dest_driver_free; self->time_reopen = -1; self->retries.max = MAX_RETRIES_OF_FAILED_INSERT_DEFAULT; } void log_threaded_dest_driver_message_accept(LogThrDestDriver *self, LogMessage *msg) { self->retries.counter = 0; step_sequence_number(&self->seq_num); log_queue_ack_backlog(self->queue, 1); log_msg_unref(msg); } void log_threaded_dest_driver_message_drop(LogThrDestDriver *self, LogMessage *msg) { stats_counter_inc(self->dropped_messages); log_threaded_dest_driver_message_accept(self, msg); } void log_threaded_dest_driver_message_rewind(LogThrDestDriver *self, LogMessage *msg) { log_queue_rewind_backlog(self->queue, 1); log_msg_unref(msg); } void log_threaded_dest_driver_set_max_retries(LogDriver *s, gint max_retries) { LogThrDestDriver *self = (LogThrDestDriver *)s; self->retries.max = max_retries; } syslog-ng-syslog-ng-3.13.2/lib/logthrdestdrv.h000066400000000000000000000066111321171025300212530ustar00rootroot00000000000000/* * Copyright (c) 2013, 2014 Balabit * Copyright (c) 2013, 2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGTHRDESTDRV_H #define LOGTHRDESTDRV_H #include "syslog-ng.h" #include "driver.h" #include "stats/stats-registry.h" #include "logqueue.h" #include "mainloop-worker.h" #include #include typedef enum { WORKER_INSERT_RESULT_DROP, WORKER_INSERT_RESULT_ERROR, WORKER_INSERT_RESULT_REWIND, WORKER_INSERT_RESULT_SUCCESS, WORKER_INSERT_RESULT_NOT_CONNECTED } worker_insert_result_t; typedef struct _LogThrDestDriver LogThrDestDriver; struct _LogThrDestDriver { LogDestDriver super; StatsCounterItem *dropped_messages; StatsCounterItem *queued_messages; StatsCounterItem *processed_messages; StatsCounterItem *written_messages; StatsCounterItem *memory_usage; gboolean suspended; gboolean under_termination; time_t time_reopen; LogQueue *queue; /* Worker stuff */ struct { gboolean connected; void (*thread_init) (LogThrDestDriver *s); void (*thread_deinit) (LogThrDestDriver *s); worker_insert_result_t (*insert) (LogThrDestDriver *s, LogMessage *msg); gboolean (*connect) (LogThrDestDriver *s); void (*worker_message_queue_empty)(LogThrDestDriver *s); void (*disconnect) (LogThrDestDriver *s); } worker; struct { void (*retry_over) (LogThrDestDriver *s, LogMessage *msg); } messages; struct { gchar *(*stats_instance) (LogThrDestDriver *s); } format; gint stats_source; gint32 seq_num; struct { gint counter; gint max; } retries; void (*queue_method) (LogThrDestDriver *s); WorkerOptions worker_options; struct iv_event wake_up_event; struct iv_event shutdown_event; struct iv_timer timer_reopen; struct iv_timer timer_throttle; struct iv_task do_work; }; gboolean log_threaded_dest_driver_deinit_method(LogPipe *s); gboolean log_threaded_dest_driver_start(LogPipe *s); void log_threaded_dest_driver_init_instance(LogThrDestDriver *self, GlobalConfig *cfg); void log_threaded_dest_driver_free(LogPipe *s); void log_threaded_dest_driver_message_accept(LogThrDestDriver *self, LogMessage *msg); void log_threaded_dest_driver_message_drop(LogThrDestDriver *self, LogMessage *msg); void log_threaded_dest_driver_message_rewind(LogThrDestDriver *self, LogMessage *msg); void log_threaded_dest_driver_set_max_retries(LogDriver *s, gint max_retries); #endif syslog-ng-syslog-ng-3.13.2/lib/logwriter.c000066400000000000000000001453021321171025300203720ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logwriter.h" #include "messages.h" #include "stats/stats-registry.h" #include "hostname.h" #include "host-resolve.h" #include "seqnum.h" #include "str-utils.h" #include "find-crlf.h" #include "mainloop.h" #include "mainloop-io-worker.h" #include "mainloop-call.h" #include "ml-batched-timer.h" #include "str-format.h" #include "scratch-buffers.h" #include #include #include #include #include #include #include #include #include typedef enum { /* flush modes */ /* business as usual, flush when the buffer is full */ LW_FLUSH_NORMAL, /* flush the buffer immediately please */ LW_FLUSH_FORCE, } LogWriterFlushMode; struct _LogWriter { LogPipe super; LogQueue *queue; guint32 flags:31; gint32 seq_num; StatsCounterItem *dropped_messages; StatsCounterItem *suppressed_messages; StatsCounterItem *processed_messages; StatsCounterItem *queued_messages; StatsCounterItem *written_messages; StatsCounterItem *memory_usage; LogPipe *control; LogWriterOptions *options; LogMessage *last_msg; guint32 last_msg_count; GString *line_buffer; gchar *stats_id; gchar *stats_instance; struct iv_fd fd_watch; struct iv_timer suspend_timer; struct iv_task immed_io_task; struct iv_event queue_filled; MainLoopIOWorkerJob io_job; GStaticMutex suppress_lock; MlBatchedTimer suppress_timer; MlBatchedTimer mark_timer; struct iv_timer reopen_timer; gboolean work_result; gint pollable_state; LogProtoClient *proto, *pending_proto; gboolean watches_running:1, suspended:1, working:1, waiting_for_throttle:1; gboolean pending_proto_present; GCond *pending_proto_cond; GStaticMutex pending_proto_lock; }; /** * LogWriter behaviour * ~~~~~~~~~~~~~~~~~~~ * * LogWriter is a core element of syslog-ng sending messages out to some * kind of destination represented by a UNIX fd. Outgoing messages are sent * to the target asynchronously, first by placing them to a queue and then * sending messages when poll() indicates that the fd is writable. * * * Flow control * ------------ * For a simple log writer without a disk buffer messages are placed on a * GQueue and they are acknowledged when the send() system call returned * success. This is more complex when disk buffering is used, in which case * messages are put to the "disk buffer" first and acknowledged immediately. * (this way the reader never stops when the disk buffer area is not yet * full). When disk buffer reaches its limit, messages are added to the the * usual GQueue and messages get acknowledged when they are moved to the * disk buffer. * **/ static gboolean log_writer_flush(LogWriter *self, LogWriterFlushMode flush_mode); static void log_writer_broken(LogWriter *self, gint notify_code); static void log_writer_start_watches(LogWriter *self); static void log_writer_stop_watches(LogWriter *self); static void log_writer_update_watches(LogWriter *self); static void log_writer_suspend(LogWriter *self); static void log_writer_free_proto(LogWriter *self); static void log_writer_set_proto(LogWriter *self, LogProtoClient *proto); static void log_writer_set_pending_proto(LogWriter *self, LogProtoClient *proto, gboolean present); static void log_writer_msg_ack(gint num_msg_acked, gpointer user_data) { LogWriter *self = (LogWriter *)user_data; log_queue_ack_backlog(self->queue, num_msg_acked); } static void log_writer_msg_rewind(gpointer user_data) { LogWriter *self = (LogWriter *)user_data; log_queue_rewind_backlog_all(self->queue); } void log_writer_set_flags(LogWriter *self, guint32 flags) { g_assert((self->super.flags & PIF_INITIALIZED) == 0); self->flags = flags; } guint32 log_writer_get_flags(LogWriter *self) { return self->flags; } /* returns a reference */ LogQueue * log_writer_get_queue(LogWriter *s) { LogWriter *self = (LogWriter *) s; return log_queue_ref(self->queue); } /* consumes the reference */ void log_writer_set_queue(LogWriter *self, LogQueue *queue) { log_queue_unref(self->queue); self->queue = log_queue_ref(queue); log_queue_set_use_backlog(self->queue, TRUE); } static void log_writer_work_perform(gpointer s) { LogWriter *self = (LogWriter *) s; g_assert((self->super.flags & PIF_INITIALIZED) != 0); self->work_result = log_writer_flush(self, LW_FLUSH_NORMAL); } static void log_writer_work_finished(gpointer s) { LogWriter *self = (LogWriter *) s; main_loop_assert_main_thread(); self->waiting_for_throttle = FALSE; if (self->pending_proto_present) { /* pending proto is only set in the main thread, so no need to * lock it before coming here. After we're syncing with the * log_writer_reopen() call, quite possibly coming from a * non-main thread. */ g_static_mutex_lock(&self->pending_proto_lock); log_writer_free_proto(self); log_writer_set_proto(self, self->pending_proto); log_writer_set_pending_proto(self, NULL, FALSE); g_cond_signal(self->pending_proto_cond); g_static_mutex_unlock(&self->pending_proto_lock); } if (!self->work_result) { log_writer_broken(self, NC_WRITE_ERROR); if (self->proto) { log_writer_suspend(self); msg_notice("Suspending write operation because of an I/O error", evt_tag_int("fd", log_proto_client_get_fd(self->proto)), evt_tag_int("time_reopen", self->options->time_reopen)); } goto exit; } if ((self->super.flags & PIF_INITIALIZED) && self->proto) { /* reenable polling the source, but only if we're still initialized */ log_writer_start_watches(self); } exit: log_pipe_unref(&self->super); } static void log_writer_io_flush_output(gpointer s) { LogWriter *self = (LogWriter *) s; main_loop_assert_main_thread(); log_writer_stop_watches(self); log_pipe_ref(&self->super); if ((self->options->options & LWO_THREADED)) { main_loop_io_worker_job_submit(&self->io_job); } else { /* Checking main_loop_io_worker_job_quit() helps to speed up the * reload process. If reload/shutdown is requested we shouldn't do * anything here, a final flush will be attempted in * log_writer_deinit(). * * Our current understanding is that it doesn't prevent race * conditions of any kind. */ if (!main_loop_worker_job_quit()) { log_writer_work_perform(s); log_writer_work_finished(s); } } } static void log_writer_io_error(gpointer s) { LogWriter *self = (LogWriter *) s; if (self->fd_watch.handler_out == NULL && self->fd_watch.handler_in == NULL) { msg_debug("POLLERR occurred while idle", evt_tag_int("fd", log_proto_client_get_fd(self->proto))); log_writer_broken(self, NC_WRITE_ERROR); return; } else { /* in case we have an error state but we also asked for read/write * polling, the error should be handled by the I/O callback. But we * need not call that explicitly as ivykis does that for us. */ } log_writer_update_watches(self); } static void log_writer_io_check_eof(gpointer s) { LogWriter *self = (LogWriter *) s; msg_error("EOF occurred while idle", evt_tag_int("fd", log_proto_client_get_fd(self->proto))); log_writer_broken(self, NC_CLOSE); } static void log_writer_error_suspend_elapsed(gpointer s) { LogWriter *self = (LogWriter *) s; self->suspended = FALSE; msg_notice("Error suspend timeout has elapsed, attempting to write again", evt_tag_int("fd", log_proto_client_get_fd(self->proto))); log_writer_start_watches(self); } static void log_writer_update_fd_callbacks(LogWriter *self, GIOCondition cond) { main_loop_assert_main_thread(); if (self->pollable_state > 0) { if (self->flags & LW_DETECT_EOF && (cond & G_IO_IN) == 0 && (cond & G_IO_OUT)) { /* if output is enabled, and we're in DETECT_EOF mode, and input is * not needed by the log protocol, install the eof check callback to * destroy the connection if an EOF is received. */ iv_fd_set_handler_in(&self->fd_watch, log_writer_io_check_eof); } else if (cond & G_IO_IN) { /* in case the protocol requested G_IO_IN, it means that it needs to * invoke read in the flush code, so just install the flush_output * handler for input */ iv_fd_set_handler_in(&self->fd_watch, log_writer_io_flush_output); } else { /* otherwise we're not interested in input */ iv_fd_set_handler_in(&self->fd_watch, NULL); } if (cond & G_IO_OUT) iv_fd_set_handler_out(&self->fd_watch, log_writer_io_flush_output); else iv_fd_set_handler_out(&self->fd_watch, NULL); iv_fd_set_handler_err(&self->fd_watch, log_writer_io_error); } else { /* fd is not pollable, assume it is always writable */ if (cond & G_IO_OUT) { if (!iv_task_registered(&self->immed_io_task)) iv_task_register(&self->immed_io_task); } else if (iv_task_registered(&self->immed_io_task)) { iv_task_unregister(&self->immed_io_task); } } } static void log_writer_arm_suspend_timer(LogWriter *self, void (*handler)(void *), gint timeout_msec) { main_loop_assert_main_thread(); if (iv_timer_registered(&self->suspend_timer)) iv_timer_unregister(&self->suspend_timer); iv_validate_now(); self->suspend_timer.handler = handler; self->suspend_timer.expires = iv_now; timespec_add_msec(&self->suspend_timer.expires, timeout_msec); iv_timer_register(&self->suspend_timer); } static void log_writer_queue_filled(gpointer s) { LogWriter *self = (LogWriter *) s; main_loop_assert_main_thread(); /* * NOTE: This theory is somewhat questionable, e.g. I'm not 100% sure it * is the right scenario, but the race was closed. So take this with a * grain of salt. * * The queue_filled callback is running in the main thread. Because of the * possible delay caused by iv_event_post() the callback might be * delivered event after stop_watches() has been called. * * - log_writer_schedule_update_watches() is called by the reader * thread, which calls iv_event_post() * - the main thread calls stop_watches() in work_perform * - the event is delivered in the main thread * * But since stop/start watches always run in the main thread and we do * too, we can check if this is the case. A LogWriter without watches * running is busy writing out data to the destination, e.g. a * start_watches is to be expected once log_writer_work_finished() is run * at the end of the deferred work, executed by the I/O threads. */ if (self->watches_running) log_writer_update_watches((LogWriter *) s); } /* NOTE: runs in the source thread */ static void log_writer_schedule_update_watches(LogWriter *self) { iv_event_post(&self->queue_filled); } static void log_writer_suspend(LogWriter *self) { /* flush code indicates that we need to suspend our writing activities * until time_reopen elapses */ log_writer_arm_suspend_timer(self, log_writer_error_suspend_elapsed, self->options->time_reopen * 1e3); self->suspended = TRUE; } static void log_writer_update_watches(LogWriter *self) { gint fd; GIOCondition cond = 0; gint timeout_msec = 0; main_loop_assert_main_thread(); /* NOTE: we either start the suspend_timer or enable the fd_watch. The two MUST not happen at the same time. */ if (log_proto_client_prepare(self->proto, &fd, &cond) || self->waiting_for_throttle || log_queue_check_items(self->queue, &timeout_msec, (LogQueuePushNotifyFunc) log_writer_schedule_update_watches, self, NULL)) { /* flush_lines number of element is already available and throttle would permit us to send. */ log_writer_update_fd_callbacks(self, cond); } else if (timeout_msec) { /* few elements are available, but less than flush_lines, we need to start a timer to initiate a flush */ log_writer_update_fd_callbacks(self, 0); self->waiting_for_throttle = TRUE; log_writer_arm_suspend_timer(self, (void (*)(void *)) log_writer_update_watches, timeout_msec); } else { /* no elements or no throttle space, wait for a wakeup by the queue * when the required number of items are added. see the * log_queue_check_items and its parallel_push argument above */ log_writer_update_fd_callbacks(self, 0); } } static gboolean is_file_regular(gint fd) { struct stat st; if (fstat(fd, &st) >= 0) { return S_ISREG(st.st_mode); } /* if stat fails, that's interesting, but we should probably poll * it, hopefully that's less likely to cause spinning */ return FALSE; } static void log_writer_start_watches(LogWriter *self) { gint fd; GIOCondition cond; if (self->watches_running) return; log_proto_client_prepare(self->proto, &fd, &cond); self->fd_watch.fd = fd; if (self->pollable_state < 0) { if (is_file_regular(fd)) self->pollable_state = 0; else self->pollable_state = !iv_fd_register_try(&self->fd_watch); } else if (self->pollable_state > 0) iv_fd_register(&self->fd_watch); log_writer_update_watches(self); self->watches_running = TRUE; } static void log_writer_stop_watches(LogWriter *self) { if (self->watches_running) { if (iv_timer_registered(&self->reopen_timer)) iv_timer_unregister(&self->reopen_timer); if (iv_timer_registered(&self->suspend_timer)) iv_timer_unregister(&self->suspend_timer); if (iv_fd_registered(&self->fd_watch)) iv_fd_unregister(&self->fd_watch); if (iv_task_registered(&self->immed_io_task)) iv_task_unregister(&self->immed_io_task); log_queue_reset_parallel_push(self->queue); self->watches_running = FALSE; } } static void log_writer_arm_suppress_timer(LogWriter *self) { ml_batched_timer_postpone(&self->suppress_timer, self->options->suppress); } /** * Remember the last message for dup detection. * * NOTE: suppress_lock must be held. **/ static void log_writer_record_last_message(LogWriter *self, LogMessage *lm) { if (self->last_msg) log_msg_unref(self->last_msg); log_msg_ref(lm); self->last_msg = lm; self->last_msg_count = 0; } /* * NOTE: suppress_lock must be held. */ static void log_writer_release_last_message(LogWriter *self) { if (self->last_msg) log_msg_unref(self->last_msg); self->last_msg = NULL; self->last_msg_count = 0; } /* * NOTE: suppress_lock must be held. */ static void log_writer_emit_suppress_summary(LogWriter *self) { LogMessage *m; LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; gchar buf[1024]; gssize len; const gchar *p; msg_debug("Suppress timer elapsed, emitting suppression summary"); len = g_snprintf(buf, sizeof(buf), "Last message '%.20s' repeated %d times, suppressed by syslog-ng on %s", log_msg_get_value(self->last_msg, LM_V_MESSAGE, NULL), self->last_msg_count, get_local_hostname_fqdn()); m = log_msg_new_internal(self->last_msg->pri, buf); p = log_msg_get_value(self->last_msg, LM_V_HOST, &len); log_msg_set_value(m, LM_V_HOST, p, len); p = log_msg_get_value(self->last_msg, LM_V_PROGRAM, &len); log_msg_set_value(m, LM_V_PROGRAM, p, len); path_options.ack_needed = FALSE; log_queue_push_tail(self->queue, m, &path_options); log_writer_release_last_message(self); } static gboolean log_writer_suppress_timeout(gpointer pt) { LogWriter *self = (LogWriter *) pt; main_loop_assert_main_thread(); /* NOTE: this will probably do nothing as we are the timer callback, but * we may not do it with the suppress_lock held */ ml_batched_timer_cancel(&self->suppress_timer); g_static_mutex_lock(&self->suppress_lock); /* NOTE: we may be waken up an extra time if the suppress_timer setup race * is lost, see the comment at log_writer_is_msg_suppressed() for an * explanation */ if (self->last_msg_count > 0) log_writer_emit_suppress_summary(self); g_static_mutex_unlock(&self->suppress_lock); return FALSE; } static gboolean _is_message_a_mark(LogMessage *msg) { return strcmp(log_msg_get_value(msg, LM_V_MESSAGE, NULL), "-- MARK --") == 0; } static gboolean _is_message_a_repetition(LogMessage *msg, LogMessage *last) { return strcmp(log_msg_get_value(last, LM_V_MESSAGE, NULL), log_msg_get_value(msg, LM_V_MESSAGE, NULL)) == 0 && strcmp(log_msg_get_value(last, LM_V_HOST, NULL), log_msg_get_value(msg, LM_V_HOST, NULL)) == 0 && strcmp(log_msg_get_value(last, LM_V_PROGRAM, NULL), log_msg_get_value(msg, LM_V_PROGRAM, NULL)) == 0 && strcmp(log_msg_get_value(last, LM_V_PID, NULL), log_msg_get_value(msg, LM_V_PID, NULL)) == 0; } static gboolean _is_time_within_the_suppress_timeout(LogWriter *self, LogMessage *msg) { return self->last_msg->timestamps[LM_TS_RECVD].tv_sec >= msg->timestamps[LM_TS_RECVD].tv_sec - self->options->suppress; } /** * log_writer_is_msg_suppressed: * * This function is called to suppress duplicate messages from a given host. * * Locking notes: * * There's a strict ordering requirement between suppress_lock and * interacting with the main loop (which ml_batched_timer beind * suppress_timer is doing). * * The reason is that the main thread (running * the main loop) sometimes acquires suppress_lock (at suppress timer * expiration) and while blocking on suppress_lock it cannot service * main_loop_calls() * * This function makes it sure that ml_batched_timer_update/cancel calls are * only done with the suppress lock released. * * If we do this, we might have a few unfortunate side effects due to races * that we also try to handle: * * Two messages race, one of these matches the recorded last message, * the other doesn't. In this case, moving the update on the suppress_timer * outside of the lock region might cause two different races: * * 1) matching message comes first, then non-matching * * This case the suppress_lock protected region decides that the suppress * timer needs to fire (#1) and then the other decides that it needs to * be cancelled. (#2) * * If these are processed in order, then we are the same as if the two was * also protected by the mutex (which is ok) * * If they are reversed, e.g. we first cancels the timer and the second arms it, * then we might have a timer wakeup which will find no suppressed messages * to report (as the non-matching message will set last_msg_count to zero). This * spurious wakeup should be handled by the expiration callback. * * 1) non-matching message comes first, then matching * * This is simply a message reordering case, e.g. we don't * want any suppressions to be emitted. * * In this case the locked regions finds that neither messages matched * the recorded one, thus both times they decide to cancel the timer, which * is ok. Timer cancellation can be reordered as they will have the same * effect anyway. * * Returns TRUE to indicate that the message is to be suppressed. **/ static gboolean log_writer_is_msg_suppressed(LogWriter *self, LogMessage *lm) { gboolean need_to_arm_suppress_timer; gboolean need_to_cancel_suppress_timer = FALSE; if (self->options->suppress <= 0) return FALSE; g_static_mutex_lock(&self->suppress_lock); if (self->last_msg) { if (_is_time_within_the_suppress_timeout(self, lm) && _is_message_a_repetition(lm, self->last_msg) && !_is_message_a_mark(lm)) { stats_counter_inc(self->suppressed_messages); self->last_msg_count++; /* we only create the timer if this is the first suppressed message, otherwise it is already running. */ need_to_arm_suppress_timer = self->last_msg_count == 1; g_static_mutex_unlock(&self->suppress_lock); /* this has to be outside of suppress_lock */ if (need_to_arm_suppress_timer) log_writer_arm_suppress_timer(self); msg_debug("Suppressing duplicate message", evt_tag_str("host", log_msg_get_value(lm, LM_V_HOST, NULL)), evt_tag_str("msg", log_msg_get_value(lm, LM_V_MESSAGE, NULL))); return TRUE; } else { if (self->last_msg_count) log_writer_emit_suppress_summary(self); else log_writer_release_last_message(self); need_to_cancel_suppress_timer = TRUE; } } log_writer_record_last_message(self, lm); g_static_mutex_unlock(&self->suppress_lock); if (need_to_cancel_suppress_timer) ml_batched_timer_cancel(&self->suppress_timer); return FALSE; } static void log_writer_postpone_mark_timer(LogWriter *self) { if (self->options->mark_freq > 0) ml_batched_timer_postpone(&self->mark_timer, self->options->mark_freq); } /* this is the callback function that gets called when the MARK timeout * elapsed. It runs in the main thread. */ static void log_writer_mark_timeout(void *cookie) { LogWriter *self = (LogWriter *)cookie; LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; const gchar *hostname; gsize hostname_len; LogMessage *msg; main_loop_assert_main_thread(); msg = log_msg_new_mark(); /* timeout: there was no new message on the writer or it is in periodical mode */ hostname = resolve_sockaddr_to_hostname(&hostname_len, msg->saddr, &self->options->host_resolve_options); log_msg_set_value(msg, LM_V_HOST, hostname, hostname_len); if (!log_writer_is_msg_suppressed(self, msg)) { log_queue_push_tail(self->queue, msg, &path_options); stats_counter_inc(self->processed_messages); } else { log_msg_drop(msg, &path_options, AT_PROCESSED); } /* we need to issue another MARK in all mark-mode cases that already * triggered this callback (dst-idle, host-idle, periodical). The * original setup of the timer is at a different location: * - log_writer_queue() for "*-idle" modes * - log_writer_init() for periodical mode */ log_writer_postpone_mark_timer(self); } /* NOTE: runs in the reader thread */ static void log_writer_queue(LogPipe *s, LogMessage *lm, const LogPathOptions *path_options, gpointer user_data) { LogWriter *self = (LogWriter *) s; LogPathOptions local_options; gint mark_mode = self->options->mark_mode; if (!path_options->flow_control_requested && ((self->proto == NULL || self->suspended) || !(self->flags & LW_SOFT_FLOW_CONTROL))) { /* NOTE: this code ACKs the message back if there's a write error in * order not to hang the client in case of a disk full */ path_options = log_msg_break_ack(lm, path_options, &local_options); } if (log_writer_is_msg_suppressed(self, lm)) { log_msg_drop(lm, path_options, AT_PROCESSED); return; } if (mark_mode != MM_INTERNAL && (lm->flags & LF_INTERNAL) && (lm->flags & LF_MARK)) { /* drop MARK messages generated by internal() in case our mark-mode != internal */ log_msg_drop(lm, path_options, AT_PROCESSED); return; } if (mark_mode == MM_DST_IDLE || (mark_mode == MM_HOST_IDLE && !(lm->flags & LF_LOCAL))) { /* in dst-idle and host-idle most, messages postpone the MARK itself */ log_writer_postpone_mark_timer(self); } stats_counter_inc(self->processed_messages); log_queue_push_tail(self->queue, lm, path_options); } static void log_writer_append_value(GString *result, LogMessage *lm, NVHandle handle, gboolean use_nil, gboolean append_space) { const gchar *value; gssize value_len; value = log_msg_get_value(lm, handle, &value_len); if (use_nil && value_len == 0) g_string_append_c(result, '-'); else { gchar *space; space = strchr(value, ' '); if (!space) g_string_append_len(result, value, value_len); else g_string_append_len(result, value, space - value); } if (append_space) g_string_append_c(result, ' '); } static void log_writer_do_padding(LogWriter *self, GString *result) { if (!self->options->padding) return; if(G_UNLIKELY(self->options->padding < result->len)) { msg_warning("Padding is too small to hold the full message", evt_tag_int("padding", self->options->padding), evt_tag_int("msg_size", result->len)); g_string_set_size(result, self->options->padding); return; } /* store the original length of the result */ gint len = result->len; gint padd_bytes = self->options->padding - result->len; /* set the size to the padded size, this will allocate the string */ g_string_set_size(result, self->options->padding); memset(result->str + len - 1, '\0', padd_bytes); } void log_writer_format_log(LogWriter *self, LogMessage *lm, GString *result) { LogTemplate *template = NULL; LogStamp *stamp; guint32 seq_num; static NVHandle meta_seqid = 0; if (!meta_seqid) meta_seqid = log_msg_get_value_handle(".SDATA.meta.sequenceId"); if (lm->flags & LF_LOCAL) { seq_num = self->seq_num; } else { const gchar *seqid; gssize seqid_length; seqid = log_msg_get_value(lm, meta_seqid, &seqid_length); APPEND_ZERO(seqid, seqid, seqid_length); if (seqid[0]) seq_num = strtol(seqid, NULL, 10); else seq_num = 0; } /* no template was specified, use default */ stamp = &lm->timestamps[LM_TS_STAMP]; g_string_truncate(result, 0); if ((self->flags & LW_SYSLOG_PROTOCOL) || (self->options->options & LWO_SYSLOG_PROTOCOL)) { gssize len; /* we currently hard-wire version 1 */ g_string_append_c(result, '<'); format_uint32_padded(result, 0, 0, 10, lm->pri); g_string_append_c(result, '>'); g_string_append_c(result, '1'); g_string_append_c(result, ' '); log_stamp_append_format(stamp, result, TS_FMT_ISO, time_zone_info_get_offset(self->options->template_options.time_zone_info[LTZ_SEND], stamp->tv_sec), self->options->template_options.frac_digits); g_string_append_c(result, ' '); log_writer_append_value(result, lm, LM_V_HOST, TRUE, TRUE); log_writer_append_value(result, lm, LM_V_PROGRAM, TRUE, TRUE); log_writer_append_value(result, lm, LM_V_PID, TRUE, TRUE); log_writer_append_value(result, lm, LM_V_MSGID, TRUE, TRUE); len = result->len; log_msg_append_format_sdata(lm, result, seq_num); if (len == result->len) { /* NOTE: sd_param format did not generate any output, take it as an empty SD string */ g_string_append_c(result, '-'); } if (self->options->template) { g_string_append_c(result, ' '); if (lm->flags & LF_UTF8) g_string_append_len(result, "\xEF\xBB\xBF", 3); log_template_append_format(self->options->template, lm, &self->options->template_options, LTZ_SEND, seq_num, NULL, result); } else { const gchar *p; p = log_msg_get_value(lm, LM_V_MESSAGE, &len); g_string_append_c(result, ' '); if (len != 0) { if (lm->flags & LF_UTF8) g_string_append_len(result, "\xEF\xBB\xBF", 3); g_string_append_len(result, p, len); } } g_string_append_c(result, '\n'); log_writer_do_padding(self, result); } else { if (self->options->template) { template = self->options->template; } else if (self->flags & LW_FORMAT_FILE) { template = self->options->file_template; } else if ((self->flags & LW_FORMAT_PROTO)) { template = self->options->proto_template; } if (template) { log_template_format(template, lm, &self->options->template_options, LTZ_SEND, seq_num, NULL, result); } else { const gchar *p; gssize len; if (self->flags & LW_FORMAT_FILE) { log_stamp_format(stamp, result, self->options->template_options.ts_format, time_zone_info_get_offset(self->options->template_options.time_zone_info[LTZ_SEND], stamp->tv_sec), self->options->template_options.frac_digits); } else if (self->flags & LW_FORMAT_PROTO) { g_string_append_c(result, '<'); format_uint32_padded(result, 0, 0, 10, lm->pri); g_string_append_c(result, '>'); /* always use BSD timestamp by default, the use can override this using a custom template */ log_stamp_append_format(stamp, result, TS_FMT_BSD, time_zone_info_get_offset(self->options->template_options.time_zone_info[LTZ_SEND], stamp->tv_sec), self->options->template_options.frac_digits); } g_string_append_c(result, ' '); p = log_msg_get_value(lm, LM_V_HOST, &len); g_string_append_len(result, p, len); g_string_append_c(result, ' '); p = log_msg_get_value(lm, LM_V_LEGACY_MSGHDR, &len); if (len > 0) { g_string_append_len(result, p, len); } else { p = log_msg_get_value(lm, LM_V_PROGRAM, &len); if (len > 0) { g_string_append_len(result, p, len); p = log_msg_get_value(lm, LM_V_PID, &len); if (len > 0) { g_string_append_c(result, '['); g_string_append_len(result, p, len); g_string_append_c(result, ']'); } g_string_append_len(result, ": ", 2); } } p = log_msg_get_value(lm, LM_V_MESSAGE, &len); g_string_append_len(result, p, len); g_string_append_c(result, '\n'); log_writer_do_padding(self, result); } } if (self->options->options & LWO_NO_MULTI_LINE) { gchar *p; p = result->str; /* NOTE: the size is calculated to leave trailing new line */ while ((p = find_cr_or_lf(p, result->str + result->len - p - 1))) { *p = ' '; p++; } } } static void log_writer_broken(LogWriter *self, gint notify_code) { log_writer_stop_watches(self); log_pipe_notify(self->control, notify_code, self); } static void log_writer_realloc_line_buffer(LogWriter *self) { self->line_buffer->str = g_malloc(self->line_buffer->allocated_len); self->line_buffer->str[0] = 0; self->line_buffer->len = 0; } /* * Write messages to the underlying file descriptor using the installed * LogProtoClient instance. This is called whenever the output is ready to accept * further messages, and once during config deinitialization, in order to * flush messages still in the queue, in the hope that most of them can be * written out. * * In threaded mode, this function is invoked as part of the "output" task * (in essence, this is the function that performs the output task). * */ static gboolean log_writer_flush_finalize(LogWriter *self) { LogProtoStatus status = log_proto_client_flush(self->proto); if (status != LPS_SUCCESS) return FALSE; return TRUE; } gboolean log_writer_write_message(LogWriter *self, LogMessage *msg, LogPathOptions *path_options, gboolean *write_error) { gboolean consumed = FALSE; *write_error = FALSE; log_msg_refcache_start_consumer(msg, path_options); msg_set_context(msg); log_writer_format_log(self, msg, self->line_buffer); if (!(msg->flags & LF_INTERNAL)) { msg_debug("Outgoing message", evt_tag_str("message",self->line_buffer->str)); } if (self->line_buffer->len) { LogProtoStatus status = log_proto_client_post(self->proto, (guchar *)self->line_buffer->str, self->line_buffer->len, &consumed); if (consumed) log_writer_realloc_line_buffer(self); if (status == LPS_ERROR) { if ((self->options->options & LWO_IGNORE_ERRORS) != 0) { if (!consumed) { g_free(self->line_buffer->str); log_writer_realloc_line_buffer(self); consumed = TRUE; } } else { *write_error = TRUE; consumed = FALSE; } } } else { msg_debug("Error posting log message as template() output resulted in an empty string, skipping message"); consumed = TRUE; } if (consumed) { if (msg->flags & LF_LOCAL) step_sequence_number(&self->seq_num); log_msg_unref(msg); msg_set_context(NULL); log_msg_refcache_stop(); return TRUE; } else { msg_debug("Can't send the message rewind backlog", evt_tag_str("message",self->line_buffer->str)); log_queue_rewind_backlog(self->queue, 1); log_msg_unref(msg); msg_set_context(NULL); log_msg_refcache_stop(); return FALSE; } } static inline LogMessage * log_writer_queue_pop_message(LogWriter *self, LogPathOptions *path_options, gboolean force_flush) { if (force_flush) return log_queue_pop_head_ignore_throttle(self->queue, path_options); else return log_queue_pop_head(self->queue, path_options); } /* * @flush_mode specifies how hard LogWriter is trying to send messages to * the actual destination: * * * LW_FLUSH_NORMAL - business as usual, flush when the buffer is full * LW_FLUSH_FORCE - flush the buffer immediately please * */ gboolean log_writer_flush(LogWriter *self, LogWriterFlushMode flush_mode) { gboolean write_error = FALSE; if (!self->proto) return FALSE; /* NOTE: in case we're reloading or exiting we flush all queued items as * long as the destination can consume it. This is not going to be an * infinite loop, since the reader will cease to produce new messages when * main_loop_io_worker_job_quit() is set. */ while ((!main_loop_worker_job_quit() || flush_mode == LW_FLUSH_FORCE) && !write_error) { LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; LogMessage *msg = log_writer_queue_pop_message(self, &path_options, flush_mode == LW_FLUSH_FORCE); if (!msg) break; ScratchBuffersMarker mark; scratch_buffers_mark(&mark); if (!log_writer_write_message(self, msg, &path_options, &write_error)) { scratch_buffers_reclaim_marked(mark); break; } scratch_buffers_reclaim_marked(mark); if (!write_error) stats_counter_inc(self->written_messages); } if (write_error) return FALSE; return log_writer_flush_finalize(self); } static void log_writer_reopen_timeout(void *cookie) { LogWriter *self = (LogWriter *)cookie; log_pipe_notify(self->control, NC_REOPEN_REQUIRED, self); } static void log_writer_init_watches(LogWriter *self) { IV_FD_INIT(&self->fd_watch); self->fd_watch.cookie = self; IV_TASK_INIT(&self->immed_io_task); self->immed_io_task.cookie = self; self->immed_io_task.handler = log_writer_io_flush_output; IV_TIMER_INIT(&self->suspend_timer); self->suspend_timer.cookie = self; ml_batched_timer_init(&self->suppress_timer); self->suppress_timer.cookie = self; self->suppress_timer.handler = (void (*)(void *)) log_writer_suppress_timeout; self->suppress_timer.ref_cookie = (gpointer (*)(gpointer)) log_pipe_ref; self->suppress_timer.unref_cookie = (void (*)(gpointer)) log_pipe_unref; ml_batched_timer_init(&self->mark_timer); self->mark_timer.cookie = self; self->mark_timer.handler = (void (*)(void *)) log_writer_mark_timeout; self->mark_timer.ref_cookie = (gpointer (*)(gpointer)) log_pipe_ref; self->mark_timer.unref_cookie = (void (*)(gpointer)) log_pipe_unref; IV_TIMER_INIT(&self->reopen_timer); self->reopen_timer.cookie = self; self->reopen_timer.handler = (void (*)(void *)) log_writer_reopen_timeout; IV_EVENT_INIT(&self->queue_filled); self->queue_filled.cookie = self; self->queue_filled.handler = log_writer_queue_filled; main_loop_io_worker_job_init(&self->io_job); self->io_job.user_data = self; self->io_job.work = (void (*)(void *)) log_writer_work_perform; self->io_job.completion = (void (*)(void *)) log_writer_work_finished; } static void _register_counters(LogWriter *self) { stats_lock(); { StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, self->options->stats_source | SCS_DESTINATION, self->stats_id, self->stats_instance); if (self->options->suppress > 0) stats_register_counter(self->options->stats_level, &sc_key, SC_TYPE_SUPPRESSED, &self->suppressed_messages); stats_register_counter(self->options->stats_level, &sc_key, SC_TYPE_DROPPED, &self->dropped_messages); stats_register_counter(self->options->stats_level, &sc_key, SC_TYPE_PROCESSED, &self->processed_messages); stats_register_counter(self->options->stats_level, &sc_key, SC_TYPE_QUEUED, &self->queued_messages); stats_register_counter(self->options->stats_level, &sc_key, SC_TYPE_WRITTEN, &self->written_messages); stats_register_counter_and_index(STATS_LEVEL1, &sc_key, SC_TYPE_MEMORY_USAGE, &self->memory_usage); } stats_unlock(); } static void _update_memory_usage_counter_when_fifo_is_used(LogWriter *self) { if (!g_strcmp0(self->queue->type, "FIFO") && self->memory_usage) { LogPipe *_pipe = &self->super; load_counter_from_persistent_storage(log_pipe_get_config(_pipe), self->memory_usage); } } static gboolean log_writer_init(LogPipe *s) { LogWriter *self = (LogWriter *) s; if (self->queue == NULL) { return FALSE; } iv_event_register(&self->queue_filled); if ((self->options->options & LWO_NO_STATS) == 0 && !self->dropped_messages) _register_counters(self); log_queue_set_counters(self->queue, self->queued_messages, self->dropped_messages, self->memory_usage); _update_memory_usage_counter_when_fifo_is_used(self); if (self->proto) { LogProtoClient *proto; proto = self->proto; log_writer_set_proto(self, NULL); log_writer_reopen(self, proto); } if (self->options->mark_mode == MM_PERIODICAL) { /* periodical marks should be emitted even if no message is received, * so we need a timer right from the start */ log_writer_postpone_mark_timer(self); } return TRUE; } static void _unregister_counters(LogWriter *self) { if (self->memory_usage) save_counter_to_persistent_storage(log_pipe_get_config(&self->super), self->memory_usage); stats_lock(); { StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, self->options->stats_source | SCS_DESTINATION, self->stats_id, self->stats_instance); stats_unregister_counter(&sc_key, SC_TYPE_DROPPED, &self->dropped_messages); stats_unregister_counter(&sc_key, SC_TYPE_SUPPRESSED, &self->suppressed_messages); stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &self->processed_messages); stats_unregister_counter(&sc_key, SC_TYPE_QUEUED, &self->queued_messages); stats_unregister_counter(&sc_key, SC_TYPE_WRITTEN, &self->written_messages); stats_unregister_counter(&sc_key, SC_TYPE_MEMORY_USAGE, &self->memory_usage); } stats_unlock(); } static gboolean log_writer_deinit(LogPipe *s) { LogWriter *self = (LogWriter *) s; main_loop_assert_main_thread(); log_queue_reset_parallel_push(self->queue); log_writer_flush(self, LW_FLUSH_FORCE); /* FIXME: by the time we arrive here, it must be guaranteed that no * _queue() call is running in a different thread, otherwise we'd need * some kind of locking. */ log_writer_stop_watches(self); iv_event_unregister(&self->queue_filled); if (iv_timer_registered(&self->reopen_timer)) iv_timer_unregister(&self->reopen_timer); ml_batched_timer_unregister(&self->suppress_timer); ml_batched_timer_unregister(&self->mark_timer); _unregister_counters(self); log_queue_set_counters(self->queue, NULL, NULL, NULL); return TRUE; } static void log_writer_free(LogPipe *s) { LogWriter *self = (LogWriter *) s; log_writer_free_proto(self); if (self->line_buffer) g_string_free(self->line_buffer, TRUE); log_queue_unref(self->queue); if (self->last_msg) log_msg_unref(self->last_msg); g_free(self->stats_id); g_free(self->stats_instance); ml_batched_timer_free(&self->mark_timer); ml_batched_timer_free(&self->suppress_timer); g_static_mutex_free(&self->suppress_lock); g_static_mutex_free(&self->pending_proto_lock); g_cond_free(self->pending_proto_cond); log_pipe_free_method(s); } /* FIXME: this is inherently racy */ gboolean log_writer_has_pending_writes(LogWriter *self) { return !log_queue_is_empty_racy(self->queue) || !self->watches_running; } gboolean log_writer_opened(LogWriter *self) { return self->proto != NULL; } static void log_writer_free_proto(LogWriter *self) { if (self->proto) log_proto_client_free(self->proto); self->proto = NULL; } static void log_writer_set_proto(LogWriter *self, LogProtoClient *proto) { self->proto = proto; if (proto) { LogProtoClientFlowControlFuncs flow_control_funcs; flow_control_funcs.ack_callback = log_writer_msg_ack; flow_control_funcs.rewind_callback = log_writer_msg_rewind; flow_control_funcs.user_data = self; log_proto_client_set_client_flow_control(self->proto, &flow_control_funcs); } } static void log_writer_set_pending_proto(LogWriter *self, LogProtoClient *proto, gboolean present) { self->pending_proto = proto; self->pending_proto_present = present; } /* run in the main thread in reaction to a log_writer_reopen to change * the destination LogProtoClient instance. It needs to be ran in the main * thread as it reregisters the watches associated with the main * thread. */ void log_writer_reopen_deferred(gpointer s) { gpointer *args = (gpointer *) s; LogWriter *self = args[0]; LogProtoClient *proto = args[1]; if (!proto) { iv_validate_now(); self->reopen_timer.expires = iv_now; self->reopen_timer.expires.tv_sec += self->options->time_reopen; if (iv_timer_registered(&self->reopen_timer)) iv_timer_unregister(&self->reopen_timer); iv_timer_register(&self->reopen_timer); } init_sequence_number(&self->seq_num); if (self->io_job.working) { /* NOTE: proto can be NULL but it is present... */ log_writer_set_pending_proto(self, proto, TRUE); return; } log_writer_stop_watches(self); log_writer_free_proto(self); log_writer_set_proto(self, proto); if (proto) log_writer_start_watches(self); } /* * This function can be called from any threads, from the main thread * as well as I/O worker threads. It takes care about going to the * main thread to actually switch LogProtoClient under this writer. * * The writer may still be operating, (e.g. log_pipe_deinit/init is * not needed). * * In case we're running in a non-main thread, then by the time this * function returns, the reopen has finished. In case it is called * from the main thread, this function may defer updating self->proto * until the worker thread has finished. The reason for this * difference is: * * - if LogWriter is busy, then updating the LogProtoClient instance is * deferred to log_writer_work_finished(), but that runs in the * main thread. * * - normally, even this deferred update is waited for, but in case * we're in the main thread, we can't block. * * This situation could probably be improved, maybe the synchonous * return of log_writer_reopen() is not needed by call sites, but I * was not sure, and right before release I didn't want to take the * risky approach. */ void log_writer_reopen(LogWriter *s, LogProtoClient *proto) { LogWriter *self = (LogWriter *) s; gpointer args[] = { s, proto }; main_loop_call((MainLoopTaskFunc) log_writer_reopen_deferred, args, TRUE); if (!main_loop_is_main_thread()) { g_static_mutex_lock(&self->pending_proto_lock); while (self->pending_proto_present) { g_cond_wait(self->pending_proto_cond, g_static_mutex_get_mutex(&self->pending_proto_lock)); } g_static_mutex_unlock(&self->pending_proto_lock); } } void log_writer_set_options(LogWriter *self, LogPipe *control, LogWriterOptions *options, const gchar *stats_id, const gchar *stats_instance) { self->control = control; self->options = options; if (control) self->super.expr_node = control->expr_node; if (self->stats_id) g_free(self->stats_id); self->stats_id = stats_id ? g_strdup(stats_id) : NULL; if (self->stats_instance) g_free(self->stats_instance); self->stats_instance = stats_instance ? g_strdup(stats_instance) : NULL; } LogWriter * log_writer_new(guint32 flags, GlobalConfig *cfg) { LogWriter *self = g_new0(LogWriter, 1); log_pipe_init_instance(&self->super, cfg); self->super.init = log_writer_init; self->super.deinit = log_writer_deinit; self->super.queue = log_writer_queue; self->super.free_fn = log_writer_free; self->flags = flags; self->line_buffer = g_string_sized_new(128); self->pollable_state = -1; init_sequence_number(&self->seq_num); log_writer_init_watches(self); g_static_mutex_init(&self->suppress_lock); g_static_mutex_init(&self->pending_proto_lock); self->pending_proto_cond = g_cond_new(); return self; } void log_writer_options_defaults(LogWriterOptions *options) { options->template = NULL; options->flush_lines = -1; options->flush_timeout = -1; log_template_options_defaults(&options->template_options); options->time_reopen = -1; options->suppress = -1; options->padding = 0; options->mark_mode = MM_GLOBAL; options->mark_freq = -1; host_resolve_options_defaults(&options->host_resolve_options); } void log_writer_options_set_template_escape(LogWriterOptions *options, gboolean enable) { if (options->template && options->template->def_inline) { log_template_set_escape(options->template, enable); } else { msg_error("Macro escaping can only be specified for inline templates"); } } void log_writer_options_set_mark_mode(LogWriterOptions *options, gchar *mark_mode) { options->mark_mode = cfg_lookup_mark_mode(mark_mode); } /* * NOTE: _init needs to be idempotent when called multiple times w/o invoking _destroy * * Rationale: * - init is called from driver init (e.g. affile_sd_init), * - destroy is called from driver free method (e.g. affile_sd_free, NOT affile_sd_deinit) * * The reason: * - when initializing the reloaded configuration fails for some reason, * we have to fall back to the old configuration, thus we cannot dump * the information stored in the Options structure at deinit time, but * have to recover it when the old configuration is initialized. * * For the reasons above, init and destroy behave the following way: * * - init is idempotent, it can be called multiple times without leaking * memory, and without loss of information * - destroy is only called once, when the options are indeed to be destroyed * * Also important to note is that when init is called multiple times, the * GlobalConfig reference is the same, this means that it is enough to * remember whether init was called already and return w/o doing anything in * that case, which is actually how idempotency is implemented here. */ void log_writer_options_init(LogWriterOptions *options, GlobalConfig *cfg, guint32 option_flags) { if (options->initialized) return; log_template_options_init(&options->template_options, cfg); host_resolve_options_init(&options->host_resolve_options, &cfg->host_resolve_options); log_proto_client_options_init(&options->proto_options.super, cfg); options->options |= option_flags; if (options->flush_lines == -1) options->flush_lines = cfg->flush_lines; if (options->flush_timeout == -1) options->flush_timeout = cfg->flush_timeout; if (options->suppress == -1) options->suppress = cfg->suppress; if (options->time_reopen == -1) options->time_reopen = cfg->time_reopen; options->file_template = log_template_ref(cfg->file_template); options->proto_template = log_template_ref(cfg->proto_template); if (cfg->threaded) options->options |= LWO_THREADED; /* per-destination MARK messages */ if (options->mark_mode == MM_GLOBAL) { /* get the global option */ options->mark_mode = cfg->mark_mode; } if (options->mark_freq == -1) { /* not initialized, use the global mark freq */ options->mark_freq = cfg->mark_freq; } options->initialized = TRUE; } void log_writer_options_destroy(LogWriterOptions *options) { log_template_options_destroy(&options->template_options); host_resolve_options_destroy(&options->host_resolve_options); log_proto_client_options_destroy(&options->proto_options.super); log_template_unref(options->template); log_template_unref(options->file_template); log_template_unref(options->proto_template); options->initialized = FALSE; } gint log_writer_options_lookup_flag(const gchar *flag) { if (strcmp(flag, "syslog_protocol") == 0 || strcmp(flag, "syslog-protocol") == 0) return LWO_SYSLOG_PROTOCOL; if (strcmp(flag, "no-multi-line") == 0 || strcmp(flag, "no_multi_line") == 0) return LWO_NO_MULTI_LINE; if (strcmp(flag, "threaded") == 0) return LWO_THREADED; if (strcmp(flag, "ignore-errors") == 0 || strcmp(flag, "ignore_errors") == 0) return LWO_IGNORE_ERRORS; msg_error("Unknown dest writer flag", evt_tag_str("flag", flag)); return 0; } syslog-ng-syslog-ng-3.13.2/lib/logwriter.h000066400000000000000000000067371321171025300204070ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOG_WRITER_H_INCLUDED #define LOG_WRITER_H_INCLUDED #include "logpipe.h" #include "template/templates.h" #include "logqueue.h" #include "logproto/logproto-client.h" #include "timeutils.h" /* writer constructor flags */ #define LW_DETECT_EOF 0x0001 #define LW_FORMAT_FILE 0x0002 #define LW_FORMAT_PROTO 0x0004 #define LW_SYSLOG_PROTOCOL 0x0008 #define LW_SOFT_FLOW_CONTROL 0x0010 /* writer options (set by the user) */ #define LWO_SYSLOG_PROTOCOL 0x0001 #define LWO_NO_MULTI_LINE 0x0002 /* we don't want to have a dropped counter for this writer */ #define LWO_NO_STATS 0x0004 /* several writers use the same counter */ #define LWO_SHARE_STATS 0x0008 #define LWO_THREADED 0x0010 #define LWO_IGNORE_ERRORS 0x0020 typedef struct _LogWriterOptions { gboolean initialized; /* bitmask of LWO_* */ guint32 options; /* minimum number of entries to trigger a flush */ gint flush_lines; /* flush anyway if this time was elapsed */ gint flush_timeout; LogTemplate *template; LogTemplate *file_template; LogTemplate *proto_template; LogTemplateOptions template_options; HostResolveOptions host_resolve_options; LogProtoClientOptionsStorage proto_options; gint time_reopen; gint suppress; gint padding; gint mark_mode; gint mark_freq; gint stats_level; gint stats_source; } LogWriterOptions; typedef struct _LogWriter LogWriter; void log_writer_set_flags(LogWriter *self, guint32 flags); guint32 log_writer_get_flags(LogWriter *self); void log_writer_set_options(LogWriter *self, LogPipe *control, LogWriterOptions *options, const gchar *stats_id, const gchar *stats_instance); void log_writer_format_log(LogWriter *self, LogMessage *lm, GString *result); gboolean log_writer_has_pending_writes(LogWriter *self); gboolean log_writer_opened(LogWriter *self); void log_writer_reopen(LogWriter *self, LogProtoClient *proto); void log_writer_set_queue(LogWriter *self, LogQueue *queue); LogQueue *log_writer_get_queue(LogWriter *s); LogWriter *log_writer_new(guint32 flags, GlobalConfig *cfg); void log_writer_options_set_template_escape(LogWriterOptions *options, gboolean enable); void log_writer_options_defaults(LogWriterOptions *options); void log_writer_options_init(LogWriterOptions *options, GlobalConfig *cfg, guint32 option_flags); void log_writer_options_destroy(LogWriterOptions *options); void log_writer_options_set_mark_mode(LogWriterOptions *options, gchar *mark_mode); gint log_writer_options_lookup_flag(const gchar *flag); #endif syslog-ng-syslog-ng-3.13.2/lib/mainloop-call.c000066400000000000000000000102121321171025300210720ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "mainloop-call.h" #include "tls-support.h" #include #include #include /************************************************************************************ * Cross-thread function calls into the main loop ************************************************************************************/ typedef struct _MainLoopTaskCallSite MainLoopTaskCallSite; struct _MainLoopTaskCallSite { struct iv_list_head list; MainLoopTaskFunc func; gpointer user_data; gpointer result; gboolean pending; gboolean wait; GCond *cond; GStaticMutex lock; }; TLS_BLOCK_START { MainLoopTaskCallSite call_info; } TLS_BLOCK_END; #define call_info __tls_deref(call_info) static GStaticMutex main_task_lock = G_STATIC_MUTEX_INIT; static struct iv_list_head main_task_queue = IV_LIST_HEAD_INIT(main_task_queue); static struct iv_event main_task_posted; gpointer main_loop_call(MainLoopTaskFunc func, gpointer user_data, gboolean wait) { if (main_loop_is_main_thread()) return func(user_data); g_static_mutex_lock(&main_task_lock); /* check if a previous call is being executed */ g_static_mutex_lock(&call_info.lock); if (call_info.pending) { /* yes, it is still running, indicate that we need to be woken up */ call_info.wait = TRUE; g_static_mutex_unlock(&call_info.lock); while (call_info.pending) g_cond_wait(call_info.cond, g_static_mutex_get_mutex(&main_task_lock)); } else { g_static_mutex_unlock(&call_info.lock); } /* call_info.lock is no longer needed, since we're the only ones using call_info now */ INIT_IV_LIST_HEAD(&call_info.list); call_info.pending = TRUE; call_info.func = func; call_info.user_data = user_data; call_info.wait = wait; iv_list_add(&call_info.list, &main_task_queue); iv_event_post(&main_task_posted); if (wait) { while (call_info.pending) g_cond_wait(call_info.cond, g_static_mutex_get_mutex(&main_task_lock)); } g_static_mutex_unlock(&main_task_lock); return call_info.result; } static void main_loop_call_handler(gpointer user_data) { g_static_mutex_lock(&main_task_lock); while (!iv_list_empty(&main_task_queue)) { MainLoopTaskCallSite *site; gpointer result; site = iv_list_entry(main_task_queue.next, MainLoopTaskCallSite, list); iv_list_del_init(&site->list); g_static_mutex_unlock(&main_task_lock); result = site->func(site->user_data); g_static_mutex_lock(&site->lock); site->result = result; site->pending = FALSE; g_static_mutex_unlock(&site->lock); g_static_mutex_lock(&main_task_lock); if (site->wait) g_cond_signal(site->cond); } g_static_mutex_unlock(&main_task_lock); } void main_loop_call_thread_init(void) { call_info.cond = g_cond_new(); } void main_loop_call_thread_deinit(void) { if (call_info.cond) g_cond_free(call_info.cond); } void main_loop_call_init(void) { IV_EVENT_INIT(&main_task_posted); main_task_posted.cookie = NULL; main_task_posted.handler = main_loop_call_handler; iv_event_register(&main_task_posted); } void main_loop_call_deinit(void) { iv_event_unregister(&main_task_posted); } syslog-ng-syslog-ng-3.13.2/lib/mainloop-call.h000066400000000000000000000024671321171025300211140ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MAINLOOP_CALL_H_INCLUDED #define MAINLOOP_CALL_H_INCLUDED 1 #include "mainloop.h" gpointer main_loop_call(MainLoopTaskFunc func, gpointer user_data, gboolean wait); void main_loop_call_thread_init(void); void main_loop_call_thread_deinit(void); void main_loop_call_init(void); void main_loop_call_deinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/mainloop-io-worker.c000066400000000000000000000067531321171025300221140ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "mainloop-io-worker.h" #include "mainloop-worker.h" #include "mainloop-call.h" #include "logqueue.h" #include "scratch-buffers.h" /************************************************************************************ * I/O worker threads ************************************************************************************/ static struct iv_work_pool main_loop_io_workers; /* NOTE: runs in the main thread */ void main_loop_io_worker_job_submit(MainLoopIOWorkerJob *self) { g_assert(self->working == FALSE); if (main_loop_workers_quit) return; main_loop_worker_job_start(); self->working = TRUE; iv_work_pool_submit_work(&main_loop_io_workers, &self->work_item); } /* NOTE: runs in the actual worker thread spawned by the * main_loop_io_workers thread pool */ static void _work(MainLoopIOWorkerJob *self) { self->work(self->user_data); main_loop_worker_invoke_batch_callbacks(); scratch_buffers_explicit_gc(); } /* NOTE: runs in the main thread */ static void _complete(MainLoopIOWorkerJob *self) { self->working = FALSE; self->completion(self->user_data); main_loop_worker_job_complete(); } void main_loop_io_worker_job_init(MainLoopIOWorkerJob *self) { IV_WORK_ITEM_INIT(&self->work_item); self->work_item.cookie = self; self->work_item.work = (void (*)(void *)) _work; self->work_item.completion = (void (*)(void *)) _complete; } static gint get_processor_count(void) { #ifdef _SC_NPROCESSORS_ONLN return sysconf(_SC_NPROCESSORS_ONLN); #else return -1; #endif } void main_loop_io_worker_init(void) { if (main_loop_io_workers.max_threads == 0) { main_loop_io_workers.max_threads = MIN(MAX(MAIN_LOOP_MIN_WORKER_THREADS, get_processor_count()), MAIN_LOOP_MAX_WORKER_THREADS); } main_loop_io_workers.thread_start = (void (*)(void *)) main_loop_worker_thread_start; main_loop_io_workers.thread_stop = (void (*)(void *)) main_loop_worker_thread_stop; iv_work_pool_create(&main_loop_io_workers); log_queue_set_max_threads(MIN(main_loop_io_workers.max_threads, MAIN_LOOP_MAX_WORKER_THREADS)); } void main_loop_io_worker_deinit(void) { iv_work_pool_put(&main_loop_io_workers); } static GOptionEntry main_loop_io_worker_options[] = { { "worker-threads", 0, 0, G_OPTION_ARG_INT, &main_loop_io_workers.max_threads, "Set the number of I/O worker threads", "" }, { NULL }, }; void main_loop_io_worker_add_options(GOptionContext *ctx) { g_option_context_add_main_entries(ctx, main_loop_io_worker_options, NULL); } syslog-ng-syslog-ng-3.13.2/lib/mainloop-io-worker.h000066400000000000000000000031271321171025300221110ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MAINLOOP_IO_WORKER_H_INCLUDED #define MAINLOOP_IO_WORKER_H_INCLUDED 1 #include "mainloop-worker.h" #include typedef struct _MainLoopIOWorkerJob { void (*work)(gpointer user_data); void (*completion)(gpointer user_data); gpointer user_data; gboolean working:1; struct iv_work_item work_item; } MainLoopIOWorkerJob; void main_loop_io_worker_job_init(MainLoopIOWorkerJob *self); void main_loop_io_worker_job_submit(MainLoopIOWorkerJob *self); void main_loop_io_worker_add_options(GOptionContext *ctx); void main_loop_io_worker_init(void); void main_loop_io_worker_deinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/mainloop-worker.c000066400000000000000000000262051321171025300215010ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "mainloop-worker.h" #include "mainloop-call.h" #include "tls-support.h" #include "apphook.h" #include "messages.h" #include "scratch-buffers.h" #include typedef enum { GENERAL_THREAD = 0, OUTPUT_THREAD, EXTERNAL_INPUT_THREAD, MAIN_LOOP_WORKER_TYPE_MAX} MainLoopWorkerType; TLS_BLOCK_START { /* Thread IDs are low numbered integers that can be used to index * per-thread data in an array. IDs get reused and the smallest possible * ID is allocated for newly started threads. */ /* the thread id is shifted by one, to make 0 the uninitialized state, * e.g. everything that sets it adds +1, everything that queries it * subtracts 1 */ gint main_loop_worker_id; MainLoopWorkerType main_loop_worker_type; struct iv_list_head batch_callbacks; } TLS_BLOCK_END; #define main_loop_worker_id __tls_deref(main_loop_worker_id) #define batch_callbacks __tls_deref(batch_callbacks) #define main_loop_worker_type __tls_deref(main_loop_worker_type) GQueue sync_call_actions = G_QUEUE_INIT; /* cause workers to stop, no new I/O jobs to be submitted */ volatile gboolean main_loop_workers_quit; volatile gboolean is_reloading_scheduled; /* number of I/O worker jobs running */ static gint main_loop_jobs_running; static struct iv_task main_loop_workers_reenable_jobs_task; /* thread ID allocation */ static GStaticMutex main_loop_workers_idmap_lock = G_STATIC_MUTEX_INIT; static guint64 main_loop_workers_idmap[MAIN_LOOP_WORKER_TYPE_MAX]; static void _allocate_thread_id(void) { gint id; g_static_mutex_lock(&main_loop_workers_idmap_lock); /* NOTE: this algorithm limits the number of I/O worker threads to 64, * since the ID map is stored in a single 64 bit integer. If we ever need * more threads than that, we can generalize this algorithm further. */ main_loop_worker_id = 0; if(main_loop_worker_type != EXTERNAL_INPUT_THREAD) { for (id = 0; id < MAIN_LOOP_MAX_WORKER_THREADS; id++) { if ((main_loop_workers_idmap[main_loop_worker_type] & (1 << id)) == 0) { /* id not yet used */ main_loop_worker_id = (id + 1) + (main_loop_worker_type * MAIN_LOOP_MAX_WORKER_THREADS); main_loop_workers_idmap[main_loop_worker_type] |= (1 << id); break; } } } g_static_mutex_unlock(&main_loop_workers_idmap_lock); } static void _release_thread_id(void) { g_static_mutex_lock(&main_loop_workers_idmap_lock); if (main_loop_worker_id) { main_loop_workers_idmap[main_loop_worker_type] &= ~(1 << (main_loop_worker_id - 1)); main_loop_worker_id = 0; } g_static_mutex_unlock(&main_loop_workers_idmap_lock); } /* NOTE: only used by the unit test program to emulate worker threads with * LogQueue, other threads acquire a thread id when they start up. */ void main_loop_worker_set_thread_id(gint id) { main_loop_worker_id = id + 1; } gint main_loop_worker_get_thread_id(void) { return main_loop_worker_id - 1; } typedef struct _WorkerExitNotification { WorkerExitNotificationFunc func; gpointer user_data; } WorkerExitNotification; static GList *exit_notification_list = NULL; static void _register_exit_notification_callback(WorkerExitNotificationFunc func, gpointer user_data) { WorkerExitNotification *cfunc = g_new(WorkerExitNotification, 1); cfunc->func = func; cfunc->user_data = user_data; exit_notification_list = g_list_append(exit_notification_list, cfunc); } static void _invoke_worker_exit_callback(WorkerExitNotification *func) { func->func(func->user_data); } static void _request_all_threads_to_exit(void) { g_list_foreach(exit_notification_list, (GFunc) _invoke_worker_exit_callback, NULL); g_list_foreach(exit_notification_list, (GFunc) g_free, NULL); g_list_free(exit_notification_list); exit_notification_list = NULL; main_loop_workers_quit = TRUE; } /* Call this function from worker threads, when you start up */ void main_loop_worker_thread_start(void *cookie) { WorkerOptions *worker_options = cookie; main_loop_worker_type = GENERAL_THREAD; if (worker_options && worker_options->is_output_thread) { main_loop_worker_type = OUTPUT_THREAD; } else if(worker_options && worker_options->is_external_input) { main_loop_worker_type = EXTERNAL_INPUT_THREAD; } _allocate_thread_id(); INIT_IV_LIST_HEAD(&batch_callbacks); g_mutex_lock(&workers_running_lock); main_loop_workers_running++; g_mutex_unlock(&workers_running_lock); app_thread_start(); } /* Call this function from worker threads, when you stop */ void main_loop_worker_thread_stop(void) { app_thread_stop(); _release_thread_id(); g_mutex_lock(&workers_running_lock); main_loop_workers_running--; g_mutex_unlock(&workers_running_lock); g_cond_signal(&thread_halt_cond); } void main_loop_worker_run_gc(void) { scratch_buffers_explicit_gc(); } /* * This function is called in the main thread prior to starting the * processing of a work item in a worker thread. */ void main_loop_worker_job_start(void) { main_loop_assert_main_thread(); main_loop_jobs_running++; } typedef struct { void (*func)(gpointer user_data); gpointer user_data; } SyncCallAction; void _register_sync_call_action(GQueue *q, void (*func)(gpointer user_data), gpointer user_data) { SyncCallAction *action = g_new0(SyncCallAction, 1); action->func = func; action->user_data = user_data; g_queue_push_tail(q, action); } void _consume_action(SyncCallAction *action, gpointer dummy) { action->func(action->user_data); g_free(action); } static void _invoke_sync_call_actions(void) { g_queue_foreach(&sync_call_actions, (GFunc)_consume_action, NULL); g_queue_clear(&sync_call_actions); } /* * This function is called in the main thread after a job was finished in * one of the worker threads. * * If an intrusive operation (reload, termination) is pending and the number * of workers has dropped to zero, it commences with the intrusive * operation, as in that case we can safely assume that all workers exited. */ void main_loop_worker_job_complete(void) { main_loop_assert_main_thread(); main_loop_jobs_running--; if (main_loop_workers_quit && main_loop_jobs_running == 0) { /* NOTE: we can't reenable I/O jobs by setting * main_loop_io_workers_quit to FALSE right here, because a task * generated by the old config might still be sitting in the task * queue, to be invoked once we return from here. Tasks cannot be * cancelled, thus we have to get to the end of the currently running * task queue. * * Thus we register another task * (&main_loop_io_workers_reenable_jobs_task), which is guaranteed to * be added to the end of the task queue, which reenables task * submission. * * * A second constraint is that any tasks submitted by the reload * logic (sitting behind the sync_func() call below), MUST be * registered after the reenable_jobs_task, because otherwise some * I/O events will be missed, due to main_loop_io_workers_quit being * TRUE. * * * |OldTask1|OldTask2|OldTask3| ReenableTask |NewTask1|NewTask2|NewTask3| * ^ * | ivykis task list * * OldTasks get dropped because _quit is TRUE, NewTasks have to be * executed properly, otherwise we'd hang. */ iv_task_register(&main_loop_workers_reenable_jobs_task); _invoke_sync_call_actions(); } } /* * Register a function to be called back when the current I/O job is * finished (in the worker thread). * * NOTE: we only support one pending callback at a time, may become a list of callbacks if needed in the future */ void main_loop_worker_register_batch_callback(WorkerBatchCallback *cb) { iv_list_add(&cb->list, &batch_callbacks); } void main_loop_worker_invoke_batch_callbacks(void) { struct iv_list_head *lh, *lh2; iv_list_for_each_safe(lh, lh2, &batch_callbacks) { WorkerBatchCallback *cb = iv_list_entry(lh, WorkerBatchCallback, list); iv_list_del_init(&cb->list); cb->func(cb->user_data); } } typedef struct _WorkerThreadParams { WorkerThreadFunc func; gpointer data; WorkerOptions *worker_options; } WorkerThreadParams; static gpointer _worker_thread_func(gpointer st) { WorkerThreadParams *p = st; main_loop_worker_thread_start(p->worker_options); p->func(p->data); main_loop_call((MainLoopTaskFunc) main_loop_worker_job_complete, NULL, TRUE); main_loop_worker_thread_stop(); /* NOTE: this assert aims to validate that the worker thread in fact * invokes main_loop_worker_invoke_batch_callbacks() during its operation. * Please do so every once a couple of messages, hopefully you have a * natural barrier that let's you decide when, the easiest would be * log-fetch-limit(), but other limits may also be applicable. */ g_assert(iv_list_empty(&batch_callbacks)); g_free(st); return NULL; } void main_loop_create_worker_thread(WorkerThreadFunc func, WorkerExitNotificationFunc terminate_func, gpointer data, WorkerOptions *worker_options) { GThread *h; WorkerThreadParams *p; main_loop_assert_main_thread(); p = g_new0(WorkerThreadParams, 1); p->func = func; p->data = data; p->worker_options = worker_options; main_loop_worker_job_start(); if (terminate_func) _register_exit_notification_callback(terminate_func, data); h = g_thread_create_full(_worker_thread_func, p, 1024 * 1024, FALSE, TRUE, G_THREAD_PRIORITY_NORMAL, NULL); g_assert(h != NULL); } static void _reenable_worker_jobs(void *s) { main_loop_workers_quit = FALSE; if (is_reloading_scheduled) msg_notice("Configuration reload finished"); is_reloading_scheduled = FALSE; } void main_loop_worker_sync_call(void (*func)(gpointer user_data), gpointer user_data) { _register_sync_call_action(&sync_call_actions, func, user_data); if (main_loop_jobs_running == 0) { _invoke_sync_call_actions(); _reenable_worker_jobs(NULL); } else { _request_all_threads_to_exit(); } } void main_loop_worker_init(void) { IV_TASK_INIT(&main_loop_workers_reenable_jobs_task); main_loop_workers_reenable_jobs_task.handler = _reenable_worker_jobs; } void main_loop_worker_deinit(void) { } syslog-ng-syslog-ng-3.13.2/lib/mainloop-worker.h000066400000000000000000000056571321171025300215160ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MAINLOOP_WORKER_H_INCLUDED #define MAINLOOP_WORKER_H_INCLUDED 1 #include "mainloop.h" #include #define MAIN_LOOP_MIN_WORKER_THREADS 2 #define MAIN_LOOP_MAX_WORKER_THREADS 64 /* * A batch callback is registered during the processing of messages in a * given thread. Batch callbacks are invoked when the batch is complete. * * This mechanism is used by LogQueueFifo implementation, that consumes * messages into a per-thread, unlocked queue first and once the whole batch * is in, it grabs a lock and propagates the elements towards the consumer. */ typedef struct _WorkerBatchCallback { struct iv_list_head list; MainLoopTaskFunc func; gpointer user_data; } WorkerBatchCallback; typedef struct _WorkerOptions { gboolean is_output_thread; gboolean is_external_input; } WorkerOptions; static inline void worker_batch_callback_init(WorkerBatchCallback *self) { INIT_IV_LIST_HEAD(&self->list); } void main_loop_worker_register_batch_callback(WorkerBatchCallback *cb); void main_loop_worker_invoke_batch_callbacks(void); typedef void (*WorkerThreadFunc)(gpointer user_data); typedef void (*WorkerExitNotificationFunc)(gpointer user_data); void main_loop_worker_set_thread_id(gint id); gint main_loop_worker_get_thread_id(void); void main_loop_worker_job_start(void); void main_loop_worker_job_complete(void); void main_loop_worker_thread_start(void *cookie); void main_loop_worker_thread_stop(void); void main_loop_worker_run_gc(void); void main_loop_create_worker_thread(WorkerThreadFunc func, WorkerExitNotificationFunc terminate_func, gpointer data, WorkerOptions *worker_options); void main_loop_worker_sync_call(void (*func)(void *user_data), void *user_data); void main_loop_worker_init(void); void main_loop_worker_deinit(void); extern volatile gboolean main_loop_workers_quit; extern volatile gboolean is_reloading_scheduled; static inline gboolean main_loop_worker_job_quit(void) { return main_loop_workers_quit; } #endif syslog-ng-syslog-ng-3.13.2/lib/mainloop.c000066400000000000000000000402611321171025300201700ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "mainloop.h" #include "mainloop-worker.h" #include "mainloop-io-worker.h" #include "mainloop-call.h" #include "apphook.h" #include "cfg.h" #include "stats/stats-registry.h" #include "messages.h" #include "children.h" #include "control/control-main.h" #include "reloc.h" #include "service-management.h" #include "persist-state.h" #include "run-id.h" #include "host-id.h" #include "debugger/debugger-main.h" #include "plugin.h" #include "resolved-configurable-paths.h" #include "scratch-buffers.h" #include #include #include #include #include #include /** * Processing model * ================ * * This comment documents how the work performed by syslog-ng is * partitioned between threads. First of all it is useful to know that * the configuration is translated to a tree of LogPipe instances, as * described in a comment in logpipe.h. * * The basic assumptions for threading: * - configuration file is parsed in the main thread * - the log pipe tree is built in the main thread * - processing of messages is stalled while the * configuration is reloaded * - the _queue() operation for LogPipe instances can happen in * multiple threads * - notifications accross LogPipe instances happen in the main thread * * This boils down to: * =================== * - If not otherwise specified LogPipe derived classes can only be * instantiated (e.g. new()) or initialized/deinitialized (_init/deinit) * in the main thread. Exceptions to this rule are documented below. * - All queue operations finish before either deinit is called. * - Locking is only needed between multiple invocations of _queue() * in parallel threads, and any other main thread activity. * * Threading model * =============== * - the main thread manages the configuration and polls for I/O * using epoll * - whenever an I/O event happens, work may be delegated to worker * threads. Currently only the LogReader/LogWriter classes make use * of worker threads, everything else remains in the main thread * (internal messages, incoming connections, etc). * - _all_ I/O polling must be registered in the main thread (update_watches * and friends) * */ ThreadId main_thread_handle; GCond thread_halt_cond; GMutex workers_running_lock = G_STATIC_MUTEX_INIT; struct _MainLoop { /* * This variable is used to detect that syslog-ng is being terminated, in which * case ongoing reload operations are aborted. * * The variable is deeply embedded in various mainloop callbacks to get out * of an ongoing reload and start doing the termination instead. A better * solution would be to use a queue for intrusive, worker-stopping * operations and serialize such tasks so they won't interfere which each other. * * This interference is now implemented by conditionals scattered around the code. * * Example: * * reload is now taking two steps (marked R in the figure below) * 1) parse the configuration and request worker threads to be stopped * 2) apply the configuration once all threads exited * * termination is also taking two steps * 1) send out the shutting down message and start waiting 100msec * 2) terminate the mainloop * * The problem happens when reload and termination happen at around the same * time and these steps are interleaved. * * Normal operation: RRTT (e.g. reload finishes, then termination) * Problematic case: RTRT (e.g. reload starts, termination starts, config apply, terminate) * * In the problematic case, two independent operations do similar things to * the mainloop, and to prevent misfortune we need to handle this case explicitly. * * Were the two operations serialized by some kind of queue, the problems * would be gone. */ gboolean _is_terminating; /* signal handling */ struct iv_signal sighup_poll; struct iv_signal sigterm_poll; struct iv_signal sigint_poll; struct iv_signal sigchild_poll; struct iv_signal sigusr1_poll; struct iv_event exit_requested; struct iv_event reload_config_requested; struct iv_timer exit_timer; /* Currently running configuration, should not be used outside the mainloop * logic. If anything needs access to the GlobalConfig instance at runtime, * it needs to save that during initialization. If anything needs the * config being parsed (e.g. in the bison generated code), it should * consult the value of "configuration", which is NULL after the parsing is * finished. */ GlobalConfig *current_configuration; /* the old configuration that is being reloaded */ GlobalConfig *old_config; /* the pending configuration we wish to switch to */ GlobalConfig *new_config; MainLoopOptions *options; }; static MainLoop main_loop; MainLoop * main_loop_get_instance(void) { return &main_loop; } void main_loop_set_server_mode(MainLoop *self, gboolean server_mode) { self->options->server_mode = server_mode; } gboolean main_loop_is_server_mode(MainLoop *self) { return self->options->server_mode; } /* called when syslog-ng first starts up */ gboolean main_loop_initialize_state(GlobalConfig *cfg, const gchar *persist_filename) { gboolean success; cfg->state = persist_state_new(persist_filename); if (!persist_state_start(cfg->state)) return FALSE; run_id_init(cfg->state); host_id_init(cfg->state); success = cfg_init(cfg); if (success) persist_state_commit(cfg->state); else persist_state_cancel(cfg->state); return success; } static inline gboolean main_loop_is_terminating(MainLoop *self) { return self->_is_terminating; } /* called to apply the new configuration once all I/O worker threads have finished */ static void main_loop_reload_config_apply(gpointer user_data) { MainLoop *self = (MainLoop *) user_data; if (main_loop_is_terminating(self)) { if (self->new_config) { cfg_free(self->new_config); self->new_config = NULL; } is_reloading_scheduled = FALSE; return; } self->old_config->persist = persist_config_new(); cfg_deinit(self->old_config); cfg_persist_config_move(self->old_config, self->new_config); if (cfg_init(self->new_config)) { msg_verbose("New configuration initialized"); persist_config_free(self->new_config->persist); self->new_config->persist = NULL; cfg_free(self->old_config); self->current_configuration = self->new_config; service_management_clear_status(); } else { msg_error("Error initializing new configuration, reverting to old config"); service_management_publish_status("Error initializing new configuration, using the old config"); cfg_persist_config_move(self->new_config, self->old_config); cfg_deinit(self->new_config); if (!cfg_init(self->old_config)) { /* hmm. hmmm, error reinitializing old configuration, we're hosed. * Best is to kill ourselves in the hope that the supervisor * restarts us. */ kill(getpid(), SIGQUIT); g_assert_not_reached(); } persist_config_free(self->old_config->persist); self->old_config->persist = NULL; cfg_free(self->new_config); self->current_configuration = self->old_config; goto finish; } /* this is already running with the new config in place */ app_post_config_loaded(); msg_notice("Configuration reload request received, reloading configuration"); finish: self->new_config = NULL; self->old_config = NULL; return; } /* initiate configuration reload */ void main_loop_reload_config_initiate(gpointer user_data) { MainLoop *self = (MainLoop *) user_data; if (main_loop_is_terminating(self)) return; if (is_reloading_scheduled) { msg_notice("Error initiating reload, reload is already ongoing"); return; } service_management_publish_status("Reloading configuration"); self->old_config = self->current_configuration; app_pre_config_loaded(); self->new_config = cfg_new(0); if (!cfg_read_config(self->new_config, resolvedConfigurablePaths.cfgfilename, FALSE, NULL)) { cfg_free(self->new_config); self->new_config = NULL; self->old_config = NULL; msg_error("Error parsing configuration", evt_tag_str(EVT_TAG_FILENAME, resolvedConfigurablePaths.cfgfilename)); service_management_publish_status("Error parsing new configuration, using the old config"); return; } is_reloading_scheduled = TRUE; main_loop_worker_sync_call(main_loop_reload_config_apply, self); } static void block_till_workers_exit() { gint64 end_time; end_time = g_get_monotonic_time() + 15*G_TIME_SPAN_SECOND; g_mutex_lock(&workers_running_lock); while (main_loop_workers_running) if (!g_cond_wait_until(&thread_halt_cond, &workers_running_lock, end_time)) { /* timeout has passed. */ fprintf(stderr, "Main thread timed out (15s) while waiting workers threads to exit. " "workers_running: %d. Continuing ...\n", main_loop_workers_running); break; } g_mutex_unlock (&workers_running_lock); } /************************************************************************************ * syncronized exit ************************************************************************************/ static void main_loop_exit_finish(gpointer user_data) { MainLoop *self = (MainLoop *) user_data; /* deinit the current configuration, as at this point we _know_ that no * threads are running. This will unregister ivykis tasks and timers * that could fire while the configuration is being destructed */ cfg_deinit(self->current_configuration); iv_quit(); } static void main_loop_exit_timer_elapsed(gpointer user_data) { MainLoop *self = (MainLoop *) user_data; main_loop_worker_sync_call(main_loop_exit_finish, self); } static void main_loop_exit_initiate(gpointer user_data) { MainLoop *self = (MainLoop *) user_data; if (main_loop_is_terminating(self)) return; msg_notice("syslog-ng shutting down", evt_tag_str("version", SYSLOG_NG_VERSION)); IV_TIMER_INIT(&self->exit_timer); iv_validate_now(); self->exit_timer.expires = iv_now; self->exit_timer.handler = main_loop_exit_timer_elapsed; self->exit_timer.cookie = self; timespec_add_msec(&self->exit_timer.expires, 100); iv_timer_register(&self->exit_timer); self->_is_terminating = TRUE; } /************************************************************************************ * signal handlers ************************************************************************************/ static void sig_hup_handler(gpointer user_data) { MainLoop *self = (MainLoop *) user_data; main_loop_reload_config_initiate(self); } static void sig_term_handler(gpointer user_data) { MainLoop *self = (MainLoop *) user_data; main_loop_exit_initiate(self); } static void sig_child_handler(gpointer user_data) { pid_t pid; int status; /* this may handle multiple SIGCHLD signals, however it doesn't * matter if one or multiple SIGCHLD was received assuming that * all exited child process are waited for */ do { pid = waitpid(-1, &status, WNOHANG); child_manager_sigchild(pid, status); } while (pid > 0); } static void sig_usr1_handler(gpointer user_data) { app_reopen(); } static void _ignore_signal(gint signum) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; sigaction(signum, &sa, NULL); } static void _register_signal_handler(struct iv_signal *signal_poll, gint signum, void (*handler)(void *), gpointer user_data) { IV_SIGNAL_INIT(signal_poll); signal_poll->signum = signum; signal_poll->flags = IV_SIGNAL_FLAG_EXCLUSIVE; signal_poll->cookie = user_data; signal_poll->handler = handler; iv_signal_register(signal_poll); } static void setup_signals(MainLoop *self) { _ignore_signal(SIGPIPE); _register_signal_handler(&self->sighup_poll, SIGHUP, sig_hup_handler, self); _register_signal_handler(&self->sigchild_poll, SIGCHLD, sig_child_handler, self); _register_signal_handler(&self->sigterm_poll, SIGTERM, sig_term_handler, self); _register_signal_handler(&self->sigint_poll, SIGINT, sig_term_handler, self); _register_signal_handler(&self->sigusr1_poll, SIGUSR1, sig_usr1_handler, self); } /************************************************************************************ * syslog-ng main loop ************************************************************************************/ static void _register_event(struct iv_event *event, void (*handler)(void *), gpointer user_data) { IV_EVENT_INIT(event); event->handler = handler; event->cookie = user_data; iv_event_register(event); } static void main_loop_init_events(MainLoop *self) { _register_event(&self->exit_requested, main_loop_exit_initiate, self); _register_event(&self->reload_config_requested, main_loop_reload_config_initiate, self); } void main_loop_exit(MainLoop *self) { iv_event_post(&self->exit_requested); return; } void main_loop_reload_config(MainLoop *self) { iv_event_post(&self->reload_config_requested); return; } void main_loop_init(MainLoop *self, MainLoopOptions *options) { service_management_publish_status("Starting up..."); self->options = options; main_thread_handle = get_thread_id(); scratch_buffers_automatic_gc_init(); main_loop_worker_init(); main_loop_io_worker_init(); main_loop_call_init(); main_loop_init_events(self); if (!self->options->syntax_only) control_init(self, resolvedConfigurablePaths.ctlfilename); setup_signals(self); } /* * Returns: exit code to be returned to the calling process, 0 on success. */ int main_loop_read_and_init_config(MainLoop *self) { MainLoopOptions *options = self->options; self->current_configuration = cfg_new(0); if (!cfg_read_config(self->current_configuration, resolvedConfigurablePaths.cfgfilename, options->syntax_only, options->preprocess_into)) { return 1; } if (options->syntax_only || options->preprocess_into) { return 0; } if (!main_loop_initialize_state(self->current_configuration, resolvedConfigurablePaths.persist_file)) { return 2; } return 0; } static void main_loop_free_config(MainLoop *self) { cfg_free(self->current_configuration); self->current_configuration = NULL; } void main_loop_deinit(MainLoop *self) { main_loop_free_config(self); if (!self->options->syntax_only) control_destroy(); iv_event_unregister(&self->exit_requested); iv_event_unregister(&self->reload_config_requested); main_loop_call_deinit(); main_loop_io_worker_deinit(); main_loop_worker_deinit(); block_till_workers_exit(); scratch_buffers_automatic_gc_deinit(); } void main_loop_run(MainLoop *self) { msg_notice("syslog-ng starting up", evt_tag_str("version", SYSLOG_NG_VERSION)); /* main loop */ service_management_indicate_readiness(); service_management_clear_status(); if (self->options->interactive_mode) { cfg_load_module(self->current_configuration, "python"); debugger_start(self, self->current_configuration); } iv_main(); service_management_publish_status("Shutting down..."); } void main_loop_add_options(GOptionContext *ctx) { main_loop_io_worker_add_options(ctx); } syslog-ng-syslog-ng-3.13.2/lib/mainloop.h000066400000000000000000000045011321171025300201720ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MAINLOOP_H_INCLUDED #define MAINLOOP_H_INCLUDED #include "syslog-ng.h" #include "thread-utils.h" volatile gint main_loop_workers_running; typedef struct _MainLoop MainLoop; typedef struct _MainLoopOptions { gchar *preprocess_into; gboolean syntax_only; gboolean interactive_mode; gboolean server_mode; } MainLoopOptions; extern ThreadId main_thread_handle; extern GCond thread_halt_cond; extern GMutex workers_running_lock; typedef gpointer (*MainLoopTaskFunc)(gpointer user_data); static inline void main_loop_assert_main_thread(void) { #if SYSLOG_NG_ENABLE_DEBUG g_assert(threads_equal(main_thread_handle, get_thread_id())); #endif } static inline gboolean main_loop_is_main_thread(void) { return threads_equal(main_thread_handle, get_thread_id()); } void main_loop_reload_config(MainLoop *self); void main_loop_exit(MainLoop *self); int main_loop_read_and_init_config(MainLoop *self); void main_loop_run(MainLoop *self); MainLoop *main_loop_get_instance(void); void main_loop_init(MainLoop *self, MainLoopOptions *options); void main_loop_deinit(MainLoop *self); void main_loop_add_options(GOptionContext *ctx); gboolean main_loop_is_server_mode(MainLoop *self); void main_loop_set_server_mode(MainLoop *self, gboolean server_mode); gboolean main_loop_initialize_state(GlobalConfig *cfg, const gchar *persist_filename); #endif syslog-ng-syslog-ng-3.13.2/lib/memtrace.c000066400000000000000000000356171321171025300201600ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "syslog-ng.h" #if SYSLOG_NG_ENABLE_MEMTRACE #define REALLY_TRACE_MALLOC 1 #define SYSLOG_NG_ENABLE_HEAP_TRACE 1 #include #include #include #include #include #include #include #include #include #include #define MEMTRACE_BACKTRACE_LEN 64 #define MEMTRACE_BACKTRACE_BUF_LEN (MEMTRACE_BACKTRACE_LEN * 11 + 1) #define MEMTRACE_CANARY_SIZE 2 #define MEMTRACE_CANARY_FILL 0xcd #define MEMTRACE_CANARY_CHECK 0xcdcdcdcd #define MEMTRACE_CANARY_OVERHEAD sizeof(ZMemTraceCanary) * 2 typedef struct _ZMemTraceCanary { gint size; gint neg_size; guint32 canary[MEMTRACE_CANARY_SIZE]; } ZMemTraceCanary; typedef struct _ZMemTraceEntry { guint32 next; guint32 ptr; guint32 size; gpointer backtrace[MEMTRACE_BACKTRACE_LEN]; } ZMemTraceEntry; typedef struct _ZMemTraceHead { guint32 list; GStaticMutex lock; gulong size; } ZMemTraceHead; #define MEMTRACE_HASH_SIZE 32768 #define MEMTRACE_HASH_MASK (32767 << 3) #define MEMTRACE_HASH_SHIFT 3 /* at most this amount of blocks can be allocated at the same time * This preallocates MEMTRACE_HEAP_SIZE * sizeof(ZMemTraceEntry), * which is 268 bytes currently. (17MB) */ #define MEMTRACE_HEAP_SIZE 65536 #define MEMTRACE_TEMP_HEAP_SIZE 32768 ZMemTraceHead mem_trace_hash[MEMTRACE_HASH_SIZE]; ZMemTraceEntry mem_trace_heap[MEMTRACE_HEAP_SIZE]; guint32 mem_trace_free_list = -1; guint32 mem_block_count = 0, mem_allocated_size = 0, mem_alloc_count = 0; gboolean mem_trace_initialized = FALSE; GStaticMutex mem_trace_lock = G_STATIC_MUTEX_INIT; gint mem_trace_log_fd = -1; gchar *mem_trace_filename = "/var/tmp/zorp-memtrace.log"; gboolean mem_trace_canaries = TRUE; gchar temp_heap[MEMTRACE_TEMP_HEAP_SIZE]; gint temp_brk = 0; gint mem_trace_recurse = 0; #define TMP_ALLOCATED(ptr) (((guint32) ((char *) ptr - temp_heap)) < MEMTRACE_TEMP_HEAP_SIZE) void *(*old_malloc)(size_t size); void (*old_free)(void *ptr); void *(*old_realloc)(void *ptr, size_t size); void *(*old_calloc)(size_t nmemb, size_t size); void z_mem_trace_init(gchar *tracefile) { int i; if (!mem_trace_initialized) { mem_trace_initialized = TRUE; for (i = 0; i < MEMTRACE_HEAP_SIZE; i++) { mem_trace_heap[i].next = i+1; } mem_trace_heap[MEMTRACE_HEAP_SIZE - 1].next = -1; mem_trace_free_list = 0; for (i = 0; i < MEMTRACE_HASH_SIZE; i++) { mem_trace_hash[i].list = -1; g_static_mutex_init(&mem_trace_hash[i].lock); } old_malloc = dlsym(RTLD_NEXT, "malloc"); old_free = dlsym(RTLD_NEXT, "free"); old_realloc = dlsym(RTLD_NEXT, "realloc"); old_calloc = dlsym(RTLD_NEXT, "calloc"); if (tracefile) { mem_trace_filename = g_new0(gchar, strlen("/var/tmp/") + strlen(tracefile) + 1); g_snprintf(mem_trace_filename, strlen("/var/tmp/") + strlen(tracefile) + 1, "%s%s", "/var/tmp/", tracefile); } } } static guint32 z_mem_trace_hash(guint32 ptr) { return (ptr & MEMTRACE_HASH_MASK) >> MEMTRACE_HASH_SHIFT; } void z_mem_trace_bt(gpointer backtrace[]) { /* NOTE: this is i386 specific */ gpointer x; gpointer *ebp = &x+1; gint i = 0; while ((ebp > &x) && *ebp && i < MEMTRACE_BACKTRACE_LEN - 1) { gpointer value = *(ebp + 1); backtrace[i] = value; i++; ebp = *ebp; } backtrace[i] = NULL; } static char * z_mem_trace_format_bt(gpointer backtrace[], gchar *buf, gint buflen) { gchar *p = buf; gint i, len; for (i = 0; i < MEMTRACE_BACKTRACE_LEN && buflen >= 12 && backtrace[i]; i++) { len = sprintf(buf, "%p,", backtrace[i]); buf += len; buflen -= len; } return p; } static void z_mem_trace_printf(char *format, ...) { gchar buf[1024]; gint len; va_list l; va_start(l, format); len = vsnprintf(buf, sizeof(buf), format, l); va_end(l); mem_trace_log_fd = open(mem_trace_filename, O_CREAT | O_WRONLY | O_APPEND, 0600); if (mem_trace_log_fd != -1) { write(mem_trace_log_fd, buf, len); close(mem_trace_log_fd); } } void z_mem_trace_stats(void) { z_mem_trace_printf("time: %d, allocs: %ld, blocks: %ld, size: %ld\n", time(NULL), mem_alloc_count, mem_block_count, mem_allocated_size); } static gpointer z_mem_trace_check_canaries(gpointer ptr); void z_mem_trace_dump(void) { int i; z_mem_trace_printf("memdump begins\n"); for (i = 0; i < MEMTRACE_HASH_SIZE; i++) { ZMemTraceHead *head = &mem_trace_hash[i]; ZMemTraceEntry *entry; int cur; g_static_mutex_lock(&head->lock); cur = head->list; while (cur != -1) { char backtrace_buf[MEMTRACE_BACKTRACE_BUF_LEN]; entry = &mem_trace_heap[cur]; z_mem_trace_printf("ptr=%p, size=%d, backtrace=%s\n", entry->ptr, entry->size, z_mem_trace_format_bt(entry->backtrace, backtrace_buf, sizeof(backtrace_buf))); if (mem_trace_canaries) { z_mem_trace_check_canaries((gpointer)entry->ptr); } cur = entry->next; } g_static_mutex_unlock(&head->lock); } } /** * @ptr raw pointer * @size original size * * returns the pointer to be returned */ static gpointer z_mem_trace_fill_canaries(gpointer ptr, gint size) { if (!ptr) return ptr; if (mem_trace_canaries) { ZMemTraceCanary *p_before = (ZMemTraceCanary *) ptr; ZMemTraceCanary *p_after = (ZMemTraceCanary *)(((gchar *) ptr) + sizeof(ZMemTraceCanary) + size); memset(p_before->canary, MEMTRACE_CANARY_FILL, sizeof(p_before->canary)); memset(p_after->canary, MEMTRACE_CANARY_FILL, sizeof(p_after->canary)); p_before->size = p_after->size = size; p_before->neg_size = p_after->neg_size = -size; return (gpointer) (p_before + 1); } else return ptr; } /** * @ptr user pointer * * returns the pointer to be freed * * Aborts if the canaries are touched. * */ static gpointer z_mem_trace_check_canaries(gpointer ptr) { if (!ptr) return ptr; if (mem_trace_canaries) { ZMemTraceCanary *p_before = ((ZMemTraceCanary *) ptr) - 1; ZMemTraceCanary *p_after; int i; if (p_before->size != -p_before->neg_size) { z_mem_trace_printf("Inconsystency in canaries; ptr=%p\n", ptr); abort(); } p_after = (ZMemTraceCanary *) (((gchar *) ptr) + p_before->size); if (p_after->size != p_before->size || p_after->neg_size != p_before->neg_size) { z_mem_trace_printf("Inconsystency in canaries; ptr=%p\n", ptr); abort(); } for (i = 0; i < MEMTRACE_CANARY_SIZE; i++) { if (p_before->canary[i] != p_after->canary[i] || p_before->canary[i] != MEMTRACE_CANARY_CHECK) { z_mem_trace_printf("Touched canary; ptr=%p\n", ptr); abort(); } } return (gpointer) p_before; } return ptr; } static gboolean z_mem_trace_add(gpointer ptr, gint size, gpointer backtrace[]) { guint32 hash, new_ndx; ZMemTraceEntry *new; ZMemTraceHead *head; gchar backtrace_buf[8192]; hash = z_mem_trace_hash((guint32) ptr); g_static_mutex_lock(&mem_trace_lock); if (mem_trace_free_list == -1) { return FALSE; } mem_block_count++; mem_alloc_count++; if ((mem_alloc_count % 1000) == 0) z_mem_trace_stats(); mem_allocated_size += size; new_ndx = mem_trace_free_list; new = &mem_trace_heap[new_ndx]; mem_trace_free_list = mem_trace_heap[mem_trace_free_list].next; g_static_mutex_unlock(&mem_trace_lock); new->ptr = (guint32) ptr; new->size = size; memmove(new->backtrace, backtrace, sizeof(new->backtrace)); head = &mem_trace_hash[hash]; g_static_mutex_lock(&head->lock); new->next = head->list; head->list = new_ndx; g_static_mutex_unlock(&head->lock); #if REALLY_TRACE_MALLOC z_mem_trace_printf("memtrace addblock; ptr=%p, size=%d, backtrace=%s\n", ptr, size, z_mem_trace_format_bt(backtrace, backtrace_buf, sizeof(backtrace_buf))); #endif return TRUE; } static gboolean z_mem_trace_del(gpointer ptr) { guint32 hash, *prev, cur; ZMemTraceHead *head; ZMemTraceEntry *entry; gchar backtrace_buf[8192]; hash = z_mem_trace_hash((guint32) ptr); head = &mem_trace_hash[hash]; g_static_mutex_lock(&head->lock); prev = &head->list; cur = head->list; while (cur != -1 && mem_trace_heap[cur].ptr != (guint32) ptr) { prev = &mem_trace_heap[cur].next; cur = mem_trace_heap[cur].next; } if (cur == -1) { g_static_mutex_unlock(&head->lock); return FALSE; } *prev = mem_trace_heap[cur].next; g_static_mutex_unlock(&head->lock); g_static_mutex_lock(&mem_trace_lock); entry = &mem_trace_heap[cur]; #if REALLY_TRACE_MALLOC z_mem_trace_printf("memtrace delblock; ptr=%p, size=%d, backtrace=%s\n", (void *) entry->ptr, entry->size, z_mem_trace_format_bt(entry->backtrace, backtrace_buf, sizeof(backtrace_buf))); #endif mem_trace_heap[cur].next = mem_trace_free_list; mem_trace_free_list = cur; mem_block_count--; mem_allocated_size -= mem_trace_heap[cur].size; g_static_mutex_unlock(&mem_trace_lock); return TRUE; } static inline guint32 z_mem_trace_lookup_chain(gpointer ptr, ZMemTraceHead *head) { guint32 cur = -1; cur = head->list; while (cur != -1 && mem_trace_heap[cur].ptr != (guint32) ptr) { cur = mem_trace_heap[cur].next; } return cur; } static int z_mem_trace_getsize(gpointer ptr) { guint32 hash, cur; int size; ZMemTraceHead *head; hash = z_mem_trace_hash((guint32) ptr); head = &mem_trace_hash[hash]; g_static_mutex_lock(&head->lock); cur = z_mem_trace_lookup_chain(ptr, head); if (cur != -1) { size = mem_trace_heap[cur].size; g_static_mutex_unlock(&head->lock); return size; } g_static_mutex_unlock(&head->lock); return -1; } void * z_malloc(size_t size, gpointer backtrace[]) { gpointer *raw_ptr, *user_ptr; raw_ptr = old_malloc(size + mem_trace_canaries * MEMTRACE_CANARY_OVERHEAD); user_ptr = z_mem_trace_fill_canaries(raw_ptr, size); if (user_ptr && !z_mem_trace_add(user_ptr, size, backtrace)) { gchar buf[MEMTRACE_BACKTRACE_BUF_LEN]; old_free(raw_ptr); z_mem_trace_printf("Out of free memory blocks; backtrace='%s'\n", z_mem_trace_format_bt(backtrace, buf, sizeof(buf))); z_mem_trace_stats(); return NULL; } return user_ptr; } void z_free(void *user_ptr, gpointer backtrace[]) { gchar backtrace_buf[MEMTRACE_BACKTRACE_BUF_LEN]; gpointer raw_ptr; gint size; raw_ptr = z_mem_trace_check_canaries(user_ptr); size = z_mem_trace_getsize(user_ptr); if (size != -1) memset(user_ptr, 0xcd, size); if (user_ptr && !z_mem_trace_del(user_ptr)) { z_mem_trace_printf("Trying to free a non-existing memory block; ptr=%p, backtrace='%s'\n", user_ptr, z_mem_trace_format_bt(backtrace, backtrace_buf, sizeof(backtrace_buf))); assert(0); } if (!TMP_ALLOCATED(raw_ptr)) old_free(raw_ptr); } void * z_realloc(void *user_ptr, size_t size, gpointer backtrace[]) { void *new_ptr, *raw_ptr = NULL; int old_size = 0; gchar buf[MEMTRACE_BACKTRACE_BUF_LEN]; if (user_ptr) { raw_ptr = z_mem_trace_check_canaries(user_ptr); old_size = z_mem_trace_getsize(user_ptr); if (old_size == -1 || !z_mem_trace_del(user_ptr)) { z_mem_trace_printf("Trying to realloc a non-existing memory block; ptr=%p, size='%d', info='%s'", user_ptr, size, z_mem_trace_format_bt(backtrace, buf, sizeof(buf))); assert(0); } } if (TMP_ALLOCATED(raw_ptr)) { /* this ptr was allocated on the temp heap, move it to real heap */ z_mem_trace_printf("reallocing space on the temp heap, moving..., ptr=%p, temp_heap=%p, diff=%d, old_size=%d\n", raw_ptr, temp_heap, (char *) raw_ptr-temp_heap, old_size); new_ptr = old_malloc(size + mem_trace_canaries * MEMTRACE_CANARY_OVERHEAD); if (new_ptr) { new_ptr = z_mem_trace_fill_canaries(new_ptr, size); /* copy user data */ memmove(new_ptr, user_ptr, old_size); } } else { new_ptr = old_realloc(raw_ptr, size + mem_trace_canaries * MEMTRACE_CANARY_OVERHEAD); /* fill_canaries doesn't touch data, only fills the canary info */ new_ptr = z_mem_trace_fill_canaries(new_ptr, size); } if (new_ptr) { z_mem_trace_add(new_ptr, size, backtrace); } return new_ptr; } void * z_calloc(size_t nmemb, size_t size, gpointer backtrace[]) { void *user_ptr, *raw_ptr; if (old_calloc == NULL) { raw_ptr = &temp_heap[temp_brk]; temp_brk += nmemb * size + mem_trace_canaries * MEMTRACE_CANARY_OVERHEAD; assert(temp_brk < MEMTRACE_TEMP_HEAP_SIZE); } else raw_ptr = old_calloc(nmemb, size + mem_trace_canaries * MEMTRACE_CANARY_OVERHEAD); user_ptr = z_mem_trace_fill_canaries(raw_ptr, nmemb * size); z_mem_trace_add(user_ptr, nmemb * size, backtrace); return user_ptr; } #undef malloc #undef free #undef realloc #undef calloc /* look up return address */ void * malloc(size_t size) { gpointer backtrace[MEMTRACE_BACKTRACE_LEN]; z_mem_trace_bt(backtrace); return z_malloc(size, backtrace); } void free(void *ptr) { gpointer backtrace[MEMTRACE_BACKTRACE_LEN]; z_mem_trace_bt(backtrace); return z_free(ptr, backtrace); } void * realloc(void *ptr, size_t size) { gpointer backtrace[MEMTRACE_BACKTRACE_LEN]; z_mem_trace_bt(backtrace); return z_realloc(ptr, size, backtrace); } void * calloc(size_t nmemb, size_t size) { gpointer backtrace[MEMTRACE_BACKTRACE_LEN]; z_mem_trace_bt(backtrace); return z_calloc(nmemb, size, backtrace); } #else void z_mem_trace_init(gchar *memtrace_file) { } void z_mem_trace_stats(void) { } void z_mem_trace_dump(void) { } #endif syslog-ng-syslog-ng-3.13.2/lib/memtrace.h000066400000000000000000000027001321171025300201500ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef ZORP_MEMTRACE_H_INCLUDED #define ZORP_MEMTRACE_H_INCLUDED void z_mem_trace_init(gchar *memtrace_file); void z_mem_trace_stats(void); void z_mem_trace_dump(void); #if SYSLOG_NG_ENABLE_MEMTRACE #include void *z_malloc(size_t size, gpointer backtrace[]); void z_free(void *ptr, gpointer backtrace[]); void *z_realloc(void *ptr, size_t size, gpointer backtrace[]); void *z_calloc(size_t nmemb, size_t size, gpointer backtrace[]); #endif #endif syslog-ng-syslog-ng-3.13.2/lib/merge-grammar.py000077500000000000000000000042271321171025300213100ustar00rootroot00000000000000#!/usr/bin/env python ############################################################################# # Copyright (c) 2010-2017 Balabit # # This 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 2.1 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As an additional exemption you are allowed to compile & link against the # OpenSSL libraries as published by the OpenSSL project. See the file # COPYING for details. # ############################################################################# # # TODOs: # * be more clever about which rules to include as bison generates a lot of # warnings about unused rules # from __future__ import print_function import fileinput import os import sys grammar_file = os.path.join(os.environ.get('top_srcdir', ''), 'lib/cfg-grammar.y') if not os.path.isfile(grammar_file): grammar_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'cfg-grammar.y') if not os.path.isfile(grammar_file): sys.exit('Error opening cfg-grammar.y') def include_block(block_type): start_marker = 'START_' + block_type end_marker = 'END_' + block_type with open(grammar_file) as f: in_block = False for line in f: if start_marker in line: in_block = True elif end_marker in line: in_block = False elif in_block: print(line, end='') for line in fileinput.input(): if 'INCLUDE_DECLS' in line: include_block('DECLS') elif 'INCLUDE_RULES' in line: include_block('RULES') else: print(line, end='') syslog-ng-syslog-ng-3.13.2/lib/messages.c000066400000000000000000000176301321171025300201650ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "messages.h" #include "logmsg/logmsg.h" #include #include #include #include #include #include #include enum { /* processing a non-internal message, we're definitely not recursing */ RECURSE_STATE_OK = 0, /* processing an internal message currently, followup internal messages will be suppressed */ RECURSE_STATE_WATCH = 1, /* supress all internal messages */ RECURSE_STATE_SUPPRESS = 2 }; typedef struct _MsgContext { guint16 recurse_state; gboolean recurse_warning:1; gchar recurse_trigger[128]; } MsgContext; gboolean startup_debug_flag = 0; gboolean debug_flag = 0; gboolean verbose_flag = 0; gboolean trace_flag = 0; gboolean log_stderr = FALSE; gboolean skip_timestamp_on_stderr = FALSE; static MsgPostFunc msg_post_func; static EVTCONTEXT *evt_context; static GStaticPrivate msg_context_private = G_STATIC_PRIVATE_INIT; static GStaticMutex evtlog_lock = G_STATIC_MUTEX_INIT; static MsgContext * msg_get_context(void) { MsgContext *context; context = g_static_private_get(&msg_context_private); if (!context) { context = g_new0(MsgContext, 1); g_static_private_set(&msg_context_private, context, g_free); } return context; } void msg_set_context(LogMessage *msg) { MsgContext *context = msg_get_context(); if (msg && (msg->flags & LF_INTERNAL)) { if (msg->recursed) context->recurse_state = RECURSE_STATE_SUPPRESS; else context->recurse_state = RECURSE_STATE_WATCH; } else { context->recurse_state = RECURSE_STATE_OK; } } static gboolean msg_limit_internal_message(const gchar *msg) { MsgContext *context; if (!evt_context) return FALSE; context = msg_get_context(); if (context->recurse_state >= RECURSE_STATE_SUPPRESS) { if (!context->recurse_warning) { msg_event_send( msg_event_create(EVT_PRI_WARNING, "internal() messages are looping back, preventing loop by suppressing all internal messages until the current message is processed", evt_tag_str("trigger-msg", context->recurse_trigger), evt_tag_str("first-suppressed-msg", msg), NULL)); context->recurse_warning = TRUE; } return FALSE; } return TRUE; } static gchar * msg_format_timestamp(gchar *buf, gsize buflen) { struct tm tm; GTimeVal now; gint len; time_t now_sec; g_get_current_time(&now); now_sec = now.tv_sec; cached_localtime(&now_sec, &tm); len = strftime(buf, buflen, "%Y-%m-%dT%H:%M:%S", &tm); if (len < buflen) g_snprintf(buf + len, buflen - len, ".%06ld", now.tv_usec); return buf; } static void msg_send_formatted_message_to_stderr(const char *msg) { gchar tmtime[128]; if (skip_timestamp_on_stderr) fprintf(stderr, "%s\n", msg); else fprintf(stderr, "[%s] %s\n", msg_format_timestamp(tmtime, sizeof(tmtime)), msg); } void msg_send_formatted_message(int prio, const char *msg) { if (G_UNLIKELY(log_stderr || (msg_post_func == NULL && (prio & 0x7) <= EVT_PRI_WARNING))) { msg_send_formatted_message_to_stderr(msg); } else if (msg_post_func) { LogMessage *m; MsgContext *context = msg_get_context(); if (context->recurse_state == RECURSE_STATE_OK) { context->recurse_warning = FALSE; g_strlcpy(context->recurse_trigger, msg, sizeof(context->recurse_trigger)); } m = log_msg_new_internal(prio, msg); m->recursed = context->recurse_state >= RECURSE_STATE_WATCH; msg_post_message(m); } } static void msg_event_send_with_suppression(EVTREC *e, gboolean (*suppress)(const gchar *msg)) { gchar *msg; msg = evt_format(e); if (!suppress || suppress(msg)) msg_send_formatted_message(evt_rec_get_syslog_pri(e) | EVT_FAC_SYSLOG, msg); free(msg); msg_event_free(e); } void msg_event_send(EVTREC *e) { msg_event_send_with_suppression(e, NULL); } void msg_event_suppress_recursions_and_send(EVTREC *e) { msg_event_send_with_suppression(e, msg_limit_internal_message); } EVTREC * msg_event_create(gint prio, const gchar *desc, EVTTAG *tag1, ...) { EVTREC *e; va_list va; g_static_mutex_lock(&evtlog_lock); e = evt_rec_init(evt_context, prio, desc); if (tag1) { evt_rec_add_tag(e, tag1); va_start(va, tag1); evt_rec_add_tagsv(e, va); va_end(va); } g_static_mutex_unlock(&evtlog_lock); return e; } EVTREC * msg_event_create_from_desc(gint prio, const char *desc) { return msg_event_create(prio, desc, NULL); } void msg_event_free(EVTREC *e) { g_static_mutex_lock(&evtlog_lock); evt_rec_free(e); g_static_mutex_unlock(&evtlog_lock); } void msg_log_func(const gchar *log_domain, GLogLevelFlags log_flags, const gchar *msg, gpointer user_data) { int pri = EVT_PRI_INFO; if (log_flags & G_LOG_LEVEL_DEBUG) pri = EVT_PRI_DEBUG; else if (log_flags & G_LOG_LEVEL_WARNING) pri = EVT_PRI_WARNING; else if (log_flags & G_LOG_LEVEL_ERROR) pri = EVT_PRI_ERR; pri |= EVT_FAC_SYSLOG; msg_send_formatted_message(pri, msg); } void msg_set_post_func(MsgPostFunc func) { msg_post_func = func; } void msg_post_message(LogMessage *msg) { if (msg_post_func) msg_post_func(msg); else log_msg_unref(msg); } static guint g_log_handler_id; static guint glib_handler_id; void msg_init(gboolean interactive) { if (evt_context) return; if (!interactive) { g_log_handler_id = g_log_set_handler(G_LOG_DOMAIN, 0xff, msg_log_func, NULL); glib_handler_id = g_log_set_handler("GLib", 0xff, msg_log_func, NULL); } else { log_stderr = TRUE; skip_timestamp_on_stderr = TRUE; } evt_context = evt_ctx_init("syslog-ng", EVT_FAC_SYSLOG); } void msg_deinit(void) { evt_ctx_free(evt_context); evt_context = NULL; log_stderr = TRUE; if (g_log_handler_id) { g_log_remove_handler(G_LOG_DOMAIN, g_log_handler_id); g_log_handler_id = 0; } if (glib_handler_id) { g_log_remove_handler("GLib", glib_handler_id); glib_handler_id = 0; } } static GOptionEntry msg_option_entries[] = { { "startup-debug", 'r', 0, G_OPTION_ARG_NONE, &startup_debug_flag, "Enable debug logging during startup", NULL}, { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose_flag, "Be a bit more verbose", NULL }, { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug_flag, "Enable debug messages", NULL}, { "trace", 't', 0, G_OPTION_ARG_NONE, &trace_flag, "Enable trace messages", NULL }, { "stderr", 'e', 0, G_OPTION_ARG_NONE, &log_stderr, "Log messages to stderr", NULL}, { NULL } }; void msg_add_option_group(GOptionContext *ctx) { GOptionGroup *group; group = g_option_group_new("log", "Log options", "Log options", NULL, NULL); g_option_group_add_entries(group, msg_option_entries); g_option_context_add_group(ctx, group); } syslog-ng-syslog-ng-3.13.2/lib/messages.h000066400000000000000000000111701321171025300201630ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MESSAGES_H_INCLUDED #define MESSAGES_H_INCLUDED #include "syslog-ng.h" #include extern int startup_debug_flag; extern int debug_flag; extern int verbose_flag; extern int trace_flag; extern int log_stderr; typedef void (*MsgPostFunc)(LogMessage *msg); void msg_set_context(LogMessage *msg); EVTREC *msg_event_create(gint prio, const char *desc, EVTTAG *tag1, ...) __attribute__((nonnull(2))); EVTREC *msg_event_create_from_desc(gint prio, const char *desc); void msg_event_free(EVTREC *e); void msg_event_send(EVTREC *e); void msg_event_suppress_recursions_and_send(EVTREC *e); void msg_set_post_func(MsgPostFunc func); void msg_init(gboolean interactive); void msg_deinit(void); void msg_add_option_group(GOptionContext *ctx); /* fatal->warning goes out to the console during startup, notice and below * comes goes to the log even during startup */ #define msg_fatal(desc, tags...) msg_event_suppress_recursions_and_send(msg_event_create(EVT_PRI_CRIT, desc, ##tags, NULL )) #define msg_error(desc, tags...) msg_event_suppress_recursions_and_send(msg_event_create(EVT_PRI_ERR, desc, ##tags, NULL )) #define msg_warning(desc, tags...) msg_event_suppress_recursions_and_send(msg_event_create(EVT_PRI_WARNING, desc, ##tags, NULL )) #define msg_notice(desc, tags...) msg_event_suppress_recursions_and_send(msg_event_create(EVT_PRI_NOTICE, desc, ##tags, NULL )) #define msg_info(desc, tags...) msg_event_suppress_recursions_and_send(msg_event_create(EVT_PRI_INFO, desc, ##tags, NULL )) /* just like msg_info, but prepends the message with a timestamp -- useful in interactive * tools with long running time to provide some feedback */ #define msg_progress(desc, tags...) \ do { \ time_t t; \ char *timestamp, *newdesc; \ \ t = time(0); \ timestamp = ctime(&t); \ timestamp[strlen(timestamp) - 1] = 0; \ newdesc = g_strdup_printf("[%s] %s", timestamp, desc); \ msg_event_send(msg_event_create(EVT_PRI_INFO, newdesc, ##tags, NULL )); \ g_free(newdesc); \ } while (0) #define msg_verbose(desc, tags...) \ do { \ if (G_UNLIKELY(verbose_flag)) \ msg_info(desc, ##tags ); \ } while (0) #define msg_debug(desc, tags...) \ do { \ if (G_UNLIKELY(debug_flag)) \ msg_event_suppress_recursions_and_send( \ msg_event_create(EVT_PRI_DEBUG, desc, ##tags, NULL )); \ } while (0) #if SYSLOG_NG_ENABLE_DEBUG #define msg_trace(desc, tags...) \ do { \ if (G_UNLIKELY(trace_flag)) \ msg_event_suppress_recursions_and_send( \ msg_event_create(EVT_PRI_DEBUG, desc, ##tags, NULL )); \ } while (0) #else #define msg_trace(desc, tags...) #endif #define __once() \ ({ \ static gboolean __guard = TRUE; \ gboolean __current_guard = __guard; \ __guard = FALSE; \ __current_guard; \ }) #define msg_warning_once(desc, tags...) \ do { \ if (__once()) \ msg_warning(desc, ##tags ); \ } while (0) void msg_post_message(LogMessage *msg); void msg_send_formatted_message(int prio, const char *msg); #endif syslog-ng-syslog-ng-3.13.2/lib/misc.c000066400000000000000000000025361321171025300173100ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "misc.h" #include "dnscache.h" #include "messages.h" #include "gprocess.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include syslog-ng-syslog-ng-3.13.2/lib/misc.h000066400000000000000000000022051321171025300173060ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MISC_H_INCLUDED #define MISC_H_INCLUDED #include "syslog-ng.h" #include "gsockaddr.h" #include #include #endif syslog-ng-syslog-ng-3.13.2/lib/ml-batched-timer.c000066400000000000000000000124721321171025300214730ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "ml-batched-timer.h" #include "mainloop-call.h" /* callback to be invoked when the timeout triggers */ static void ml_batched_timer_handle(MlBatchedTimer *self) { self->handler(self->cookie); } /* function called using main_loop_call() in case the suppress timer needs * to be updated. It is running in the main thread, thus is able to * reregister our ivykis timer */ static void ml_batched_timer_perform_update(MlBatchedTimer *self) { main_loop_assert_main_thread(); if (iv_timer_registered(&self->timer)) iv_timer_unregister(&self->timer); self->timer.expires = self->expires; if (self->timer.expires.tv_sec > 0) iv_timer_register(&self->timer); self->unref_cookie(self->cookie); } static inline gboolean ml_batched_timer_expiration_changed(MlBatchedTimer *self, struct timespec *next_expires) { return ((next_expires->tv_sec != self->expires.tv_sec) || (next_expires->tv_nsec != self->expires.tv_nsec)); } /* * Update the timer in a deferred manner, possibly batching the results of * multiple updates to the underlying ivykis timer. This is necessary as * suppress timer updates must run in the main thread, and updating it every * time a new message comes in would cause enormous latency in the fast * path. By collecting multiple updates the overhead is drastically * reduced. */ static void ml_batched_timer_update(MlBatchedTimer *self, struct timespec *next_expires) { /* NOTE: this check is racy as self->expires might be updated in a * different thread without holding a lock. * * When we lose the race, that means that another thread has already * updated the expires field, but we see the old value. In this case two * things may happen: * * 1) we skip an update because of the race * * We're going to skip the update if the other set the "expires" field to * the same value we intended to set it. This is not an issue, it doesn't * matter whether we or the other thread updates the timer. * * 2) we perform an update because of the race * * In this case, the other thread has updated the field, but we still * see the old value, thus we decide another update is due. We go * into the locked path, which will sort things out. * * In both cases we are fine. */ if (ml_batched_timer_expiration_changed(self, next_expires)) { g_static_mutex_lock(&self->lock); /* check if we've lost the race */ if (ml_batched_timer_expiration_changed(self, next_expires)) { /* we need to update the timer */ self->expires = *next_expires; self->ref_cookie(self->cookie); g_static_mutex_unlock(&self->lock); main_loop_call((MainLoopTaskFunc) ml_batched_timer_perform_update, self, FALSE); } else g_static_mutex_unlock(&self->lock); } } /* Update the expire time of this timer to the current time plus @sec. Can * be invoked from any threads. */ void ml_batched_timer_postpone(MlBatchedTimer *self, glong sec) { struct timespec next_expires; iv_validate_now(); /* we deliberately use nsec == 0 in order to increase the likelyhood that * we target the same second, in case only a fraction of a second has * passed between two updates. */ next_expires.tv_nsec = 0; next_expires.tv_sec = iv_now.tv_sec + sec; ml_batched_timer_update(self, &next_expires); } /* cancel the timer for the time being. Can be invoked from any threads. */ void ml_batched_timer_cancel(MlBatchedTimer *self) { struct timespec next_expires; next_expires.tv_sec = 0; next_expires.tv_nsec = 0; ml_batched_timer_update(self, &next_expires); } /* unregister the underlying ivykis timer, can only be called from the main thread. */ void ml_batched_timer_unregister(MlBatchedTimer *self) { main_loop_assert_main_thread(); if (iv_timer_registered(&self->timer)) iv_timer_unregister(&self->timer); self->expires.tv_sec = 0; self->expires.tv_nsec = 0; } /* one-time initialization of the MlBatchedTimer structure */ void ml_batched_timer_init(MlBatchedTimer *self) { g_static_mutex_init(&self->lock); IV_TIMER_INIT(&self->timer); self->timer.cookie = self; self->timer.handler = (void (*)(void *)) ml_batched_timer_handle; } /* Free MlBatchedTimer state. */ void ml_batched_timer_free(MlBatchedTimer *self) { g_static_mutex_free(&self->lock); } syslog-ng-syslog-ng-3.13.2/lib/ml-batched-timer.h000066400000000000000000000032231321171025300214720ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef ML_BATCHED_TIMER_INCLUDED #define ML_BATCHED_TIMER_INCLUDED #include "mainloop.h" #include /* timer which only updates */ typedef struct _MlBatchedTimer { GStaticMutex lock; struct iv_timer timer; struct timespec expires; gpointer cookie; void *(*ref_cookie)(gpointer self); void (*unref_cookie)(gpointer self); void (*handler)(gpointer self); } MlBatchedTimer; void ml_batched_timer_postpone(MlBatchedTimer *self, glong sec); void ml_batched_timer_cancel(MlBatchedTimer *self); void ml_batched_timer_unregister(MlBatchedTimer *self); void ml_batched_timer_init(MlBatchedTimer *self); void ml_batched_timer_free(MlBatchedTimer *self); #endif syslog-ng-syslog-ng-3.13.2/lib/module-config.c000066400000000000000000000025741321171025300211070ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "module-config.h" gboolean module_config_init(ModuleConfig *s, GlobalConfig *cfg) { if (s->init) return s->init(s, cfg); return TRUE; } void module_config_deinit(ModuleConfig *s, GlobalConfig *cfg) { if (s->deinit) s->deinit(s, cfg); } void module_config_free_method(ModuleConfig *s) { } void module_config_free(ModuleConfig *s) { if (s->free_fn) s->free_fn(s); g_free(s); } syslog-ng-syslog-ng-3.13.2/lib/module-config.h000066400000000000000000000035101321171025300211030ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MODULE_CONFIG_H_INCLUDED #define MODULE_CONFIG_H_INCLUDED 1 #include "syslog-ng.h" typedef struct _ModuleConfig ModuleConfig; /* This class encapsulates global (e.g. GlobalConfig) level settings for * modules. It can be used to store state that is not related to a specific * LogPipe instance. Such an example is the python block embedded in the * configuration used by the Python module. */ struct _ModuleConfig { /* init/deinit is hooked into configuration init/deinit */ gboolean (*init)(ModuleConfig *s, GlobalConfig *cfg); void (*deinit)(ModuleConfig *s, GlobalConfig *cfg); void (*free_fn)(ModuleConfig *s); }; gboolean module_config_init(ModuleConfig *s, GlobalConfig *cfg); void module_config_deinit(ModuleConfig *s, GlobalConfig *cfg); void module_config_free_method(ModuleConfig *s); void module_config_free(ModuleConfig *s); #endif syslog-ng-syslog-ng-3.13.2/lib/msg-format.c000066400000000000000000000117471321171025300204350ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "msg-format.h" #include "cfg.h" #include "plugin.h" #include "plugin-types.h" void msg_format_inject_parse_error(LogMessage *msg, const guchar *data, gsize length, gint problem_position) { gchar buf[2048]; log_msg_clear(msg); msg->timestamps[LM_TS_STAMP] = msg->timestamps[LM_TS_RECVD]; log_msg_set_value(msg, LM_V_HOST, "", 0); g_snprintf(buf, sizeof(buf), "Error processing log message: %.*s>@<%.*s", (gint) problem_position-1, data,(gint) (length-problem_position+1), data+problem_position-1); log_msg_set_value(msg, LM_V_MESSAGE, buf, -1); log_msg_set_value(msg, LM_V_PROGRAM, "syslog-ng", 9); g_snprintf(buf, sizeof(buf), "%d", (int) getpid()); log_msg_set_value(msg, LM_V_PID, buf, -1); msg->pri = LOG_SYSLOG | LOG_ERR; } void msg_format_options_defaults(MsgFormatOptions *options) { options->flags = LP_EXPECT_HOSTNAME | LP_STORE_LEGACY_MSGHDR; options->recv_time_zone = NULL; options->recv_time_zone_info = NULL; options->bad_hostname = NULL; options->default_pri = 0xFFFF; options->sdata_param_value_max = 65535; } /* NOTE: _init needs to be idempotent when called multiple times w/o invoking _destroy */ void msg_format_options_init(MsgFormatOptions *options, GlobalConfig *cfg) { Plugin *p; if (options->initialized) return; if (cfg->bad_hostname_compiled) options->bad_hostname = &cfg->bad_hostname; if (options->recv_time_zone == NULL) options->recv_time_zone = g_strdup(cfg->recv_time_zone); if (options->recv_time_zone_info == NULL) options->recv_time_zone_info = time_zone_info_new(options->recv_time_zone); if (!options->format) options->format = g_strdup("syslog"); p = cfg_find_plugin(cfg, LL_CONTEXT_FORMAT, options->format); if (p) options->format_handler = plugin_construct(p); options->initialized = TRUE; } void msg_format_options_copy(MsgFormatOptions *options, const MsgFormatOptions *source) { g_assert(!options->initialized); options->format = g_strdup(source->format); options->flags = source->flags; options->default_pri = source->default_pri; options->recv_time_zone = g_strdup(source->recv_time_zone); options->sdata_param_value_max = source->sdata_param_value_max; } void msg_format_options_destroy(MsgFormatOptions *options) { if (options->format) { g_free(options->format); options->format = NULL; } if (options->recv_time_zone) { g_free(options->recv_time_zone); options->recv_time_zone = NULL; } if (options->recv_time_zone_info) { time_zone_info_free(options->recv_time_zone_info); options->recv_time_zone_info = NULL; } options->initialized = FALSE; } CfgFlagHandler msg_format_flag_handlers[] = { { "no-parse", CFH_SET, offsetof(MsgFormatOptions, flags), LP_NOPARSE }, { "check-hostname", CFH_SET, offsetof(MsgFormatOptions, flags), LP_CHECK_HOSTNAME }, { "syslog-protocol", CFH_SET, offsetof(MsgFormatOptions, flags), LP_SYSLOG_PROTOCOL }, { "assume-utf8", CFH_SET, offsetof(MsgFormatOptions, flags), LP_ASSUME_UTF8 }, { "validate-utf8", CFH_SET, offsetof(MsgFormatOptions, flags), LP_VALIDATE_UTF8 }, { "sanitize-utf8", CFH_SET, offsetof(MsgFormatOptions, flags), LP_SANITIZE_UTF8 }, { "no-multi-line", CFH_SET, offsetof(MsgFormatOptions, flags), LP_NO_MULTI_LINE }, { "store-legacy-msghdr", CFH_SET, offsetof(MsgFormatOptions, flags), LP_STORE_LEGACY_MSGHDR }, { "store-raw-message", CFH_SET, offsetof(MsgFormatOptions, flags), LP_STORE_RAW_MESSAGE }, { "dont-store-legacy-msghdr", CFH_CLEAR, offsetof(MsgFormatOptions, flags), LP_STORE_LEGACY_MSGHDR }, { "expect-hostname", CFH_SET, offsetof(MsgFormatOptions, flags), LP_EXPECT_HOSTNAME }, { "no-hostname", CFH_CLEAR, offsetof(MsgFormatOptions, flags), LP_EXPECT_HOSTNAME }, { NULL }, }; gboolean msg_format_options_process_flag(MsgFormatOptions *options, gchar *flag) { return cfg_process_flag(msg_format_flag_handlers, options, flag); } syslog-ng-syslog-ng-3.13.2/lib/msg-format.h000066400000000000000000000071131321171025300204320ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MSG_FORMAT_H_INCLUDED #define MSG_FORMAT_H_INCLUDED #include "syslog-ng.h" #include "timeutils.h" #include "logproto/logproto-server.h" #include enum { /* don't parse the message, put everything into $MSG */ LP_NOPARSE = 0x0001, /* check if the hostname contains valid characters and assume it is part of the program field if it isn't */ LP_CHECK_HOSTNAME = 0x0002, /* message is using RFC5424 format */ LP_SYSLOG_PROTOCOL = 0x0004, /* the caller knows the message is valid UTF-8 */ LP_ASSUME_UTF8 = 0x0008, /* validate that all characters are indeed UTF-8 and mark the message as valid when relaying */ LP_VALIDATE_UTF8 = 0x0010, /* sanitize input and force it to be valid UTF-8 by escaping */ LP_SANITIZE_UTF8 = 0x0020, /* the message may not contain NL characters, strip them if it does */ LP_NO_MULTI_LINE = 0x0040, /* don't store MSGHDR in the LEGACY_MSGHDR macro */ LP_STORE_LEGACY_MSGHDR = 0x0080, /* expect a hostname field in the message */ LP_EXPECT_HOSTNAME = 0x0100, /* message is locally generated and should be marked with LF_LOCAL */ LP_LOCAL = 0x0200, /* for the date part of a message, only skip it, don't fully parse - recommended for keep_timestamp(no) */ LP_NO_PARSE_DATE = 0x0400, LP_STORE_RAW_MESSAGE = 0x0800, }; typedef struct _MsgFormatHandler MsgFormatHandler; typedef struct _MsgFormatOptions { gboolean initialized; gchar *format; MsgFormatHandler *format_handler; guint32 flags; guint16 default_pri; gchar *recv_time_zone; TimeZoneInfo *recv_time_zone_info; regex_t *bad_hostname; gint sdata_param_value_max; } MsgFormatOptions; struct _MsgFormatHandler { /* this method has a chance to change the LogProto related options to * match the requirements of the "format" in question. This is used by * the "pacct" plugin to set the record length the proper size */ LogProtoServer *(*construct_proto)(const MsgFormatOptions *options, LogTransport *transport, const LogProtoServerOptions *proto_options); void (*parse)(const MsgFormatOptions *options, const guchar *data, gsize length, LogMessage *msg); }; void msg_format_options_defaults(MsgFormatOptions *options); void msg_format_options_init(MsgFormatOptions *parse_options, GlobalConfig *cfg); void msg_format_options_destroy(MsgFormatOptions *parse_options); void msg_format_options_copy(MsgFormatOptions *options, const MsgFormatOptions *source); gboolean msg_format_options_process_flag(MsgFormatOptions *options, gchar *flag); void msg_format_inject_parse_error(LogMessage *msg, const guchar *data, gsize length, gint problem_position); #endif syslog-ng-syslog-ng-3.13.2/lib/parse-number.c000066400000000000000000000076111321171025300207540ustar00rootroot00000000000000/* * Copyright (c) 2013-2014 Balabit * Copyright (c) 2013 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "parse-number.h" #include #include #include static gboolean _valid_unit(const gchar unit_char) { return (unit_char == 'B' || unit_char == 'b'); } static gboolean _valid_exponent(const gchar exponent_char) { gchar e = exponent_char; return e == 'k' || e == 'K' || e == 'm' || e == 'M' || e == 'g' || e == 'G'; } static gboolean _parse_suffix(const gchar *suffix, gchar *exponent_char, gchar *base_char, gchar *unit_char) { gint suffix_len; suffix_len = strlen(suffix); if (suffix_len > 3) return FALSE; if (suffix_len == 0) return TRUE; if (suffix_len == 3) { *exponent_char = suffix[0]; *base_char = suffix[1]; *unit_char = suffix[2]; } else if (suffix_len == 2) { *exponent_char = suffix[0]; if (_valid_unit(suffix[1])) *unit_char = suffix[1]; else *base_char = suffix[1]; } else if (suffix_len == 1) { if (_valid_exponent(suffix[0])) *exponent_char = suffix[0]; else if (_valid_unit(suffix[0])) *unit_char = suffix[0]; else return FALSE; } return TRUE; } static gboolean _determine_multiplier(gchar base_char, gint *multiplier) { if (base_char == 0) *multiplier = 1000; else if (base_char == 'I' || base_char == 'i') *multiplier = 1024; else return FALSE; return TRUE; } static gboolean _validate_unit(gchar unit_char) { if (unit_char && !_valid_unit(unit_char)) return FALSE; return TRUE; } static gboolean _process_exponent(gchar exponent_char, gint64 *d, gint multiplier) { switch (exponent_char) { case 'G': case 'g': (*d) *= multiplier; case 'm': case 'M': (*d) *= multiplier; case 'K': case 'k': (*d) *= multiplier; case 0: return TRUE; default: return FALSE; } } static gboolean _process_suffix(const gchar *suffix, gint64 *d) { gchar exponent_char = 0, base_char = 0, unit_char = 0; gint multiplier = 0; if (!_parse_suffix(suffix, &exponent_char, &base_char, &unit_char)) return FALSE; if (!_determine_multiplier(base_char, &multiplier)) return FALSE; if (!_validate_unit(unit_char)) return FALSE; if (!_process_exponent(exponent_char, d, multiplier)) return FALSE; return TRUE; } static gboolean _parse_number(const gchar *s, gchar **endptr, gint64 *d) { gint64 val; errno = 0; val = strtoll(s, endptr, 0); if (errno == ERANGE || errno == EINVAL) return FALSE; if (*endptr == s) return FALSE; *d = val; return TRUE; } gboolean parse_number(const gchar *s, gint64 *d) { gchar *endptr; if (!_parse_number(s, &endptr, d)) return FALSE; if (*endptr) return FALSE; return TRUE; } gboolean parse_number_with_suffix(const gchar *s, gint64 *d) { gchar *endptr; if (!_parse_number(s, &endptr, d)) return FALSE; return _process_suffix(endptr, d); } syslog-ng-syslog-ng-3.13.2/lib/parse-number.h000066400000000000000000000023301321171025300207520ustar00rootroot00000000000000/* * Copyright (c) 2013-2014 Balabit * Copyright (c) 2013 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PARSE_NUMBER_H_INCLUDED #define PARSE_NUMBER_H_INCLUDED #include "syslog-ng.h" gboolean parse_number_with_suffix(const gchar *str, gint64 *result); gboolean parse_number(const gchar *str, gint64 *result); #endif syslog-ng-syslog-ng-3.13.2/lib/parser/000077500000000000000000000000001321171025300174775ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/parser/CMakeLists.txt000066400000000000000000000003071321171025300222370ustar00rootroot00000000000000set(PARSER_HEADERS parser/parser-expr.h parser/parser-expr-parser.h PARENT_SCOPE ) set(PARSER_SOURCES parser/parser-expr.c parser/parser-expr-parser.c PARENT_SCOPE ) syslog-ng-syslog-ng-3.13.2/lib/parser/Makefile.am000066400000000000000000000006661321171025300215430ustar00rootroot00000000000000parserincludedir = ${pkgincludedir}/parser parserinclude_HEADERS = \ lib/parser/parser-expr.h \ lib/parser/parser-expr-parser.h parser_sources = \ lib/parser/parser-expr.c \ lib/parser/parser-expr-parser.c \ lib/parser/parser-expr-grammar.y BUILT_SOURCES += \ lib/parser/parser-expr-grammar.y \ lib/parser/parser-expr-grammar.c \ lib/parser/parser-expr-grammar.h EXTRA_DIST += lib/parser/parser-expr-grammar.ym syslog-ng-syslog-ng-3.13.2/lib/parser/parser-expr-grammar.ym000066400000000000000000000046641321171025300237540ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code requires { #include "parser/parser-expr-parser.h" #include "cfg-tree.h" } %code { #include "syslog-names.h" #include "parser/parser-expr-grammar.h" #include "plugin.h" #include "cfg-grammar.h" } %name-prefix "parser_expr_" %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogExprNode **result} %parse-param {gpointer arg} %type parser_expr %type parser_expr_list /* INCLUDE_DECLS */ %% start : parser_expr_list { *result = $1; if (yychar != YYEMPTY) { cfg_lexer_unput_token(lexer, &yylval); } YYACCEPT; } ; parser_expr_list : parser_expr semicolons parser_expr_list { $$ = log_expr_node_append_tail(log_expr_node_new_pipe($1, &@1), $3); } | log_fork semicolons parser_expr_list { $$ = log_expr_node_append_tail($1, $3); } | { $$ = NULL; } ; parser_expr : LL_IDENTIFIER { Plugin *p; gint context = LL_CONTEXT_PARSER; p = cfg_find_plugin(configuration, context, $1); CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); last_parser = (LogParser *) cfg_parse_plugin(configuration, p, &@1, NULL); free($1); if (!last_parser) { YYERROR; } $$ = last_parser; } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/lib/parser/parser-expr-parser.c000066400000000000000000000032051321171025300234050ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "parser/parser-expr-parser.h" #include "parser/parser-expr.h" #include "parser/parser-expr-grammar.h" extern int parser_expr_debug; int parser_expr_parse(CfgLexer *lexer, LogExprNode **node, gpointer arg); static CfgLexerKeyword parser_expr_keywords[] = { { "file", KW_FILE }, { NULL } }; CfgParser parser_expr_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &parser_expr_debug, #endif .name = "parser expression", .context = LL_CONTEXT_PARSER, .keywords = parser_expr_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer)) parser_expr_parse, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(parser_expr_, LogExprNode **) syslog-ng-syslog-ng-3.13.2/lib/parser/parser-expr-parser.h000066400000000000000000000023401321171025300234110ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PARSER_EXPR_PARSER_H_INCLUDED #define PARSER_EXPR_PARSER_H_INCLUDED #include "cfg-parser.h" #include "parser/parser-expr.h" extern CfgParser parser_expr_parser; CFG_PARSER_DECLARE_LEXER_BINDING(parser_expr_, LogExprNode **) #endif syslog-ng-syslog-ng-3.13.2/lib/parser/parser-expr.c000066400000000000000000000105261321171025300221170ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "parser/parser-expr.h" #include "template/templates.h" #include "logmatcher.h" #include /* NOTE: consumes template */ void log_parser_set_template(LogParser *self, LogTemplate *template) { log_template_unref(self->template); self->template = template; } gboolean log_parser_process_message(LogParser *self, LogMessage **pmsg, const LogPathOptions *path_options) { LogMessage *msg = *pmsg; gboolean success; if (G_LIKELY(!self->template)) { NVTable *payload = nv_table_ref(msg->payload); const gchar *value; gssize value_len; /* NOTE: the process function may set values in the LogMessage * instance, which in turn can trigger nv_table_realloc() to be * called. However in case nv_table_realloc() finds a refcounter > 1, * it'll always _move_ the structure and leave the old one intact, * until its refcounter drops to zero. If that wouldn't be the case, * nv_table_realloc() could make our payload pointer and the * LM_V_MESSAGE pointer we pass to process() go stale. */ value = log_msg_get_value(msg, LM_V_MESSAGE, &value_len); success = self->process(self, pmsg, path_options, value, value_len); nv_table_unref(payload); } else { GString *input = g_string_sized_new(256); log_template_format(self->template, msg, NULL, LTZ_LOCAL, 0, NULL, input); success = self->process(self, pmsg, path_options, input->str, input->len); g_string_free(input, TRUE); } if (!success) stats_counter_inc(self->super.discarded_messages); return success; } static void log_parser_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { LogParser *self = (LogParser *) s; gboolean success; success = log_parser_process_message(self, &msg, path_options); msg_debug("Message parsing complete", evt_tag_int("result", success), evt_tag_str("rule", self->name), log_pipe_location_tag(s)); if (success) { log_pipe_forward_msg(s, msg, path_options); } else { if (path_options->matched) (*path_options->matched) = FALSE; log_msg_drop(msg, path_options, AT_PROCESSED); } } gboolean log_parser_init_method(LogPipe *s) { LogParser *self = (LogParser *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!self->name && s->expr_node) self->name = cfg_tree_get_rule_name(&cfg->tree, ENC_PARSER, s->expr_node); stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_PARSER, self->name, NULL ); stats_register_counter(1, &sc_key, SC_TYPE_DISCARDED, &self->super.discarded_messages); stats_unlock(); return TRUE; } void log_parser_free_method(LogPipe *s) { LogParser *self = (LogParser *) s; stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_PARSER, self->name, NULL ); stats_unregister_counter(&sc_key, SC_TYPE_DISCARDED, &self->super.discarded_messages); stats_unlock(); g_free(self->name); log_template_unref(self->template); log_pipe_free_method(s); } void log_parser_init_instance(LogParser *self, GlobalConfig *cfg) { log_pipe_init_instance(&self->super, cfg); self->super.init = log_parser_init_method; self->super.deinit = log_parser_deinit_method; self->super.free_fn = log_parser_free_method; self->super.queue = log_parser_queue; } syslog-ng-syslog-ng-3.13.2/lib/parser/parser-expr.h000066400000000000000000000044061321171025300221240ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGPARSER_H_INCLUDED #define LOGPARSER_H_INCLUDED #include "logmsg/logmsg.h" #include "messages.h" #include "logpipe.h" #include "template/templates.h" #include "stats/stats-registry.h" #include typedef struct _LogParser LogParser; struct _LogParser { LogPipe super; LogTemplate *template; gboolean (*process)(LogParser *s, LogMessage **pmsg, const LogPathOptions *path_options, const gchar *input, gsize input_len); gchar *name; }; static inline gboolean log_parser_deinit_method(LogPipe *s) { /* NOTE: placeholder for the future and to pair up with * log_parser_init_method(). There's no log_pipe_deinit_method() to call */ return TRUE; } gboolean log_parser_init_method(LogPipe *s); void log_parser_set_template(LogParser *self, LogTemplate *template); void log_parser_init_instance(LogParser *self, GlobalConfig *cfg); void log_parser_free_method(LogPipe *self); static inline gboolean log_parser_process(LogParser *self, LogMessage **pmsg, const LogPathOptions *path_options, const gchar *input, gssize input_len) { if (input_len < 0) input_len = strlen(input); return self->process(self, pmsg, path_options, input, input_len); } gboolean log_parser_process_message(LogParser *self, LogMessage **pmsg, const LogPathOptions *path_options); #endif syslog-ng-syslog-ng-3.13.2/lib/pathutils.c000066400000000000000000000046021321171025300203660ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 2013 Viktor Juhasz * Copyright (c) 2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "pathutils.h" #include #include gboolean is_file_directory(const char *filename) { return g_file_test(filename, G_FILE_TEST_EXISTS) && g_file_test(filename, G_FILE_TEST_IS_DIR); }; gboolean is_file_regular(const char *filename) { return g_file_test(filename, G_FILE_TEST_EXISTS) && g_file_test(filename, G_FILE_TEST_IS_REGULAR); }; gboolean is_file_device(const gchar *name) { struct stat st; if (stat(name, &st) >= 0) return S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode); else return FALSE; } gchar * find_file_in_path(const gchar *path, const gchar *filename, GFileTest test) { gchar **dirs; gchar *fullname = NULL; gint i; if (filename[0] == '/' || !path) { if (g_file_test(filename, test)) return g_strdup(filename); return NULL; } dirs = g_strsplit(path, G_SEARCHPATH_SEPARATOR_S, 0); i = 0; while (dirs && dirs[i]) { fullname = g_build_filename(dirs[i], filename, NULL); if (g_file_test(fullname, test)) break; g_free(fullname); fullname = NULL; i++; } g_strfreev(dirs); return fullname; } const gchar * get_filename_extension(const gchar *filename) { if (!filename) return NULL; const gchar *start_ext = strrchr(filename, '.'); if (!start_ext || start_ext[1] == '\0' || start_ext == filename) return NULL; return start_ext + 1; } syslog-ng-syslog-ng-3.13.2/lib/pathutils.h000066400000000000000000000025571321171025300204020ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 2013 Viktor Juhasz * Copyright (c) 2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef _PATHUTILS_H #define _PATHUTILS_H #include "syslog-ng.h" gboolean is_file_regular(const char *filename); gboolean is_file_directory(const char *filename); gboolean is_file_device(const gchar *name); gchar *find_file_in_path(const gchar *path, const gchar *filename, GFileTest test); const gchar* get_filename_extension(const gchar *filename); #endif syslog-ng-syslog-ng-3.13.2/lib/pe-versioning.h000066400000000000000000000017361321171025300211500ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ syslog-ng-syslog-ng-3.13.2/lib/persist-state.c000066400000000000000000000725561321171025300211750ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "persist-state.h" #include "serialize.h" #include "messages.h" #include "fdhelpers.h" #include #include #include #include #include #include typedef struct _PersistFileHeader { union { struct { /* should contain SLP4, everything is Big-Endian */ /* 64 bytes for file header */ gchar magic[4]; /* should be zero, any non-zero value is not supported and causes the state to be dropped */ guint32 flags; /* number of name-value keys in the file */ guint32 key_count; /* space reserved for additional information in the header */ gchar __reserved1[52]; /* initial key store where the first couple of NV keys are stored, sized to align the header to 4k boundary */ gchar initial_key_store[4032]; }; gchar __padding[4096]; }; } PersistFileHeader; #define PERSIST_FILE_INITIAL_SIZE 16384 #define PERSIST_STATE_KEY_BLOCK_SIZE 4096 /* * The syslog-ng persistent state is a set of name-value pairs, * updated atomically during syslog-ng runtime. When syslog-ng * initializes its configuration it allocates chunks of memory to * represent its own state which gets mmapped from a file. * * Whenever syslog-ng writes to the state memory, it gets atomically * written to the persistent file. * * Allocated blocks have a name in order to make it possible to fetch * the same state even between syslog-ng restarts. * * Thus PersistState has two memory areas to represent the information * - the key store containing names and the associated offset * information basically in a sequential file * - the state area containing the values * * When a new NV pair is registered, syslog-ng allocates the requested * area in the state, and writes a new record to the key store * file containing the name of the state entry and its length * information. If the same name is reused, it is appended to the * key store, never updated in-line. * * If syslog-ng crashes then both the state and the keystore should be * left where it was. The information processed the following way: * - the key store file is read into memory and a new key store file is * produced (to ensure that unused state entries are dropped) * - a new state file is produced, again unused data is dropped * * Old persist files can be converted the same way. * * We're using a trick to represent both areas in the same file: some * space is allocated initially for the key store and once that fills * up, syslog-ng allocates another key store area and chains these * areas up using a next pointer. * * Value blocks are prefixed with an 8 byte header, containing the * following information: * - block size (4 bytes) * - format version (1 byte) * - whether the block is in use (1 byte) * * Cleaning up: * ------------ * * It can be seen that no explicit deallocation is performed on the * persistent file, in effect it could grow indefinitely. There's a * simple cleanup procedure though: * * - on every startup, the persist file is rewritten, entries with an * in_use bit set are copied to the new one, with the in_use bit cleared * - whenever syslog-ng looks up (e.g. uses) an entry, its in_use bit is set again * * This way unused entries in the persist file are reaped when * syslog-ng restarts. * * Trusts: * ------- * * We don't trust the on-disk file when following a reference * (e.g. offset, or object size) however we do trust the internal hash * table built after validating the disk contents. This means that if * you look up a key in the hashtable you can use the returned offset * blindly without checking. However when reading the same value from * the file you need to check it whether it is inside the mapped file. * */ struct _PersistState { gint version; gchar *commited_filename; gchar *temp_filename; gint fd; gint mapped_counter; GMutex *mapped_lock; GCond *mapped_release_cond; guint32 current_size; guint32 current_ofs; gpointer current_map; PersistFileHeader *header; /* keys being used */ GHashTable *keys; PersistEntryHandle current_key_block; gint current_key_ofs; gint current_key_size; }; typedef struct _PersistEntry { PersistEntryHandle ofs; } PersistEntry; /* everything is big-endian */ typedef struct _PersistValueHeader { guint32 size; guint8 in_use; guint8 version; guint16 __padding; } PersistValueHeader; /* lowest layer, "store" functions manage the file on disk */ static void _wait_until_map_release(PersistState *self) { g_mutex_lock(self->mapped_lock); if (self->mapped_counter != 0) g_cond_wait(self->mapped_release_cond, self->mapped_lock); g_assert(self->mapped_counter == 0); } static gboolean _grow_store(PersistState *self, guint32 new_size) { int pgsize = getpagesize(); gboolean result = FALSE; _wait_until_map_release(self); if ((new_size & (pgsize-1)) != 0) { new_size = ((new_size / pgsize) + 1) * pgsize; } if (new_size > self->current_size) { gchar zero = 0; if (lseek(self->fd, new_size - 1, SEEK_SET) < 0) goto exit; if (write(self->fd, &zero, 1) != 1) goto exit; if (self->current_map) munmap(self->current_map, self->current_size); self->current_size = new_size; self->current_map = mmap(NULL, self->current_size, PROT_READ | PROT_WRITE, MAP_SHARED, self->fd, 0); if (self->current_map == MAP_FAILED) { self->current_map = NULL; goto exit; } self->header = (PersistFileHeader *) self->current_map; memcpy(&self->header->magic, "SLP4", 4); } result = TRUE; exit: g_mutex_unlock(self->mapped_lock); return result; } static gboolean _create_store(PersistState *self) { self->fd = open(self->temp_filename, O_RDWR | O_CREAT | O_TRUNC, 0600); if (self->fd < 0) { msg_error("Error creating persistent state file", evt_tag_str("filename", self->temp_filename), evt_tag_errno("error", errno)); return FALSE; } g_fd_set_cloexec(self->fd, TRUE); self->current_key_block = offsetof(PersistFileHeader, initial_key_store); self->current_key_ofs = 0; self->current_key_size = sizeof((((PersistFileHeader *) NULL))->initial_key_store); return _grow_store(self, PERSIST_FILE_INITIAL_SIZE); } static gboolean _commit_store(PersistState *self) { /* NOTE: we don't need to remap the file in case it is renamed */ return rename(self->temp_filename, self->commited_filename) >= 0; } /* "value" layer that handles memory block allocation in the file, without working with keys */ static PersistEntryHandle _alloc_value(PersistState *self, guint32 orig_size, gboolean in_use, guint8 version) { PersistEntryHandle result; PersistValueHeader *header; guint32 size = orig_size; /* round up size to 8 bytes boundary */ if ((size & 0x7)) size = ((size >> 3) + 1) << 3; if (self->current_ofs + size + sizeof(PersistValueHeader) > self->current_size) { if (!_grow_store(self, self->current_size + sizeof(PersistValueHeader) + size)) return 0; } result = self->current_ofs + sizeof(PersistValueHeader); /* fill value header */ header = (PersistValueHeader *) persist_state_map_entry(self, self->current_ofs); header->size = GUINT32_TO_BE(orig_size); header->in_use = in_use; header->version = version; persist_state_unmap_entry(self, self->current_ofs); self->current_ofs += size + sizeof(PersistValueHeader); return result; } static PersistValueHeader * _map_header_of_entry_from_handle(PersistState *self, PersistEntryHandle handle) { PersistValueHeader *header; if (handle > self->current_size) { msg_error("Corrupted handle in persist_state_lookup_entry, handle value too large", evt_tag_printf("handle", "%08x", handle)); return NULL; } header = (PersistValueHeader *) persist_state_map_entry(self, handle - sizeof(PersistValueHeader)); if (GUINT32_FROM_BE(header->size) + handle > self->current_size) { msg_error("Corrupted entry header found in persist_state_lookup_entry, size too large", evt_tag_printf("handle", "%08x", handle), evt_tag_int("size", GUINT32_FROM_BE(header->size)), evt_tag_int("file_size", self->current_size)); return NULL; } return header; } static void _free_value(PersistState *self, PersistEntryHandle handle) { if (handle) { PersistValueHeader *header; header = _map_header_of_entry_from_handle(self, handle); header->in_use = 0; persist_state_unmap_entry(self, handle); } } /* key management */ gboolean persist_state_lookup_key(PersistState *self, const gchar *key, PersistEntryHandle *handle) { PersistEntry *entry; entry = g_hash_table_lookup(self->keys, key); if (entry) { *handle = entry->ofs; return TRUE; } return FALSE; } gboolean persist_state_rename_entry(PersistState *self, const gchar *old_key, const gchar *new_key) { PersistEntry *entry; gpointer old_orig_key; if (g_hash_table_lookup_extended(self->keys, old_key, &old_orig_key, (gpointer *)&entry)) { if (g_hash_table_steal(self->keys, old_key)) { g_free(old_orig_key); g_hash_table_insert(self->keys, g_strdup(new_key), entry); return TRUE; } } return FALSE; } /* * NOTE: can only be called from the main thread (e.g. log_pipe_init/deinit). */ static gboolean _add_key(PersistState *self, const gchar *key, PersistEntryHandle handle) { PersistEntry *entry; gpointer key_area; gboolean new_block_created = FALSE; SerializeArchive *sa; g_assert(key[0] != 0); entry = g_new(PersistEntry, 1); entry->ofs = handle; g_hash_table_insert(self->keys, g_strdup(key), entry); /* we try to insert the key into the current block first, then if it doesn't fit, we create a new block */ while (1) { /* the size of the key block chain part, 4 byte for the empty string length, guint32 for the link to the next block */ guint32 chain_size = sizeof(guint32) + sizeof(guint32); gboolean success; key_area = persist_state_map_entry(self, self->current_key_block); /* we reserve space for the next area pointer */ sa = serialize_buffer_archive_new(key_area + self->current_key_ofs, self->current_key_size - self->current_key_ofs - chain_size); sa->silent = TRUE; success = serialize_write_cstring(sa, key, -1) && serialize_write_uint32(sa, handle); if (!success) { serialize_archive_free(sa); if (!new_block_created) { PersistEntryHandle new_block; /* we unmap the key_area as otherwise we can't grow because of the pending maps */ persist_state_unmap_entry(self, self->current_key_block); /* ah, we couldn't fit into the current block, create a new one and link it off the old one */ new_block = _alloc_value(self, PERSIST_STATE_KEY_BLOCK_SIZE, TRUE, 0); if (!new_block) { msg_error("Unable to allocate space in the persistent file for key store"); return FALSE; } key_area = persist_state_map_entry(self, self->current_key_block); sa = serialize_buffer_archive_new(key_area + self->current_key_ofs, self->current_key_size - self->current_key_ofs); if (!serialize_write_cstring(sa, "", 0) || !serialize_write_uint32(sa, new_block)) { /* hmmm. now this is bad, we couldn't write the tail of the block even though we always reserved space for it, this is a programming error somewhere in this function. */ g_assert_not_reached(); } serialize_archive_free(sa); persist_state_unmap_entry(self, self->current_key_block); self->current_key_block = new_block; self->current_key_size = PERSIST_STATE_KEY_BLOCK_SIZE; self->current_key_ofs = 0; new_block_created = TRUE; } else { /* if this happens, that means that the current key * entry won't fit even into a freshly initialized key * block, this means that the key is too large. */ msg_error("Persistent key too large, it cannot be larger than somewhat less than 4k", evt_tag_str("key", key)); persist_state_unmap_entry(self, self->current_key_block); return FALSE; } } else { self->header->key_count = GUINT32_TO_BE(GUINT32_FROM_BE(self->header->key_count) + 1); self->current_key_ofs += serialize_buffer_archive_get_pos(sa); serialize_archive_free(sa); persist_state_unmap_entry(self, self->current_key_block); return TRUE; } } g_assert_not_reached(); } /* process an on-disk persist file into the current one */ /* function to load v2 and v3 format persistent files */ static gboolean _load_v23(PersistState *self, gint version, SerializeArchive *sa) { gchar *key, *value; while (serialize_read_cstring(sa, &key, NULL)) { gsize len; guint32 str_len; if (key[0] && serialize_read_cstring(sa, &value, &len)) { gpointer new_block; PersistEntryHandle new_handle; /* add length of the string */ new_handle = _alloc_value(self, len + sizeof(str_len), FALSE, version); new_block = persist_state_map_entry(self, new_handle); /* NOTE: we add an extra length field to the old value, as our * persist_state_lookup_string() needs that. * persist_state_lookup_string is used to fetch disk queue file * names. It could have been solved somewhat better, but now it * doesn't justify a persist-state file format change. */ str_len = GUINT32_TO_BE(len); memcpy(new_block, &str_len, sizeof(str_len)); memcpy(new_block + sizeof(str_len), value, len); persist_state_unmap_entry(self, new_handle); /* add key to the current file */ _add_key(self, key, new_handle); g_free(value); g_free(key); } else { g_free(key); break; } } return TRUE; } static gboolean _load_v4(PersistState *self, gboolean load_all_entries) { gint fd; gint64 file_size; gpointer map; gpointer key_block; guint32 key_size; PersistFileHeader *header; gint key_count, i; fd = open(self->commited_filename, O_RDONLY); if (fd < 0) { /* no previous data found */ return TRUE; } file_size = lseek(fd, 0, SEEK_END); if (file_size > ((1LL << 31) - 1)) { msg_error("Persistent file too large", evt_tag_str("filename", self->commited_filename), evt_tag_printf("size", "%" G_GINT64_FORMAT, file_size)); return FALSE; } map = mmap(NULL, file_size, PROT_READ, MAP_SHARED, fd, 0); close(fd); if (map == MAP_FAILED) { msg_error("Error mapping persistent file into memory", evt_tag_str("filename", self->commited_filename), evt_tag_errno("error", errno)); return FALSE; } header = (PersistFileHeader *) map; key_block = ((gchar *) map) + offsetof(PersistFileHeader, initial_key_store); key_size = sizeof((((PersistFileHeader *) NULL))->initial_key_store); key_count = GUINT32_FROM_BE(header->key_count); i = 0; while (i < key_count) { gchar *name; guint32 entry_ofs, chain_ofs; SerializeArchive *sa; sa = serialize_buffer_archive_new(key_block, key_size); while (i < key_count) { if (!serialize_read_cstring(sa, &name, NULL)) { serialize_archive_free(sa); msg_error("Persistent file format error, unable to fetch key name"); goto free_and_exit; } if (name[0]) { if (serialize_read_uint32(sa, &entry_ofs)) { PersistValueHeader *value_header; i++; if (entry_ofs < sizeof(PersistFileHeader) || entry_ofs > file_size) { serialize_archive_free(sa); g_free(name); msg_error("Persistent file format error, entry offset is out of bounds"); goto free_and_exit; } value_header = (PersistValueHeader *) ((gchar *) map + entry_ofs - sizeof(PersistValueHeader)); if ((value_header->in_use) || load_all_entries) { gpointer new_block; PersistEntryHandle new_handle; new_handle = _alloc_value(self, GUINT32_FROM_BE(value_header->size), FALSE, value_header->version); new_block = persist_state_map_entry(self, new_handle); memcpy(new_block, value_header + 1, GUINT32_FROM_BE(value_header->size)); persist_state_unmap_entry(self, new_handle); /* add key to the current file */ _add_key(self, name, new_handle); } g_free(name); } else { /* bad format */ serialize_archive_free(sa); g_free(name); msg_error("Persistent file format error, unable to fetch key name"); goto free_and_exit; } } else { g_free(name); if (serialize_read_uint32(sa, &chain_ofs)) { /* end of block, chain to the next one */ if (chain_ofs == 0 || chain_ofs > file_size) { msg_error("Persistent file format error, key block chain offset is too large or zero", evt_tag_printf("key_block", "%08lx", (gulong) ((gchar *) key_block - (gchar *) map)), evt_tag_printf("key_size", "%d", key_size), evt_tag_int("ofs", chain_ofs)); serialize_archive_free(sa); goto free_and_exit; } key_block = ((gchar *) map) + chain_ofs; key_size = GUINT32_FROM_BE(*(guint32 *) (((gchar *) key_block) - sizeof(PersistValueHeader))); if (chain_ofs + key_size > file_size) { msg_error("Persistent file format error, key block size is too large", evt_tag_int("key_size", key_size)); serialize_archive_free(sa); goto free_and_exit; } break; } else { serialize_archive_free(sa); msg_error("Persistent file format error, unable to fetch chained key block offset"); goto free_and_exit; } } } serialize_archive_free(sa); } free_and_exit: munmap(map, file_size); return TRUE; } static gboolean _load(PersistState *self, gboolean all_errors_are_fatal, gboolean load_all_entries) { FILE *persist_file; gboolean success = FALSE; persist_file = fopen(self->commited_filename, "r"); if (persist_file) { SerializeArchive *sa; gchar magic[4]; gint version; sa = serialize_file_archive_new(persist_file); serialize_read_blob(sa, magic, 4); if (memcmp(magic, "SLP", 3) != 0) { msg_error("Persistent configuration file is in invalid format, ignoring"); success = all_errors_are_fatal ? FALSE : TRUE; goto close_and_exit; } version = magic[3] - '0'; if (version >= 2 && version <= 3) { success = _load_v23(self, version, sa); } else if (version == 4) { success = _load_v4(self, load_all_entries); } else { msg_error("Persistent configuration file has an unsupported major version, ignoring", evt_tag_int("version", version)); success = TRUE; } close_and_exit: fclose(persist_file); serialize_archive_free(sa); } else { if (all_errors_are_fatal) { msg_error("Failed to open persist file!", evt_tag_str("filename", self->commited_filename), evt_tag_str("error", strerror(errno))); success = FALSE; } else success = TRUE; } return success; } /** * All persistent data accesses must be guarded by a _map and _unmap * call in order to get a dereferencable pointer. It is not safe to * save this pointer for longer terms as the underlying mapping may * change when the file grows. * * Threading NOTE: this can be called from any kind of threads. * * NOTE: it is not safe to keep an entry mapped while synchronizing with the * main thread (e.g. mutexes, condvars, main_loop_call()), because * map_entry() may block the main thread in _grow_store(). **/ gpointer persist_state_map_entry(PersistState *self, PersistEntryHandle handle) { /* we count the number of mapped entries in order to know if we're * safe to remap the file region */ g_mutex_lock(self->mapped_lock); self->mapped_counter++; g_mutex_unlock(self->mapped_lock); return (gpointer) (((gchar *) self->current_map) + (guint32) handle); } /* * Threading NOTE: this can be called from any kind of threads. */ void persist_state_unmap_entry(PersistState *self, PersistEntryHandle handle) { g_mutex_lock(self->mapped_lock); g_assert(self->mapped_counter >= 1); self->mapped_counter--; if (self->mapped_counter == 0) { g_cond_signal(self->mapped_release_cond); } g_mutex_unlock(self->mapped_lock); } static PersistValueHeader * _map_header_of_entry(PersistState *self, const gchar *persist_name, PersistEntryHandle *handle) { if (!persist_state_lookup_key(self, persist_name, handle)) return NULL; return _map_header_of_entry_from_handle(self, *handle); } PersistEntryHandle persist_state_alloc_entry(PersistState *self, const gchar *persist_name, gsize alloc_size) { PersistEntryHandle handle; persist_state_remove_entry(self, persist_name); handle = _alloc_value(self, alloc_size, TRUE, self->version); if (!handle) return 0; if (!_add_key(self, persist_name, handle)) { _free_value(self, handle); return 0; } return handle; } PersistEntryHandle persist_state_lookup_entry(PersistState *self, const gchar *key, gsize *size, guint8 *version) { PersistEntryHandle handle; PersistValueHeader *header; header = _map_header_of_entry(self, key, &handle); if (header) { header->in_use = TRUE; *size = GUINT32_FROM_BE(header->size); *version = header->version; persist_state_unmap_entry(self, handle); return handle; } else return 0; } gboolean persist_state_remove_entry(PersistState *self, const gchar *key) { PersistEntryHandle handle; if (!persist_state_lookup_key(self, key, &handle)) return FALSE; _free_value(self, handle); return TRUE; } typedef struct _PersistStateKeysForeachData { PersistStateForeachFunc func; gpointer userdata; PersistState *storage; } PersistStateKeysForeachData; static void _foreach_entry_func(gpointer key, gpointer value, gpointer userdata) { PersistStateKeysForeachData *data = (PersistStateKeysForeachData *) userdata; PersistEntry *entry = (PersistEntry *) value; gchar *name = (gchar *) key; PersistValueHeader *header = persist_state_map_entry(data->storage, entry->ofs - sizeof(PersistValueHeader)); gint size = GUINT32_FROM_BE(header->size); persist_state_unmap_entry(data->storage, entry->ofs); gpointer *state = persist_state_map_entry(data->storage, entry->ofs); data->func(name, size, state, data->userdata); persist_state_unmap_entry(data->storage, entry->ofs); } void persist_state_foreach_entry(PersistState *self, PersistStateForeachFunc func, gpointer userdata) { PersistStateKeysForeachData data; data.func = func; data.userdata = userdata; data.storage = self; g_hash_table_foreach(self->keys, _foreach_entry_func, &data); } /* easier to use string based interface */ gchar * persist_state_lookup_string(PersistState *self, const gchar *key, gsize *length, guint8 *version) { PersistEntryHandle handle; gpointer block; SerializeArchive *sa; gchar *result; gsize result_len, size; guint8 result_version; gboolean success; if (!(handle = persist_state_lookup_entry(self, key, &size, &result_version))) return NULL; block = persist_state_map_entry(self, handle); sa = serialize_buffer_archive_new(block, size); success = serialize_read_cstring(sa, &result, &result_len); serialize_archive_free(sa); persist_state_unmap_entry(self, handle); if (!success) return NULL; if (length) *length = result_len; if (version) *version = result_version; return result; } void persist_state_alloc_string(PersistState *self, const gchar *persist_name, const gchar *value, gssize len) { PersistEntryHandle handle; SerializeArchive *sa; GString *buf; gboolean success; gpointer block; if (len < 0) len = strlen(value); buf = g_string_sized_new(len + 5); sa = serialize_string_archive_new(buf); success = serialize_write_cstring(sa, value, len); g_assert(success == TRUE); serialize_archive_free(sa); handle = persist_state_alloc_entry(self, persist_name, buf->len); block = persist_state_map_entry(self, handle); memcpy(block, buf->str, buf->len); persist_state_unmap_entry(self, handle); g_string_free(buf, TRUE); } const gchar * persist_state_get_filename(PersistState *self) { return self->commited_filename; } gboolean persist_state_start_dump(PersistState *self) { if (!_create_store(self)) return FALSE; if (!_load(self, TRUE, TRUE)) return FALSE; return TRUE; } gboolean persist_state_start_edit(PersistState *self) { if (!_create_store(self)) return FALSE; if (!_load(self, FALSE, TRUE)) return FALSE; return TRUE; } gboolean persist_state_start(PersistState *self) { if (!_create_store(self)) return FALSE; if (!_load(self, FALSE, FALSE)) return FALSE; return TRUE; } /* * This function commits the current store as the "persistent" file by * renaming the temp file we created to build the loaded * information. Once this function returns, then the current * persistent file will be visible to the next relaunch of syslog-ng, * even if we crashed. */ gboolean persist_state_commit(PersistState *self) { if (!_commit_store(self)) return FALSE; return TRUE; } static void _destroy(PersistState *self) { g_mutex_lock(self->mapped_lock); g_assert(self->mapped_counter == 0); g_mutex_unlock(self->mapped_lock); if (self->fd >= 0) close(self->fd); if (self->current_map) munmap(self->current_map, self->current_size); unlink(self->temp_filename); g_mutex_free(self->mapped_lock); g_cond_free(self->mapped_release_cond); g_free(self->temp_filename); g_free(self->commited_filename); g_hash_table_destroy(self->keys); } static void _init(PersistState *self, gchar *commited_filename, gchar *temp_filename) { self->keys = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); self->current_ofs = sizeof(PersistFileHeader); self->mapped_lock = g_mutex_new(); self->mapped_release_cond = g_cond_new(); self->version = 4; self->fd = -1; self->commited_filename = commited_filename; self->temp_filename = temp_filename; } /* * This routine should revert to the persist_state_new() state, * e.g. just like the PersistState object wasn't started yet. */ void persist_state_cancel(PersistState *self) { gchar *commited_filename, *temp_filename; commited_filename = g_strdup(self->commited_filename); temp_filename = g_strdup(self->temp_filename); _destroy(self); memset(self, 0, sizeof(*self)); _init(self, commited_filename, temp_filename); } PersistState * persist_state_new(const gchar *filename) { PersistState *self = g_new0(PersistState, 1); _init(self, g_strdup(filename), g_strdup_printf("%s-", filename)); return self; } void persist_state_free(PersistState *self) { _destroy(self); g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/persist-state.h000066400000000000000000000051651321171025300211720ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PERSIST_STATE_H_INCLUDED #define PERSIST_STATE_H_INCLUDED #include "syslog-ng.h" typedef struct _PersistState PersistState; typedef guint32 PersistEntryHandle; gpointer persist_state_map_entry(PersistState *self, PersistEntryHandle handle); void persist_state_unmap_entry(PersistState *self, PersistEntryHandle handle); PersistEntryHandle persist_state_alloc_entry(PersistState *self, const gchar *persist_name, gsize alloc_size); PersistEntryHandle persist_state_lookup_entry(PersistState *self, const gchar *persist_name, gsize *size, guint8 *version); gboolean persist_state_remove_entry(PersistState *self, const gchar *persist_name); gchar *persist_state_lookup_string(PersistState *self, const gchar *key, gsize *length, guint8 *version); gboolean persist_state_rename_entry(PersistState *self, const gchar *old_key, const gchar *new_key); void persist_state_alloc_string(PersistState *self, const gchar *persist_name, const gchar *value, gssize len); void persist_state_free_entry(PersistEntryHandle handle); typedef void (*PersistStateForeachFunc)(gchar* name, gint entry_size, gpointer entry, gpointer userdata); void persist_state_foreach_entry(PersistState *self, PersistStateForeachFunc func, gpointer userdata); gboolean persist_state_start(PersistState *self); gboolean persist_state_start_edit(PersistState *self); gboolean persist_state_start_dump(PersistState *self); const gchar *persist_state_get_filename(PersistState *self); gboolean persist_state_commit(PersistState *self); void persist_state_cancel(PersistState *self); PersistState *persist_state_new(const gchar *filename); void persist_state_free(PersistState *self); #endif syslog-ng-syslog-ng-3.13.2/lib/persistable-state-header.h000066400000000000000000000031031321171025300232320ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * Copyright (c) 2012-2013 Viktor Juhasz * Copyright (c) 2012-2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef _PERSISTABLE_STATE_HEADER_H #define _PERSISTABLE_STATE_HEADER_H typedef struct _PersistableStateHeader { guint8 version; /* this indicates that the members in the struct are stored in * big-endian byte order. if the byte ordering of the struct doesn't * match the current CPU byte ordering, then the members are * byte-swapped when the state is loaded. * * Every State structure must have it's own byte-order swapping function */ guint8 big_endian:1; } PersistableStateHeader; #endif syslog-ng-syslog-ng-3.13.2/lib/persistable-state-presenter.c000066400000000000000000000034551321171025300240160ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 2013 Viktor Juhasz * Copyright (c) 2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "persistable-state-presenter.h" #include "logmsg/logmsg.h" #include "str-format.h" static GHashTable *persist_state_storage = NULL; PersistableStatePresenterConstructFunc persistable_state_presenter_get_constructor_by_prefix(const gchar *prefix) { PersistableStatePresenterConstructFunc result = NULL; if (persist_state_storage) { result = g_hash_table_lookup(persist_state_storage, prefix); } return result; } void persistable_state_presenter_register_constructor(const gchar *prefix, PersistableStatePresenterConstructFunc handler) { if (!persist_state_storage) { persist_state_storage = g_hash_table_new(g_str_hash, g_str_equal); } g_hash_table_insert(persist_state_storage, (gpointer) prefix, handler); } syslog-ng-syslog-ng-3.13.2/lib/persistable-state-presenter.h000066400000000000000000000051551321171025300240220ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 2013 Viktor Juhasz * Copyright (c) 2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PERSISTABLE_STATE_PRESENTER_H_INCLUDED #define PERSISTABLE_STATE_PRESENTER_H_INCLUDED #include "syslog-ng.h" #include "persist-state.h" #include "presented-persistable-state.h" #include "persistable-state-header.h" struct _PersistableStatePresenter { gboolean (*dump)(PersistableStateHeader *state, PresentedPersistableState *representation); gboolean (*load)(PersistableStateHeader *state, PresentedPersistableState *representation); PersistEntryHandle (*alloc)(PersistState *state, const gchar *name); }; typedef struct _PersistableStatePresenter PersistableStatePresenter; static inline gboolean persistable_state_presenter_load(PersistableStatePresenter *self, PersistableStateHeader *state, PresentedPersistableState *representation) { g_assert(self->load != NULL); return self->load(state, representation); } static inline gboolean persistable_state_presenter_dump(PersistableStatePresenter *self, PersistableStateHeader *state, PresentedPersistableState *representation) { g_assert(self->dump != NULL); return self->dump(state, representation); } static inline PersistEntryHandle persistable_state_presenter_alloc(PersistableStatePresenter *self, PersistState *state, const gchar *name) { g_assert(self->alloc != NULL); return self->alloc(state, name); } typedef PersistableStatePresenter* (*PersistableStatePresenterConstructFunc)(const gchar *name); PersistableStatePresenterConstructFunc persistable_state_presenter_get_constructor_by_prefix(const gchar *prefix); void persistable_state_presenter_register_constructor(const gchar *prefix, PersistableStatePresenterConstructFunc handler); #endif syslog-ng-syslog-ng-3.13.2/lib/plugin-types.h000066400000000000000000000040001321171025300210060ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PLUGIN_TYPES_H_INCLUDED #define PLUGIN_TYPES_H_INCLUDED /* * Plugin types are defined by the configuration grammar (LL_CONTEXT_*) * tokens, but in order to avoid having to directly include cfg-grammar.h * (and for the ensuing WTF comments) define this headers to make it a bit * more visible that the reason for including that is the definition of * those tokens. * * In the future we might as well generate this header file, but for now we * simply poison the namespace with all bison generated macros, as no * practical issue has come up until now. */ #include "cfg-grammar.h" /* bitmask to cover non-context flags in the "plugin_type", e.g. * LL_CONTEXT_FLAG_* */ #define LL_CONTEXT_FLAGS 0xF00 /* indicates that a plugin is actually a generator, e.g. it is registered * as LL_CONTEXT_SOURCE but instead of running through the normal plugin * instantiation via Plugin->parse, let it generate a configuration snippet * that will be parsed normally. */ #define LL_CONTEXT_FLAG_GENERATOR 0x0100 #endif syslog-ng-syslog-ng-3.13.2/lib/plugin.c000066400000000000000000000501501321171025300176460ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "plugin.h" #include "plugin-types.h" #include "messages.h" #include "pathutils.h" #include "resolved-configurable-paths.h" #include #include #include #include #include #ifdef _AIX #define G_MODULE_SUFFIX "a" #endif static void plugin_candidate_set_module_name(PluginCandidate *self, const gchar *module_name) { g_free(self->module_name); self->module_name = g_strdup(module_name); } PluginCandidate * plugin_candidate_new(gint plugin_type, const gchar *name, const gchar *module_name) { PluginCandidate *self = g_new0(PluginCandidate, 1); self->super.type = plugin_type; self->super.name = g_strdup(name); self->module_name = g_strdup(module_name); self->super.failure_info.aux_data = NULL; return self; } void plugin_candidate_free(PluginCandidate *self) { g_free(self->super.name); g_free(self->module_name); g_free(self); } /* construct a plugin without having a configuration file to parse */ gpointer plugin_construct(Plugin *self) { g_assert(self->parser == NULL); if (self->construct) { return self->construct(self); } return NULL; } static gboolean _is_log_pipe(Plugin *self) { switch (self->type) { case LL_CONTEXT_SOURCE: case LL_CONTEXT_DESTINATION: case LL_CONTEXT_PARSER: case LL_CONTEXT_FILTER: case LL_CONTEXT_REWRITE: return TRUE; default: return FALSE; } } gpointer plugin_construct_from_config(Plugin *self, CfgLexer *lexer, gpointer arg) { gpointer instance = NULL; g_assert(self->construct == NULL); if (!cfg_parser_parse(self->parser, lexer, &instance, arg)) { cfg_parser_cleanup(self->parser, instance); return NULL; } if (_is_log_pipe(self)) { LogPipe *p = (LogPipe *)instance; p->plugin_name = g_strdup(self->name); if (self->failure_info.aux_data != NULL) p->init = self->failure_info.aux_data; } return instance; } /***************************************************************************** * Implementation of PluginContext *****************************************************************************/ static Plugin * plugin_find_in_list(GList *head, gint plugin_type, const gchar *plugin_name) { GList *p; Plugin *plugin; gint i; /* this function can only use the first two fields in plugin (type & * name), because it may be supplied a list of PluginCandidate * instances too */ for (p = head; p; p = g_list_next(p)) { plugin = p->data; if (plugin->type == plugin_type) { for (i = 0; plugin->name[i] && plugin_name[i]; i++) { if (plugin->name[i] != plugin_name[i] && !((plugin->name[i] == '-' || plugin->name[i] == '_') && (plugin_name[i] == '-' || plugin_name[i] == '_'))) { break; } } if (plugin_name[i] == 0 && plugin->name[i] == 0) return plugin; } } return NULL; } void plugin_register(PluginContext *context, Plugin *p, gint number) { gint i; for (i = 0; i < number; i++) { Plugin *existing_plugin; existing_plugin = plugin_find_in_list(context->plugins, p[i].type, p[i].name); if (existing_plugin) { msg_debug("Attempted to register the same plugin multiple times, dropping the old one", evt_tag_str("context", cfg_lexer_lookup_context_name_by_type(p[i].type)), evt_tag_str("name", p[i].name)); context->plugins = g_list_remove(context->plugins, existing_plugin); } context->plugins = g_list_prepend(context->plugins, &p[i]); } } Plugin * plugin_find(PluginContext *context, gint plugin_type, const gchar *plugin_name) { Plugin *p; PluginCandidate *candidate; /* try registered plugins first */ p = plugin_find_in_list(context->plugins, plugin_type, plugin_name); if (p) { return p; } candidate = (PluginCandidate *) plugin_find_in_list(context->candidate_plugins, plugin_type, plugin_name); if (!candidate) return NULL; /* try to autoload the module */ plugin_load_module(context, candidate->module_name, NULL); /* by this time it should've registered */ p = plugin_find_in_list(context->plugins, plugin_type, plugin_name); if (p) { p->failure_info.aux_data = candidate->super.failure_info.aux_data; return p; } else { msg_error("This module claims to support a plugin, which it didn't register after loading", evt_tag_str("module", candidate->module_name), evt_tag_str("context", cfg_lexer_lookup_context_name_by_type(plugin_type)), evt_tag_str("name", plugin_name)); } return NULL; } static ModuleInfo * plugin_get_module_info(GModule *mod) { ModuleInfo *module_info = NULL; if (mod && g_module_symbol(mod, "module_info", (gpointer *) &module_info)) return module_info; return NULL; } static gchar * plugin_get_module_init_name(const gchar *module_name) { gchar *module_init_func; gchar *p; module_init_func = g_strdup_printf("%s_module_init", module_name); for (p = module_init_func; *p; p++) { if ((*p) == '-') *p = '_'; } return module_init_func; } static GModule * plugin_dlopen_module_as_filename(const gchar *module_file_name, const gchar *module_name) { GModule *mod = NULL; msg_trace("Trying to open module", evt_tag_str("module", module_name), evt_tag_str("filename", module_file_name), NULL); mod = g_module_open(module_file_name, G_MODULE_BIND_LAZY); if (!mod) { msg_error("Error opening plugin module", evt_tag_str("module", module_name), evt_tag_str("error", g_module_error()), NULL); return NULL; } return mod; } static GModule * plugin_dlopen_module_as_dir_and_filename(const gchar *module_dir_name, const gchar *module_file_name, const gchar *module_name) { gchar *path; GModule *mod; path = g_build_path(G_DIR_SEPARATOR_S, module_dir_name, module_file_name, NULL); mod = plugin_dlopen_module_as_filename(path, module_name); g_free(path); return mod; } static GModule * plugin_dlopen_module_on_path(const gchar *module_name, const gchar *module_path) { gchar *plugin_module_name = NULL; gchar **module_path_dirs, *p, *dot; GModule *mod; gint i; module_path_dirs = g_strsplit(module_path ? : "", G_SEARCHPATH_SEPARATOR_S, 0); i = 0; while (module_path_dirs && module_path_dirs[i]) { plugin_module_name = g_module_build_path(module_path_dirs[i], module_name); if (is_file_regular(plugin_module_name)) break; /* also check if a libtool archive exists (for example in the build directory) */ #ifndef _AIX dot = strrchr(plugin_module_name, '.'); if (dot) { *dot = 0; p = g_strdup_printf("%s.la", plugin_module_name); g_free(plugin_module_name); plugin_module_name = p; } if (is_file_regular(plugin_module_name)) break; /* On AIX the modules in .a files */ #else dot = strrchr(plugin_module_name, '.'); if (dot) { *dot = 0; p = g_strdup_printf("%s.a", plugin_module_name); g_free(plugin_module_name); plugin_module_name = p; } if (is_file_regular(plugin_module_name)) break; #endif g_free(plugin_module_name); plugin_module_name = NULL; i++; } g_strfreev(module_path_dirs); if (!plugin_module_name) { msg_error("Plugin module not found in 'module-path'", evt_tag_str("module-path", module_path), evt_tag_str("module", module_name)); return NULL; } mod = plugin_dlopen_module_as_filename(plugin_module_name, module_name); g_free(plugin_module_name); return mod; } gboolean plugin_load_module(PluginContext *context, const gchar *module_name, CfgArgs *args) { GModule *mod; static GModule *main_module_handle; gboolean (*init_func)(PluginContext *context, CfgArgs *args); gchar *module_init_func; gboolean result; ModuleInfo *module_info; /* lookup in the main executable */ if (!main_module_handle) main_module_handle = g_module_open(NULL, 0); module_init_func = plugin_get_module_init_name(module_name); if (g_module_symbol(main_module_handle, module_init_func, (gpointer *) &init_func)) { /* already linked in, no need to load explicitly */ goto call_init; } /* try to load it from external .so */ mod = plugin_dlopen_module_on_path(module_name, context->module_path); if (!mod) { g_free(module_init_func); return FALSE; } g_module_make_resident(mod); module_info = plugin_get_module_info(mod); if (module_info->canonical_name) { g_free(module_init_func); module_init_func = plugin_get_module_init_name(module_info->canonical_name ? : module_name); } if (!g_module_symbol(mod, module_init_func, (gpointer *) &init_func)) { msg_error("Error finding init function in module", evt_tag_str("module", module_name), evt_tag_str("symbol", module_init_func), evt_tag_str("error", g_module_error())); g_free(module_init_func); return FALSE; } call_init: g_free(module_init_func); result = (*init_func)(context, args); if (result) msg_verbose("Module loaded and initialized successfully", evt_tag_str("module", module_name)); else msg_error("Module initialization failed", evt_tag_str("module", module_name)); return result; } /************************************************************ * Candidate modules ************************************************************/ static void _free_candidate_plugin_list(GList *candidate_plugins) { g_list_foreach(candidate_plugins, (GFunc) plugin_candidate_free, NULL); g_list_free(candidate_plugins); } /* This functions runs in a separate process during startup, thus we don't * really have a means to report errors, stderr may not be available. */ static void _enumerate_and_dump_plugin_info_in_modules(const gchar *module_path, int output_fd) { GModule *mod; gchar **mod_paths; gint i, j; FILE *discovery; discovery = fdopen(output_fd, "w"); if (!discovery) return; mod_paths = g_strsplit(module_path ? : "", G_SEARCHPATH_SEPARATOR_S, 0); for (i = 0; mod_paths[i]; i++) { GDir *dir; const gchar *fname; dir = g_dir_open(mod_paths[i], 0, NULL); if (!dir) continue; while ((fname = g_dir_read_name(dir))) { if (g_str_has_suffix(fname, G_MODULE_SUFFIX)) { gchar *module_name; ModuleInfo *module_info; const gchar *so_basename = fname; if (g_str_has_prefix(fname, "lib")) so_basename = fname + 3; module_name = g_strndup(so_basename, (gint) (strlen(so_basename) - strlen(G_MODULE_SUFFIX) - 1)); mod = plugin_dlopen_module_as_dir_and_filename(mod_paths[i], fname, module_name); module_info = plugin_get_module_info(mod); if (module_info) { for (j = 0; j < module_info->plugins_len; j++) { Plugin *plugin = &module_info->plugins[j]; fprintf(discovery, "%s %d %s\n", module_name, plugin->type, plugin->name); } } g_free(module_name); if (mod) g_module_close(mod); else mod = NULL; } } g_dir_close(dir); } g_strfreev(mod_paths); fclose(discovery); } static GList * _parse_and_load_plugin_info_in_modules(int input_fd) { FILE *discovery; GList *candidate_plugins = NULL; gchar module_name[4096]; gint plugin_type; gchar plugin_name[256]; discovery = fdopen(input_fd, "r"); if (!discovery) { msg_error("Error happened while opening plugin discovery output, fdopen() failed", evt_tag_errno("error", errno)); return NULL; } while (fscanf(discovery, "%4095s %d %255s\n", module_name, &plugin_type, plugin_name) == 3) { PluginCandidate *candidate_plugin; candidate_plugin = (PluginCandidate *) plugin_find_in_list(candidate_plugins, plugin_type, plugin_name); msg_debug("Registering candidate plugin", evt_tag_str("module", module_name), evt_tag_str("context", cfg_lexer_lookup_context_name_by_type(plugin_type)), evt_tag_str("name", plugin_name)); if (candidate_plugin) { msg_debug("Duplicate plugin candidate, overriding previous registration with the new one", evt_tag_str("old-module", candidate_plugin->module_name), evt_tag_str("new-module", module_name), evt_tag_str("context", cfg_lexer_lookup_context_name_by_type(plugin_type)), evt_tag_str("name", plugin_name)); plugin_candidate_set_module_name(candidate_plugin, module_name); } else { candidate_plugins = g_list_prepend(candidate_plugins, plugin_candidate_new(plugin_type, plugin_name, module_name)); } } if (!feof(discovery)) { msg_error("Error parsing the output of the discovery process, " "not all lines were consumed, this is an internal error."); } fclose(discovery); return candidate_plugins; } GList * plugin_discover_candidate_modules(const gchar *module_path) { pid_t discover_pid; int discover_pipe[2]; if (pipe(discover_pipe) < 0) { msg_error("Error creating pipe for discover process", evt_tag_errno("error", errno)); return NULL; } if ((discover_pid = fork()) < 0) { msg_error("Error creating discover process, fork() failed", evt_tag_errno("error", errno)); return NULL; } if (discover_pid == 0) { close(discover_pipe[0]); _enumerate_and_dump_plugin_info_in_modules(module_path, dup(discover_pipe[1])); close(discover_pipe[1]); _exit(0); } else { int exit_code; GList *candidate_modules; close(discover_pipe[1]); candidate_modules = _parse_and_load_plugin_info_in_modules(dup(discover_pipe[0])); close(discover_pipe[0]); if (waitpid(discover_pid, &exit_code, 0) < 0) { msg_error("Error waiting for discover process, waitpid() failed", evt_tag_errno("error", errno)); _free_candidate_plugin_list(candidate_modules); return NULL; } if (exit_code != 0) { msg_error("Error in discover process, exit code is not zero", evt_tag_int("exit_code", WEXITSTATUS(exit_code)), evt_tag_int("status", exit_code)); _free_candidate_plugin_list(candidate_modules); return NULL; } return candidate_modules; } } void plugin_load_candidate_modules(PluginContext *context) { if (context->candidate_plugins) return; context->candidate_plugins = plugin_discover_candidate_modules(context->module_path); } static void _free_plugin(Plugin *plugin, gpointer user_data) { if (plugin->free_fn) plugin->free_fn(plugin); } static void plugin_free_plugins(PluginContext *context) { g_list_foreach(context->plugins, (GFunc) _free_plugin, NULL); g_list_free(context->plugins); context->plugins = NULL; } void plugin_context_set_module_path(PluginContext *context, const gchar *module_path) { g_free(context->module_path); context->module_path = g_strdup(module_path); } void plugin_context_init_instance(PluginContext *context) { memset(context, 0, sizeof(*context)); plugin_context_set_module_path(context, resolvedConfigurablePaths.initial_module_path); } void plugin_context_deinit_instance(PluginContext *context) { plugin_free_plugins(context); _free_candidate_plugin_list(context->candidate_plugins); context->candidate_plugins = NULL; g_free(context->module_path); } /* global functions */ void plugin_list_modules(FILE *out, gboolean verbose) { GModule *mod; gchar **mod_paths; gint i, j, k; gboolean first = TRUE; mod_paths = g_strsplit(resolvedConfigurablePaths.initial_module_path, ":", 0); for (i = 0; mod_paths[i]; i++) { GDir *dir; const gchar *fname; dir = g_dir_open(mod_paths[i], 0, NULL); if (!dir) continue; while ((fname = g_dir_read_name(dir))) { if (g_str_has_suffix(fname, G_MODULE_SUFFIX)) { gchar *module_name; ModuleInfo *module_info; const gchar *so_basename = fname; if (g_str_has_prefix(fname, "lib")) so_basename = fname + 3; module_name = g_strndup(so_basename, (gint) (strlen(so_basename) - strlen(G_MODULE_SUFFIX) - 1)); mod = plugin_dlopen_module_as_dir_and_filename(mod_paths[i], fname, module_name); module_info = plugin_get_module_info(mod); if (verbose) { fprintf(out, "Module: %s\n", module_name); if (mod) { if (!module_info) { fprintf(out, "Status: Unable to resolve module_info variable, probably not a syslog-ng module\n"); } else { gchar **lines; fprintf(out, "Status: ok\n" "Version: %s\n" "Core-Revision: %s\n" "Description:\n", module_info->version, module_info->core_revision); lines = g_strsplit(module_info->description, "\n", 0); for (k = 0; lines[k]; k++) fprintf(out, " %s\n", lines[k][0] ? lines[k] : "."); g_strfreev(lines); fprintf(out, "Plugins:\n"); for (j = 0; j < module_info->plugins_len; j++) { Plugin *plugin = &module_info->plugins[j]; fprintf(out, " %-15s %s\n", cfg_lexer_lookup_context_name_by_type(plugin->type), plugin->name); } } } else { fprintf(out, "Status: Unable to dlopen shared object, probably not a syslog-ng module\n"); } fprintf(out, "\n"); } else if (module_info) { fprintf(out, "%s%s", first ? "" : ",", module_name); first = FALSE; } g_free(module_name); if (mod) g_module_close(mod); } } g_dir_close(dir); } g_strfreev(mod_paths); if (!verbose) fprintf(out, "\n"); } syslog-ng-syslog-ng-3.13.2/lib/plugin.h000066400000000000000000000072451321171025300176620ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PLUGIN_H_INCLUDED #define PLUGIN_H_INCLUDED #include "cfg-parser.h" typedef struct _PluginFailureInfo { gconstpointer aux_data; } PluginFailureInfo; typedef struct _PluginBase { /* NOTE: the start of this structure must match the Plugin struct, thus it has to be changed together with Plugin */ gint type; gchar *name; PluginFailureInfo failure_info; } PluginBase; typedef struct _PluginCandidate { PluginBase super; gchar *module_name; } PluginCandidate; /* A plugin actually registered by a module. See PluginCandidate in * the implementation module, which encapsulates a demand-loadable * plugin, not yet loaded. * * A plugin serves as the factory for an extension point (=plugin). In * contrast with the "module" which is the shared object itself which * registers plugins. Each module can register a number of plugins, * not just one. */ typedef struct _Plugin Plugin; struct _Plugin { /* NOTE: the first two fields must match PluginCandidate struct defined in the plugin.c module, please modify them both at the same time! */ gint type; const gchar *name; PluginFailureInfo failure_info; CfgParser *parser; gpointer (*construct)(Plugin *self); void (*free_fn)(Plugin *s); }; gpointer plugin_construct(Plugin *self); gpointer plugin_construct_from_config(Plugin *self, CfgLexer *lexer, gpointer arg); typedef struct _ModuleInfo ModuleInfo; struct _ModuleInfo { /* name of the module to be loaded as */ const gchar *canonical_name; /* version number if any */ const gchar *version; /* copyright information, homepage and other important information about the module */ const gchar *description; /* git sha that identifies the core revision that this was compiled for */ const gchar *core_revision; Plugin *plugins; gint plugins_len; /* the higher the better */ }; struct _PluginContext { GList *plugins; GList *candidate_plugins; gchar *module_path; }; /* instantiate a new plugin */ Plugin *plugin_find(PluginContext *context, gint plugin_type, const gchar *plugin_name); /* plugin side API */ PluginCandidate * plugin_candidate_new(gint plugin_type, const gchar *name, const gchar *module_name); void plugin_candidate_free(PluginCandidate *self); void plugin_register(PluginContext *context, Plugin *p, gint number); gboolean plugin_load_module(PluginContext *context, const gchar *module_name, CfgArgs *args); void plugin_list_modules(FILE *out, gboolean verbose); void plugin_load_candidate_modules(PluginContext *context); void plugin_context_set_module_path(PluginContext *context, const gchar *module_path); void plugin_context_init_instance(PluginContext *context); void plugin_context_deinit_instance(PluginContext *context); #endif syslog-ng-syslog-ng-3.13.2/lib/poll-events.c000066400000000000000000000026341321171025300206240ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "poll-events.h" void poll_events_invoke_callback(PollEvents *self) { self->callback(self->callback_data); } void poll_events_set_callback(PollEvents *self, PollCallback callback, gpointer user_data) { self->callback = callback; self->callback_data = user_data; } void poll_events_init(PollEvents *self) { } void poll_events_free(PollEvents *self) { if (self->free_fn) self->free_fn(self); g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/poll-events.h000066400000000000000000000041231321171025300206240ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef POLL_EVENTS_H_INCLUDED #define POLL_EVENTS_H_INCLUDED #include "syslog-ng.h" typedef struct _PollEvents PollEvents; typedef void (*PollCallback)(gpointer user_data); struct _PollEvents { PollCallback callback; gpointer callback_data; void (*start_watches)(PollEvents *self); void (*stop_watches)(PollEvents *self); void (*update_watches)(PollEvents *self, GIOCondition cond); void (*free_fn)(PollEvents *self); }; static inline void poll_events_start_watches(PollEvents *self) { if (self->start_watches) self->start_watches(self); } static inline void poll_events_stop_watches(PollEvents *self) { self->stop_watches(self); } static inline void poll_events_update_watches(PollEvents *self, GIOCondition cond) { self->update_watches(self, cond); } static inline void poll_events_suspend_watches(PollEvents *self) { poll_events_update_watches(self, 0); } void poll_events_invoke_callback(PollEvents *self); void poll_events_set_callback(PollEvents *self, PollCallback callback, gpointer user_data); void poll_events_init(PollEvents *self); void poll_events_free(PollEvents *self); #endif syslog-ng-syslog-ng-3.13.2/lib/poll-fd-events.c000066400000000000000000000050141321171025300212060ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "poll-fd-events.h" #include typedef struct _PollFdEvents { PollEvents super; struct iv_fd fd_watch; } PollFdEvents; #define IV_FD_CALLBACK(x) ((void (*)(void *)) (x)) static void poll_fd_events_start_watches(PollEvents *s) { PollFdEvents *self = (PollFdEvents *) s; iv_fd_register(&self->fd_watch); } static void poll_fd_events_stop_watches(PollEvents *s) { PollFdEvents *self = (PollFdEvents *) s; if (iv_fd_registered(&self->fd_watch)) iv_fd_unregister(&self->fd_watch); } static void poll_fd_events_update_watches(PollEvents *s, GIOCondition cond) { PollFdEvents *self = (PollFdEvents *) s; if (cond & G_IO_IN) iv_fd_set_handler_in(&self->fd_watch, IV_FD_CALLBACK(poll_events_invoke_callback)); else iv_fd_set_handler_in(&self->fd_watch, NULL); if (cond & G_IO_OUT) iv_fd_set_handler_out(&self->fd_watch, IV_FD_CALLBACK(poll_events_invoke_callback)); else iv_fd_set_handler_out(&self->fd_watch, NULL); if (cond & (G_IO_IN + G_IO_OUT)) iv_fd_set_handler_err(&self->fd_watch, IV_FD_CALLBACK(poll_events_invoke_callback)); else iv_fd_set_handler_err(&self->fd_watch, NULL); } PollEvents * poll_fd_events_new(gint fd) { PollFdEvents *self = g_new0(PollFdEvents, 1); g_assert(fd >= 0); self->super.start_watches = poll_fd_events_start_watches; self->super.stop_watches = poll_fd_events_stop_watches; self->super.update_watches = poll_fd_events_update_watches; IV_FD_INIT(&self->fd_watch); self->fd_watch.fd = fd; self->fd_watch.cookie = self; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/poll-fd-events.h000066400000000000000000000021741321171025300212170ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef POLL_FD_EVENTS_H_INCLUDED #define POLL_FD_EVENTS_H_INCLUDED #include "poll-events.h" PollEvents *poll_fd_events_new(gint fd); #endif syslog-ng-syslog-ng-3.13.2/lib/pragma-grammar.ym000066400000000000000000000063721321171025300214550ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code requires { #include "pragma-parser.h" #include "plugin.h" #include "cfg.h" #include "messages.h" #include } %name-prefix "pragma_" %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {gpointer *result} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_VERSION %token KW_DEFINE %token KW_MODULE %code { #include CfgArgs *last_module_args = NULL; gint __process_version_string(gchar *value) { gchar *p, *end; gint major, minor; p = strchr(value, '.'); if (p) { major = strtol(value, &end, 10); if (end == p) { minor = strtol(p+1, &end, 10); if (end) { return (major << 8) + minor; } } } return 0; } } %% start : { lexer->tokenize_eol++; } stmt_and_eol { lexer->tokenize_eol--; if (yychar != YYEMPTY) { cfg_lexer_unput_token(lexer, &yylval); } YYACCEPT; } stmt_and_eol : pragma_stmt LL_EOL | include_stmt ; pragma_stmt : KW_VERSION ':' string_or_number { configuration->parsed_version = __process_version_string($3); free($3); } | define_stmt | module_stmt ; include_stmt : KW_INCLUDE string LL_EOL { CHECK_ERROR(cfg_lexer_include_file(lexer, $2), @2, "Error including %s", $2); free($2); } ; define_stmt : KW_DEFINE LL_IDENTIFIER string_or_number { msg_debug("Global value changed", evt_tag_str("define", $2), evt_tag_str("value", $3)); cfg_args_set(configuration->globals, $2, $3); free($2); free($3); } module_stmt : KW_MODULE string { last_module_args = cfg_args_new(); } module_params { plugin_load_module(&configuration->plugin_context, $2, last_module_args); free($2); cfg_args_unref(last_module_args); last_module_args = NULL; } ; module_params : module_param module_params | ; module_param : LL_IDENTIFIER '(' string_or_number ')' { cfg_args_set(last_module_args, $1, $3); free($1); free($3); } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/lib/pragma-parser.c000066400000000000000000000031621321171025300211120ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "pragma-parser.h" #include "pragma-grammar.h" extern int pragma_debug; int pragma_parse(CfgLexer *lexer, gpointer *result, gpointer arg); static CfgLexerKeyword pragma_keywords[] = { { "version", KW_VERSION, }, { "include", KW_INCLUDE, }, { "module", KW_MODULE, }, { "define", KW_DEFINE, }, { CFG_KEYWORD_STOP }, }; CfgParser pragma_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &pragma_debug, #endif .name = "pragma", .context = LL_CONTEXT_PRAGMA, .keywords = pragma_keywords, .parse = pragma_parse, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(pragma_, gpointer *) syslog-ng-syslog-ng-3.13.2/lib/pragma-parser.h000066400000000000000000000022501321171025300211140ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PRAGMA_PARSER_H_INCLUDED #define PRAGMA_PARSER_H_INCLUDED #include "cfg-parser.h" extern CfgParser pragma_parser; CFG_PARSER_DECLARE_LEXER_BINDING(pragma_, gpointer *) #endif syslog-ng-syslog-ng-3.13.2/lib/presented-persistable-state.h000066400000000000000000000074761321171025300240140ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 2013 Viktor Juhasz * Copyright (c) 2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PRESENTED_PERSISTABLE_STATE_H_INCLUDED #define PRESENTED_PERSISTABLE_STATE_H_INCLUDED #include "syslog-ng.h" typedef struct _PresentedPersistableState PresentedPersistableState; struct _PresentedPersistableState { void (*add_string)(PresentedPersistableState *self, gchar* name, gchar* value); void (*add_boolean)(PresentedPersistableState *self, gchar* name, gboolean value); void (*add_int64)(PresentedPersistableState *self, gchar *name, gint64 value); void (*add_int)(PresentedPersistableState *self, gchar *name, gint value); const gchar* (*get_string)(PresentedPersistableState *self, gchar *name); gboolean (*get_boolean)(PresentedPersistableState *self, gchar *name); gint (*get_int)(PresentedPersistableState *self, gchar *name); gint64 (*get_int64)(PresentedPersistableState *self, gchar *name); void (*foreach)(PresentedPersistableState *self, void (callback)(gchar *name, const gchar *value, gpointer user_data), gpointer user_data); gboolean (*does_name_exist)(PresentedPersistableState *self, gchar *name); void (*free)(PresentedPersistableState *self); }; static inline void presented_persistable_state_add_string(PresentedPersistableState *self, gchar *name, gchar *value) { self->add_string(self, name, value); } static inline void presented_persistable_state_add_boolean(PresentedPersistableState *self, gchar *name, gboolean value) { self->add_boolean(self, name, value); } static inline void presented_persistable_state_add_int(PresentedPersistableState *self, gchar *name, gint value) { self->add_int(self, name, value); } static inline void presented_persistable_state_add_int64(PresentedPersistableState *self, gchar *name, gint64 value) { self->add_int64(self, name, value); } static inline const gchar * presented_persistable_state_get_string(PresentedPersistableState *self, gchar *name) { return self->get_string(self, name); } static inline gboolean presented_persistable_state_get_boolean(PresentedPersistableState *self, gchar *name) { return self->get_boolean(self, name); } static inline gint presented_persistable_state_get_int(PresentedPersistableState *self, gchar *name) { return self->get_int(self, name); } static inline gint64 presented_persistable_state_get_int64(PresentedPersistableState *self, gchar *name) { return self->get_int64(self, name); } static inline void presented_persistable_state_foreach(PresentedPersistableState *self, void (callback)(gchar *name, const gchar *value, gpointer user_data), gpointer user_data) { self->foreach(self, callback, user_data); } static inline gboolean presented_persistable_state_does_name_exist(PresentedPersistableState *self, gchar *name) { return self->does_name_exist(self, name); } static inline void presented_persistable_state_free(PresentedPersistableState *self) { self->free(self); } #endif syslog-ng-syslog-ng-3.13.2/lib/rcptid.c000066400000000000000000000104371321171025300176410ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 2013 Viktor Juhasz * Copyright (c) 2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "rcptid.h" #include "messages.h" #include "str-format.h" static struct _RcptidService { PersistState *persist_state; PersistEntryHandle persist_handle; GStaticMutex lock; } rcptid_service = { .lock = G_STATIC_MUTEX_INIT }; /* NOTE: RcptIdInstance is a singleton, so we don't pass self around as an argument */ #define self (&rcpt_instance) static RcptidState * rcptid_map_state(void) { return (RcptidState *) persist_state_map_entry(rcptid_service.persist_state, rcptid_service.persist_handle); } static void rcptid_unmap_state(void) { persist_state_unmap_entry(rcptid_service.persist_state, rcptid_service.persist_handle); } static gboolean rcptid_is_initialized(void) { return rcptid_service.persist_state != NULL; } static gboolean rcptid_restore_entry(void) { RcptidState *data = rcptid_map_state(); if (data->header.version > 0) { msg_error("Internal error restoring log reader state, stored data is too new", evt_tag_int("version", data->header.version)); return FALSE; } if ((data->header.big_endian && G_BYTE_ORDER == G_LITTLE_ENDIAN) || (!data->header.big_endian && G_BYTE_ORDER == G_BIG_ENDIAN)) { data->header.big_endian = !data->header.big_endian; data->g_rcptid = GUINT64_SWAP_LE_BE(data->g_rcptid); } rcptid_unmap_state(); return TRUE; } static gboolean rcptid_create_new_entry(void) { RcptidState *data; rcptid_service.persist_handle = persist_state_alloc_entry(rcptid_service.persist_state, "next.rcptid", sizeof(RcptidState)); if (!rcptid_service.persist_handle) { msg_error("Error allocating RCPTID structure in persist-state"); return FALSE; } data = rcptid_map_state(); data->header.version = 0; data->header.big_endian = (G_BYTE_ORDER == G_BIG_ENDIAN); data->g_rcptid = 1; rcptid_unmap_state(); return TRUE; } void rcptid_append_formatted_id(GString *result, guint64 rcptid) { if (rcptid) { format_uint64_padded(result, 0, 0, 10, rcptid); } } void rcptid_set_id(guint64 id) { RcptidState *data; if (!rcptid_is_initialized()) return; g_static_mutex_lock(&rcptid_service.lock); data = rcptid_map_state(); data->g_rcptid = id; rcptid_unmap_state(); g_static_mutex_unlock(&rcptid_service.lock); } guint64 rcptid_generate_id(void) { RcptidState *data; guint64 new_id; if (!rcptid_is_initialized()) return 0; g_static_mutex_lock(&rcptid_service.lock); data = rcptid_map_state(); new_id = data->g_rcptid++; if (data->g_rcptid == 0) data->g_rcptid = 1; rcptid_unmap_state(); g_static_mutex_unlock(&rcptid_service.lock); return new_id; } /*restore RCTPID from persist file, if possible, else create new enrty point with "next.rcptid" name*/ gboolean rcptid_init(PersistState *state, gboolean use_rcptid) { gsize size; guint8 version; g_assert(rcptid_service.persist_state == NULL); if (!use_rcptid) return TRUE; rcptid_service.persist_state = state; rcptid_service.persist_handle = persist_state_lookup_entry(state, "next.rcptid", &size, &version); if (rcptid_service.persist_handle) return rcptid_restore_entry(); else return rcptid_create_new_entry(); } void rcptid_deinit(void) { rcptid_service.persist_state = NULL; } syslog-ng-syslog-ng-3.13.2/lib/rcptid.h000066400000000000000000000027151321171025300176460ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 2013 Viktor Juhasz * Copyright (c) 2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef _RCPTID_H #define _RCPTID_H #include "syslog-ng.h" #include "persist-state.h" #include "persistable-state-header.h" typedef struct _RcptidState { PersistableStateHeader header; guint64 g_rcptid; } RcptidState; void rcptid_set_id(guint64 id); guint64 rcptid_generate_id(void); void rcptid_append_formatted_id(GString *result, guint64 rcptid); gboolean rcptid_init(PersistState *state, gboolean use_rcptid); void rcptid_deinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/reloc.c000066400000000000000000000125361321171025300174620ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "reloc.h" #include "cache.h" #include #include #include #include #include Cache *path_cache; typedef struct _PathResolver { CacheResolver super; GHashTable *configure_variables; } PathResolver; void path_resolver_add_configure_variable(CacheResolver *s, const gchar *name, const gchar *value) { PathResolver *self = (PathResolver *) s; g_hash_table_insert(self->configure_variables, g_strdup(name), g_strdup(value)); } static void path_resolver_populate_configure_variables(PathResolver *self, const gchar *sysprefix) { path_resolver_add_configure_variable(&self->super, "${prefix}", sysprefix); path_resolver_add_configure_variable(&self->super, "${exec_prefix}", SYSLOG_NG_PATH_EXECPREFIX); path_resolver_add_configure_variable(&self->super, "${libexecdir}", SYSLOG_NG_PATH_LIBEXECDIR); path_resolver_add_configure_variable(&self->super, "${datarootdir}", SYSLOG_NG_PATH_DATAROOTDIR); path_resolver_add_configure_variable(&self->super, "${datadir}", SYSLOG_NG_PATH_DATADIR); path_resolver_add_configure_variable(&self->super, "${localstatedir}", SYSLOG_NG_PATH_LOCALSTATEDIR); } /* NOTE: we really don't have an easy way to handle errors, as installation * paths are resolved quite early while syslog-ng starts up. The best is to * abort, as an error is either a problem in the configure variables OR a * coding mistake. For now, we desperately try to write an error message to * stderr and then abort the process. */ #define handle_fatal_error(fmt, ...) \ do { \ fprintf(stderr, fmt, __VA_ARGS__); \ g_assert_not_reached(); \ } while (0) gpointer path_resolver_resolve(CacheResolver *s, const gchar *orig) { PathResolver *self = (PathResolver *) s; gchar *subst_start = NULL; gchar *subst_end = NULL; gchar *new_value, *prefix, *suffix, *replacement, *value; gchar *confvar; gint prefix_len, confvar_len; /* Find variable enclosed within ${...}, replace with the value in * configure_variables. Repeat until no more substitutions can be made. * */ value = g_strdup(orig); subst_start = strstr(value, "${"); while (subst_start != NULL) { prefix = NULL; prefix_len = 0; suffix = NULL; subst_end = strchr(subst_start, '}'); if (subst_end == NULL) handle_fatal_error("Relocation resolution error: missing '}' in string '%s'. Please re-compile syslog-ng with proper path variables.\n", value); /* extract confvar */ confvar_len = (subst_end + 1) - subst_start; confvar = g_strndup(subst_start, confvar_len); /* lookup replacement */ replacement = g_hash_table_lookup(self->configure_variables, confvar); if (replacement == NULL) handle_fatal_error("Relocation resolution error: Unknown configure variable: '%s' in string '%s'.\nPlease re-compile syslog-ng with proper path variables.\n", confvar, value); g_free(confvar); /* replace confvar with replacement */ suffix = (subst_end + 1); prefix_len = subst_start - value; prefix = g_strndup(value, prefix_len); /* construct the new value */ new_value = g_strconcat(prefix, replacement, suffix, NULL); g_free(prefix); /* commit the new value */ g_free(value); value = new_value; subst_start = strstr(value, "${"); } return value; } static void path_resolver_free(CacheResolver *s) { PathResolver *self = (PathResolver *) s; g_hash_table_unref(self->configure_variables); } CacheResolver * path_resolver_new(const gchar *sysprefix) { PathResolver *self = g_new0(PathResolver, 1); self->super.resolve_elem = path_resolver_resolve; self->super.free_elem = g_free; self->super.free_fn = path_resolver_free; self->configure_variables = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); path_resolver_populate_configure_variables(self, sysprefix); return &self->super; } static gchar * lookup_sysprefix(void) { gchar *v; v = getenv("SYSLOGNG_PREFIX"); if (v) return v; return SYSLOG_NG_PATH_PREFIX; } const gchar * get_installation_path_for(const gchar *template) { if (!path_cache) path_cache = cache_new(path_resolver_new(lookup_sysprefix())); return cache_lookup(path_cache, template); } void reloc_deinit(void) { if (path_cache) { cache_free(path_cache); path_cache = NULL; } } syslog-ng-syslog-ng-3.13.2/lib/reloc.h000066400000000000000000000024401321171025300174600ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef RELOC_H_INCLUDED #define RELOC_H_INCLUDED #include "syslog-ng.h" #include "cache.h" void path_resolver_add_configure_variable(CacheResolver *self, const gchar *name, const gchar *value); CacheResolver *path_resolver_new(const gchar *sysprefix); const gchar *get_installation_path_for(const gchar *template); void reloc_deinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/resolved-configurable-paths.c000066400000000000000000000030171321171025300237460ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * Copyright (c) 2016 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "resolved-configurable-paths.h" #include "reloc.h" ResolvedConfigurablePaths resolvedConfigurablePaths; void resolved_configurable_paths_init(ResolvedConfigurablePaths *self) { resolvedConfigurablePaths.cfgfilename = get_installation_path_for(PATH_SYSLOG_NG_CONF); resolvedConfigurablePaths.persist_file = get_installation_path_for(PATH_PERSIST_CONFIG); resolvedConfigurablePaths.ctlfilename = get_installation_path_for(PATH_CONTROL_SOCKET); resolvedConfigurablePaths.initial_module_path = get_installation_path_for(SYSLOG_NG_MODULE_PATH); } syslog-ng-syslog-ng-3.13.2/lib/resolved-configurable-paths.h000066400000000000000000000026401321171025300237540ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * Copyright (c) 2016 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef RESOLVED_CONFIGURABLE_PATHS_H_INCLUDED #define RESOLVED_CONFIGURABLE_PATHS_H_INCLUDED #include typedef struct _ResolvedConfigurablePaths { const gchar *cfgfilename; const gchar *persist_file; const gchar *ctlfilename; const gchar *initial_module_path; } ResolvedConfigurablePaths; extern ResolvedConfigurablePaths resolvedConfigurablePaths; void resolved_configurable_paths_init(ResolvedConfigurablePaths *self); #endif syslog-ng-syslog-ng-3.13.2/lib/rewrite/000077500000000000000000000000001321171025300176645ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/rewrite/CMakeLists.txt000066400000000000000000000007571321171025300224350ustar00rootroot00000000000000set(REWRITE_HEADERS rewrite/rewrite-expr.h rewrite/rewrite-set-tag.h rewrite/rewrite-set.h rewrite/rewrite-subst.h rewrite/rewrite-expr-parser.h rewrite/rewrite-groupset.h rewrite/rewrite-unset.h PARENT_SCOPE ) set(REWRITE_SOURCES rewrite/rewrite-expr.c rewrite/rewrite-set-tag.c rewrite/rewrite-set.c rewrite/rewrite-subst.c rewrite/rewrite-expr-parser.c rewrite/rewrite-groupset.c rewrite/rewrite-unset.c PARENT_SCOPE ) syslog-ng-syslog-ng-3.13.2/lib/rewrite/Makefile.am000066400000000000000000000014731321171025300217250ustar00rootroot00000000000000rewriteincludedir = ${pkgincludedir}/rewrite rewriteinclude_HEADERS = \ lib/rewrite/rewrite-expr.h \ lib/rewrite/rewrite-set-tag.h \ lib/rewrite/rewrite-set.h \ lib/rewrite/rewrite-unset.h \ lib/rewrite/rewrite-subst.h \ lib/rewrite/rewrite-expr-parser.h \ lib/rewrite/rewrite-groupset.h rewrite_sources = \ lib/rewrite/rewrite-expr.c \ lib/rewrite/rewrite-set-tag.c \ lib/rewrite/rewrite-set.c \ lib/rewrite/rewrite-unset.c \ lib/rewrite/rewrite-subst.c \ lib/rewrite/rewrite-expr-parser.c \ lib/rewrite/rewrite-expr-grammar.y \ lib/rewrite/rewrite-groupset.c BUILT_SOURCES += \ lib/rewrite/rewrite-expr-grammar.y \ lib/rewrite/rewrite-expr-grammar.c \ lib/rewrite/rewrite-expr-grammar.h EXTRA_DIST += lib/rewrite/rewrite-expr-grammar.ym include lib/rewrite/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-expr-grammar.ym000066400000000000000000000152711321171025300243220ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code requires { #include "rewrite/rewrite-expr-parser.h" } %code { #include "rewrite/rewrite-expr-grammar.h" #include "rewrite/rewrite-set-tag.h" #include "rewrite/rewrite-set.h" #include "rewrite/rewrite-unset.h" #include "rewrite/rewrite-subst.h" #include "rewrite/rewrite-groupset.h" #include "filter/filter-expr.h" #include "filter/filter-expr-parser.h" #include "cfg-grammar.h" #include "syslog-names.h" #include "plugin.h" #include LogRewrite *last_rewrite; } %name-prefix "rewrite_expr_" %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogExprNode **result} %parse-param {gpointer arg} %type rewrite_expr %type rewrite_expr_list %type rewrite_template_content /* INCLUDE_DECLS */ %token KW_CONDITION %token KW_SET_TAG %token KW_CLEAR_TAG %token KW_GROUP_SET %token KW_GROUP_UNSET %token KW_SET %token KW_UNSET %token KW_SUBST %token KW_VALUE %token KW_VALUES %% start : rewrite_expr_list log_last_junction { *result = log_expr_node_append_tail($1, $2); if (yychar != YYEMPTY) { cfg_lexer_unput_token(lexer, &yylval); } YYACCEPT; } ; rewrite_expr_list : rewrite_expr semicolons rewrite_expr_list { $$ = log_expr_node_append_tail(log_expr_node_new_pipe($1, &@1), $3); } | log_junction semicolons rewrite_expr_list { $$ = log_expr_node_append_tail($1, $3); } | { $$ = NULL; } ; rewrite_template_content : string { GError *error = NULL; $$ = log_template_new(configuration, $1); CHECK_ERROR_GERROR(log_template_compile($$, $1, &error), @1, error, "error compiling replacement"); free($1); } ; rewrite_expr : KW_SUBST '(' string rewrite_template_content { last_rewrite = log_rewrite_subst_new($4, configuration); log_template_unref($4); } rewrite_subst_opts ')' { GError *error = NULL; CHECK_ERROR_GERROR(log_rewrite_subst_compile_pattern(last_rewrite, $3, &error), @3, error, "error compiling search pattern"); free($3); $$ = last_rewrite; } | KW_SET '(' rewrite_template_content { last_rewrite = log_rewrite_set_new($3, configuration); last_template_options = log_rewrite_set_get_template_options(last_rewrite); log_template_unref($3); } rewrite_set_opts ')' { $$ = last_rewrite; } | KW_UNSET { last_rewrite = log_rewrite_unset_new(configuration); } '(' rewrite_set_opts ')' { $$ = last_rewrite; } | KW_SET_TAG '(' string ')' { $$ = log_rewrite_set_tag_new($3, TRUE, configuration); free($3); } | KW_CLEAR_TAG '(' string ')' { $$ = log_rewrite_set_tag_new($3, FALSE, configuration); free($3); } | KW_GROUP_SET '(' rewrite_template_content { last_rewrite = log_rewrite_groupset_new($3, configuration); log_template_unref($3); } rewrite_groupset_opts ')' { $$ = last_rewrite; } | KW_GROUP_UNSET '(' { last_rewrite = log_rewrite_groupunset_new(configuration); } rewrite_groupset_opts ')' { $$ = last_rewrite; } | LL_IDENTIFIER { Plugin *p; gint context = LL_CONTEXT_REWRITE; p = cfg_find_plugin(configuration, context, $1); CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); last_rewrite = (LogRewrite *) cfg_parse_plugin(configuration, p, &@1, NULL); free($1); if (!last_rewrite) { YYERROR; } $$ = last_rewrite; } ; rewrite_groupset_opts : rewrite_groupset_opt rewrite_groupset_opts | ; rewrite_groupset_opt : KW_VALUES '(' string_list ')' { log_rewrite_groupset_add_fields(last_rewrite, $3); } | rewrite_condition_opt ; rewrite_subst_opts : rewrite_subst_opt rewrite_subst_opts | ; rewrite_subst_opt : { last_matcher_options = log_rewrite_subst_get_matcher_options(last_rewrite); } matcher_option | rewrite_expr_opt ; rewrite_set_opts : rewrite_set_opt rewrite_set_opts | ; rewrite_set_opt : rewrite_expr_opt | template_option ; rewrite_expr_opts : rewrite_expr_opt rewrite_expr_opts | ; rewrite_expr_opt : KW_VALUE '(' string ')' { const gchar *p = $3; if (p[0] == '$') { msg_warning("Value references in rewrite rules should not use the '$' prefix, those are only needed in templates", evt_tag_str("value", $3), cfg_lexer_format_location_tag(lexer, &@3)); p++; } last_rewrite->value_handle = log_msg_get_value_handle(p); CHECK_ERROR(!log_msg_is_handle_macro(last_rewrite->value_handle), @3, "%s is read-only, it cannot be changed in rewrite rules", p); CHECK_ERROR(log_msg_is_value_name_valid(p), @3, "%s is not a valid name for a name-value pair, perhaps a misspelled .SDATA reference?", p); free($3); } | rewrite_condition_opt ; rewrite_condition_opt : KW_CONDITION '(' { FilterExprNode *filter_expr; CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&filter_expr_parser, lexer, (gpointer *) &filter_expr, NULL), @1); log_rewrite_set_condition(last_rewrite, filter_expr); } ')' ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-expr-parser.c000066400000000000000000000040021321171025300237530ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "rewrite/rewrite-expr-parser.h" #include "rewrite/rewrite-expr.h" #include "rewrite/rewrite-expr-grammar.h" extern int rewrite_expr_debug; int rewrite_expr_parse(CfgLexer *lexer, LogExprNode **node, gpointer arg); static CfgLexerKeyword rewrite_expr_keywords[] = { { "set", KW_SET }, { "unset", KW_UNSET }, { "subst", KW_SUBST }, { "set_tag", KW_SET_TAG }, { "clear_tag", KW_CLEAR_TAG }, { "condition", KW_CONDITION }, { "groupset", KW_GROUP_SET }, { "groupunset", KW_GROUP_UNSET }, { "value", KW_VALUE }, { "values", KW_VALUES }, { NULL } }; CfgParser rewrite_expr_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &rewrite_expr_debug, #endif .name = "rewrite expression", .context = LL_CONTEXT_REWRITE, .keywords = rewrite_expr_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer)) rewrite_expr_parse, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(rewrite_expr_, LogExprNode **) syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-expr-parser.h000066400000000000000000000023321321171025300237640ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef REWRITE_EXPR_PARSER_H_INCLUDED #define REWRITE_EXPR_PARSER_H_INCLUDED #include "cfg-parser.h" #include "cfg-tree.h" extern CfgParser rewrite_expr_parser; CFG_PARSER_DECLARE_LEXER_BINDING(rewrite_expr_, LogExprNode **) #endif syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-expr.c000066400000000000000000000057741321171025300225020ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "rewrite/rewrite-expr.h" /* rewrite */ void log_rewrite_set_condition(LogRewrite *self, FilterExprNode *condition) { self->condition = condition; } static void log_rewrite_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { LogRewrite *self = (LogRewrite *) s; gssize length; const gchar *value; if (self->condition && !filter_expr_eval_root(self->condition, &msg, path_options)) { msg_debug("Rewrite condition unmatched, skipping rewrite", evt_tag_str("value", log_msg_get_value_name(self->value_handle, NULL))); } else { self->process(self, &msg, path_options); } if (G_UNLIKELY(debug_flag)) { value = log_msg_get_value(msg, self->value_handle, &length); msg_debug("Rewrite expression evaluation result", evt_tag_str("value", log_msg_get_value_name(self->value_handle, NULL)), evt_tag_printf("new_value", "%.*s", (gint) length, value), evt_tag_str("rule", self->name), log_pipe_location_tag(s)); } log_pipe_forward_msg(s, msg, path_options); } gboolean log_rewrite_init_method(LogPipe *s) { LogRewrite *self = (LogRewrite *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (self->condition && self->condition->init) self->condition->init(self->condition, log_pipe_get_config(s)); if (!self->name) self->name = cfg_tree_get_rule_name(&cfg->tree, ENC_REWRITE, s->expr_node); return TRUE; } void log_rewrite_free_method(LogPipe *s) { LogRewrite *self = (LogRewrite *) s; if (self->condition) filter_expr_unref(self->condition); g_free(self->name); log_pipe_free_method(s); } void log_rewrite_init_instance(LogRewrite *self, GlobalConfig *cfg) { log_pipe_init_instance(&self->super, cfg); /* indicate that the rewrite rule is changing the message */ self->super.free_fn = log_rewrite_free_method; self->super.queue = log_rewrite_queue; self->super.init = log_rewrite_init_method; self->value_handle = LM_V_MESSAGE; } syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-expr.h000066400000000000000000000031361321171025300224750ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef REWRITE_H_INCLUDED #define REWRITE_H_INCLUDED #include "logpipe.h" #include "filter/filter-expr.h" typedef struct _LogRewrite LogRewrite; struct _LogRewrite { LogPipe super; NVHandle value_handle; FilterExprNode *condition; void (*process)(LogRewrite *s, LogMessage **pmsg, const LogPathOptions *path_options); gchar *name; }; /* LogRewrite, abstract class */ gboolean log_rewrite_init_method(LogPipe *s); void log_rewrite_set_condition(LogRewrite *s, FilterExprNode *condition); void log_rewrite_init_instance(LogRewrite *self, GlobalConfig *cfg); void log_rewrite_free_method(LogPipe *self); #endif syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-groupset.c000066400000000000000000000112301321171025300233540ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Viktor Juhász * Copyright (c) 2014 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "rewrite-groupset.h" typedef struct _LogRewriteGroupSetCallbackData { LogMessage *msg; LogTemplate *template; } LogRewriteGroupSetCallbackData; /* TODO escape '\0' when passing down the value */ static gboolean log_rewrite_groupset_foreach_func(const gchar *name, TypeHint type, const gchar *value, gsize value_len, gpointer user_data) { LogRewriteGroupSetCallbackData *callback_data = (LogRewriteGroupSetCallbackData *) user_data; LogMessage *msg = callback_data->msg; LogTemplate *template = callback_data->template; GString *result; result = g_string_sized_new(64); log_template_format(template, msg, NULL, LTZ_LOCAL, 0, value, result); NVHandle handle = log_msg_get_value_handle(name); log_msg_set_value(msg, handle, result->str, result->len); g_string_free(result, TRUE); return FALSE; } static gboolean log_rewrite_groupunset_foreach_func(const gchar *name, TypeHint type, const gchar *value, gsize value_len, gpointer user_data) { LogRewriteGroupSetCallbackData *callback_data = (LogRewriteGroupSetCallbackData *) user_data; LogMessage *msg = callback_data->msg; NVHandle handle = log_msg_get_value_handle(name); log_msg_unset_value(msg, handle); return FALSE; } static void log_rewrite_groupset_process(LogRewrite *s, LogMessage **msg, const LogPathOptions *path_options) { LogRewriteGroupSet *self = (LogRewriteGroupSet *) s; LogRewriteGroupSetCallbackData userdata; log_msg_make_writable(msg, path_options); userdata.msg = *msg; userdata.template = self->replacement; value_pairs_foreach(self->query, self->vp_func, *msg, 0, LTZ_LOCAL, NULL, &userdata); } static void __free_field(gpointer field, gpointer user_data) { g_free(field); } void log_rewrite_groupset_add_fields(LogRewrite *rewrite, GList *fields) { LogRewriteGroupSet *self = (LogRewriteGroupSet *) rewrite; GList *head; for (head = fields; head; head = head->next) { value_pairs_add_glob_pattern(self->query, head->data, TRUE); } g_list_foreach(fields, __free_field, NULL); g_list_free(fields); } static LogPipe * log_rewrite_groupset_clone(LogPipe *s) { LogRewriteGroupSet *self = (LogRewriteGroupSet *) s; LogRewriteGroupSet *cloned = (LogRewriteGroupSet *)log_rewrite_groupset_new(self->replacement, log_pipe_get_config(&self->super.super) ); value_pairs_unref(cloned->query); cloned->query = value_pairs_ref(self->query); cloned->vp_func = self->vp_func; if (self->super.condition) cloned->super.condition = filter_expr_ref(self->super.condition); return &cloned->super.super; }; void log_rewrite_groupset_free(LogPipe *s) { LogRewriteGroupSet *self = (LogRewriteGroupSet *) s; value_pairs_unref(self->query); log_template_unref(self->replacement); log_rewrite_free_method(s); } LogRewrite * log_rewrite_groupset_new(LogTemplate *template, GlobalConfig *cfg) { LogRewriteGroupSet *self = g_new0(LogRewriteGroupSet, 1); log_rewrite_init_instance(&self->super, cfg); self->super.super.free_fn = log_rewrite_groupset_free; self->super.process = log_rewrite_groupset_process; self->super.super.clone = log_rewrite_groupset_clone; self->replacement = log_template_ref(template); self->query = value_pairs_new(); self->vp_func = log_rewrite_groupset_foreach_func; return &self->super; } LogRewrite * log_rewrite_groupunset_new(GlobalConfig *cfg) { LogRewriteGroupSet *self = (LogRewriteGroupSet *)log_rewrite_groupset_new(NULL, cfg); self->vp_func = log_rewrite_groupunset_foreach_func; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-groupset.h000066400000000000000000000026561321171025300233750ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "rewrite/rewrite-expr.h" #include "value-pairs/value-pairs.h" typedef struct _LogRewriteGroupSet { LogRewrite super; ValuePairs *query; LogTemplate *replacement; VPForeachFunc vp_func; } LogRewriteGroupSet; LogRewrite *log_rewrite_groupset_new(LogTemplate *template, GlobalConfig *cfg); LogRewrite *log_rewrite_groupunset_new(GlobalConfig *cfg); void log_rewrite_groupset_add_fields(LogRewrite *rewrite, GList *fields); syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-set-tag.c000066400000000000000000000047001321171025300230540ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "rewrite-set-tag.h" /* LogRewriteSetTag * * This class implements the "set-tag" expression in a rewrite rule. */ typedef struct _LogRewriteSetTag LogRewriteSetTag; struct _LogRewriteSetTag { LogRewrite super; LogTagId tag_id; gboolean value; }; static void log_rewrite_set_tag_process(LogRewrite *s, LogMessage **pmsg, const LogPathOptions *path_options) { LogRewriteSetTag *self = (LogRewriteSetTag *) s; log_msg_make_writable(pmsg, path_options); log_msg_set_tag_by_id_onoff(*pmsg, self->tag_id, self->value); } static LogPipe * log_rewrite_set_tag_clone(LogPipe *s) { LogRewriteSetTag *self = (LogRewriteSetTag *) s; LogRewriteSetTag *cloned; cloned = g_new0(LogRewriteSetTag, 1); log_rewrite_init_instance(&cloned->super, s->cfg); cloned->super.super.clone = log_rewrite_set_tag_clone; cloned->super.process = log_rewrite_set_tag_process; if (self->super.condition) cloned->super.condition = filter_expr_ref(self->super.condition); cloned->tag_id = self->tag_id; cloned->value = self->value; return &cloned->super.super; } LogRewrite * log_rewrite_set_tag_new(const gchar *tag_name, gboolean value, GlobalConfig *cfg) { LogRewriteSetTag *self = g_new0(LogRewriteSetTag, 1); log_rewrite_init_instance(&self->super, cfg); self->super.super.clone = log_rewrite_set_tag_clone; self->super.process = log_rewrite_set_tag_process; self->tag_id = log_tags_get_by_name(tag_name); self->value = value; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-set-tag.h000066400000000000000000000023151321171025300230610ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef REWRITE_SET_TAG_H_INCLUDED #define REWRITE_SET_TAG_H_INCLUDED #include "rewrite-expr.h" /* LogRewriteSetTag */ LogRewrite *log_rewrite_set_tag_new(const gchar *tag_name, gboolean onoff, GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-set.c000066400000000000000000000064351321171025300223120ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "rewrite-set.h" /* LogRewriteSet * * This class implements the "set" expression in a rewrite rule. */ typedef struct _LogRewriteSet LogRewriteSet; struct _LogRewriteSet { LogRewrite super; LogTemplate *value_template; LogTemplateOptions template_options; }; LogTemplateOptions * log_rewrite_set_get_template_options(LogRewrite *s) { LogRewriteSet *self = (LogRewriteSet *) s; return &self->template_options; } static void log_rewrite_set_process(LogRewrite *s, LogMessage **pmsg, const LogPathOptions *path_options) { LogRewriteSet *self = (LogRewriteSet *) s; GString *result; result = g_string_sized_new(64); log_template_format(self->value_template, *pmsg, &self->template_options, LTZ_SEND, 0, NULL, result); log_msg_make_writable(pmsg, path_options); log_msg_set_value(*pmsg, self->super.value_handle, result->str, result->len); g_string_free(result, TRUE); } static LogPipe * log_rewrite_set_clone(LogPipe *s) { LogRewriteSet *self = (LogRewriteSet *) s; LogRewriteSet *cloned; cloned = (LogRewriteSet *) log_rewrite_set_new(self->value_template, s->cfg); cloned->super.value_handle = self->super.value_handle; if (self->super.condition) cloned->super.condition = filter_expr_ref(self->super.condition); return &cloned->super.super; } static void log_rewrite_set_free(LogPipe *s) { LogRewriteSet *self = (LogRewriteSet *) s; log_template_options_destroy(&self->template_options); log_template_unref(self->value_template); log_rewrite_free_method(s); } gboolean log_rewrite_set_init_method(LogPipe *s) { LogRewriteSet *self = (LogRewriteSet *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (log_rewrite_init_method(s)) { log_template_options_init(&self->template_options, cfg); return TRUE; } else return FALSE; } LogRewrite * log_rewrite_set_new(LogTemplate *new_value, GlobalConfig *cfg) { LogRewriteSet *self = g_new0(LogRewriteSet, 1); log_rewrite_init_instance(&self->super, cfg); self->super.super.free_fn = log_rewrite_set_free; self->super.super.clone = log_rewrite_set_clone; self->super.super.init = log_rewrite_set_init_method; self->super.process = log_rewrite_set_process; self->value_template = log_template_ref(new_value); log_template_options_defaults(&self->template_options); return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-set.h000066400000000000000000000024001321171025300223030ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef REWRITE_SET_H_INCLUDED #define REWRITE_SET_H_INCLUDED #include "rewrite/rewrite-expr.h" /* LogRewriteSet */ LogRewrite *log_rewrite_set_new(LogTemplate *new_value, GlobalConfig *cfg); LogTemplateOptions *log_rewrite_set_get_template_options(LogRewrite *s); #endif syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-subst.c000066400000000000000000000075501321171025300226560ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "rewrite-subst.h" /* LogRewriteSubst * * This class implements the "subst" expression in a rewrite rule. */ typedef struct _LogRewriteSubst LogRewriteSubst; struct _LogRewriteSubst { LogRewrite super; LogMatcherOptions matcher_options; LogMatcher *matcher; LogTemplate *replacement; }; LogMatcherOptions * log_rewrite_subst_get_matcher_options(LogRewrite *s) { LogRewriteSubst *self = (LogRewriteSubst *) s; return &self->matcher_options; } void log_rewrite_subst_process(LogRewrite *s, LogMessage **pmsg, const LogPathOptions *path_options) { LogRewriteSubst *self = (LogRewriteSubst *) s; const gchar *value; gchar *new_value; gssize length; gssize new_length = -1; value = log_msg_get_value(*pmsg, self->super.value_handle, &length); log_msg_make_writable(pmsg, path_options); new_value = log_matcher_replace(self->matcher, *pmsg, self->super.value_handle, value, length, self->replacement, &new_length); if (new_value) { log_msg_set_value(*pmsg, self->super.value_handle, new_value, new_length); } g_free(new_value); } gboolean log_rewrite_subst_compile_pattern(LogRewrite *s, const gchar *regexp, GError **error) { LogRewriteSubst *self = (LogRewriteSubst *) s; GlobalConfig *cfg = log_pipe_get_config(&s->super); log_matcher_options_init(&self->matcher_options, cfg); self->matcher = log_matcher_new(cfg, &self->matcher_options); if (!log_matcher_is_replace_supported(self->matcher)) { g_set_error(error, LOG_MATCHER_ERROR, 0, "subst() only supports matchers that allow replacement, glob is not one of these"); return FALSE; } return log_matcher_compile(self->matcher, regexp, error); } static LogPipe * log_rewrite_subst_clone(LogPipe *s) { LogRewriteSubst *self = (LogRewriteSubst *) s; LogRewriteSubst *cloned; cloned = (LogRewriteSubst *) log_rewrite_subst_new(self->replacement, s->cfg); cloned->matcher = log_matcher_ref(self->matcher); cloned->super.value_handle = self->super.value_handle; if (self->super.condition) cloned->super.condition = filter_expr_ref(self->super.condition); return &cloned->super.super; } void log_rewrite_subst_free(LogPipe *s) { LogRewriteSubst *self = (LogRewriteSubst *) s; log_matcher_unref(self->matcher); log_template_unref(self->replacement); log_matcher_options_destroy(&self->matcher_options); log_rewrite_free_method(s); } LogRewrite * log_rewrite_subst_new(LogTemplate *replacement, GlobalConfig *cfg) { LogRewriteSubst *self = g_new0(LogRewriteSubst, 1); log_rewrite_init_instance(&self->super, cfg); self->super.super.free_fn = log_rewrite_subst_free; self->super.super.clone = log_rewrite_subst_clone; self->super.process = log_rewrite_subst_process; self->replacement = log_template_ref(replacement); log_matcher_options_defaults(&self->matcher_options); return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-subst.h000066400000000000000000000025741321171025300226640ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef REWRITE_SUBST_H_INCLUDED #define REWRITE_SUBST_H_INCLUDED #include "rewrite-expr.h" #include "logmatcher.h" /* LogRewriteSubst */ LogMatcherOptions *log_rewrite_subst_get_matcher_options(LogRewrite *s); gboolean log_rewrite_subst_compile_pattern(LogRewrite *s, const gchar *regexp, GError **error); LogRewrite *log_rewrite_subst_new(LogTemplate *replacement, GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-unset.c000066400000000000000000000041641321171025300226520ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 1998-2016 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "rewrite-unset.h" /* LogRewriteUnset * * This class implements the "unset" expression in a rewrite rule. */ typedef struct _LogRewriteUnset LogRewriteUnset; struct _LogRewriteUnset { LogRewrite super; }; static void log_rewrite_unset_process(LogRewrite *s, LogMessage **pmsg, const LogPathOptions *path_options) { LogRewriteUnset *self = (LogRewriteUnset *) s; log_msg_make_writable(pmsg, path_options); log_msg_unset_value(*pmsg, self->super.value_handle); } static LogPipe * log_rewrite_unset_clone(LogPipe *s) { LogRewriteUnset *self = (LogRewriteUnset *) s; LogRewriteUnset *cloned; cloned = (LogRewriteUnset *) log_rewrite_unset_new(s->cfg); cloned->super.value_handle = self->super.value_handle; if (self->super.condition) cloned->super.condition = filter_expr_ref(self->super.condition); return &cloned->super.super; } LogRewrite * log_rewrite_unset_new(GlobalConfig *cfg) { LogRewriteUnset *self = g_new0(LogRewriteUnset, 1); log_rewrite_init_instance(&self->super, cfg); self->super.super.clone = log_rewrite_unset_clone; self->super.process = log_rewrite_unset_process; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/rewrite/rewrite-unset.h000066400000000000000000000022451321171025300226550ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef REWRITE_UNSET_H_INCLUDED #define REWRITE_UNSET_H_INCLUDED #include "rewrite/rewrite-expr.h" /* LogRewriteSet */ LogRewrite *log_rewrite_unset_new(GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/lib/rewrite/tests/000077500000000000000000000000001321171025300210265ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/rewrite/tests/Makefile.am000066400000000000000000000005221321171025300230610ustar00rootroot00000000000000lib_rewrite_tests_TESTS = \ lib/rewrite/tests/test_rewrite check_PROGRAMS += ${lib_rewrite_tests_TESTS} lib_rewrite_tests_test_rewrite_CFLAGS = $(TEST_CFLAGS) lib_rewrite_tests_test_rewrite_LDADD = $(TEST_LDADD) \ $(PREOPEN_SYSLOGFORMAT) lib_rewrite_tests_test_rewrite_SOURCES = \ lib/rewrite/tests/test_rewrite.c syslog-ng-syslog-ng-3.13.2/lib/rewrite/tests/test_rewrite.c000066400000000000000000000357421321171025300237250ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "apphook.h" #include "plugin.h" #include "testutils.h" #include "config_parse_lib.h" #include "cfg-grammar.h" #include "rewrite/rewrite-expr.h" void expect_config_parse_failure(const char *raw_rewrite_rule) { char raw_config[1024]; configuration = cfg_new_snippet(); snprintf(raw_config, sizeof(raw_config), "rewrite s_test{ %s };", raw_rewrite_rule); assert_false(parse_config(raw_config, LL_CONTEXT_ROOT, NULL, NULL), ASSERTION_ERROR("Parsing the given configuration failed")); cfg_free(configuration); }; LogRewrite * create_rewrite_rule(const char *raw_rewrite_rule) { char raw_config[1024]; configuration = cfg_new_snippet(); snprintf(raw_config, sizeof(raw_config), "rewrite s_test{ %s }; log{ rewrite(s_test); };", raw_rewrite_rule); assert_true(parse_config(raw_config, LL_CONTEXT_ROOT, NULL, NULL), ASSERTION_ERROR("Parsing the given configuration failed")); assert_true(cfg_init(configuration), ASSERTION_ERROR("Config initialization failed")); LogExprNode *expr_node = cfg_tree_get_object(&configuration->tree, ENC_REWRITE, "s_test"); return (LogRewrite *)expr_node->children->object; } LogMessage * create_message_with_fields(const char *field_name, ...) { va_list args; const char *arg; LogMessage *msg = log_msg_new_empty(); msg->timestamps[LM_TS_STAMP].tv_sec = 365 * 24 * 3600; arg = field_name; va_start(args, field_name); while (arg != NULL) { NVHandle handle = log_msg_get_value_handle(arg); arg = va_arg(args, char *); log_msg_set_value(msg, handle, arg, -1); arg = va_arg(args, char *); } va_end(args); return msg; } LogMessage * create_message_with_field(const char *field_name, const char *field_value) { return create_message_with_fields(field_name, field_value, NULL); } void invoke_rewrite_rule(LogRewrite *pipe_, LogMessage *msg) { LogPathOptions po = LOG_PATH_OPTIONS_INIT; log_pipe_queue((LogPipe *) pipe_, log_msg_ref(msg), &po); }; void rewrite_teardown(LogMessage *msg) { log_msg_unref(msg); cfg_free(configuration); } void test_condition_success(void) { LogRewrite *test_rewrite = create_rewrite_rule("set(\"00100\", value(\"device_id\") condition(program(\"ARCGIS\")));"); LogMessage *msg = create_message_with_field("PROGRAM", "ARCGIS"); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "device_id", "00100", -1, ASSERTION_ERROR("Bad device_id")); rewrite_teardown(msg); } void test_reference_on_condition_cloned(void) { LogRewrite *test_rewrite = create_rewrite_rule("set(\"00100\", value(\"device_id\") condition(program(\"ARCGIS\")));"); LogPipe *cloned_rule = log_pipe_clone(&test_rewrite->super); assert_guint32(test_rewrite->condition->ref_cnt, 2, ASSERTION_ERROR("Bad reference number of condition")); log_pipe_unref(cloned_rule); assert_guint32(test_rewrite->condition->ref_cnt, 1, ASSERTION_ERROR("Bad reference number of condition")); cfg_free(configuration); } void test_set_field_exist_and_set_literal_string(void) { LogRewrite *test_rewrite = create_rewrite_rule("set(\"value\" value(\"field1\") );"); LogMessage *msg = create_message_with_field("field1", "oldvalue"); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "value", -1, ASSERTION_ERROR("Couldn't set message field")); rewrite_teardown(msg); } void test_set_field_not_exist_and_set_literal_string(void) { LogRewrite *test_rewrite = create_rewrite_rule("set(\"value\" value(\"field1\") );"); LogMessage *msg = log_msg_new_empty(); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "value", -1, ASSERTION_ERROR("Couldn't set message field when it doesn't exists")); rewrite_teardown(msg); } void test_set_field_exist_and_set_template_string(void) { LogRewrite *test_rewrite = create_rewrite_rule("set(\"$field2\" value(\"field1\") );"); LogMessage *msg = create_message_with_fields("field1", "oldvalue", "field2","newvalue", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "newvalue", -1, ASSERTION_ERROR("Couldn't set message field with template value")); rewrite_teardown(msg); } void test_subst_field_exist_and_substring_substituted(void) { LogRewrite *test_rewrite = create_rewrite_rule("subst(\"substring\" \"substitute\" value(\"field1\") );"); LogMessage *msg = create_message_with_fields("field1", "asubstringb", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "asubstituteb", -1, ASSERTION_ERROR("Couldn't subst message field with literal")); rewrite_teardown(msg); } void test_subst_field_exist_and_substring_substituted_with_template(void) { LogRewrite *test_rewrite = create_rewrite_rule("subst(\"substring\" \"$field2\" value(\"field1\") );"); LogMessage *msg = create_message_with_fields("field1", "asubstringb", "field2","substitute", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "asubstituteb", -1, ASSERTION_ERROR("Couldn't subst message field with template")); rewrite_teardown(msg); } void test_subst_field_exist_and_substring_substituted_only_once_without_global(void) { LogRewrite *test_rewrite = create_rewrite_rule("subst(\"substring\" \"substitute\" value(\"field1\") );"); LogMessage *msg = create_message_with_fields("field1", "substring substring", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "substitute substring", -1, ASSERTION_ERROR("Field substituted more than once without global flag")); rewrite_teardown(msg); } void test_subst_field_exist_and_substring_substituted_every_occurence_with_global(void) { LogRewrite *test_rewrite = create_rewrite_rule("subst(\"substring\" \"substitute\" value(\"field1\") flags(global) );"); LogMessage *msg = create_message_with_fields("field1", "substring substring", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "substitute substitute", -1, ASSERTION_ERROR("Field substituted less than every occurence with global flag")); rewrite_teardown(msg); } void test_subst_field_exist_and_substring_substituted_when_regexp_matched(void) { LogRewrite *test_rewrite = create_rewrite_rule("subst(\"[0-9]+\" \"substitute\" value(\"field1\") );"); LogMessage *msg = create_message_with_fields("field1", "a123b", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "asubstituteb", -1, ASSERTION_ERROR("Couldn't subst message field with literal")); rewrite_teardown(msg); } void test_set_field_exist_and_group_set_literal_string(void) { LogRewrite *test_rewrite = create_rewrite_rule("groupset(\"value\" values(\"field1\") );"); LogMessage *msg = create_message_with_field("field1", "oldvalue"); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "value", -1, ASSERTION_ERROR("Couldn't set message field")); rewrite_teardown(msg); } void test_set_field_honors_time_zone(void) { LogRewrite *test_rewrite = create_rewrite_rule("set('${ISODATE}' value('UTCDATE') time-zone('Asia/Tokyo'));"); LogMessage *msg = create_message_with_fields("field1", "a123b", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "UTCDATE", "1971-01-01T09:00:00+09:00", -1, ASSERTION_ERROR("Couldn't use time-zone option in rewrite-set")); rewrite_teardown(msg); } void test_set_field_exist_and_group_set_multiple_fields_with_glob_pattern_literal_string(void) { LogRewrite *test_rewrite = create_rewrite_rule("groupset(\"value\" values(\"field.*\") );"); LogMessage *msg = create_message_with_fields("field.name1", "oldvalue","field.name2", "oldvalue", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field.name1", "value", -1, ASSERTION_ERROR("Couldn't set message field")); assert_msg_field_equals(msg, "field.name2", "value", -1, ASSERTION_ERROR("Couldn't set message field")); rewrite_teardown(msg); } void test_set_field_exist_and_group_set_multiple_fields_with_glob_question_mark_pattern_literal_string(void) { LogRewrite *test_rewrite = create_rewrite_rule("groupset(\"value\" values(\"field?\") );"); LogMessage *msg = create_message_with_fields("field1", "oldvalue","field2", "oldvalue", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "value", -1, ASSERTION_ERROR("Couldn't set message field")); assert_msg_field_equals(msg, "field2", "value", -1, ASSERTION_ERROR("Couldn't set message field")); rewrite_teardown(msg); } void test_set_field_exist_and_group_set_multiple_fields_with_multiple_glob_pattern_literal_string(void) { LogRewrite *test_rewrite = create_rewrite_rule("groupset(\"value\" values(\"field1\" \"field2\") );"); LogMessage *msg = create_message_with_fields("field1", "oldvalue","field2", "oldvalue", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "value", -1, ASSERTION_ERROR("Couldn't set message field")); assert_msg_field_equals(msg, "field2", "value", -1, ASSERTION_ERROR("Couldn't set message field")); rewrite_teardown(msg); } void test_set_field_exist_and_group_set_template_string(void) { LogRewrite *test_rewrite = create_rewrite_rule("groupset(\"$field2\" values(\"field1\") );"); LogMessage *msg = create_message_with_fields("field1", "oldvalue", "field2", "value", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "value", -1, ASSERTION_ERROR("Couldn't set message field")); rewrite_teardown(msg); } void test_set_field_exist_and_group_set_template_string_with_old_value(void) { LogRewrite *test_rewrite = create_rewrite_rule("groupset(\"$_ alma\" values(\"field1\") );"); LogMessage *msg = create_message_with_field("field1", "value"); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "value alma", -1, ASSERTION_ERROR("Couldn't set message field")); rewrite_teardown(msg); } void test_set_field_exist_and_group_set_when_condition_doesnt_match(void) { LogRewrite *test_rewrite = create_rewrite_rule("groupset(\"value\" values(\"field1\") condition( program(\"program1\") ) );"); LogMessage *msg = create_message_with_fields("field1", "oldvalue", "PROGRAM", "program2", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "oldvalue", -1, ASSERTION_ERROR("Shouldn't rewrite when condition doesn't match")); rewrite_teardown(msg); } void test_set_field_exist_and_group_set_when_condition_matches(void) { LogRewrite *test_rewrite = create_rewrite_rule("groupset(\"value\" values(\"field1\") condition( program(\"program\") ) );"); LogMessage *msg = create_message_with_fields("field1", "oldvalue", "PROGRAM", "program", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_equals(msg, "field1", "value", -1, ASSERTION_ERROR("Shouldn't rewrite when condition doesn't match")); rewrite_teardown(msg); } void test_set_field_cloned(void) { LogRewrite *test_rewrite = create_rewrite_rule("groupset(\"value\" values(\"field1\") condition( program(\"program\") ) );"); LogPipe *cloned_rule = log_pipe_clone(&test_rewrite->super); assert_true(cloned_rule != NULL, ASSERTION_ERROR("Can't cloned the rewrite")); log_pipe_unref(cloned_rule); cfg_free(configuration); } void test_set_field_invalid_template(void) { expect_config_parse_failure("groupset(\"${alma\" values(\"field1\") );"); } static void test_unset_field_disappears(void) { LogRewrite *test_rewrite = create_rewrite_rule("unset(value('field1'));"); LogMessage *msg = create_message_with_fields("field1", "oldvalue", "PROGRAM", "foobar", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_unset(msg, "field1", ASSERTION_ERROR("field1 should be unset")); assert_msg_field_equals(msg, "PROGRAM", "foobar", -1, ASSERTION_ERROR("field1 should be unset")); rewrite_teardown(msg); } static void test_groupunset_field_disappears(void) { LogRewrite *test_rewrite = create_rewrite_rule("groupunset(values('field?'));"); LogMessage *msg = create_message_with_fields("field1", "oldvalue", "field2", "oldvalue2", "PROGRAM", "foobar", NULL); invoke_rewrite_rule(test_rewrite, msg); assert_msg_field_unset(msg, "field1", ASSERTION_ERROR("field1 should be unset")); assert_msg_field_unset(msg, "field2", ASSERTION_ERROR("field2 should be unset")); assert_msg_field_equals(msg, "PROGRAM", "foobar", -1, ASSERTION_ERROR("field1 should be unset")); rewrite_teardown(msg); } int main(int argc, char **argv) { app_startup(); putenv("TZ=MET-1METDST"); tzset(); start_grabbing_messages(); test_condition_success(); test_reference_on_condition_cloned(); test_set_field_exist_and_set_literal_string(); test_set_field_not_exist_and_set_literal_string(); test_set_field_exist_and_set_template_string(); test_subst_field_exist_and_substring_substituted(); test_subst_field_exist_and_substring_substituted_with_template(); test_subst_field_exist_and_substring_substituted_only_once_without_global(); test_subst_field_exist_and_substring_substituted_every_occurence_with_global(); test_subst_field_exist_and_substring_substituted_when_regexp_matched(); test_set_field_honors_time_zone(); test_set_field_exist_and_group_set_literal_string(); test_set_field_exist_and_group_set_multiple_fields_with_glob_pattern_literal_string(); test_set_field_exist_and_group_set_multiple_fields_with_glob_question_mark_pattern_literal_string(); test_set_field_exist_and_group_set_multiple_fields_with_multiple_glob_pattern_literal_string(); test_set_field_exist_and_group_set_template_string(); test_set_field_exist_and_group_set_template_string_with_old_value(); test_set_field_invalid_template(); test_set_field_exist_and_group_set_when_condition_doesnt_match(); test_set_field_exist_and_group_set_when_condition_matches(); test_set_field_cloned(); test_unset_field_disappears(); test_groupunset_field_disappears(); stop_grabbing_messages(); } syslog-ng-syslog-ng-3.13.2/lib/ringbuffer.c000066400000000000000000000071221321171025300205020ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 2014 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "ringbuffer.h" void ring_buffer_init(RingBuffer *self) { self->head = 0; self->tail = 0; self->count = 0; self->capacity = 0; self->element_size = 0; self->buffer = NULL; } void ring_buffer_alloc(RingBuffer *self, guint32 element_size, guint32 capacity) { g_assert(capacity > 0); self->head = 0; self->tail = 0; self->count = 0; self->capacity = capacity; self->element_size = element_size; self->buffer = g_malloc0(element_size * self->capacity); } gboolean ring_buffer_is_allocated(RingBuffer *self) { return (self->buffer != NULL); } void ring_buffer_free(RingBuffer *self) { g_free(self->buffer); self->head = 0; self->tail = 0; self->count = 0; self->capacity = 0; self->element_size = 0; self->buffer = NULL; } gboolean ring_buffer_is_full(RingBuffer *self) { return self->capacity == self->count ? TRUE : FALSE; } gboolean ring_buffer_is_empty(RingBuffer *self) { return (self->count == 0) ? TRUE : FALSE; } gpointer ring_buffer_push(RingBuffer *self) { gpointer r = NULL; r = ring_buffer_tail(self); if (!r) return NULL; ++self->count; self->tail = (self->tail + 1) % self->capacity; return r; } gpointer ring_buffer_tail (RingBuffer *self) { gpointer r = NULL; g_assert(self->buffer != NULL); if (ring_buffer_is_full(self)) return NULL; r = self->buffer + self->tail * self->element_size; return r; } gpointer ring_buffer_pop(RingBuffer *self) { gpointer r = NULL; g_assert(self->buffer != NULL); if (ring_buffer_is_empty(self)) return NULL; r = self->buffer + self->head * self->element_size; --self->count; self->head = (self->head + 1) % self->capacity; return r; } gboolean ring_buffer_drop(RingBuffer *self, guint32 n) { g_assert(self->buffer != NULL); if (ring_buffer_count(self) < n) return FALSE; self->count -= n; self->head = (self->head + n) % self->capacity; return TRUE; } guint32 ring_buffer_capacity(RingBuffer *self) { return self->buffer ? self->capacity : 0; } guint32 ring_buffer_count(RingBuffer *self) { return self->count; } gpointer ring_buffer_element_at(RingBuffer *self, guint32 idx) { g_assert(self->buffer != NULL); if (idx >= self->count) return NULL; return self->buffer + ((self->head + idx) % self->capacity) * self->element_size; } guint32 ring_buffer_get_continual_range_length(RingBuffer *self, RingBufferIsContinuousPredicate pred) { guint32 r = 0, i; g_assert(self->buffer != NULL); for (i = 0; i < ring_buffer_count(self); i++) { if (!pred(ring_buffer_element_at(self, i))) { break; } ++r; } return r; } syslog-ng-syslog-ng-3.13.2/lib/ringbuffer.h000066400000000000000000000040421321171025300205050ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 2014 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef RINGBUFFER_H_INCLUDED #define RINGBUFFER_H_INCLUDED #include typedef struct _RingBuffer { gpointer buffer; guint32 head; guint32 tail; guint32 count; guint32 capacity; guint32 element_size; } RingBuffer; typedef gboolean(*RingBufferIsContinuousPredicate)(gpointer element); void ring_buffer_init(RingBuffer *self); void ring_buffer_alloc(RingBuffer *self, guint32 size_of_element, guint32 capacity); gboolean ring_buffer_is_allocated(RingBuffer *self); void ring_buffer_free(RingBuffer *self); gboolean ring_buffer_is_full(RingBuffer *self); gboolean ring_buffer_is_empty(RingBuffer *self); gpointer ring_buffer_push(RingBuffer *self); gpointer ring_buffer_pop(RingBuffer *self); gpointer ring_buffer_tail(RingBuffer *self); gboolean ring_buffer_drop(RingBuffer *self, guint32 n); guint32 ring_buffer_capacity(RingBuffer *self); guint32 ring_buffer_count(RingBuffer *self); gpointer ring_buffer_element_at(RingBuffer *self, guint32 idx); guint32 ring_buffer_get_continual_range_length(RingBuffer *self, RingBufferIsContinuousPredicate pred); #endif syslog-ng-syslog-ng-3.13.2/lib/run-id.c000066400000000000000000000040531321171025300175470ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 2013 Viktor Juhasz * Copyright (c) 2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "run-id.h" #include "persistable-state-header.h" #include "str-format.h" #define RUN_ID_PERSIST_KEY "run_id" int cached_run_id = 0; typedef struct _RunIDState { PersistableStateHeader header; gint run_id; } RunIDState; void run_id_init(PersistState *state) { gsize size; guint8 version; PersistEntryHandle handle; RunIDState *run_id_state; handle = persist_state_lookup_entry(state, RUN_ID_PERSIST_KEY, &size, &version); if (handle == 0) { handle = persist_state_alloc_entry(state, RUN_ID_PERSIST_KEY, sizeof(RunIDState) ); } run_id_state = persist_state_map_entry(state, handle); run_id_state->run_id++; cached_run_id = run_id_state->run_id; persist_state_unmap_entry(state, handle); }; int run_id_get(void) { return cached_run_id; }; gboolean run_id_is_same_run(gint other_id) { return cached_run_id == other_id; }; void run_id_append_formatted_id(GString *str) { if (cached_run_id) format_uint32_padded(str, 0, 0, 10, cached_run_id); }; void run_id_deinit(void) { cached_run_id = 0; }; syslog-ng-syslog-ng-3.13.2/lib/run-id.h000066400000000000000000000024041321171025300175520ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 2013 Viktor Juhasz * Copyright (c) 2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef _RUN_ID_H #define _RUN_ID_H #include "persist-state.h" void run_id_init(PersistState *state); void run_id_deinit(void); int run_id_get(void); gboolean run_id_is_same_run(gint other_run_id); void run_id_append_formatted_id(GString* str); #endif syslog-ng-syslog-ng-3.13.2/lib/scanner/000077500000000000000000000000001321171025300176345ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/scanner/CMakeLists.txt000066400000000000000000000001321321171025300223700ustar00rootroot00000000000000add_subdirectory(csv-scanner) add_subdirectory(list-scanner) add_subdirectory(kv-scanner) syslog-ng-syslog-ng-3.13.2/lib/scanner/csv-scanner/000077500000000000000000000000001321171025300220565ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/scanner/csv-scanner/CMakeLists.txt000066400000000000000000000002211321171025300246110ustar00rootroot00000000000000set(CSV_SCANNER_HEADERS csv-scanner/csv-scanner.h PARENT_SCOPE) set(CSV_SCANNER_SOURCES csv-scanner/csv-scanner.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/scanner/csv-scanner/Makefile.am000066400000000000000000000003121321171025300241060ustar00rootroot00000000000000csvscannerincludedir = ${pkgincludedir}/scanner/csv-scanner csvscannerinclude_HEADERS = \ lib/scanner/csv-scanner/csv-scanner.h csvscanner_sources = \ lib/scanner/csv-scanner/csv-scanner.c syslog-ng-syslog-ng-3.13.2/lib/scanner/csv-scanner/csv-scanner.c000066400000000000000000000252061321171025300244510ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "csv-scanner.h" #include "str-utils.h" #include "string-list.h" #include "scratch-buffers.h" #include /************************************************************************ * CSVScannerOptions ************************************************************************/ void csv_scanner_options_set_flags(CSVScannerOptions *options, guint32 flags) { options->flags = flags; } void csv_scanner_options_set_dialect(CSVScannerOptions *options, CSVScannerDialect dialect) { options->dialect = dialect; } void csv_scanner_options_set_columns(CSVScannerOptions *options, GList *columns) { string_list_free(options->columns); options->columns = columns; } void csv_scanner_options_set_delimiters(CSVScannerOptions *options, const gchar *delimiters) { g_free(options->delimiters); options->delimiters = g_strdup(delimiters); } void csv_scanner_options_set_string_delimiters(CSVScannerOptions *options, GList *string_delimiters) { string_list_free(options->string_delimiters); options->string_delimiters = string_delimiters; } void csv_scanner_options_set_quotes_start_and_end(CSVScannerOptions *options, const gchar *quotes_start, const gchar *quotes_end) { g_free(options->quotes_start); g_free(options->quotes_end); options->quotes_start = g_strdup(quotes_start); options->quotes_end = g_strdup(quotes_end); } void csv_scanner_options_set_quotes(CSVScannerOptions *options, const gchar *quotes) { csv_scanner_options_set_quotes_start_and_end(options, quotes, quotes); } void csv_scanner_options_set_quote_pairs(CSVScannerOptions *options, const gchar *quote_pairs) { gint i; g_free(options->quotes_start); g_free(options->quotes_end); options->quotes_start = g_malloc((strlen(quote_pairs) / 2) + 1); options->quotes_end = g_malloc((strlen(quote_pairs) / 2) + 1); for (i = 0; quote_pairs[i] && quote_pairs[i+1]; i += 2) { options->quotes_start[i / 2] = quote_pairs[i]; options->quotes_end[i / 2] = quote_pairs[i + 1]; } options->quotes_start[i / 2] = 0; options->quotes_end[i / 2] = 0; } void csv_scanner_options_set_null_value(CSVScannerOptions *options, const gchar *null_value) { g_free(options->null_value); options->null_value = null_value && null_value[0] ? g_strdup(null_value) : NULL; } void csv_scanner_options_copy(CSVScannerOptions *dst, CSVScannerOptions *src) { csv_scanner_options_set_delimiters(dst, src->delimiters); csv_scanner_options_set_quotes_start_and_end(dst, src->quotes_start, src->quotes_end); csv_scanner_options_set_null_value(dst, src->null_value); csv_scanner_options_set_string_delimiters(dst, string_list_clone(src->string_delimiters)); csv_scanner_options_set_columns(dst, string_list_clone(src->columns)); dst->dialect = src->dialect; dst->flags = src->flags; } void csv_scanner_options_clean(CSVScannerOptions *options) { g_free(options->quotes_start); g_free(options->quotes_end); g_free(options->null_value); g_free(options->delimiters); string_list_free(options->string_delimiters); string_list_free(options->columns); } /************************************************************************ * CSVScanner ************************************************************************/ static gboolean _is_whitespace_char(const gchar *str) { return (*str == ' ' || *str == '\t'); } static void _skip_whitespace(const gchar **src) { while (_is_whitespace_char(*src)) (*src)++; } static void _switch_to_next_column(CSVScanner *self) { if (!self->current_column && self->src && self->src[0]) self->current_column = self->options->columns; else if (self->current_column) self->current_column = self->current_column->next; g_string_truncate(self->current_value, 0); } static gboolean _is_last_column(CSVScanner *self) { return self->current_column && self->current_column->next == NULL; } static gboolean _is_at_the_end_of_columns(CSVScanner *self) { return self->current_column == NULL; } static void _parse_opening_quote_character(CSVScanner *self) { gchar *quote = _strchr_optimized_for_single_char_haystack(self->options->quotes_start, *self->src); if (quote != NULL) { /* ok, quote character found */ self->src++; self->current_quote = self->options->quotes_end[quote - self->options->quotes_start]; } else { /* we didn't start with a quote character, no need for escaping, delimiter terminates */ self->current_quote = 0; } } static void _parse_left_whitespace(CSVScanner *self) { if ((self->options->flags & CSV_SCANNER_STRIP_WHITESPACE) == 0) return; _skip_whitespace(&self->src); } static void _parse_character_with_quotation(CSVScanner *self) { /* quoted character */ if (self->options->dialect == CSV_SCANNER_ESCAPE_BACKSLASH && *self->src == '\\' && *(self->src + 1)) { self->src++; } else if (self->options->dialect == CSV_SCANNER_ESCAPE_DOUBLE_CHAR && *self->src == self->current_quote && *(self->src+1) == self->current_quote) { self->src++; } else if (*self->src == self->current_quote) { self->current_quote = 0; self->src++; return; } g_string_append_c(self->current_value, *self->src); self->src++; } /* searches for str in list and returns the first occurence, otherwise NULL */ static const gboolean _match_string_delimiters_at_current_position(const char *input, GList *string_delimiters, int *result_length) { GList *l; for (l = string_delimiters; l; l = l->next) { gint len = strlen(l->data); if (strncmp(input, l->data, len) == 0) { *result_length = len; return TRUE; } } return FALSE; } static gboolean _parse_string_delimiters_at_current_position(CSVScanner *self) { gint delim_len; if (!self->options->string_delimiters) return FALSE; if (_match_string_delimiters_at_current_position(self->src, self->options->string_delimiters, &delim_len)) { self->src += delim_len; return TRUE; } return FALSE; } static gboolean _parse_character_delimiters_at_current_position(CSVScanner *self) { if (_strchr_optimized_for_single_char_haystack(self->options->delimiters, *self->src) != NULL) { self->src++; return TRUE; } return FALSE; } static gboolean _parse_delimiter(CSVScanner *self) { if (_parse_string_delimiters_at_current_position(self)) return TRUE; if (_parse_character_delimiters_at_current_position(self)) return TRUE; return FALSE; } static void _parse_unquoted_literal_character(CSVScanner *self) { g_string_append_c(self->current_value, *self->src); self->src++; } static void _parse_value_with_whitespace_and_delimiter(CSVScanner *self) { while (*self->src) { if (self->current_quote) { /* within quotation marks */ _parse_character_with_quotation(self); } else { /* unquoted value */ if (_parse_delimiter(self)) break; _parse_unquoted_literal_character(self); } } } static gint _get_value_length_without_right_whitespace(CSVScanner *self) { gint len = self->current_value->len; while (len > 0 && _is_whitespace_char(self->current_value->str + len - 1)) len--; return len; } static void _translate_rstrip_whitespace(CSVScanner *self) { if (self->options->flags & CSV_SCANNER_STRIP_WHITESPACE) g_string_truncate(self->current_value, _get_value_length_without_right_whitespace(self)); } static void _translate_null_value(CSVScanner *self) { if (self->options->null_value && strcmp(self->current_value->str, self->options->null_value) == 0) g_string_truncate(self->current_value, 0); } static void _translate_value(CSVScanner *self) { _translate_rstrip_whitespace(self); _translate_null_value(self); } gboolean csv_scanner_scan_next(CSVScanner *self) { _switch_to_next_column(self); if (!self->src || !self->current_column) return FALSE; if (_is_last_column(self) && (self->options->flags & CSV_SCANNER_GREEDY)) { g_string_assign(self->current_value, self->src); self->src = NULL; return TRUE; } else if (self->src[0] == 0) { /* no more input data and a real column, not a greedy one */ return FALSE; } else { _parse_opening_quote_character(self); _parse_left_whitespace(self); _parse_value_with_whitespace_and_delimiter(self); _translate_value(self); return TRUE; } } const gchar * csv_scanner_get_current_name(CSVScanner *self) { return (const gchar *) self->current_column->data; } gboolean csv_scanner_is_scan_finished(CSVScanner *self) { if ((self->options->flags & CSV_SCANNER_DROP_INVALID) && (!_is_at_the_end_of_columns(self) || (self->src && *self->src))) { /* there are unfilled variables, OR not all of the input was processed * and "drop-invalid" flag is specified */ return FALSE; } return TRUE; } void csv_scanner_init(CSVScanner *scanner, CSVScannerOptions *options, const gchar *input) { memset(scanner, 0, sizeof(*scanner)); scanner->src = input; scanner->current_value = scratch_buffers_alloc(); scanner->current_column = NULL; scanner->options = options; } void csv_scanner_deinit(CSVScanner *self) { } const gchar * csv_scanner_get_current_value(CSVScanner *self) { return self->current_value->str; } gint csv_scanner_get_current_value_len(CSVScanner *self) { return self->current_value->len; } gchar * csv_scanner_dup_current_value(CSVScanner *self) { return g_strndup(csv_scanner_get_current_value(self), csv_scanner_get_current_value_len(self)); } syslog-ng-syslog-ng-3.13.2/lib/scanner/csv-scanner/csv-scanner.h000066400000000000000000000062561321171025300244620ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CSVSCANNER_H_INCLUDED #define CSVSCANNER_H_INCLUDED #include "syslog-ng.h" typedef enum { CSV_SCANNER_ESCAPE_NONE, CSV_SCANNER_ESCAPE_BACKSLASH, CSV_SCANNER_ESCAPE_DOUBLE_CHAR } CSVScannerDialect; #define CSV_SCANNER_STRIP_WHITESPACE 0x0001 #define CSV_SCANNER_GREEDY 0x0002 #define CSV_SCANNER_DROP_INVALID 0x0004 typedef struct _CSVScannerOptions { GList *columns; gchar *delimiters; gchar *quotes_start; gchar *quotes_end; gchar *null_value; GList *string_delimiters; CSVScannerDialect dialect; guint32 flags; } CSVScannerOptions; void csv_scanner_options_clean(CSVScannerOptions *options); void csv_scanner_options_copy(CSVScannerOptions *dst, CSVScannerOptions *src); void csv_scanner_options_set_dialect(CSVScannerOptions *options, CSVScannerDialect dialect); void csv_scanner_options_set_flags(CSVScannerOptions *options, guint32 flags); void csv_scanner_options_set_columns(CSVScannerOptions *options, GList *columns); void csv_scanner_options_set_delimiters(CSVScannerOptions *options, const gchar *delimiters); void csv_scanner_options_set_string_delimiters(CSVScannerOptions *options, GList *string_delimiters); void csv_scanner_options_set_quotes_start_and_end(CSVScannerOptions *options, const gchar *quotes_start, const gchar *quotes_end); void csv_scanner_options_set_quotes(CSVScannerOptions *options, const gchar *quotes); void csv_scanner_options_set_quote_pairs(CSVScannerOptions *options, const gchar *quote_pairs); void csv_scanner_options_set_null_value(CSVScannerOptions *options, const gchar *null_value); typedef struct { CSVScannerOptions *options; GList *current_column; const gchar *src; GString *current_value; gchar current_quote; } CSVScanner; const gchar *csv_scanner_get_current_name(CSVScanner *pstate); const gchar *csv_scanner_get_current_value(CSVScanner *pstate); gint csv_scanner_get_current_value_len(CSVScanner *self); gboolean csv_scanner_scan_next(CSVScanner *pstate); gboolean csv_scanner_is_scan_finished(CSVScanner *pstate); gchar *csv_scanner_dup_current_value(CSVScanner *self); void csv_scanner_init(CSVScanner *pstate, CSVScannerOptions *options, const gchar *input); void csv_scanner_deinit(CSVScanner *pstate); #endif syslog-ng-syslog-ng-3.13.2/lib/scanner/kv-scanner/000077500000000000000000000000001321171025300217035ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/scanner/kv-scanner/CMakeLists.txt000066400000000000000000000002131321171025300244370ustar00rootroot00000000000000set(KV_SCANNER_HEADERS kv-scanner/kv-scanner.h PARENT_SCOPE) set(KV_SCANNER_SOURCES kv-scanner/kv-scanner.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/scanner/kv-scanner/Makefile.am000066400000000000000000000003641321171025300237420ustar00rootroot00000000000000kvscannerincludedir = ${pkgincludedir}/scanner/kv-scanner kvscannerinclude_HEADERS = \ lib/scanner/kv-scanner/kv-scanner.h kvscanner_sources = \ lib/scanner/kv-scanner/kv-scanner.c include lib/scanner/kv-scanner/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/scanner/kv-scanner/kv-scanner.c000066400000000000000000000207601321171025300241230ustar00rootroot00000000000000/* * Copyright (c) 2015-2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "kv-scanner.h" #include "str-repr/decode.h" #include "str-repr/encode.h" #include "scratch-buffers.h" #include static inline gboolean _is_valid_key_character(gchar c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '_') || (c == '.') || (c == '-'); } static inline const gchar * _locate_separator(KVScanner *self, const gchar *start) { return strchr(start, self->value_separator); } static inline void _locate_start_of_key(KVScanner *self, const gchar *end_of_key, const gchar **start_of_key) { const gchar *input = &self->input[self->input_pos]; const gchar *cur; cur = end_of_key; while (cur > input && self->is_valid_key_character(*(cur - 1))) cur--; *start_of_key = cur; } static inline void _locate_end_of_key(KVScanner *self, const gchar *separator, const gchar **end_of_key) { const gchar *input = &self->input[self->input_pos]; const gchar *cur; /* this function locates the character pointing right next to the end of * the key, e.g. with this input * foo = bar * * it would start with the '=' sign and skip spaces backwards, to locate * the space right next to "foo" */ cur = separator; while (cur > input && (*(cur - 1)) == ' ') cur--; *end_of_key = cur; } static inline gboolean _extract_key_from_positions(KVScanner *self, const gchar *start_of_key, const gchar *end_of_key) { gint len = end_of_key - start_of_key; if (len >= 1) { g_string_assign_len(self->key, start_of_key, len); return TRUE; } return FALSE; } static inline void _extract_stray_word(KVScanner *self, const gchar *stray_word, gssize len) { if (len < 0) len = strlen(stray_word); if (self->stray_words && len > 0) { while (len > 0 && stray_word[len - 1] == ' ') len--; while (len > 0 && stray_word[0] == ' ') { stray_word++; len--; } if (len > 0) { if (self->stray_words->len) g_string_append_c(self->stray_words, ','); str_repr_encode_append(self->stray_words, stray_word, len, ","); } } } static gboolean _should_stop(KVScanner *self) { const gchar *input = &self->input[self->input_pos]; return *input == self->stop_char; } static gboolean _extract_key(KVScanner *self) { const gchar *input = &self->input[self->input_pos]; const gchar *start_of_key, *end_of_key; const gchar *separator; separator = _locate_separator(self, input); while (separator) { _locate_end_of_key(self, separator, &end_of_key); _locate_start_of_key(self, end_of_key, &start_of_key); if (_extract_key_from_positions(self, start_of_key, end_of_key)) { _extract_stray_word(self, input, start_of_key - input); self->input_pos = separator - self->input + 1; return TRUE; } separator = _locate_separator(self, separator + 1); } _extract_stray_word(self, input, -1); return FALSE; } static gboolean _is_quoted(const gchar *input) { return *input == '\'' || *input == '\"'; } static gboolean _key_follows(KVScanner *self, const gchar *cur) { const gchar *key = cur; while (self->is_valid_key_character(*key)) key++; while (*key == ' ') key++; return (key != cur) && (*key == self->value_separator); } static inline void _skip_spaces(const gchar **input) { const gchar *cur = *input; while (*cur == ' ') cur++; *input = cur; } static inline gboolean _end_of_string(const gchar *cur) { return *cur == 0; } static inline gboolean _pair_separator(KVScanner *self, const gchar *cur, const gchar **new_cur) { if (self->pair_separator && (strncmp(cur, self->pair_separator, self->pair_separator_len) == 0)) { *new_cur = cur + self->pair_separator_len; return TRUE; } return FALSE; } static inline gboolean _pair_separator_starts_with_a_space(KVScanner *self) { return (self->pair_separator && self->pair_separator[0] == ' '); } static gboolean _match_delimiter(const gchar *cur, const gchar **new_cur, gpointer user_data) { KVScanner *self = (gpointer) user_data; gboolean result = FALSE; if (!self->value_was_quoted && *cur == ' ') { if (_pair_separator_starts_with_a_space(self) && _pair_separator(self, cur, new_cur)) { result = TRUE; } else { _skip_spaces(&cur); if (_end_of_string(cur) || _key_follows(self, cur)) { *new_cur = cur; result = TRUE; } else if (_pair_separator(self, cur, new_cur)) { result = TRUE; } } } else if (*cur == ' ') { result = TRUE; *new_cur = cur + 1; } else if (*cur == self->stop_char) { result = TRUE; *new_cur = cur; } else { result = _pair_separator(self, cur, new_cur); } return result; } static inline void _skip_initial_spaces(KVScanner *self) { const gchar *input = &self->input[self->input_pos]; const gchar *end; while (*input == ' ' && !_match_delimiter(input, &end, self)) input++; self->input_pos = input - self->input; } static inline void _decode_value(KVScanner *self) { const gchar *input = &self->input[self->input_pos]; const gchar *end; StrReprDecodeOptions options = { 0, .match_delimiter = _match_delimiter, .match_delimiter_data = self, .delimiter_chars = { ' ', self->pair_separator[0], self->stop_char }, }; self->value_was_quoted = _is_quoted(input); if (str_repr_decode_with_options(self->value, input, &end, &options)) { self->input_pos = end - self->input; } else { /* quotation error, set was_quoted to FALSE */ self->value_was_quoted = FALSE; } } static void _extract_optional_annotation(KVScanner *self) { if (self->extract_annotation) self->extract_annotation(self); } static void _extract_value(KVScanner *self) { self->value_was_quoted = FALSE; _skip_initial_spaces(self); _decode_value(self); } static inline void _transform_value(KVScanner *self) { if (self->transform_value) { g_string_truncate(self->decoded_value, 0); if (self->transform_value(self)) g_string_assign_len(self->value, self->decoded_value->str, self->decoded_value->len); } } gboolean kv_scanner_scan_next(KVScanner *s) { KVScanner *self = (KVScanner *)s; if (_should_stop(self)) return FALSE; if (!_extract_key(self)) return FALSE; _extract_optional_annotation(self); _extract_value(self); _transform_value(s); return TRUE; } void kv_scanner_deinit(KVScanner *self) { } void kv_scanner_init(KVScanner *self, gchar value_separator, const gchar *pair_separator, gboolean extract_stray_words) { memset(self, 0, sizeof(*self)); self->key = scratch_buffers_alloc(); self->value = scratch_buffers_alloc(); self->decoded_value = scratch_buffers_alloc(); if (extract_stray_words) self->stray_words = scratch_buffers_alloc(); self->value_separator = value_separator; self->pair_separator = pair_separator ? : ", "; self->pair_separator_len = strlen(self->pair_separator); self->is_valid_key_character = _is_valid_key_character; self->stop_char = 0; } KVScanner * kv_scanner_new(gchar value_separator, const gchar *pair_separator, gboolean extract_stray_words) { KVScanner *self = g_new0(KVScanner, 1); kv_scanner_init(self, value_separator, pair_separator, extract_stray_words); return self; } void kv_scanner_free(KVScanner *self) { kv_scanner_deinit(self); g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/scanner/kv-scanner/kv-scanner.h000066400000000000000000000062201321171025300241230ustar00rootroot00000000000000/* * Copyright (c) 2015-2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef KV_SCANNER_H_INCLUDED #define KV_SCANNER_H_INCLUDED #include "syslog-ng.h" #include "str-utils.h" typedef struct _KVScanner KVScanner; typedef gboolean (*KVTransformValueFunc)(KVScanner *); typedef void (*KVExtractAnnotationFunc)(KVScanner *); typedef gboolean (*KVIsValidKeyCharFunc)(gchar c); struct _KVScanner { const gchar *input; gsize input_pos; GString *key; GString *value; GString *decoded_value; GString *stray_words; gboolean value_was_quoted; gchar value_separator; const gchar *pair_separator; gsize pair_separator_len; gchar stop_char; KVTransformValueFunc transform_value; KVExtractAnnotationFunc extract_annotation; KVIsValidKeyCharFunc is_valid_key_character; }; void kv_scanner_init(KVScanner *self, gchar value_separator, const gchar *pair_separator, gboolean extract_stray_words); void kv_scanner_deinit(KVScanner *self); static inline void kv_scanner_input(KVScanner *self, const gchar *input) { self->input = input; self->input_pos = 0; if (self->stray_words) g_string_truncate(self->stray_words, 0); } static inline const gchar * kv_scanner_get_current_key(KVScanner *self) { return self->key->str; } static inline const gchar * kv_scanner_get_current_value(KVScanner *self) { return self->value->str; } static inline const gchar * kv_scanner_get_stray_words(KVScanner *self) { return self->stray_words ? self->stray_words->str : NULL; } static inline void kv_scanner_set_transform_value(KVScanner *self, KVTransformValueFunc transform_value) { self->transform_value = transform_value; } static inline void kv_scanner_set_extract_annotation_func(KVScanner *self, KVExtractAnnotationFunc extract_annotation) { self->extract_annotation = extract_annotation; } static inline void kv_scanner_set_valid_key_character_func(KVScanner *self, KVIsValidKeyCharFunc is_valid_key_character) { self->is_valid_key_character = is_valid_key_character; } static inline void kv_scanner_set_stop_character(KVScanner *self, gchar stop_char) { self->stop_char = stop_char; } gboolean kv_scanner_scan_next(KVScanner *self); KVScanner *kv_scanner_new(gchar value_separator, const gchar *pair_separator, gboolean extract_stray_words); void kv_scanner_free(KVScanner *self); #endif syslog-ng-syslog-ng-3.13.2/lib/scanner/kv-scanner/tests/000077500000000000000000000000001321171025300230455ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/scanner/kv-scanner/tests/Makefile.am000066400000000000000000000005121321171025300250770ustar00rootroot00000000000000if ENABLE_CRITERION lib_kv_scanner_tests_TESTS = \ lib/scanner/kv-scanner/tests/test_kv_scanner check_PROGRAMS += ${lib_kv_scanner_tests_TESTS} lib_scanner_kv_scanner_tests_test_kv_scanner_CFLAGS = $(TEST_CFLAGS) -I$(top_srcdir)/lib/scanner/kv-scanner lib_scanner_kv_scanner_tests_test_kv_scanner_LDADD = $(TEST_LDADD) endif syslog-ng-syslog-ng-3.13.2/lib/scanner/kv-scanner/tests/test_kv_scanner.c000066400000000000000000000730551321171025300264130ustar00rootroot00000000000000/* * Copyright (c) 2015-2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include #include "stopwatch.h" #include "scratch-buffers.h" #include "apphook.h" #include "kv-scanner.h" static gboolean _expect_no_more_tokens(KVScanner *scanner, gchar **error) { GString *msg; gboolean ok = kv_scanner_scan_next(scanner); if (ok) { msg = g_string_new("kv_scanner is expected to return no more key-value pairs "); do { const gchar *key = kv_scanner_get_current_key(scanner); if (!key) key = ""; const gchar *value = kv_scanner_get_current_value(scanner); if (!value) value = ""; g_string_append_printf(msg, "[%s/%s]", key, value); } while (kv_scanner_scan_next(scanner)); *error = g_string_free(msg, FALSE); return FALSE; } return TRUE; } static gboolean _expect_current_key_equals(KVScanner *scanner, const gchar *expected_key, gchar **error) { const gchar *key = kv_scanner_get_current_key(scanner); if (strcmp(key, expected_key) != 0) { *error = g_strdup_printf("expected key mismatch key=%s, expected=%s", key, expected_key); return FALSE; } return TRUE; } static gboolean _expect_current_value_equals(KVScanner *scanner, const gchar *expected_value, gchar **error) { const gchar *value = kv_scanner_get_current_value(scanner); if (strcmp(value, expected_value) != 0) { *error = g_strdup_printf("expected value mismatch value=%s, expected=%s", value, expected_value); return FALSE; } return TRUE; } static gboolean _expect_next_key_value(KVScanner *scanner, const gchar *key, const gchar *value, gchar **error) { g_assert(value); gboolean ok = kv_scanner_scan_next(scanner); if (ok) { return _expect_current_key_equals(scanner, key, error) && _expect_current_value_equals(scanner, value, error); } else { *error = g_strdup_printf("kv_scanner is expected to return TRUE for scan_next(), " "first unconsumed pair: [%s/%s]", key, value); } return FALSE; } typedef struct _ScannerConfig { gchar kv_separator; const gchar *pair_separator; gboolean extract_stray_words; KVTransformValueFunc transform_value; } ScannerConfig; typedef struct _KVQElement { const gchar *const key; const gchar *const value; gboolean quoted; } KVQElement; typedef struct _KVQContainer { const gsize n; const KVQElement arg[8]; } KVQContainer; typedef struct _KVElement { const gchar *key; const gchar *value; } KVElement; typedef struct _KVContainer { gsize n; const KVElement arg[32]; } KVContainer; typedef struct Testcase_t { gchar *input; KVContainer expected; } Testcase; KVScanner * create_kv_scanner(const ScannerConfig config) { KVScanner *scanner = kv_scanner_new(config.kv_separator, config.pair_separator, config.extract_stray_words); scanner->transform_value = config.transform_value; return scanner; } #define VARARG_STRUCT(VARARG_STRUCT_cont, VARARG_STRUCT_elem, ...) \ (const VARARG_STRUCT_cont) { \ .n = sizeof((const VARARG_STRUCT_elem[]) { __VA_ARGS__ }) / sizeof(VARARG_STRUCT_elem), \ .arg = {__VA_ARGS__}\ } static gboolean _expect_kv_pairs(KVScanner *scanner, KVContainer args, gchar **error) { for (gsize i = 0; i < args.n; i++) { if (!_expect_next_key_value(scanner, args.arg[i].key, args.arg[i].value, error)) { return FALSE; } } return _expect_no_more_tokens(scanner, error); } static gboolean _expect_kvq_triplets(KVScanner *scanner, KVQContainer args, gchar **error) { for (gsize i = 0; i < args.n; i++) { if (!_expect_next_key_value(scanner, args.arg[i].key, args.arg[i].value, error)) return FALSE; if (scanner->value_was_quoted != args.arg[i].quoted) { *error = g_strdup_printf("mismatch in value_was_quoted for [%s/%s]", args.arg[i].key, args.arg[i].value); return FALSE; } } return _expect_no_more_tokens(scanner, error); } #define INIT_KVQCONTAINER(...) VARARG_STRUCT(KVQContainer, KVQElement, __VA_ARGS__) #define _IMPL_EXPECT_KVQ(SCANNER_config, TEST_KV_SCAN_input, ...) \ do { \ KVScanner *scanner = create_kv_scanner(SCANNER_config); \ gchar *error = NULL; \ \ kv_scanner_input(scanner, TEST_KV_SCAN_input); \ if (!_expect_kvq_triplets(scanner, INIT_KVQCONTAINER(__VA_ARGS__), &error)) \ { \ cr_expect(FALSE, "%s", error); \ g_free(error);\ } \ kv_scanner_free(scanner); \ } while (0) #define _EXPECT_KVQ_TRIPLETS(...) \ do { \ _IMPL_EXPECT_KVQ(((ScannerConfig) {'='}), __VA_ARGS__); \ } while(0) #define INIT_KVCONTAINER(...) VARARG_STRUCT(KVContainer, KVElement, __VA_ARGS__) #define _IMPL_EXPECT_KV(TEST_KV_SCAN_config, TEST_KV_SCAN_input, ...) \ do { \ KVScanner *scanner = create_kv_scanner(TEST_KV_SCAN_config); \ gchar *error = NULL; \ \ kv_scanner_input(scanner, TEST_KV_SCAN_input); \ if (!_expect_kv_pairs(scanner, INIT_KVCONTAINER(__VA_ARGS__), &error)) \ { \ cr_expect(FALSE, "%s", error); \ g_free(error);\ } \ cr_expect_eq(kv_scanner_get_stray_words(scanner), NULL, \ "stray words are not expected but still returned"); \ kv_scanner_free(scanner); \ } while (0) #define _EXPECT_KV_PAIRS(...) \ do { \ _IMPL_EXPECT_KV(((ScannerConfig) {'='}), __VA_ARGS__); \ } while (0) #define _EXPECT_KV_PAIRS_WITH_CONFIG(TEST_KV_SCAN_config, ...) \ do { \ _IMPL_EXPECT_KV(TEST_KV_SCAN_config, __VA_ARGS__); \ } while (0) #define _EXPECT_KV_AND_STRAY_WORDS(INPUT, STRAY, ...) \ do { \ KVScanner *scanner = create_kv_scanner(((ScannerConfig) { \ .kv_separator = '=', \ .extract_stray_words=TRUE})); \ gchar *error = NULL; \ \ kv_scanner_input(scanner, INPUT); \ if (!_expect_kv_pairs(scanner, INIT_KVCONTAINER(__VA_ARGS__), &error)) \ { \ cr_expect(FALSE, "%s", error); \ g_free(error);\ } \ cr_expect_str_eq(kv_scanner_get_stray_words(scanner), STRAY, \ "Stray words mismatch, value=%s, expected=%s", \ kv_scanner_get_stray_words(scanner), STRAY); \ kv_scanner_free(scanner); \ } while (0) Test(kv_scanner, incomplete_string_returns_no_pairs) { _EXPECT_KV_PAIRS(""); _EXPECT_KV_PAIRS("f"); _EXPECT_KV_PAIRS("fo"); _EXPECT_KV_PAIRS("foo"); } Test(kv_scanner, name_equals_value_returns_a_pair) { _EXPECT_KV_PAIRS("foo=", { "foo", "" }); _EXPECT_KV_PAIRS("foo=b", { "foo", "b" }); _EXPECT_KV_PAIRS("foo=bar", { "foo", "bar" }); _EXPECT_KV_PAIRS("foo=barbar", { "foo", "barbar" }); } Test(kv_scanner, allowed_characters_in_a_key_are_letters_digits_dash_underscore_and_dot) { _EXPECT_KV_PAIRS("FOOfoo123-_._-321oofOOF=value", {"FOOfoo123-_._-321oofOOF", "value"}); } Test(kv_scanner, initial_stray_words_are_ignored) { _EXPECT_KV_PAIRS("lorem ipsum foo=bar", { "foo", "bar" }); _EXPECT_KV_PAIRS("lorem ipsum/dolor @sitamen foo=bar", { "foo", "bar" }); _EXPECT_KV_PAIRS("lorem ipsum/dolor = foo=bar\"", { "dolor", "" }, { "foo", "bar\"" }); _EXPECT_KV_PAIRS("a b c=d", {"c", "d"}); _EXPECT_KV_PAIRS("x *k=v", { "k", "v" }); } Test(kv_scanner, non_initial_stray_words_are_added_to_the_last_value) { _EXPECT_KV_PAIRS("foo=bar lorem ipsum key=value some more values", { "foo", "bar lorem ipsum" }, { "key", "value some more values" }); } Test(kv_scanner, empty_values_in_a_series_of_key_values) { _EXPECT_KV_PAIRS("k= a=b c=d", {"k", ""}, {"a", "b"}, {"c", "d"}); _EXPECT_KV_PAIRS("k=v a= c=d", {"k", "v"}, {"a", ""}, {"c", "d"}); _EXPECT_KV_PAIRS("k=v a=b c=", {"k", "v"}, {"a", "b"}, {"c", ""}); } Test(kv_scanner, multiple_key_values_return_multiple_pairs) { _EXPECT_KV_PAIRS("key1=value1 key2=value2 key3=value3 ", { "key1", "value1" }, { "key2", "value2" }, { "key3", "value3" }); } Test(kv_scanner, spaces_between_values_are_ignored) { _EXPECT_KV_PAIRS("key1=value1 key2=value2 key3=value3 ", { "key1", "value1" }, { "key2", "value2" }, { "key3", "value3" }); } Test(kv_scanner, comma_separated_values) { _EXPECT_KV_PAIRS("key1=value1, key2=value2, key3=value3", { "key1", "value1" }, { "key2", "value2" }, { "key3", "value3" }); /* NOTE: comma on its own is not a delimiter, as the default delimiter is ", " * A testcase below would test single character separator with ';' */ _EXPECT_KV_PAIRS("key1=value1,key2=value2,key3=value3", { "key1", "value1,key2=value2,key3=value3" }); /* In value2 the spaces are considered part of the value as we don't have * a delimiter and spaces get concatenated into the value */ _EXPECT_KV_PAIRS("key1=value1, key2=value2 , key3=value3", { "key1", "value1" }, { "key2", "value2" }, { "key3", "value3" }); } Test(kv_scanner, tab_is_not_considered_a_separator) { _EXPECT_KV_PAIRS("key1=value1\tkey2=value2 key3=value3", { "key1", "value1\tkey2=value2" }, { "key3", "value3" }); _EXPECT_KV_PAIRS("key1=value1,\tkey2=value2 key3=value3", { "key1", "value1,\tkey2=value2" }, { "key3", "value3" }); _EXPECT_KV_PAIRS("key1=value1\t key2=value2 key3=value3", { "key1", "value1\t" }, { "key2", "value2" }, { "key3", "value3" }); _EXPECT_KV_PAIRS("k=\t", { "k", "\t" }); _EXPECT_KV_PAIRS("k=,\t", { "k", ",\t" }); } Test(kv_scanner, quoted_values_are_unquoted_like_c_strings) { _EXPECT_KV_PAIRS("foo=\"\\\"\" bar=baz", { "foo", "\"" }, { "bar", "baz"}); _EXPECT_KV_PAIRS("foo='\"' bar=baz", { "foo", "\"" }, { "bar", "baz"}); _EXPECT_KV_PAIRS("foo=\"bar\"", { "foo", "bar" }); _EXPECT_KV_PAIRS("key1=\"value1\" key2=\"value2\"", { "key1", "value1" }, { "key2", "value2" }); /* embedded quote */ _EXPECT_KV_PAIRS("key1=\"\\\"value1\"", { "key1", "\"value1" }); /* control sequences */ _EXPECT_KV_PAIRS("key1=\"\\b \\f \\n \\r \\t \\\\\"", { "key1", "\b \f \n \r \t \\" }); /* unknown backslash escape is left as is */ _EXPECT_KV_PAIRS("key1=\"\\p\"", { "key1", "\\p" }); _EXPECT_KV_PAIRS("key1='value1' key2='value2'", { "key1", "value1" }, { "key2", "value2" }); /* embedded quote */ _EXPECT_KV_PAIRS("key1='\\'value1'", { "key1", "'value1" }); /* control sequences */ _EXPECT_KV_PAIRS("key1='\\b \\f \\n \\r \\t \\\\'", { "key1", "\b \f \n \r \t \\" }); /* unknown backslash escape is left as is */ _EXPECT_KV_PAIRS("key1='\\p'", { "key1", "\\p" }); _EXPECT_KV_PAIRS("key1=\\b\\f\\n\\r\\t\\\\", { "key1", "\\b\\f\\n\\r\\t\\\\" }); _EXPECT_KV_PAIRS("key1=\b\f\n\r\\", { "key1", "\b\f\n\r\\" }); _EXPECT_KV_PAIRS("foo=\"bar baz\"", {"foo", "bar baz"}); } Test(kv_scanner, quotes_embedded_in_an_unquoted_value_are_left_intact) { _EXPECT_KV_PAIRS("foo=a \"bar baz\" ", {"foo", "a \"bar baz\""}); _EXPECT_KV_PAIRS("foo=a \"bar baz", {"foo", "a \"bar baz"}); _EXPECT_KV_PAIRS("foo=a \"bar baz c=d", {"foo", "a \"bar baz"}, {"c", "d"}); _EXPECT_KV_PAIRS("foo=a \"bar baz\"=f c=d a", {"foo", "a \"bar baz\"=f"}, {"c", "d a"}); _EXPECT_KV_PAIRS("foo=\\\"bar baz\\\"", {"foo", "\\\"bar baz\\\""}); } Test(kv_scanner, separator_in_an_unquoted_value_is_taken_literally) { _EXPECT_KV_PAIRS("k=a=b c=d", {"k", "a=b"}, {"c", "d"}); _EXPECT_KV_PAIRS("a==b=", {"a", "=b="}); _EXPECT_KV_PAIRS("a=,=b=a", {"a", ",=b=a"}); _EXPECT_KV_PAIRS("a= =a", {"a", "=a"}); } Test(kv_scanner, keys_without_value_separator_are_ignored) { _EXPECT_KV_PAIRS("key1 key2=value2 key3 key4=value4", { "key2", "value2 key3" }, { "key4", "value4" }); _EXPECT_KV_PAIRS("key1= key2=value2 key3= key4=value4 key5= key6=value6", { "key1", "" }, { "key2", "value2" }, { "key3", "" }, { "key4", "value4" }, { "key5", "" }, { "key6", "value6" }); } Test(kv_scanner, quoted_values_are_considered_one_token_thus_space_based_concatenation_does_not_happen) { _EXPECT_KV_PAIRS("key1=\"value foo\" key2=marker", { "key1", "value foo" }, { "key2", "marker" }); _EXPECT_KV_PAIRS("key1=\"value foo embedded_key=emb_value\" key2=marker", { "key1", "value foo embedded_key=emb_value" }, { "key2", "marker" }); /* embedded quote */ _EXPECT_KV_PAIRS("key1=\"value foo\\\"\" key2=marker", { "key1", "value foo\"" }, { "key2", "marker" }); _EXPECT_KV_PAIRS("key1='value foo\\'' key2=marker", { "key1", "value foo'" }, { "key2", "marker" }); _EXPECT_KV_PAIRS("key1=\"value foo, foo2 =@,\\\"\" key2='value foo, a='", { "key1", "value foo, foo2 =@,\"" }, { "key2", "value foo, a=" }); /* NOTE: baz is not added to the value, it is a stray word */ _EXPECT_KV_PAIRS("foo=\"bar\" baz c=d", {"foo", "bar"}, {"c", "d"}); } static gboolean _parse_value_by_incrementing_all_bytes(KVScanner *self) { gint i; g_string_assign(self->decoded_value, self->value->str); for (i = 0; i < self->decoded_value->len; i++) self->decoded_value->str[i]++; return TRUE; } Test(kv_scanner, transforms_values_if_transform_value_is_set) { ScannerConfig config = { .kv_separator = '=', .transform_value = _parse_value_by_incrementing_all_bytes }; _EXPECT_KV_PAIRS_WITH_CONFIG(config, "foo=\"bar\"", { "foo", "cbs" }); } Test(kv_scanner, pair_separator_space_disables_space_related_heuristics) { ScannerConfig config = { .kv_separator = '=', .pair_separator = " ", }; /* v2 and v4 below goes to stray words, as the pair-separator is a space, * so we disable the heuristics about spaces embedded in non-quoted values * */ _EXPECT_KV_PAIRS_WITH_CONFIG(config, "foo=v1 v2 bar=v3 v4", {"foo", "v1"}, {"bar", "v3"}); /* if the separator is multiple spaces, we still trim spaces at the end of * line (that is a partial separator). */ config.pair_separator = " "; _EXPECT_KV_PAIRS_WITH_CONFIG(config, "foo=v1 v2 bar=v3 v4 ", {"foo", "v1 v2"}, {"bar", "v3 v4"}); } Test(kv_scanner, pair_separator_causes_values_to_be_split_at_that_character) { ScannerConfig config = { .kv_separator = '=', .pair_separator = ";", }; _EXPECT_KV_PAIRS_WITH_CONFIG(config, "foo=bar; bar=foo;", {"foo", "bar"}, {"bar", "foo"}); _EXPECT_KV_PAIRS_WITH_CONFIG(config, "foo=bar;bar=foo;baz=foo", {"foo", "bar"}, {"bar", "foo"}, {"baz", "foo"}); _EXPECT_KV_PAIRS_WITH_CONFIG(config, "foo=bar;bar=foo;", {"foo", "bar"}, {"bar", "foo"}); _EXPECT_KV_PAIRS_WITH_CONFIG(config, "foo=bar baz;bar=foo;", {"foo", "bar baz"}, {"bar", "foo"}); _EXPECT_KV_PAIRS_WITH_CONFIG(config, "foo=bar baz ;bar=foo;", {"foo", "bar baz"}, {"bar", "foo"}); } Test(kv_scanner, quotation_is_stored_in_the_was_quoted_value_member) { _EXPECT_KVQ_TRIPLETS("foo=\"bar\"", {"foo", "bar", TRUE}); _EXPECT_KVQ_TRIPLETS("foo='bar'", {"foo", "bar", TRUE}); _EXPECT_KVQ_TRIPLETS("foo=bar", {"foo", "bar", FALSE}); _EXPECT_KVQ_TRIPLETS("foo='bar' k=v", {"foo", "bar", TRUE}, {"k", "v", FALSE}); } Test(kv_scanner, spaces_around_value_separator_are_ignored) { ScannerConfig config= { .kv_separator=':', }; _IMPL_EXPECT_KV(config, "key1: \"value1\" key2 : value2 key3 :value3 ", {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}); } Test(kv_scanner, value_separator_is_used_to_separate_key_from_value) { ScannerConfig config= { .kv_separator = ':', }; _EXPECT_KV_PAIRS_WITH_CONFIG(config, "key1:value1 key2:value2 key3:value3 ", { "key1", "value1" }, { "key2", "value2" }, { "key3", "value3" }); } Test(kv_scanner, invalid_value_encoding_is_copied_literally) { _EXPECT_KV_PAIRS("k=\xc3", { "k", "\xc3" }); _EXPECT_KV_PAIRS("k=\xc3v", { "k", "\xc3v" }); _EXPECT_KV_PAIRS("k=\xff", { "k", "\xff" }); _EXPECT_KV_PAIRS("k=\xffv", { "k", "\xffv" }); _EXPECT_KV_PAIRS("k=\"\xc3\"", { "k", "\xc3" }); _EXPECT_KV_PAIRS("k=\"\xc3v\"", { "k", "\xc3v" }); _EXPECT_KV_PAIRS("k=\"\xff\"", { "k", "\xff" }); _EXPECT_KV_PAIRS(" k=\"\xffv\"", { "k", "\xffv" }); } Test(kv_scanner, separator_in_key) { ScannerConfig config= { .kv_separator = '-', }; _EXPECT_KV_PAIRS_WITH_CONFIG(config, "k-v", { "k", "v" }); _EXPECT_KV_PAIRS_WITH_CONFIG(config, "k--v", { "k", "-v" }); _EXPECT_KV_PAIRS_WITH_CONFIG(config, "---", { "-", "-" }); } Test(kv_scanner, empty_keys) { _EXPECT_KV_PAIRS("=v"); _EXPECT_KV_PAIRS("k*=v"); _EXPECT_KV_PAIRS("="); _EXPECT_KV_PAIRS("=="); _EXPECT_KV_PAIRS("==="); _EXPECT_KV_PAIRS(" ="); _EXPECT_KV_PAIRS(" =="); _EXPECT_KV_PAIRS(" ==="); _EXPECT_KV_PAIRS(" = ="); _EXPECT_KV_PAIRS(" ==k=", { "k", "" }); _EXPECT_KV_PAIRS(" = =k=", { "k", "" }); _EXPECT_KV_PAIRS(" =k=", { "k", "" }); _EXPECT_KV_PAIRS(" =k=v", { "k", "v" }); _EXPECT_KV_PAIRS(" ==k=v", { "k", "v" }); _EXPECT_KV_PAIRS(" =k=v=w", { "k", "v=w" }); } Test(kv_scanner, unclosed_quotes) { _EXPECT_KV_PAIRS("k=\"a", { "k", "\"a" }); _EXPECT_KV_PAIRS("k=\\", { "k", "\\" }); _EXPECT_KV_PAIRS("k=\"\\", { "k", "\"\\" }); _EXPECT_KV_PAIRS("k='a", { "k", "'a" }); _EXPECT_KV_PAIRS("k='\\", { "k", "'\\" }); /* backslash is not special if not within quotes */ _EXPECT_KV_PAIRS("k=\\", {"k", "\\"}); _EXPECT_KV_PAIRS("foo=bar\"", {"foo", "bar\""}); _EXPECT_KV_PAIRS("foo='bar", {"foo", "'bar"}); } Test(kv_scanner, comma_separator) { _EXPECT_KV_PAIRS(", k=v", { "k", "v" }); _EXPECT_KV_PAIRS(",k=v", { "k", "v" }); _EXPECT_KV_PAIRS("k=v,", { "k", "v," }); _EXPECT_KV_PAIRS("k=v, ", { "k", "v" }); } Test(kv_scanner, multiple_separators) { _EXPECT_KV_PAIRS("k==", { "k", "=" }); _EXPECT_KV_PAIRS("k===", { "k", "==" }); _EXPECT_KV_PAIRS("k===a", {"k", "==a"}); _EXPECT_KV_PAIRS("k===a=b", {"k", "==a=b"}); } Test(kv_scanner, keys_only_use_a_restricted_set_of_characters) { _EXPECT_KV_PAIRS("k-j=v", { "k-j", "v" }); _EXPECT_KV_PAIRS("0=v", { "0", "v" }); _EXPECT_KV_PAIRS("_=v", { "_", "v" }); _EXPECT_KV_PAIRS(":=v"); _EXPECT_KV_PAIRS(":="); _EXPECT_KV_PAIRS("Z=v", { "Z", "v" }); /* no value, as the key is not in [a-zA-Z0-9-_] */ _EXPECT_KV_PAIRS("á=v"); _EXPECT_KV_PAIRS("*k=v", { "k", "v" }); } Test(kv_scanner, unquoted_values_can_have_embedded_control_characters) { _EXPECT_KV_PAIRS("k1=\\b\\f\\n\\r\\t\\\\", {"k1", "\\b\\f\\n\\r\\t\\\\"}); _EXPECT_KV_PAIRS("k1=\b\f\n\r\\", {"k1", "\b\f\n\r\\"}); } Test(kv_scanner, spaces_are_trimmed_between_key_and_separator) { _EXPECT_KV_PAIRS("foo =bar", {"foo", "bar"}); _EXPECT_KV_PAIRS("foo= bar", {"foo", "bar"}); } Test(kv_scanner, space_is_only_a_delimiter_if_a_key_follows) { _EXPECT_KV_PAIRS("foo=bar ggg", {"foo", "bar ggg"}); _EXPECT_KV_PAIRS("foo=bar ggg baz=ez", {"foo", "bar ggg"}, {"baz", "ez"}); } Test(kv_scanner, spaces_are_trimmed_from_key_names) { _EXPECT_KV_PAIRS(" foo =bar ggg baz=ez", {"foo", "bar ggg"}, {"baz", "ez"}); _EXPECT_KV_PAIRS("foo =bar ggg baz=ez", {"foo", "bar ggg"}, {"baz", "ez"}); _EXPECT_KV_PAIRS(" foo=bar ggg baz=ez", {"foo", "bar ggg"}, {"baz", "ez"}); _EXPECT_KV_PAIRS("foo = bar ggg baz = ez", {"foo", "bar ggg"}, {"baz", "ez"}); _EXPECT_KV_PAIRS("k=== a", {"k", "== a"}); } Test(kv_scanner, initial_spaces_are_trimmed_from_values) { _EXPECT_KV_PAIRS(" k= b", {"k", "b"}); } Test(kv_scanner, stray_words_are_stored) { _EXPECT_KV_AND_STRAY_WORDS("foo=bar", "", {"foo", "bar"}); _EXPECT_KV_AND_STRAY_WORDS("alma foo=bar", "alma", {"foo", "bar"}); _EXPECT_KV_AND_STRAY_WORDS("alma foo=bar, korte bar=foo", "alma,korte", {"foo", "bar"}, {"bar", "foo"}); _EXPECT_KV_AND_STRAY_WORDS("alma foo=bar, korte bar=foo, narancs", "alma,korte,narancs", {"foo", "bar"}, {"bar", "foo"}); } Test(kv_scanner, key_buffer_underrun) { const gchar *buffer = "ab=v"; const gchar *input = buffer + 2; _EXPECT_KV_PAIRS(input); } static Testcase * _provide_cases_for_performance_test_nothing_to_parse(void) { Testcase tc[] = { { .input = "Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. \ Try to increase stolen memory size if available in BIOS.", .expected = INIT_KVCONTAINER(), }, { .input = "interrupt took too long (3136 > 3127), lowering kernel.perf_event_max_sample_rate to 63750", .expected = INIT_KVCONTAINER(), }, { .input = "Linux version 4.6.3-040603-generic (kernel@gomeisa) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-4ubuntu1) ) \ #201606241434 SMP Fri Jun 24 18:36:33 UTC 2016", .expected = INIT_KVCONTAINER(), }, {} }; return g_memdup(tc, sizeof(tc)); } static Testcase * _provide_cases_for_performance_test_parse_long_msg(void) { Testcase tc[] = { { .input = "PF: filter/forward DROP \ IN=15dd205a6ac8b0c80ab3bcdcc5649c9c830074cdbdc094ff1d79f20f17c56843 \ OUT=980816f36b77e58d342de41f85854376d10cf9bf33aa1934e129ffd77ddc833d \ SRC=cc8177fc0c8681d3d5d2a42bc1ed86990f773589592fa3100c23fae445f8a260 \ DST=5fee25396500fc798e10b4dcb0b3fb315618ff11843be59978c0d5b41cd9f12c \ LEN=71ee45a3c0db9a9865f7313dd3372cf60dca6479d46261f3542eb9346e4a04d6 \ TOS=c4dd67368286d02d62bdaa7a775b7594765d5210c9ad20cc3c24148d493353d7 \ PREC=c4dd67368286d02d62bdaa7a775b7594765d5210c9ad20cc3c24148d493353d7 \ TTL=da4ea2a5506f2693eae190d9360a1f31793c98a1adade51d93533a6f520ace1c \ ID=242a9377518dd1afaf021b2d0bfe6484e3fe48a878152f76dec99a396160022c \ PROTO=dc4030f9688d6e67dfc4c5f8f7afcbdbf5c30de866d8a3c6e1dd038768ab91c3 \ SPT=1e7996c7b0181429bba237ac2799ee5edc31aca2d5d90c39a48f9e9a3d4078bd \ DPT=ca902d4a8acbdea132ada81a004081f51c5c9279d409cee414de5a39a139fab6 \ LEN=c2356069e9d1e79ca924378153cfbbfb4d4416b1f99d41a2940bfdb66c5319db", .expected = INIT_KVCONTAINER( {"IN", "15dd205a6ac8b0c80ab3bcdcc5649c9c830074cdbdc094ff1d79f20f17c56843"}, {"OUT", "980816f36b77e58d342de41f85854376d10cf9bf33aa1934e129ffd77ddc833d"}, {"SRC", "cc8177fc0c8681d3d5d2a42bc1ed86990f773589592fa3100c23fae445f8a260"}, {"DST", "5fee25396500fc798e10b4dcb0b3fb315618ff11843be59978c0d5b41cd9f12c"}, {"LEN", "71ee45a3c0db9a9865f7313dd3372cf60dca6479d46261f3542eb9346e4a04d6"}, {"TOS", "c4dd67368286d02d62bdaa7a775b7594765d5210c9ad20cc3c24148d493353d7"}, {"PREC", "c4dd67368286d02d62bdaa7a775b7594765d5210c9ad20cc3c24148d493353d7"}, {"TTL", "da4ea2a5506f2693eae190d9360a1f31793c98a1adade51d93533a6f520ace1c"}, {"ID", "242a9377518dd1afaf021b2d0bfe6484e3fe48a878152f76dec99a396160022c"}, {"PROTO", "dc4030f9688d6e67dfc4c5f8f7afcbdbf5c30de866d8a3c6e1dd038768ab91c3"}, {"SPT", "1e7996c7b0181429bba237ac2799ee5edc31aca2d5d90c39a48f9e9a3d4078bd"}, {"DPT", "ca902d4a8acbdea132ada81a004081f51c5c9279d409cee414de5a39a139fab6"}, {"LEN", "c2356069e9d1e79ca924378153cfbbfb4d4416b1f99d41a2940bfdb66c5319db"}), }, { .input = "PF: filter/forward DROP \ IN='15dd205a6ac8b0c80ab3bcdcc5649c9c830074cdbdc094ff1d79f20f17c56843' \ OUT='980816f36b77e58d342de41f85854376d10cf9bf33aa1934e129ffd77ddc833d' \ SRC='cc8177fc0c8681d3d5d2a42bc1ed86990f773589592fa3100c23fae445f8a260' \ DST='5fee25396500fc798e10b4dcb0b3fb315618ff11843be59978c0d5b41cd9f12c' \ LEN='71ee45a3c0db9a9865f7313dd3372cf60dca6479d46261f3542eb9346e4a04d6' \ TOS='c4dd67368286d02d62bdaa7a775b7594765d5210c9ad20cc3c24148d493353d7' \ PREC='c4dd67368286d02d62bdaa7a775b7594765d5210c9ad20cc3c24148d493353d7' \ TTL='da4ea2a5506f2693eae190d9360a1f31793c98a1adade51d93533a6f520ace1c' \ ID='242a9377518dd1afaf021b2d0bfe6484e3fe48a878152f76dec99a396160022c' \ PROTO='dc4030f9688d6e67dfc4c5f8f7afcbdbf5c30de866d8a3c6e1dd038768ab91c3' \ SPT='1e7996c7b0181429bba237ac2799ee5edc31aca2d5d90c39a48f9e9a3d4078bd' \ DPT='ca902d4a8acbdea132ada81a004081f51c5c9279d409cee414de5a39a139fab6' \ LEN='c2356069e9d1e79ca924378153cfbbfb4d4416b1f99d41a2940bfdb66c5319db'", .expected = INIT_KVCONTAINER( {"IN", "15dd205a6ac8b0c80ab3bcdcc5649c9c830074cdbdc094ff1d79f20f17c56843"}, {"OUT", "980816f36b77e58d342de41f85854376d10cf9bf33aa1934e129ffd77ddc833d"}, {"SRC", "cc8177fc0c8681d3d5d2a42bc1ed86990f773589592fa3100c23fae445f8a260"}, {"DST", "5fee25396500fc798e10b4dcb0b3fb315618ff11843be59978c0d5b41cd9f12c"}, {"LEN", "71ee45a3c0db9a9865f7313dd3372cf60dca6479d46261f3542eb9346e4a04d6"}, {"TOS", "c4dd67368286d02d62bdaa7a775b7594765d5210c9ad20cc3c24148d493353d7"}, {"PREC", "c4dd67368286d02d62bdaa7a775b7594765d5210c9ad20cc3c24148d493353d7"}, {"TTL", "da4ea2a5506f2693eae190d9360a1f31793c98a1adade51d93533a6f520ace1c"}, {"ID", "242a9377518dd1afaf021b2d0bfe6484e3fe48a878152f76dec99a396160022c"}, {"PROTO", "dc4030f9688d6e67dfc4c5f8f7afcbdbf5c30de866d8a3c6e1dd038768ab91c3"}, {"SPT", "1e7996c7b0181429bba237ac2799ee5edc31aca2d5d90c39a48f9e9a3d4078bd"}, {"DPT", "ca902d4a8acbdea132ada81a004081f51c5c9279d409cee414de5a39a139fab6"}, {"LEN", "c2356069e9d1e79ca924378153cfbbfb4d4416b1f99d41a2940bfdb66c5319db"}), }, { .input = "fw=108.53.156.38 pri=6 c=262144 m=98 msg=\"Connection Opened\" f=2 sess=\"None\" \ n=16351474 src=10.0.5.200:57719:X0:MOGWAI dst=71.250.0.14:53:X1 dstMac=f8:c0:01:73:c7:c1 proto=udp/dns sent=66", .expected = INIT_KVCONTAINER( {"fw", "108.53.156.38"}, {"pri", "6"}, {"c", "262144"}, {"m", "98"}, {"msg", "Connection Opened"}, {"f", "2"}, {"sess", "None"}, {"n", "16351474"}, {"src", "10.0.5.200:57719:X0:MOGWAI"}, {"dst", "71.250.0.14:53:X1"}, {"dstMac", "f8:c0:01:73:c7:c1"}, {"proto", "udp/dns"}, {"sent", "66"}), }, { .input = "sn=C0EAE484E43E time=\"2016-07-08 13:42:58\" fw=132.237.143.192 pri=5 c=4 m=16 msg=\"Web site access allowed\" \ app=11 sess=\"Auto\" n=5086 usr=\"DEMO\\primarystudent\" src=10.2.3.64:50682:X2-V3023 dst=157.55.240.220:443:X1 \ srcMac=00:50:56:8e:55:8e dstMac=c0:ea:e4:84:e4:40 proto=tcp/https dstname=sls.update.microsoft.com arg= code=27 \ Category=\"Information Technology/Computers\" fw_action=\"process\"", .expected = INIT_KVCONTAINER( {"sn", "C0EAE484E43E"}, {"time", "2016-07-08 13:42:58"}, {"fw", "132.237.143.192"}, {"pri", "5"}, {"c", "4"}, {"m", "16"}, {"msg", "Web site access allowed"}, {"app", "11"}, {"sess", "Auto"}, {"n", "5086"}, {"usr", "DEMO\\primarystudent"}, {"src", "10.2.3.64:50682:X2-V3023"}, {"dst", "157.55.240.220:443:X1"}, {"srcMac", "00:50:56:8e:55:8e"}, {"dstMac", "c0:ea:e4:84:e4:40"}, {"proto", "tcp/https"}, {"dstname", "sls.update.microsoft.com"}, {"arg", ""}, {"code", "27"}, {"Category", "Information Technology/Computers"}, {"fw_action", "process"}), }, { .input = "IN=em1 OUT= MAC=a2:be:d2:ab:11:af:e2:f2:00:00 SRC=192.168.2.115 DST=192.168.1.23 " "LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=9434 DF PROTO=TCP SPT=58428 DPT=443 WINDOW=8192 " "RES=0x00 SYN URGP=0", .expected = INIT_KVCONTAINER( {"IN", "em1"}, {"OUT", ""}, {"MAC", "a2:be:d2:ab:11:af:e2:f2:00:00"}, {"SRC", "192.168.2.115"}, {"DST", "192.168.1.23"}, {"LEN", "52"}, {"TOS", "0x00"}, {"PREC", "0x00"}, {"TTL", "127"}, {"ID", "9434 DF"}, {"PROTO", "TCP"}, {"SPT", "58428"}, {"DPT", "443"}, {"WINDOW", "8192"}, {"RES", "0x00 SYN"}, {"URGP", "0"}, ), }, {} }; return g_memdup(tc, sizeof(tc)); } #define ITERATION_NUMBER 100000 static void _test_performance(Testcase *tcs, gchar *title) { const Testcase *tc; gint iteration_index = 0; if (title) { printf("Performance test: %s\n", title); } for (tc = tcs; tc->input; tc++) { KVScanner scanner; start_stopwatch(); for (iteration_index = 0; iteration_index < ITERATION_NUMBER; iteration_index++) { gchar *error = NULL; kv_scanner_init(&scanner, '=', ",", FALSE); kv_scanner_input(&scanner, tc->input); if (!_expect_kv_pairs(&scanner, tc->expected, &error)) { cr_expect(FALSE, "%s", error); g_free(error); } kv_scanner_deinit(&scanner); scratch_buffers_explicit_gc(); } stop_stopwatch_and_display_result(iteration_index, "%.64s...", tc->input); } g_free(tcs); } Test(kv_scanner, performance_tests) { _test_performance(_provide_cases_for_performance_test_nothing_to_parse(), "Nothing to parse in the message"); _test_performance(_provide_cases_for_performance_test_parse_long_msg(), "Parse long strings"); } static void setup(void) { app_startup(); } static void teardown(void) { scratch_buffers_explicit_gc(); app_shutdown(); } TestSuite(kv_scanner, .init = setup, .fini = teardown); syslog-ng-syslog-ng-3.13.2/lib/scanner/list-scanner/000077500000000000000000000000001321171025300222365ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/scanner/list-scanner/CMakeLists.txt000066400000000000000000000002271321171025300247770ustar00rootroot00000000000000set(LIST_SCANNER_HEADERS list-scanner/list-scanner.h PARENT_SCOPE) set(LIST_SCANNER_SOURCES list-scanner/list-scanner.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/scanner/list-scanner/Makefile.am000066400000000000000000000004061321171025300242720ustar00rootroot00000000000000listscannerincludedir = ${pkgincludedir}/scanner/list-scanner listscannerinclude_HEADERS = \ lib/scanner/list-scanner/list-scanner.h listscanner_sources = \ lib/scanner/list-scanner/list-scanner.c include lib/scanner/list-scanner/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/scanner/list-scanner/list-scanner.c000066400000000000000000000112701321171025300250050ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "scanner/list-scanner/list-scanner.h" #include "str-repr/encode.h" #include "str-repr/decode.h" #include "str-utils.h" #include #include static void _free_input(ListScanner *self) { if (self->argv) { if (self->free_argv_payload) g_ptr_array_foreach(self->argv_buffer, (GFunc) g_free, NULL); } g_ptr_array_set_size(self->argv_buffer, 0); } static void _store_input(ListScanner *self, gint argc, gchar **argv, gboolean free_argv) { self->argc = argc; self->argv = (gchar **) self->argv_buffer->pdata; self->free_argv_payload = free_argv; self->current_arg_ndx = 0; self->current_arg = self->argv[self->current_arg_ndx]; } void list_scanner_input_va(ListScanner *self, const gchar *arg1, ...) { va_list va; gint i; const char *arg; _free_input(self); va_start(va, arg1); for (i = 0, arg = arg1; arg; i++, arg = va_arg(va, const gchar *)) { g_ptr_array_add(self->argv_buffer, g_strdup(arg)); } g_ptr_array_add(self->argv_buffer, NULL); va_end(va); _store_input(self, i, (gchar **) self->argv_buffer->pdata, TRUE); } void list_scanner_input_gstring_array(ListScanner *self, gint argc, GString *argv[]) { gint i; for (i = 0; i < argc; i++) { g_ptr_array_add(self->argv_buffer, argv[i]->str); } g_ptr_array_add(self->argv_buffer, NULL); _store_input(self, argc, (gchar **) self->argv_buffer->pdata, FALSE); } static gboolean _is_finished_with_args(ListScanner *self) { return self->current_arg_ndx >= self->argc; } static gboolean _parse_value_from_current_position(ListScanner *self) { StrReprDecodeOptions options = { 0, .delimiter_chars = ",", }; const gchar *end; /* NOTE: we always try to parse elements, even if the string is malformed, * otherwise we would be losing data. Prefer to have data in an * incorrectly formatted way, than no data at all. */ if (!str_repr_decode_with_options(self->value, self->current_arg, &end, &options)) { g_string_truncate(self->value, 0); g_string_append_len(self->value, self->current_arg, end - self->current_arg); } self->current_arg = end; return TRUE; } static gboolean _skip_if_current_arg_is_empty(ListScanner *self) { if (self->current_arg[0] == 0) { self->current_arg_ndx++; self->current_arg = self->argv[self->current_arg_ndx]; return TRUE; } return FALSE; } static gboolean _skip_unquoted_empty_value(ListScanner *self) { if (*self->current_arg == ',') { self->current_arg = self->current_arg + 1; return TRUE; } return FALSE; } static void _skip_empty_values(ListScanner *self) { while (!_is_finished_with_args(self)) { if (!_skip_if_current_arg_is_empty(self) && !_skip_unquoted_empty_value(self)) break; } return; } gboolean list_scanner_scan_next(ListScanner *self) { g_string_truncate(self->value, 0); _skip_empty_values(self); if (!_is_finished_with_args(self) && _parse_value_from_current_position(self)) return TRUE; return FALSE; } const gchar * list_scanner_get_current_value(ListScanner *self) { return self->value->str; } ListScanner * list_scanner_clone(ListScanner *self) { ListScanner *cloned = list_scanner_new(); return cloned; } void list_scanner_init(ListScanner *self) { memset(self, 0, sizeof(*self)); self->value = g_string_sized_new(32); self->argv_buffer = g_ptr_array_new(); } void list_scanner_deinit(ListScanner *self) { _free_input(self); g_string_free(self->value, TRUE); g_ptr_array_free(self->argv_buffer, TRUE); } ListScanner * list_scanner_new(void) { ListScanner *self = g_new0(ListScanner, 1); list_scanner_init(self); return self; } void list_scanner_free(ListScanner *self) { list_scanner_deinit(self); g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/scanner/list-scanner/list-scanner.h000066400000000000000000000034671321171025300250230ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LIST_SCANNER_H_INCLUDED #define LIST_SCANNER_H_INCLUDED #include "syslog-ng.h" typedef struct _ListScanner ListScanner; struct _ListScanner { gint argc; gchar **argv; GPtrArray *argv_buffer; GString *value; gboolean free_argv_payload; const gchar *current_arg; gint current_arg_ndx; gboolean current_arg_split; }; void list_scanner_input_va(ListScanner *self, const gchar *arg1, ...); void list_scanner_input_gstring_array(ListScanner *self, gint argc, GString *argv[]); gboolean list_scanner_scan_next(ListScanner *self); const gchar *list_scanner_get_current_value(ListScanner *self); ListScanner *list_scanner_clone(ListScanner *self); void list_scanner_free_method(ListScanner *self); void list_scanner_init(ListScanner *self); void list_scanner_deinit(ListScanner *self); ListScanner *list_scanner_new(void); void list_scanner_free(ListScanner *self); #endif syslog-ng-syslog-ng-3.13.2/lib/scanner/list-scanner/tests/000077500000000000000000000000001321171025300234005ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/scanner/list-scanner/tests/Makefile.am000066400000000000000000000005071321171025300254360ustar00rootroot00000000000000if ENABLE_CRITERION lib_scanner_list_scanner_tests_TESTS = \ lib/scanner/list-scanner/tests/test_list_scanner check_PROGRAMS += ${lib_scanner_list_scanner_tests_TESTS} lib_scanner_list_scanner_tests_test_list_scanner_CFLAGS = $(TEST_CFLAGS) lib_scanner_list_scanner_tests_test_list_scanner_LDADD = \ $(TEST_LDADD) endif syslog-ng-syslog-ng-3.13.2/lib/scanner/list-scanner/tests/test_list_scanner.c000066400000000000000000000163101321171025300272700ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "scanner/list-scanner/list-scanner.h" #include ListScanner *list_scanner; static void assert_no_more_tokens(void) { cr_assert(!list_scanner_scan_next(list_scanner), "list_scanner is expected to return no more key-value pairs"); } static void scan_next_token(void) { cr_assert(list_scanner_scan_next(list_scanner), "list_scanner is expected to return TRUE for scan_next"); } static void assert_current_value_is(const gchar *expected_key) { const gchar *key = list_scanner_get_current_value(list_scanner); cr_assert_str_eq(key, expected_key, "current key mismatch"); } static void assert_next_value_is(const gchar *expected_value) { scan_next_token(); assert_current_value_is(expected_value); } static void setup(void) { list_scanner = list_scanner_new(); } static void teardown(void) { list_scanner_free(list_scanner); } TestSuite(list_scanner, .init = setup, .fini = teardown); Test(list_scanner, individual_items_are_scanned) { list_scanner_input_va(list_scanner, "foo", NULL); assert_next_value_is("foo"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "foo", "bar", NULL); assert_next_value_is("foo"); assert_next_value_is("bar"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "foo", "bar", "baz", NULL); assert_next_value_is("foo"); assert_next_value_is("bar"); assert_next_value_is("baz"); assert_no_more_tokens(); } Test(list_scanner, unquoted_empty_items_are_skipped_to_make_it_easy_to_concatenate_lists) { list_scanner_input_va(list_scanner, "", NULL); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "", "foo", "bar", NULL); assert_next_value_is("foo"); assert_next_value_is("bar"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "", "", "", ",,,,", "", "", "", "foo", "bar", NULL); assert_next_value_is("foo"); assert_next_value_is("bar"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "foo", "", "bar", NULL); assert_next_value_is("foo"); assert_next_value_is("bar"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "foo,", NULL); assert_next_value_is("foo"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "''", ",foo,", "bar,", ",baz", "foobar", "\"\"", NULL); assert_next_value_is(""); assert_next_value_is("foo"); assert_next_value_is("bar"); assert_next_value_is("baz"); assert_next_value_is("foobar"); assert_next_value_is(""); assert_no_more_tokens(); } Test(list_scanner, quoted_empty_items_are_parsed_as_empty_values) { list_scanner_input_va(list_scanner, "foo", "''", "bar", NULL); assert_next_value_is("foo"); assert_next_value_is(""); assert_next_value_is("bar"); assert_no_more_tokens(); } Test(list_scanner, comma_delimiter_values_are_split) { list_scanner_input_va(list_scanner, "foo,bar", NULL); assert_next_value_is("foo"); assert_next_value_is("bar"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "foo,bar,baz", NULL); assert_next_value_is("foo"); assert_next_value_is("bar"); assert_next_value_is("baz"); assert_no_more_tokens(); } Test(list_scanner, comma_and_arg_are_equivalent) { list_scanner_input_va(list_scanner, "foo,bar,baz", "xxx", "", "yyy", NULL); assert_next_value_is("foo"); assert_next_value_is("bar"); assert_next_value_is("baz"); assert_next_value_is("xxx"); assert_next_value_is("yyy"); assert_no_more_tokens(); } Test(list_scanner, works_with_gstring_input) { GString *argv[] = { g_string_new("foo,bar,baz"), g_string_new("xxx"), g_string_new(""), g_string_new("yyy"), }; const gint argc = 4; gint i; list_scanner_input_gstring_array(list_scanner, argc, argv); assert_next_value_is("foo"); assert_next_value_is("bar"); assert_next_value_is("baz"); assert_next_value_is("xxx"); assert_next_value_is("yyy"); assert_no_more_tokens(); for (i = 0; i < argc; i++) g_string_free(argv[i], TRUE); } Test(list_scanner, handles_single_quotes) { list_scanner_input_va(list_scanner, "'foo'", NULL); assert_next_value_is("foo"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "'foo','bar'", NULL); assert_next_value_is("foo"); assert_next_value_is("bar"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "'foo,bar'", NULL); assert_next_value_is("foo,bar"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "'foo''bar'", NULL); assert_next_value_is("'foo''bar'"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "'foo'bar", NULL); assert_next_value_is("'foo'bar"); assert_no_more_tokens(); } Test(list_scanner, handles_double_quotes) { list_scanner_input_va(list_scanner, "\"foo\"", NULL); assert_next_value_is("foo"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "\"\\\"foo\"", NULL); assert_next_value_is("\"foo"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "\"foo\",\"bar\"", NULL); assert_next_value_is("foo"); assert_next_value_is("bar"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "\"foo,bar\"", NULL); assert_next_value_is("foo,bar"); assert_no_more_tokens(); /* no separator, thus two string tokens are concatenated */ list_scanner_input_va(list_scanner, "\"foo\"\"bar\"", NULL); assert_next_value_is("\"foo\"\"bar\""); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "\"foo\"bar", NULL); assert_next_value_is("\"foo\"bar"); assert_no_more_tokens(); } Test(list_scanner, malformed_quotes) { list_scanner_input_va(list_scanner, "'foo", NULL); assert_next_value_is("'foo"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "bar,'foo", NULL); assert_next_value_is("bar"); assert_next_value_is("'foo"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "bar,'foo,", NULL); assert_next_value_is("bar"); assert_next_value_is("'foo,"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "\"foo", NULL); assert_next_value_is("\"foo"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "bar,\"foo", NULL); assert_next_value_is("bar"); assert_next_value_is("\"foo"); assert_no_more_tokens(); list_scanner_input_va(list_scanner, "bar,\"foo,", NULL); assert_next_value_is("bar"); assert_next_value_is("\"foo,"); assert_no_more_tokens(); } syslog-ng-syslog-ng-3.13.2/lib/scratch-buffers.c000066400000000000000000000226741321171025300214430ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "scratch-buffers.h" #include "tls-support.h" #include "stats/stats-registry.h" #include "timeutils.h" #include "messages.h" #include /* * scratch_buffers * * The design of this API is to allow call-sites to use GString based string * buffers easily, without incurring the allocation overhead at all such * invocations and the need to always explicitly free them. * * Use-cases: * - something needs a set of GString buffers, such that their number is * not determinable at init time, so no preallocation is possible. * Allocating/freeing these buffers on-demand generates a non-trivial * overhead. * * - We need a GString buffer that is needed for the duration of the * processing of the given message, for example CSVScanner/KVScanner's * buffers. Right now, these are locked data structures or GString's * are allocated on demand, both of which slows them down. By using * this API, these could reuse existing allocations and only free them * once processing is finished of the given message. * * Design principles: * - you can allocate a GString instance using scratch_buffers_alloc() * * - these are thread specific allocations and should not be leaked * through thread boundaries, not until your own next invocation * * - you need to assume that once you return from your functions, the * previous allocations are gone! * * - you don't need to free these allocations, as they get released * automatically at the end of the message processing by the worker * thread machinery * * - if you produce too much garbage, you can still explicitly free these * buffers in bulk using the mark/reclaim functions. * * - reclaim works by freeing _all_ allocations up to a mark, so even * those that are allocated by the functions you called. Please make * sure that those do not hold references after returning. * * Other notes: * - this is not a complete garbage collector, but a very simple allocator for * buffers that creates coupling between various/independent parts of * the codebase. * * - ONLY USE IT IF YOU UNDERSTAND THE IMPLICATIONS AND PROVIDES A * MEASURABLE PERFORMANCE IMPACT. */ TLS_BLOCK_START { GPtrArray *scratch_buffers; gint scratch_buffers_used; glong scratch_buffers_bytes_reported; time_t scratch_buffers_time_of_last_maintenance; struct iv_task scratch_buffers_gc; gboolean scratch_buffers_gc_executed; } TLS_BLOCK_END; /* accessed by the test program */ StatsCounterItem *stats_scratch_buffers_count; StatsCounterItem *stats_scratch_buffers_bytes; #define scratch_buffers __tls_deref(scratch_buffers) #define scratch_buffers_used __tls_deref(scratch_buffers_used) #define scratch_buffers_bytes_reported __tls_deref(scratch_buffers_bytes_reported) #define scratch_buffers_time_of_last_maintenance __tls_deref(scratch_buffers_time_of_last_maintenance) #define scratch_buffers_gc __tls_deref(scratch_buffers_gc) #define scratch_buffers_gc_executed __tls_deref(scratch_buffers_gc_executed) /* update allocation counters once every period, in seconds */ #define SCRATCH_BUFFERS_MAINTENANCE_PERIOD 5 static void _register_gc_task(void); void scratch_buffers_mark(ScratchBuffersMarker *marker) { *marker = scratch_buffers_used; } GString * scratch_buffers_alloc_and_mark(ScratchBuffersMarker *marker) { _register_gc_task(); if (marker) scratch_buffers_mark(marker); if (scratch_buffers_used >= scratch_buffers->len) { g_ptr_array_add(scratch_buffers, g_string_sized_new(255)); stats_counter_inc(stats_scratch_buffers_count); } GString *buffer = g_ptr_array_index(scratch_buffers, scratch_buffers_used); g_string_truncate(buffer, 0); scratch_buffers_used++; return buffer; } GString * scratch_buffers_alloc(void) { return scratch_buffers_alloc_and_mark(NULL); } void scratch_buffers_reclaim_allocations(void) { scratch_buffers_reclaim_marked(0); } void scratch_buffers_reclaim_marked(ScratchBuffersMarker marker) { scratch_buffers_used = marker; } /* get a snapshot of the global allocation counter, can be racy */ gint scratch_buffers_get_global_allocation_count(void) { return stats_counter_get(stats_scratch_buffers_count); } /* get the number of thread-local allocations does not race */ gint scratch_buffers_get_local_allocation_count(void) { return scratch_buffers->len; } glong scratch_buffers_get_local_allocation_bytes(void) { glong bytes = 0; for (gint i = 0; i < scratch_buffers->len; i++) { GString *str = g_ptr_array_index(scratch_buffers, i); bytes += str->allocated_len; } return bytes; } gint scratch_buffers_get_local_usage_count(void) { return scratch_buffers_used; } void scratch_buffers_update_stats(void) { glong prev_reported = scratch_buffers_bytes_reported; scratch_buffers_bytes_reported = scratch_buffers_get_local_allocation_bytes(); stats_counter_add(stats_scratch_buffers_bytes, -prev_reported + scratch_buffers_bytes_reported); } void scratch_buffers_allocator_init(void) { scratch_buffers = g_ptr_array_sized_new(256); } void scratch_buffers_allocator_deinit(void) { /* check if GC was executed */ if (scratch_buffers_used > 0 && !scratch_buffers_gc_executed) { msg_warning("WARNING: an exiting thread left behind scratch buffers garbage without ever calling the GC. This message could indicate a memory leak", evt_tag_int("count", scratch_buffers->len), evt_tag_long("bytes", scratch_buffers_bytes_reported)); } /* remove our values from stats */ stats_counter_add(stats_scratch_buffers_count, -scratch_buffers->len); stats_counter_add(stats_scratch_buffers_bytes, -scratch_buffers_bytes_reported); /* free thread local scratch buffers */ for (int i = 0; i < scratch_buffers->len; i++) { GString *buffer = g_ptr_array_index(scratch_buffers, i); g_string_free(buffer, TRUE); } g_ptr_array_free(scratch_buffers, TRUE); } /********************************************************* * Lazy stats update *********************************************************/ static gboolean _thread_maintenance_period_elapsed(void) { if (!scratch_buffers_time_of_last_maintenance) return TRUE; if (scratch_buffers_time_of_last_maintenance - cached_g_current_time_sec() >= SCRATCH_BUFFERS_MAINTENANCE_PERIOD) return TRUE; return FALSE; } static void _thread_maintenance_update_time(void) { scratch_buffers_time_of_last_maintenance = cached_g_current_time_sec(); } void scratch_buffers_lazy_update_stats(void) { if (_thread_maintenance_period_elapsed()) { scratch_buffers_update_stats(); _thread_maintenance_update_time(); } } /********************************************************* * Ivykis task based garbage collector *********************************************************/ void scratch_buffers_explicit_gc(void) { scratch_buffers_lazy_update_stats(); scratch_buffers_reclaim_allocations(); scratch_buffers_gc_executed = TRUE; } static void _garbage_collect_scratch_buffers(gpointer arg) { scratch_buffers_explicit_gc(); } static void _register_gc_task(void) { if (scratch_buffers_gc.handler && iv_inited() && !iv_task_registered(&scratch_buffers_gc)) iv_task_register(&scratch_buffers_gc); } void scratch_buffers_automatic_gc_init(void) { IV_TASK_INIT(&scratch_buffers_gc); if (iv_inited()) { /* the automatic GC requires an ivykis thread */ scratch_buffers_gc.handler = _garbage_collect_scratch_buffers; } } void scratch_buffers_automatic_gc_deinit(void) { if (iv_task_registered(&scratch_buffers_gc)) iv_task_unregister(&scratch_buffers_gc); } void scratch_buffers_global_init(void) { StatsClusterKey sc_key; stats_lock(); stats_cluster_logpipe_key_set(&sc_key, SCS_GLOBAL, "scratch_buffers_count", NULL); stats_register_counter(0, &sc_key, SC_TYPE_QUEUED, &stats_scratch_buffers_count); stats_cluster_logpipe_key_set(&sc_key, SCS_GLOBAL, "scratch_buffers_bytes", NULL); stats_register_counter(0, &sc_key, SC_TYPE_QUEUED, &stats_scratch_buffers_bytes); stats_unlock(); } void scratch_buffers_global_deinit(void) { StatsClusterKey sc_key; stats_lock(); stats_cluster_logpipe_key_set(&sc_key, SCS_GLOBAL, "scratch_buffers_count", NULL); stats_unregister_counter(&sc_key, SC_TYPE_QUEUED, &stats_scratch_buffers_count); stats_cluster_logpipe_key_set(&sc_key, SCS_GLOBAL, "scratch_buffers_bytes", NULL); stats_unregister_counter(&sc_key, SC_TYPE_QUEUED, &stats_scratch_buffers_bytes); stats_unlock(); } syslog-ng-syslog-ng-3.13.2/lib/scratch-buffers.h000066400000000000000000000040771321171025300214450ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef SCRATCH_BUFFERS2_H_INCLUDED #define SCRATCH_BUFFERS2_H_INCLUDED 1 #include "syslog-ng.h" typedef gint32 ScratchBuffersMarker; GString *scratch_buffers_alloc(void); GString *scratch_buffers_alloc_and_mark(ScratchBuffersMarker *marker); void scratch_buffers_mark(ScratchBuffersMarker *marker); void scratch_buffers_reclaim_allocations(void); void scratch_buffers_reclaim_marked(ScratchBuffersMarker marker); gint scratch_buffers_get_global_allocation_count(void); gint scratch_buffers_get_local_allocation_count(void); glong scratch_buffers_get_local_allocation_bytes(void); gint scratch_buffers_get_local_usage_count(void); void scratch_buffers_update_stats(void); /* lazy stats update */ void scratch_buffers_lazy_update_stats(void); /* garbage collector */ void scratch_buffers_explicit_gc(void); void scratch_buffers_allocator_init(void); void scratch_buffers_allocator_deinit(void); void scratch_buffers_automatic_gc_init(void); void scratch_buffers_automatic_gc_deinit(void); void scratch_buffers_global_init(void); void scratch_buffers_global_deinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/seqnum.h000066400000000000000000000024011321171025300176610ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef SEQNUM_H_INLCLUDED #define SEQNUM_H_INLCLUDED 1 #include "syslog-ng.h" static inline void init_sequence_number(gint32 *seqnum) { *seqnum = 1; } static inline void step_sequence_number(gint32 *seqnum) { (*seqnum)++; if (*seqnum < 0) *seqnum = 1; } #endif syslog-ng-syslog-ng-3.13.2/lib/serialize.c000066400000000000000000000144061321171025300203430ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "serialize.h" #include "messages.h" #include #include #include typedef struct _SerializeFileArchive { SerializeArchive super; FILE *f; } SerializeFileArchive; typedef struct _SerializeStringArchive { SerializeArchive super; gsize pos; GString *string; } SerializeStringArchive; typedef struct _SerializeBufferArchive { SerializeArchive super; gsize pos; gsize len; gchar *buff; } SerializeBufferArchive; void _serialize_handle_errors(SerializeArchive *self, const gchar *error_desc, GError *error) { if (error) g_set_error(&self->error, G_FILE_ERROR, G_FILE_ERROR_IO, "%s: %s", error_desc, error->message); if (!self->silent) { msg_error(error_desc, evt_tag_str("error", error->message)); } g_error_free(error); } void serialize_archive_free(SerializeArchive *self) { g_clear_error(&self->error); g_slice_free1(self->len, self); } static gboolean serialize_file_archive_read_bytes(SerializeArchive *s, gchar *buf, gsize buflen, GError **error) { SerializeFileArchive *self = (SerializeFileArchive *) s; gssize bytes_read; g_return_val_if_fail(error == NULL || (*error) == NULL, FALSE); bytes_read = fread(buf, 1, buflen, self->f); if (bytes_read < 0 || bytes_read != buflen) { g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_IO, "Error reading file (%s)", bytes_read < 0 ? g_strerror(errno) : "short read"); return FALSE; } return TRUE; } static gboolean serialize_file_archive_write_bytes(SerializeArchive *s, const gchar *buf, gsize buflen, GError **error) { SerializeFileArchive *self = (SerializeFileArchive *) s; gssize bytes_written; g_return_val_if_fail(error == NULL || (*error) == NULL, FALSE); bytes_written = fwrite(buf, 1, buflen, self->f); if (bytes_written < 0 || bytes_written != buflen) { g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_IO, "Error writing file (%s)", bytes_written < 0 ? g_strerror(errno) : "short write"); return FALSE; } return TRUE; } SerializeArchive * serialize_file_archive_new(FILE *f) { SerializeFileArchive *self = g_slice_new0(SerializeFileArchive); self->super.read_bytes = serialize_file_archive_read_bytes; self->super.write_bytes = serialize_file_archive_write_bytes; self->super.len = sizeof(SerializeFileArchive); self->f = f; return &self->super; } void serialize_string_archive_reset(SerializeArchive *sa) { SerializeStringArchive *self = (SerializeStringArchive *) sa; self->pos = 0; } static gboolean serialize_string_archive_read_bytes(SerializeArchive *s, gchar *buf, gsize buflen, GError **error) { SerializeStringArchive *self = (SerializeStringArchive *) s; g_return_val_if_fail(error == NULL || (*error) == NULL, FALSE); if ((gssize) self->pos + buflen > (gssize) self->string->len) { g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_IO, "Error reading from string, stored data too short"); return FALSE; } memcpy(buf, &self->string->str[self->pos], buflen); self->pos += buflen; return TRUE; } static gboolean serialize_string_archive_write_bytes(SerializeArchive *s, const gchar *buf, gsize buflen, GError **error) { SerializeStringArchive *self = (SerializeStringArchive *) s; g_return_val_if_fail(error == NULL || (*error) == NULL, FALSE); g_string_append_len(self->string, buf, buflen); return TRUE; } SerializeArchive * serialize_string_archive_new(GString *str) { SerializeStringArchive *self = g_slice_new0(SerializeStringArchive); self->super.read_bytes = serialize_string_archive_read_bytes; self->super.write_bytes = serialize_string_archive_write_bytes; self->super.len = sizeof(SerializeStringArchive); self->string = str; return &self->super; } static gboolean serialize_buffer_archive_read_bytes(SerializeArchive *s, gchar *buf, gsize buflen, GError **error) { SerializeBufferArchive *self = (SerializeBufferArchive *) s; g_return_val_if_fail(error == NULL || (*error) == NULL, FALSE); if ((gssize) self->pos + buflen > (gssize) self->len) { g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_IO, "Error reading from buffer, stored data too short"); return FALSE; } memcpy(buf, &self->buff[self->pos], buflen); self->pos += buflen; return TRUE; } static gboolean serialize_buffer_archive_write_bytes(SerializeArchive *s, const gchar *buf, gsize buflen, GError **error) { SerializeBufferArchive *self = (SerializeBufferArchive *) s; g_return_val_if_fail(error == NULL || (*error) == NULL, FALSE); if (self->pos + buflen > self->len) { g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_IO, "Error writing to buffer, buffer is too small"); return FALSE; } memcpy(self->buff + self->pos, buf, buflen); self->pos += buflen; return TRUE; } gsize serialize_buffer_archive_get_pos(SerializeArchive *s) { SerializeBufferArchive *self = (SerializeBufferArchive *) s; return self->pos; } SerializeArchive * serialize_buffer_archive_new(gchar *buff, gsize len) { SerializeBufferArchive *self = g_slice_new0(SerializeBufferArchive); self->super.read_bytes = serialize_buffer_archive_read_bytes; self->super.write_bytes = serialize_buffer_archive_write_bytes; self->super.len = sizeof(SerializeBufferArchive); self->buff = buff; self->len = len; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/serialize.h000066400000000000000000000163411321171025300203500ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef SERIALIZE_H_INCLUDED #define SERIALIZE_H_INCLUDED #include "syslog-ng.h" #include #include typedef struct _SerializeArchive SerializeArchive; struct _SerializeArchive { GError *error; guint16 len; guint16 silent:1; gboolean (*read_bytes)(SerializeArchive *archive, gchar *buf, gsize count, GError **error); gboolean (*write_bytes)(SerializeArchive *archive, const gchar *buf, gsize count, GError **error); }; /* this is private and is only published so that the inline functions below can invoke it */ void _serialize_handle_errors(SerializeArchive *self, const gchar *error_desc, GError *error); static inline gboolean serialize_archive_read_bytes(SerializeArchive *self, gchar *buf, gsize buflen) { GError *error = NULL; if ((self->error == NULL) && !self->read_bytes(self, buf, buflen, &error)) _serialize_handle_errors(self, "Error reading serialized data", error); return self->error == NULL; } static inline gboolean serialize_archive_write_bytes(SerializeArchive *self, const gchar *buf, gsize buflen) { GError *error = NULL; if ((self->error == NULL) && !self->write_bytes(self, buf, buflen, &error)) _serialize_handle_errors(self, "Error writing serialized data", error); return self->error == NULL; } static inline gboolean serialize_write_uint32(SerializeArchive *archive, guint32 value) { guint32 n; n = GUINT32_TO_BE(value); return serialize_archive_write_bytes(archive, (gchar *) &n, sizeof(n)); } static inline gboolean serialize_read_uint32(SerializeArchive *archive, guint32 *value) { guint32 n; if (serialize_archive_read_bytes(archive, (gchar *) &n, sizeof(n))) { *value = GUINT32_FROM_BE(n); return TRUE; } return FALSE; } /* NOTE: this function writes to the array to convert it to big endian. It * is converted back to native byte order before returning */ static inline gboolean serialize_write_uint32_array(SerializeArchive *archive, guint32 *values, gsize elements) { const int buffer_size = 128; guint32 converted_values[buffer_size]; gint converted_ndx; while (elements > 0) { for (converted_ndx = 0; converted_ndx < buffer_size && converted_ndx < elements; converted_ndx++) converted_values[converted_ndx] = GUINT32_TO_BE(values[converted_ndx]); if (!serialize_archive_write_bytes(archive, (void *) converted_values, converted_ndx * sizeof(guint32))) return FALSE; values += converted_ndx; elements -= converted_ndx; } return TRUE; } static inline gboolean serialize_read_uint32_array(SerializeArchive *archive, guint32 *values, gsize elements) { if (serialize_archive_read_bytes(archive, (void *) values, elements * sizeof(guint32))) { for (int i = 0; i < elements; i++) values[i] = GUINT32_FROM_BE(values[i]); return TRUE; } return FALSE; } static inline gboolean serialize_write_uint64(SerializeArchive *archive, guint64 value) { guint64 n; n = GUINT64_TO_BE(value); return serialize_archive_write_bytes(archive, (gchar *) &n, sizeof(n)); } static inline gboolean serialize_read_uint64(SerializeArchive *archive, guint64 *value) { guint64 n; if (serialize_archive_read_bytes(archive, (gchar *) &n, sizeof(n))) { *value = GUINT64_FROM_BE(n); return TRUE; } return FALSE; } static inline gboolean serialize_write_uint16(SerializeArchive *archive, guint16 value) { guint16 n; n = GUINT16_TO_BE(value); return serialize_archive_write_bytes(archive, (gchar *) &n, sizeof(n)); } static inline gboolean serialize_read_uint16(SerializeArchive *archive, guint16 *value) { guint16 n; if (serialize_archive_read_bytes(archive, (gchar *) &n, sizeof(n))) { *value = GUINT16_FROM_BE(n); return TRUE; } return FALSE; } static inline gboolean serialize_write_uint8(SerializeArchive *archive, guint8 value) { guint8 n; n = value; return serialize_archive_write_bytes(archive, (gchar *) &n, sizeof(n)); } static inline gboolean serialize_read_uint8(SerializeArchive *archive, guint8 *value) { guint8 n; if (serialize_archive_read_bytes(archive, (gchar *) &n, sizeof(n))) { *value = n; return TRUE; } return FALSE; } static inline gboolean serialize_write_blob(SerializeArchive *archive, const void *blob, gsize len) { return serialize_archive_write_bytes(archive, blob, len); } static inline gboolean serialize_read_blob(SerializeArchive *archive, void *blob, gsize len) { return serialize_archive_read_bytes(archive, blob, len); } static inline gboolean serialize_write_string(SerializeArchive *archive, GString *str) { return serialize_write_uint32(archive, str->len) && serialize_archive_write_bytes(archive, str->str, str->len); } static inline gboolean serialize_read_string(SerializeArchive *archive, GString *str) { guint32 len; if (serialize_read_uint32(archive, &len)) { if (len > str->allocated_len) { gchar *p; p = g_try_realloc(str->str, len + 1); if (!p) return FALSE; str->str = p; str->str[len] = 0; str->len = len; } else g_string_set_size(str, len); return serialize_archive_read_bytes(archive, str->str, len); } return FALSE; } static inline gboolean serialize_write_cstring(SerializeArchive *archive, const gchar *str, gssize len) { if (len < 0) len = strlen(str); return serialize_write_uint32(archive, len) && (len == 0 || serialize_archive_write_bytes(archive, str, len)); } static inline gboolean serialize_read_cstring(SerializeArchive *archive, gchar **str, gsize *str_len) { guint32 len; if (serialize_read_uint32(archive, &len)) { *str = g_try_malloc(len + 1); if (!(*str)) return FALSE; (*str)[len] = 0; if (str_len) *str_len = len; return serialize_archive_read_bytes(archive, *str, len); } return FALSE; } SerializeArchive *serialize_file_archive_new(FILE *f); SerializeArchive *serialize_string_archive_new(GString *str); void serialize_string_archive_reset(SerializeArchive *sa); SerializeArchive *serialize_buffer_archive_new(gchar *buff, gsize len); gsize serialize_buffer_archive_get_pos(SerializeArchive *self); void serialize_archive_free(SerializeArchive *self); #endif syslog-ng-syslog-ng-3.13.2/lib/service-management.c000066400000000000000000000075641321171025300221350ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "service-management.h" #include "messages.h" #if SYSLOG_NG_ENABLE_SYSTEMD #include #include #include #include #endif typedef struct _ServiceManagement ServiceManagement; struct _ServiceManagement { ServiceManagementType type; void (*publish_status)(const gchar *status); void (*clear_status)(); void (*indicate_readiness)(); gboolean (*is_active)(); }; ServiceManagement *current_service_mgmt = NULL; #if SYSLOG_NG_ENABLE_SYSTEMD static inline void service_management_systemd_publish_status(const gchar *status) { gchar *status_buffer; time_t now = time(NULL); status_buffer = g_strdup_printf("STATUS=%s (%s)", status, ctime(&now)); sd_notify(0, status_buffer); g_free(status_buffer); } static inline void service_management_systemd_clear_status(void) { sd_notify(0, "STATUS="); } static inline void service_management_systemd_indicate_readiness(void) { sd_notify(0, "READY=1"); } static gboolean service_management_systemd_is_active(void) { struct stat st; if (lstat("/run/systemd/system/", &st) < 0 || !S_ISDIR(st.st_mode)) { msg_debug("Systemd is not detected as the running init system"); return FALSE; } else { msg_debug("Systemd is detected as the running init system"); return TRUE; } } #endif void service_management_publish_status(const gchar *status) { current_service_mgmt->publish_status(status); } void service_management_clear_status(void) { current_service_mgmt->clear_status(); } void service_management_indicate_readiness(void) { current_service_mgmt->indicate_readiness(); } ServiceManagementType service_management_get_type(void) { return current_service_mgmt->type; } static inline void service_management_dummy_publish_status(const gchar *status) { } static inline void service_management_dummy_clear_status(void) { } static inline void service_management_dummy_indicate_readiness(void) { } static gboolean service_management_dummy_is_active(void) { return TRUE; } ServiceManagement service_managements[] = { { .type = SMT_NONE, .publish_status = service_management_dummy_publish_status, .clear_status = service_management_dummy_clear_status, .indicate_readiness = service_management_dummy_indicate_readiness, .is_active = service_management_dummy_is_active } #if SYSLOG_NG_ENABLE_SYSTEMD ,{ .type = SMT_SYSTEMD, .publish_status = service_management_systemd_publish_status, .clear_status = service_management_systemd_clear_status, .indicate_readiness = service_management_systemd_indicate_readiness, .is_active = service_management_systemd_is_active } #endif }; void service_management_init(void) { gint i = 0; while (i < sizeof(service_managements) / sizeof(ServiceManagement)) { if (service_managements[i].is_active()) current_service_mgmt = &service_managements[i]; i++; } } syslog-ng-syslog-ng-3.13.2/lib/service-management.h000066400000000000000000000026701321171025300221330ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATUS_PUBLISHER_H_INCLUDED #define STATUS_PUBLISHER_H_INCLUDED #include "syslog-ng.h" typedef enum _ServiceManagementType { SMT_NONE, SMT_SYSTEMD, SMT_MAX } ServiceManagementType; void service_management_publish_status(const gchar *status); void service_management_clear_status(void); void service_management_indicate_readiness(void); ServiceManagementType service_management_get_type(void); void service_management_init(void); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/000077500000000000000000000000001321171025300173415ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/stats/CMakeLists.txt000066400000000000000000000013011321171025300220740ustar00rootroot00000000000000set(STATS_HEADERS stats/stats.h stats/stats-control.h stats/stats-counter.h stats/stats-cluster.h stats/stats-csv.h stats/stats-log.h stats/stats-registry.h stats/stats-syslog.h stats/stats-query.h stats/stats-query-commands.h stats/stats-cluster-logpipe.h stats/stats-cluster-single.h PARENT_SCOPE) set(STATS_SOURCES stats/stats.c stats/stats-control.c stats/stats-counter.c stats/stats-cluster.c stats/stats-csv.c stats/stats-log.c stats/stats-registry.c stats/stats-syslog.c stats/stats-query.c stats/stats-query-commands.c stats/stats-cluster-logpipe.c stats/stats-cluster-single.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/stats/Makefile.am000066400000000000000000000015231321171025300213760ustar00rootroot00000000000000statsincludedir = ${pkgincludedir}/stats statsinclude_HEADERS = \ lib/stats/stats.h \ lib/stats/stats-control.h \ lib/stats/stats-counter.h \ lib/stats/stats-cluster.h \ lib/stats/stats-csv.h \ lib/stats/stats-log.h \ lib/stats/stats-registry.h \ lib/stats/stats-syslog.h \ lib/stats/stats-query.h \ lib/stats/stats-query-commands.h \ lib/stats/stats-cluster-logpipe.h \ lib/stats/stats-cluster-single.h stats_sources = \ lib/stats/stats.c \ lib/stats/stats-control.c \ lib/stats/stats-counter.c \ lib/stats/stats-cluster.c \ lib/stats/stats-csv.c \ lib/stats/stats-log.c \ lib/stats/stats-registry.c \ lib/stats/stats-syslog.c \ lib/stats/stats-query.c \ lib/stats/stats-query-commands.c \ lib/stats/stats-cluster-logpipe.c \ lib/stats/stats-cluster-single.c include lib/stats/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/stats/stats-cluster-logpipe.c000066400000000000000000000042711321171025300237630ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 2017 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stats/stats-cluster-logpipe.h" #include "stats/stats-cluster.h" static const gchar *tag_names[SC_TYPE_MAX] = { /* [SC_TYPE_DROPPED] = */ "dropped", /* [SC_TYPE_PROCESSED] = */ "processed", /* [SC_TYPE_QUEUED] = */ "queued", /* [SC_TYPE_SUPPRESSED] = */ "suppressed", /* [SC_TYPE_STAMP] = */ "stamp", /* [SC_TYPE_MEMORY_USAGE] = */ "memory_usage", /* [SC_TYPE_DISCARDED] = */ "discarded", /* [SC_TYPE_MATCHED] = */ "matched", /* [SC_TYPE_NOT_MATCHED] = */ "not_matched", /* [SC_TYPE_WRITTEN] = */ "written", }; static void _counter_group_logpipe_free(StatsCounterGroup *counter_group) { g_free(counter_group->counters); } static void _counter_group_logpipe_init(StatsCounterGroupInit *self, StatsCounterGroup *counter_group) { counter_group->counters = g_new0(StatsCounterItem, SC_TYPE_MAX); counter_group->capacity = SC_TYPE_MAX; counter_group->counter_names = self->counter_names; counter_group->free_fn = _counter_group_logpipe_free; } void stats_cluster_logpipe_key_set(StatsClusterKey *key, guint16 component, const gchar *id, const gchar *instance) { stats_cluster_key_set(key, component, id, instance, (StatsCounterGroupInit) { tag_names, _counter_group_logpipe_init }); } syslog-ng-syslog-ng-3.13.2/lib/stats/stats-cluster-logpipe.h000066400000000000000000000033701321171025300237670ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 2017 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATS_CLUSTER_LOGPIPE_H_INCLUDED #define STATS_CLUSTER_LOGPIPE_H_INCLUDED #include "syslog-ng.h" typedef enum { SC_TYPE_DROPPED=0, /* number of messages dropped */ SC_TYPE_PROCESSED, /* number of messages processed */ SC_TYPE_QUEUED, /* number of messages on disk */ SC_TYPE_SUPPRESSED,/* number of messages suppressed */ SC_TYPE_STAMP, /* timestamp */ SC_TYPE_MEMORY_USAGE, SC_TYPE_DISCARDED, /* discarded messages of filter */ SC_TYPE_MATCHED, /* discarded messages of filter */ SC_TYPE_NOT_MATCHED, /* discarded messages of filter */ SC_TYPE_WRITTEN, /* number of sent messages */ SC_TYPE_MAX } StatsCounterGroupLogPipe; void stats_cluster_logpipe_key_set(StatsClusterKey *key, guint16 component, const gchar *id, const gchar *instance); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/stats-cluster-single.c000066400000000000000000000060641321171025300236070ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stats/stats-cluster-single.h" #include "stats/stats-cluster.h" static const gchar *tag_names[SC_TYPE_SINGLE_MAX] = { /* [SC_TYPE_SINGLE_VALUE] = */ "value", }; static void _counter_group_free(StatsCounterGroup *counter_group) { g_free(counter_group->counters); } static void _counter_group_init(StatsCounterGroupInit *self, StatsCounterGroup *counter_group) { counter_group->counters = g_new0(StatsCounterItem, SC_TYPE_SINGLE_MAX); counter_group->capacity = SC_TYPE_SINGLE_MAX; counter_group->counter_names = self->counter_names; counter_group->free_fn = _counter_group_free; } void stats_cluster_single_key_set(StatsClusterKey *key, guint16 component, const gchar *id, const gchar *instance) { stats_cluster_key_set(key, component, id, instance, (StatsCounterGroupInit) { tag_names,_counter_group_init }); } static void _counter_group_with_name_free(StatsCounterGroup *counter_group) { g_free(counter_group->counter_names); _counter_group_free(counter_group); } static void _counter_group_init_with_name(StatsCounterGroupInit *self, StatsCounterGroup *counter_group) { counter_group->counters = g_new0(StatsCounterItem, SC_TYPE_SINGLE_MAX); counter_group->capacity = SC_TYPE_SINGLE_MAX; counter_group->counter_names = self->counter_names; counter_group->free_fn = _counter_group_with_name_free; } static gboolean _group_init_equals(const StatsCounterGroupInit *self, const StatsCounterGroupInit *other) { g_assert(self != NULL && other != NULL && self->counter_names != NULL && other->counter_names != NULL); return (self->init == other->init) && (g_strcmp0(self->counter_names[0], other->counter_names[0]) == 0); } void stats_cluster_single_key_set_with_name(StatsClusterKey *key, guint16 component, const gchar *id, const gchar *instance, const gchar *name) { stats_cluster_key_set(key, component, id, instance, (StatsCounterGroupInit) { tag_names, _counter_group_init_with_name, _group_init_equals }); key->counter_group_init.counter_names = g_new0(const char *, 1); key->counter_group_init.counter_names[0] = name; } syslog-ng-syslog-ng-3.13.2/lib/stats/stats-cluster-single.h000066400000000000000000000026561321171025300236170ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATS_CLUSTER_SINGLE_H_INCLUDED #define STATS_CLUSTER_SINGLE_H_INCLUDED #include "syslog-ng.h" typedef enum { SC_TYPE_SINGLE_VALUE, SC_TYPE_SINGLE_MAX } StatsCounterGroupSingle; void stats_cluster_single_key_set(StatsClusterKey *key, guint16 component, const gchar *id, const gchar *instance); void stats_cluster_single_key_set_with_name(StatsClusterKey *key, guint16 component, const gchar *id, const gchar *instance, const gchar *name); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/stats-cluster.c000066400000000000000000000162631321171025300223320ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stats/stats-cluster.h" #include static StatsClusterKey * _clone_stats_cluster_key(StatsClusterKey *dst, const StatsClusterKey *src) { dst->component = src->component; dst->id = g_strdup(src->id ? : ""); dst->instance = g_strdup(src->instance ? : ""); dst->counter_group_init = src->counter_group_init; return dst; } void stats_cluster_key_set(StatsClusterKey *self, guint16 component, const gchar *id, const gchar *instance, StatsCounterGroupInit counter_group_init) { self->component = component; self->id = (id?id:""); self->instance = (instance?instance:""); self->counter_group_init = counter_group_init; } static void _stats_cluster_key_cloned_free(StatsClusterKey *self) { g_free((gchar *)(self->id)); g_free((gchar *)(self->instance)); } void stats_cluster_foreach_counter(StatsCluster *self, StatsForeachCounterFunc func, gpointer user_data) { gint type; for (type = 0; type < self->counter_group.capacity; type++) { if (self->live_mask & (1 << type)) { func(self, type, &self->counter_group.counters[type], user_data); } } } const gchar * stats_cluster_get_type_name(StatsCluster *self, gint type) { if (type < self->counter_group.capacity) return self->counter_group.counter_names[type]; return ""; } static const gchar * _get_module_name(gint source) { static const gchar *module_names[SCS_MAX] = { "none", "file", "pipe", "tcp", "udp", "tcp6", "udp6", "unix-stream", "unix-dgram", "syslog", "network", "internal", "logstore", "program", "sql", "sun-streams", "usertty", "group", "center", "host", "global", "mongodb", "class", "rule_id", "tag", "severity", "facility", "sender", "smtp", "amqp", "stomp", "redis", "snmp", "riemann", "journald", "java", "http", "python", "filter", "parser", "monitoring" }; return module_names[source & SCS_SOURCE_MASK]; } static const gchar * _get_component_prefix(gint source) { return (source & SCS_SOURCE ? "src." : (source & SCS_DESTINATION ? "dst." : "")); } /* buf is a scratch area which is not always used, the return value is * either a locally managed string or points to @buf. */ const gchar * stats_cluster_get_component_name(StatsCluster *self, gchar *buf, gsize buf_len) { if ((self->key.component & SCS_SOURCE_MASK) == SCS_GROUP) { if (self->key.component & SCS_SOURCE) return "source"; else if (self->key.component & SCS_DESTINATION) return "destination"; else g_assert_not_reached(); } else { g_snprintf(buf, buf_len, "%s%s", _get_component_prefix(self->key.component), _get_module_name(self->key.component)); return buf; } } gboolean stats_counter_group_init_equals(const StatsCounterGroupInit *self, const StatsCounterGroupInit *other) { if (!self || !other) return FALSE; if (self == other) return TRUE; if (self->equals) return self->equals(self, other); return (self->init == other->init) && (self->counter_names == other->counter_names); } gboolean stats_cluster_key_equal(const StatsClusterKey *key1, const StatsClusterKey *key2) { return key1->component == key2->component && strcmp(key1->id, key2->id) == 0 && strcmp(key1->instance, key2->instance) == 0 && stats_counter_group_init_equals(&key1->counter_group_init, &key2->counter_group_init); } gboolean stats_cluster_equal(const StatsCluster *sc1, const StatsCluster *sc2) { return stats_cluster_key_equal(&sc1->key, &sc2->key); } guint stats_cluster_hash(const StatsCluster *self) { return g_str_hash(self->key.id) + g_str_hash(self->key.instance) + self->key.component; } StatsCounterItem * stats_cluster_track_counter(StatsCluster *self, gint type) { gint type_mask = 1 << type; g_assert(type < self->counter_group.capacity); self->live_mask |= type_mask; self->use_count++; return &self->counter_group.counters[type]; } void stats_cluster_untrack_counter(StatsCluster *self, gint type, StatsCounterItem **counter) { g_assert(self && (self->live_mask & (1 << type)) && &self->counter_group.counters[type] == (*counter)); g_assert(self->use_count > 0); self->use_count--; *counter = NULL; } static gchar * _stats_build_query_key(StatsCluster *self) { GString *key = g_string_new(""); gchar buffer[64] = {0}; const gchar *component_name = stats_cluster_get_component_name(self, buffer, sizeof(buffer)); g_string_append(key, component_name); if (self->key.id && self->key.id[0]) { g_string_append_printf(key, ".%s", self->key.id); } if (self->key.instance && self->key.instance[0]) { g_string_append_printf(key, ".%s", self->key.instance); } return g_string_free(key, FALSE); } gboolean stats_cluster_is_alive(StatsCluster *self, gint type) { g_assert(type < self->counter_group.capacity); return ((1<live_mask); } gboolean stats_cluster_is_indexed(StatsCluster *self, gint type) { g_assert(type < self->counter_group.capacity); return ((1<indexed_mask); } StatsCluster * stats_cluster_new(const StatsClusterKey *key) { StatsCluster *self = g_new0(StatsCluster, 1); _clone_stats_cluster_key(&self->key, key); self->use_count = 0; self->query_key = _stats_build_query_key(self); key->counter_group_init.init(&self->key.counter_group_init, &self->counter_group); g_assert(self->counter_group.capacity <= sizeof(self->live_mask)*8); return self; } StatsCluster * stats_cluster_dynamic_new(const StatsClusterKey *key) { StatsCluster *sc = stats_cluster_new(key); sc->dynamic = TRUE; return sc; } void stats_counter_group_free(StatsCounterGroup *self) { if (self->free_fn) self->free_fn(self); } static void stats_cluster_free_counter_name(StatsCluster *self, gint type, StatsCounterItem *item, gpointer user_data) { g_free(item->name); } void stats_cluster_free(StatsCluster *self) { stats_cluster_foreach_counter(self, stats_cluster_free_counter_name, NULL); _stats_cluster_key_cloned_free(&self->key); g_free(self->query_key); stats_counter_group_free(&self->counter_group); g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/stats/stats-cluster.h000066400000000000000000000123671321171025300223400ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATS_CLUSTER_H_INCLUDED #define STATS_CLUSTER_H_INCLUDED 1 #include "stats/stats-counter.h" #include "stats/stats-cluster-logpipe.h" enum { /* direction bits, used to distinguish between source/destination drivers */ SCS_SOURCE = 0x0100, SCS_DESTINATION = 0x0200, /* drivers, this should be registered dynamically */ SCS_FILE = 1, SCS_PIPE = 2, SCS_TCP = 3, SCS_UDP = 4, SCS_TCP6 = 5, SCS_UDP6 = 6, SCS_UNIX_STREAM = 7, SCS_UNIX_DGRAM = 8, SCS_SYSLOG = 9, SCS_NETWORK = 10, SCS_INTERNAL = 11, SCS_LOGSTORE = 12, SCS_PROGRAM = 13, SCS_SQL = 14, SCS_SUN_STREAMS = 15, SCS_USERTTY = 16, SCS_GROUP = 17, SCS_CENTER = 18, SCS_HOST = 19, SCS_GLOBAL = 20, SCS_MONGODB = 21, SCS_CLASS = 22, SCS_RULE_ID = 23, SCS_TAG = 24, SCS_SEVERITY = 25, SCS_FACILITY = 26, SCS_SENDER = 27, SCS_SMTP = 28, SCS_AMQP = 29, SCS_STOMP = 30, SCS_REDIS = 31, SCS_SNMP = 32, SCS_RIEMANN = 33, SCS_JOURNALD = 34, SCS_JAVA = 35, SCS_HTTP = 36, SCS_PYTHON = 37, SCS_FILTER = 38, SCS_PARSER = 39, SCS_MONITORING = 40, SCS_STDIN = 41, SCS_MAX, SCS_SOURCE_MASK = 0xff }; typedef struct _StatsCounterGroup StatsCounterGroup; typedef struct _StatsCounterGroupInit StatsCounterGroupInit; struct _StatsCounterGroup { StatsCounterItem *counters; const gchar **counter_names; guint16 capacity; void (*free_fn)(StatsCounterGroup *self); }; struct _StatsCounterGroupInit { const gchar **counter_names; void (*init)(StatsCounterGroupInit *self, StatsCounterGroup *counter_group); gboolean (*equals)(const StatsCounterGroupInit *self, const StatsCounterGroupInit *other); }; gboolean stats_counter_group_init_equals(const StatsCounterGroupInit *self, const StatsCounterGroupInit *other); void stats_counter_group_free(StatsCounterGroup *self); struct _StatsClusterKey { /* syslog-ng component/driver/subsystem that registered this cluster */ guint16 component; const gchar *id; const gchar *instance; StatsCounterGroupInit counter_group_init; }; /* NOTE: This struct can only be used by the stats implementation and not by client code. */ /* StatsCluster encapsulates a set of related counters that are registered * to the same stats source. In a lot of cases, the same stats source uses * multiple counters, so keeping them at the same location makes sense. * * This also improves performance for dynamic counters that relate to * information found in the log stream. In that case multiple counters can * be registered with a single hash lookup */ typedef struct _StatsCluster { StatsClusterKey key; StatsCounterGroup counter_group; guint16 use_count; guint16 live_mask; guint16 indexed_mask; guint16 dynamic:1; gchar *query_key; } StatsCluster; typedef void (*StatsForeachCounterFunc)(StatsCluster *sc, gint type, StatsCounterItem *counter, gpointer user_data); const gchar *stats_cluster_get_type_name(StatsCluster *self, gint type); const gchar *stats_cluster_get_component_name(StatsCluster *self, gchar *buf, gsize buf_len); void stats_cluster_foreach_counter(StatsCluster *self, StatsForeachCounterFunc func, gpointer user_data); gboolean stats_cluster_key_equal(const StatsClusterKey *key1, const StatsClusterKey *key2); gboolean stats_cluster_equal(const StatsCluster *sc1, const StatsCluster *sc2); guint stats_cluster_hash(const StatsCluster *self); StatsCounterItem *stats_cluster_track_counter(StatsCluster *self, gint type); void stats_cluster_untrack_counter(StatsCluster *self, gint type, StatsCounterItem **counter); gboolean stats_cluster_is_alive(StatsCluster *self, gint type); gboolean stats_cluster_is_indexed(StatsCluster *self, gint type); StatsCluster *stats_cluster_new(const StatsClusterKey *key); StatsCluster *stats_cluster_dynamic_new(const StatsClusterKey *key); void stats_cluster_free(StatsCluster *self); void stats_cluster_key_set(StatsClusterKey *self, guint16 component, const gchar *id, const gchar *instance, StatsCounterGroupInit counter_group_ctor); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/stats-control.c000066400000000000000000000035031321171025300223220ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stats/stats-control.h" #include "stats/stats-csv.h" #include "stats/stats-counter.h" #include "control/control-commands.h" static GString * control_connection_send_stats(GString *command, gpointer user_data) { gchar *stats = stats_generate_csv(); GString *result = g_string_new(stats); g_free(stats); return result; } static GString * control_connection_reset_stats(GString *command, gpointer user_data) { GString *result = g_string_new("The statistics of syslog-ng have been reset to 0."); stats_reset_counters(); return result; } void stats_register_control_commands(void) { control_register_command("STATS", NULL, control_connection_send_stats, NULL); control_register_command("RESET_STATS", NULL, control_connection_reset_stats, NULL); } void stats_unregister_control_commands(void) { reset_control_command_list(); } syslog-ng-syslog-ng-3.13.2/lib/stats/stats-control.h000066400000000000000000000022531321171025300223300ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATS_CONTROL_H_INCLUDED #define STATS_CONTROL_H_INCLUDED 1 #include "syslog-ng.h" void stats_register_control_commands(void); void stats_unregister_control_commands(void); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/stats-counter.c000066400000000000000000000032641321171025300223250ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stats/stats-counter.h" #include "stats/stats-cluster.h" #include "stats/stats-registry.h" static void _reset_counter(StatsCluster *sc, gint type, StatsCounterItem *counter, gpointer user_data) { stats_counter_set(counter, 0); } static inline void _reset_counter_if_needed(StatsCluster *sc, gint type, StatsCounterItem *counter, gpointer user_data) { switch (type) { case SC_TYPE_QUEUED: case SC_TYPE_MEMORY_USAGE: return; default: _reset_counter(sc, type, counter, user_data); } } void stats_reset_counters(void) { stats_lock(); stats_foreach_counter(_reset_counter_if_needed, NULL); stats_unlock(); } void stats_counter_free(StatsCounterItem *counter) { if (counter->name) g_free(counter->name); } syslog-ng-syslog-ng-3.13.2/lib/stats/stats-counter.h000066400000000000000000000046051321171025300223320ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATS_COUNTER_H_INCLUDED #define STATS_COUNTER_H_INCLUDED 1 #include "syslog-ng.h" typedef struct _StatsCounterItem { gssize value; gchar *name; gint type; } StatsCounterItem; static inline void stats_counter_add(StatsCounterItem *counter, gssize add) { if (counter) g_atomic_pointer_add(&counter->value, add); } static inline void stats_counter_sub(StatsCounterItem *counter, gssize sub) { if (counter) g_atomic_pointer_add(&counter->value, -1 * sub); } static inline void stats_counter_inc(StatsCounterItem *counter) { if (counter) g_atomic_pointer_add(&counter->value, 1); } static inline void stats_counter_dec(StatsCounterItem *counter) { if (counter) g_atomic_pointer_add(&counter->value, -1); } /* NOTE: this is _not_ atomic and doesn't have to be as sets would race anyway */ static inline void stats_counter_set(StatsCounterItem *counter, gsize value) { if (counter) counter->value = value; } /* NOTE: this is _not_ atomic and doesn't have to be as sets would race anyway */ static inline gsize stats_counter_get(StatsCounterItem *counter) { gssize result = 0; if (counter) result = counter->value; return result; } static inline gchar * stats_counter_get_name(StatsCounterItem *counter) { if (counter && counter->name) return counter->name; return NULL; } void stats_reset_counters(void); void stats_counter_free(StatsCounterItem *counter); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/stats-csv.c000066400000000000000000000055621321171025300214440ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stats/stats-csv.h" #include "stats/stats-registry.h" #include "utf8utils.h" #include static gboolean has_csv_special_character(const gchar *var) { if (strchr(var, ';')) return TRUE; if (strchr(var, '\"')) return TRUE; return FALSE; } static gchar * stats_format_csv_escapevar(const gchar *var) { gchar *escaped_result; if (var[0] && has_csv_special_character(var)) { gchar *result; /* quote */ result = convert_unsafe_utf8_to_escaped_binary(var, -1, "\""); escaped_result = g_strdup_printf("\"%s\"", result); g_free(result); } else { escaped_result = convert_unsafe_utf8_to_escaped_binary(var, -1, NULL); } return escaped_result; } static void stats_format_csv(StatsCluster *sc, gint type, StatsCounterItem *counter, gpointer user_data) { GString *csv = (GString *) user_data; gchar *s_id, *s_instance, *tag_name; gchar buf[32]; gchar state; s_id = stats_format_csv_escapevar(sc->key.id); s_instance = stats_format_csv_escapevar(sc->key.instance); if (sc->dynamic) state = 'd'; else if (sc->use_count == 0) state = 'o'; else state = 'a'; tag_name = stats_format_csv_escapevar(stats_cluster_get_type_name(sc, type)); g_string_append_printf(csv, "%s;%s;%s;%c;%s;%"G_GSIZE_FORMAT"\n", stats_cluster_get_component_name(sc, buf, sizeof(buf)), s_id, s_instance, state, tag_name, stats_counter_get(&sc->counter_group.counters[type])); g_free(tag_name); g_free(s_id); g_free(s_instance); } gchar * stats_generate_csv(void) { GString *csv = g_string_sized_new(1024); g_string_append_printf(csv, "%s;%s;%s;%s;%s;%s\n", "SourceName", "SourceId", "SourceInstance", "State", "Type", "Number"); stats_lock(); stats_foreach_counter(stats_format_csv, csv); stats_unlock(); return g_string_free(csv, FALSE); } syslog-ng-syslog-ng-3.13.2/lib/stats/stats-csv.h000066400000000000000000000021521321171025300214410ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATS_CSV_H_INCLUDED #define STATS_CSV_H_INCLUDED 1 #include "syslog-ng.h" gchar *stats_generate_csv(void); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/stats-log.c000066400000000000000000000034071321171025300214260ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stats/stats-log.h" #include "stats/stats.h" static void stats_log_format_counter(StatsCluster *sc, gint type, StatsCounterItem *item, gpointer user_data) { EVTREC *e = (EVTREC *) user_data; EVTTAG *tag; gchar buf[32]; tag = evt_tag_printf(stats_cluster_get_type_name(sc, type), "%s(%s%s%s)=%"G_GSIZE_FORMAT, stats_cluster_get_component_name(sc, buf, sizeof(buf)), sc->key.id, (sc->key.id[0] && sc->key.instance[0]) ? "," : "", sc->key.instance, stats_counter_get(&sc->counter_group.counters[type])); evt_rec_add_tag(e, tag); } void stats_log_format_cluster(StatsCluster *sc, EVTREC *e) { stats_cluster_foreach_counter(sc, stats_log_format_counter, e); } syslog-ng-syslog-ng-3.13.2/lib/stats/stats-log.h000066400000000000000000000022441321171025300214310ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATS_LOG_H_INCLUDED #define STATS_LOG_H_INCLUDED #include "stats/stats-cluster.h" #include "messages.h" void stats_log_format_cluster(StatsCluster *sc, EVTREC *e); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/stats-query-commands.c000066400000000000000000000121661321171025300236130ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "messages.h" #include "stats-query-commands.h" #include "stats/stats-query.h" typedef enum _QueryCommand { QUERY_GET = 0, QUERY_GET_RESET, QUERY_GET_SUM, QUERY_GET_SUM_RESET, QUERY_LIST, QUERY_LIST_RESET, QUERY_CMD_MAX } QueryCommand; typedef gboolean (*query_cmd)(const gchar *filter_expr, GString *result); const gint CMD_STR = 0; const gint QUERY_CMD_STR = 1; const gint QUERY_FILTER_STR = 2; static void _append_reset_msg_if_found_matching_counters(gboolean found_match, GString *result) { if (found_match) { g_string_append_printf(result, "\n%s", "The selected counters of syslog-ng have been reset to 0."); } } static gboolean _ctl_format_get(StatsCounterItem *ctr, gpointer user_data) { GString *str = (GString *)user_data; g_string_append_printf(str, "%s=%"G_GSIZE_FORMAT"\n", stats_counter_get_name(ctr), stats_counter_get(ctr)); return TRUE; } static gboolean _ctl_format_name_without_value(StatsCounterItem *ctr, gpointer user_data) { GString *str = (GString *)user_data; g_string_append_printf(str, "%s\n", stats_counter_get_name(ctr)); return TRUE; } static gboolean _ctl_format_get_sum(StatsCounterItem *ctr, gpointer user_data) { gpointer *args = (gpointer *) user_data; GString *result = (GString *) args[0]; gint64 *sum = (gint64 *) args[1]; g_string_printf(result, "%" G_GINT64_FORMAT "\n", *sum); return TRUE; } static gboolean _query_get(const gchar *filter_expr, GString *result) { return stats_query_get(filter_expr, _ctl_format_get, (gpointer)result); } static gboolean _query_get_and_reset(const gchar *filter_expr, GString *result) { gboolean found_match; found_match = stats_query_get_and_reset_counters(filter_expr, _ctl_format_get, (gpointer)result); _append_reset_msg_if_found_matching_counters(found_match, result); return found_match; } static gboolean _query_list(const gchar *filter_expr, GString *result) { return stats_query_list(filter_expr, _ctl_format_name_without_value, (gpointer)result); } static gboolean _query_list_and_reset(const gchar *filter_expr, GString *result) { gboolean found_match; found_match = stats_query_list_and_reset_counters(filter_expr, _ctl_format_name_without_value, (gpointer)result); _append_reset_msg_if_found_matching_counters(found_match, result); return found_match; } static gboolean _query_get_sum(const gchar *filter_expr, GString *result) { return stats_query_get_sum(filter_expr, _ctl_format_get_sum, (gpointer)result); } static gboolean _query_get_sum_and_reset(const gchar *filter_expr, GString *result) { gboolean found_match; found_match = stats_query_get_sum_and_reset_counters(filter_expr, _ctl_format_get_sum, (gpointer)result); _append_reset_msg_if_found_matching_counters(found_match, result); return found_match; } static QueryCommand _command_str_to_id(const gchar *cmd) { if (g_str_equal(cmd, "GET_SUM")) return QUERY_GET_SUM; if (g_str_equal(cmd, "GET_SUM_RESET")) return QUERY_GET_SUM_RESET; if (g_str_equal(cmd, "GET")) return QUERY_GET; if (g_str_equal(cmd, "GET_RESET")) return QUERY_GET_RESET; if (g_str_equal(cmd, "LIST")) return QUERY_LIST; if (g_str_equal(cmd, "LIST_RESET")) return QUERY_LIST_RESET; msg_error("Unknown query command", evt_tag_str("command", cmd)); return QUERY_CMD_MAX; } static query_cmd QUERY_CMDS[] = { _query_get, _query_get_and_reset, _query_get_sum, _query_get_sum_and_reset, _query_list, _query_list_and_reset }; static gboolean _dispatch_query(gint cmd_id, const gchar *filter_expr, GString *result) { if (cmd_id < QUERY_GET || cmd_id >= QUERY_CMD_MAX) { msg_error("Invalid query command", evt_tag_int("cmd_id", cmd_id), evt_tag_str("query", filter_expr)); return FALSE; } return QUERY_CMDS[cmd_id](filter_expr, result); } GString * process_query_command(GString *command, gpointer user_data) { GString *result = g_string_new(""); gchar **cmds = g_strsplit(command->str, " ", 3); g_assert(g_str_equal(cmds[CMD_STR], "QUERY")); _dispatch_query(_command_str_to_id(cmds[QUERY_CMD_STR]), cmds[QUERY_FILTER_STR], result); g_strfreev(cmds); if (result->len == 0) g_string_assign(result, "\n"); return result; } syslog-ng-syslog-ng-3.13.2/lib/stats/stats-query-commands.h000066400000000000000000000021561321171025300236160ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATS_QUERY_COMMANDS_H_INCLUDED #define STATS_QUERY_COMMANDS_H_INCLUDED #include "syslog-ng.h" GString* process_query_command(GString *cmd, gpointer user_data); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/stats-query.c000066400000000000000000000262551321171025300220200ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "messages.h" #include "stats-query.h" #include "stats-registry.h" #include "stats.h" #include static GHashTable *counter_index; static GStaticMutex stats_query_mutex = G_STATIC_MUTEX_INIT; static GHashTable *stats_views; typedef struct _ViewRecord { GList *queries; StatsCounterItem *counter; AggregatedMetricsCb aggregate; } ViewRecord; static void _free_view_record(gpointer r) { ViewRecord *record = (ViewRecord *) r; g_list_free_full(record->queries, g_free); stats_counter_free(record->counter); g_free(record->counter); g_free(record); } void stats_register_view(gchar *name, GList *queries, const AggregatedMetricsCb aggregate) { ViewRecord *record = g_new0(ViewRecord, 1); record->counter = g_new0(StatsCounterItem, 1); record->counter->name = g_strdup(name); record->queries = queries; record->aggregate = aggregate; g_hash_table_insert(stats_views, name, record); } static void _setup_filter_expression(const gchar *expr, gchar **key_str) { if (!expr || g_str_equal(expr, "")) { *key_str = g_strdup("*"); } else { *key_str = g_strdup(expr); } } static gchar * _construct_counter_item_name(StatsCluster *sc, gint type) { GString *name = g_string_new(""); g_string_append(name, sc->query_key); g_string_append(name, "."); g_string_append(name, stats_cluster_get_type_name(sc, type)); return g_string_free(name, FALSE); } static void _add_counter_to_index(StatsCluster *sc, gint type) { StatsCounterItem *counter = &sc->counter_group.counters[type]; gchar *counter_full_name = NULL; counter_full_name = stats_counter_get_name(counter); if (counter_full_name == NULL) { counter_full_name = _construct_counter_item_name(sc, type); counter->name = counter_full_name; } g_hash_table_insert(counter_index, counter_full_name, counter); sc->indexed_mask |= (1 << type); } static void _remove_counter_from_index(StatsCluster *sc, gint type) { gchar *key = stats_counter_get_name(&sc->counter_group.counters[type]); g_hash_table_remove(counter_index, key); sc->indexed_mask |= (1 << type); } static void _index_counter(StatsCluster *sc, gint type, StatsCounterItem *counter, gpointer user_data) { if (!stats_cluster_is_indexed(sc, type) && stats_cluster_is_alive(sc, type)) { _add_counter_to_index(sc, type); } else if (stats_cluster_is_indexed(sc, type) && !stats_cluster_is_alive(sc, type)) { _remove_counter_from_index(sc, type); } } static void _update_indexes_of_cluster_if_needed(StatsCluster *sc, gpointer user_data) { stats_cluster_foreach_counter(sc, _index_counter, NULL); } static void _update_index(void) { g_static_mutex_lock(&stats_query_mutex); stats_lock(); stats_foreach_cluster(_update_indexes_of_cluster_if_needed, NULL); stats_unlock(); g_static_mutex_unlock(&stats_query_mutex); } static gboolean _is_pattern_matches_key(GPatternSpec *pattern, gpointer key) { gchar *counter_name = (gchar *) key; return g_pattern_match_string(pattern, counter_name); } static gboolean _is_single_match(const gchar *key_str) { gboolean is_wildcard = strchr(key_str, '*') ? TRUE : FALSE; gboolean is_joker = strchr(key_str, '?') ? TRUE : FALSE; return !is_wildcard && !is_joker; } static GList * _query_counter_hash(const gchar *key_str) { GPatternSpec *pattern = g_pattern_spec_new(key_str); GList *counters = NULL; gpointer key, value; GHashTableIter iter; gboolean single_match; _update_index(); single_match = _is_single_match(key_str); g_static_mutex_lock(&stats_query_mutex); g_hash_table_iter_init(&iter, counter_index); while (g_hash_table_iter_next(&iter, &key, &value)) { if (_is_pattern_matches_key(pattern, key)) { StatsCounterItem *counter = (StatsCounterItem *) value; counters = g_list_append(counters, counter); if (single_match) break; } } g_static_mutex_unlock(&stats_query_mutex); g_pattern_spec_free(pattern); return counters; } static GList * _get_input_counters_of_view(const ViewRecord *view) { GList *counters_of_view = NULL; for (GList *q = view->queries; q; q = q->next) { gchar *query = q->data; GList *selected_counters = _query_counter_hash(query); if (selected_counters == NULL) continue; counters_of_view = g_list_concat(counters_of_view, selected_counters); } return counters_of_view; } static GList * _get_aggregated_counters_from_views(GList *views) { GList *aggregated_counters = NULL; for (GList *v = views; v; v = v->next) { ViewRecord *view = v->data; GList *counters = _get_input_counters_of_view(view); if (counters == NULL) continue; view->aggregate(counters, &view->counter); aggregated_counters = g_list_append(aggregated_counters, view->counter); g_list_free(counters); } return aggregated_counters; } static GList * _get_views(const gchar *filter) { GPatternSpec *pattern = g_pattern_spec_new(filter); GList *views = NULL; gpointer key, value; GHashTableIter iter; gboolean single_match; single_match = _is_single_match(filter); g_static_mutex_lock(&stats_query_mutex); g_hash_table_iter_init(&iter, stats_views); while (g_hash_table_iter_next(&iter, &key, &value)) { if (_is_pattern_matches_key(pattern, key)) { ViewRecord *view = (ViewRecord *) value; views = g_list_append(views, view); if (single_match) break; } } g_static_mutex_unlock(&stats_query_mutex); g_pattern_spec_free(pattern); return views; } static GList * _get_aggregated_counters(const gchar *filter) { GList *views = _get_views(filter); GList *counters = _get_aggregated_counters_from_views(views); g_list_free(views); return counters; } static GList * _get_counters(const gchar *key_str) { GList *simple_counters = _query_counter_hash(key_str); GList *aggregated_counters = _get_aggregated_counters(key_str); if (simple_counters != NULL && aggregated_counters != NULL) return g_list_concat(simple_counters, aggregated_counters); if (simple_counters != NULL) return simple_counters; if (aggregated_counters != NULL) return aggregated_counters; return NULL; } static void _format_selected_counters(GList *counters, StatsFormatCb format_cb, gpointer result) { for (GList *counter = counters; counter; counter = counter->next) { StatsCounterItem *c = counter->data; format_cb(c, result); } } static void _reset_selected_counters(GList *counters) { GList *c; for (c = counters; c; c = c->next) { StatsCounterItem *counter = c->data; stats_counter_set(counter, 0); } } gboolean _stats_query_get(const gchar *expr, StatsFormatCb format_cb, gpointer result, gboolean must_reset) { if (!expr) return FALSE; gchar *key_str = NULL; GList *counters = NULL; gboolean found_match = FALSE; _setup_filter_expression(expr, &key_str); counters = _get_counters(key_str); _format_selected_counters(counters, format_cb, result); if (must_reset) _reset_selected_counters(counters); if (g_list_length(counters) > 0) found_match = TRUE; g_free(key_str); g_list_free(counters); return found_match; } gboolean stats_query_get(const gchar *expr, StatsFormatCb format_cb, gpointer result) { return _stats_query_get(expr, format_cb, result, FALSE); } gboolean stats_query_get_and_reset_counters(const gchar *expr, StatsFormatCb format_cb, gpointer result) { return _stats_query_get(expr, format_cb, result, TRUE); } static gboolean _is_timestamp(gchar *counter_name) { gchar *last_dot = strrchr(counter_name, '.'); return (g_strcmp0(last_dot, ".stamp") == 0); } void _sum_selected_counters(GList *counters, gpointer user_data) { GList *c; gpointer *args = (gpointer *) user_data; gint64 *sum = (gint64 *) args[1]; for (c = counters; c; c = c->next) { StatsCounterItem *counter = c->data; if (!_is_timestamp(stats_counter_get_name(counter))) *sum += stats_counter_get(counter); } } gboolean _stats_query_get_sum(const gchar *expr, StatsFormatCb format_cb, gpointer result, gboolean must_reset) { if (!expr) return FALSE; gchar *key_str = NULL; GList *counters = NULL; gboolean found_match = FALSE; gint64 sum = 0; gpointer args[] = {result, &sum}; _setup_filter_expression(expr, &key_str); counters = _get_counters(key_str); _sum_selected_counters(counters, (gpointer)args); _format_selected_counters(counters, format_cb, (gpointer)args); if (must_reset) _reset_selected_counters(counters); if (g_list_length(counters) > 0) found_match = TRUE; g_free(key_str); g_list_free(counters); return found_match; } gboolean stats_query_get_sum(const gchar *expr, StatsFormatCb format_cb, gpointer result) { return _stats_query_get_sum(expr, format_cb, result, FALSE); } gboolean stats_query_get_sum_and_reset_counters(const gchar *expr, StatsFormatCb format_cb, gpointer result) { return _stats_query_get_sum(expr, format_cb, result, TRUE); } gboolean _stats_query_list(const gchar *expr, StatsFormatCb format_cb, gpointer result, gboolean must_reset) { gchar *key_str = NULL; GList *counters = NULL; gboolean found_match = FALSE; _setup_filter_expression(expr, &key_str); counters = _get_counters(key_str); _format_selected_counters(counters, format_cb, result); if (must_reset) _reset_selected_counters(counters); if (g_list_length(counters) > 0) found_match = TRUE; g_free(key_str); g_list_free(counters); return found_match; } gboolean stats_query_list(const gchar *expr, StatsFormatCb format_cb, gpointer result) { return _stats_query_list(expr, format_cb, result, FALSE); } gboolean stats_query_list_and_reset_counters(const gchar *expr, StatsFormatCb format_cb, gpointer result) { return _stats_query_list(expr, format_cb, result, TRUE); } void stats_query_init(void) { counter_index = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); stats_views = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _free_view_record); } void stats_query_deinit(void) { g_hash_table_destroy(counter_index); counter_index = NULL; g_hash_table_destroy(stats_views); stats_views = NULL; } void stats_query_index_counter(StatsCluster *cluster, gint type) { _add_counter_to_index(cluster, type); } syslog-ng-syslog-ng-3.13.2/lib/stats/stats-query.h000066400000000000000000000037751321171025300220270ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATS_QUERY_H_INCLUDED #define STATS_QUERY_H_INCLUDED #include "stats-cluster.h" #include "syslog-ng.h" typedef gboolean (*StatsFormatCb)(StatsCounterItem *ctr, gpointer user_data); typedef void (*AggregatedMetricsCb)(GList *counters, StatsCounterItem **result); gboolean stats_query_list(const gchar *expr, StatsFormatCb format_cb, gpointer result); gboolean stats_query_list_and_reset_counters(const gchar *expr, StatsFormatCb format_cb, gpointer result); gboolean stats_query_get(const gchar *expr, StatsFormatCb format_cb, gpointer result); gboolean stats_query_get_and_reset_counters(const gchar *expr, StatsFormatCb format_cb, gpointer result); gboolean stats_query_get_sum(const gchar *expr, StatsFormatCb format_cb, gpointer result); gboolean stats_query_get_sum_and_reset_counters(const gchar *expr, StatsFormatCb format_cb, gpointer result); void stats_query_init(void); void stats_query_deinit(void); void stats_register_view(gchar *name, GList *queries, const AggregatedMetricsCb aggregate); void stats_query_index_counter(StatsCluster *cluster, gint type); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/stats-registry.c000066400000000000000000000252471321171025300225230ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stats/stats-registry.h" #include "stats/stats-query.h" #include "cfg.h" #include typedef struct _StatsClusterContainer { GHashTable *static_clusters; GHashTable *dynamic_clusters; } StatsClusterContainer; static StatsClusterContainer stats_cluster_container; static guint _number_of_dynamic_clusters(void) { return g_hash_table_size(stats_cluster_container.dynamic_clusters); } static GStaticMutex stats_mutex = G_STATIC_MUTEX_INIT; gboolean stats_locked; static void _insert_cluster(StatsCluster *sc) { if (sc->dynamic) g_hash_table_insert(stats_cluster_container.dynamic_clusters, &sc->key, sc); else g_hash_table_insert(stats_cluster_container.static_clusters, &sc->key, sc); } void stats_lock(void) { g_static_mutex_lock(&stats_mutex); stats_locked = TRUE; } void stats_unlock(void) { stats_locked = FALSE; g_static_mutex_unlock(&stats_mutex); } static StatsCluster * _grab_dynamic_cluster(const StatsClusterKey *sc_key) { StatsCluster *sc; sc = g_hash_table_lookup(stats_cluster_container.dynamic_clusters, sc_key); if (!sc) { if (!stats_check_dynamic_clusters_limit(_number_of_dynamic_clusters())) return NULL; sc = stats_cluster_dynamic_new(sc_key); _insert_cluster(sc); if ( !stats_check_dynamic_clusters_limit(_number_of_dynamic_clusters())) { msg_warning("Number of dynamic cluster limit has been reached.", evt_tag_int("allowed_clusters", stats_number_of_dynamic_clusters_limit())); } } return sc; } static StatsCluster * _grab_static_cluster(const StatsClusterKey *sc_key) { StatsCluster *sc; sc = g_hash_table_lookup(stats_cluster_container.static_clusters, sc_key); if (!sc) { sc = stats_cluster_new(sc_key); _insert_cluster(sc); } return sc; } static StatsCluster * _grab_cluster(gint stats_level, const StatsClusterKey *sc_key, gboolean dynamic) { if (!stats_check_level(stats_level)) return NULL; StatsCluster *sc = NULL; if (dynamic) sc = _grab_dynamic_cluster(sc_key); else sc = _grab_static_cluster(sc_key); if (!sc) return NULL; /* check that we are not overwriting a dynamic counter with a * non-dynamic one or vica versa. This could only happen if the same * key is used for both a dynamic counter and a non-dynamic one, which * is a programming error */ g_assert(sc->dynamic == dynamic); return sc; } static StatsCluster * _register_counter(gint stats_level, const StatsClusterKey *sc_key, gint type, gboolean dynamic, StatsCounterItem **counter) { StatsCluster *sc; g_assert(stats_locked); sc = _grab_cluster(stats_level, sc_key, dynamic); if (sc) { *counter = stats_cluster_track_counter(sc, type); (*counter)->type = type; } else { *counter = NULL; } return sc; } /** * stats_register_counter: * @stats_level: the required statistics level to make this counter available * @component: a reference to the syslog-ng component that this counter belongs to (SCS_*) * @id: the unique identifier of the configuration item that this counter belongs to * @instance: if a given configuration item manages multiple similar counters * this makes those unique (like destination filename in case macros are used) * @type: the counter type (processed, dropped, etc) * @counter: returned pointer to the counter * * This fuction registers a general purpose counter. Whenever multiple * objects touch the same counter all of these should register the counter * with the same name. Internally the stats subsystem counts the number of * users of the same counter in this case, thus the counter will only be * freed when all of these uses are unregistered. **/ StatsCluster * stats_register_counter(gint stats_level, const StatsClusterKey *sc_key, gint type, StatsCounterItem **counter) { return _register_counter(stats_level, sc_key, type, FALSE, counter); } StatsCluster * stats_register_counter_and_index(gint stats_level, const StatsClusterKey *sc_key, gint type, StatsCounterItem **counter) { StatsCluster *cluster = _register_counter(stats_level, sc_key, type, FALSE, counter); if (cluster) stats_query_index_counter(cluster, type); return cluster; } StatsCluster * stats_register_dynamic_counter(gint stats_level, const StatsClusterKey *sc_key, gint type, StatsCounterItem **counter) { return _register_counter(stats_level, sc_key, type, TRUE, counter); } /* * stats_instant_inc_dynamic_counter * @timestamp: if non-negative, an associated timestamp will be created and set * * Instantly create (if not exists) and increment a dynamic counter. */ void stats_register_and_increment_dynamic_counter(gint stats_level, const StatsClusterKey *sc_key, time_t timestamp) { StatsCounterItem *counter, *stamp; StatsCluster *handle; g_assert(stats_locked); handle = stats_register_dynamic_counter(stats_level, sc_key, SC_TYPE_PROCESSED, &counter); if (!handle) return; stats_counter_inc(counter); if (timestamp >= 0) { stats_register_associated_counter(handle, SC_TYPE_STAMP, &stamp); stats_counter_set(stamp, timestamp); stats_unregister_dynamic_counter(handle, SC_TYPE_STAMP, &stamp); } stats_unregister_dynamic_counter(handle, SC_TYPE_PROCESSED, &counter); } /** * stats_register_associated_counter: * @sc: the dynamic counter that was registered with stats_register_dynamic_counter * @type: the type that we want to use in the same StatsCluster instance * @counter: the returned pointer to the counter itself * * This function registers another counter type in the same StatsCounter * instance in order to avoid an unnecessary lookup. **/ void stats_register_associated_counter(StatsCluster *sc, gint type, StatsCounterItem **counter) { g_assert(stats_locked); *counter = NULL; if (!sc) return; g_assert(sc->dynamic); *counter = stats_cluster_track_counter(sc, type); } void stats_unregister_counter(const StatsClusterKey *sc_key, gint type, StatsCounterItem **counter) { StatsCluster *sc; g_assert(stats_locked); if (*counter == NULL) return; sc = g_hash_table_lookup(stats_cluster_container.static_clusters, sc_key); stats_cluster_untrack_counter(sc, type, counter); } void stats_unregister_dynamic_counter(StatsCluster *sc, gint type, StatsCounterItem **counter) { g_assert(stats_locked); if (!sc) return; stats_cluster_untrack_counter(sc, type, counter); } void save_counter_to_persistent_storage(GlobalConfig *cfg, StatsCounterItem *counter) { if (counter) { g_assert(counter->name); gssize *orig_value = g_new(gssize, 1); *orig_value = stats_counter_get(counter); cfg_persist_config_add(cfg, counter->name, orig_value, (GDestroyNotify) g_free, FALSE); } } void load_counter_from_persistent_storage(GlobalConfig *cfg, StatsCounterItem *counter) { g_assert(counter->name); gssize *orig_value = cfg_persist_config_fetch(cfg, counter->name); if (orig_value) stats_counter_set(counter, *orig_value); } static void _foreach_cluster_helper(gpointer key, gpointer value, gpointer user_data) { gpointer *args = (gpointer *) user_data; StatsForeachClusterFunc func = args[0]; gpointer func_data = args[1]; StatsCluster *sc = (StatsCluster *) value; func(sc, func_data); } void stats_foreach_cluster(StatsForeachClusterFunc func, gpointer user_data) { gpointer args[] = { func, user_data }; g_assert(stats_locked); g_hash_table_foreach(stats_cluster_container.static_clusters, _foreach_cluster_helper, args); g_hash_table_foreach(stats_cluster_container.dynamic_clusters, _foreach_cluster_helper, args); } static gboolean _foreach_cluster_remove_helper(gpointer key, gpointer value, gpointer user_data) { gpointer *args = (gpointer *) user_data; StatsForeachClusterRemoveFunc func = args[0]; gpointer func_data = args[1]; StatsCluster *sc = (StatsCluster *) value; return func(sc, func_data); } void stats_foreach_cluster_remove(StatsForeachClusterRemoveFunc func, gpointer user_data) { gpointer args[] = { func, user_data }; g_hash_table_foreach_remove(stats_cluster_container.static_clusters, _foreach_cluster_remove_helper, args); g_hash_table_foreach_remove(stats_cluster_container.dynamic_clusters, _foreach_cluster_remove_helper, args); } static void _foreach_counter_helper(StatsCluster *sc, gpointer user_data) { gpointer *args = (gpointer *) user_data; StatsForeachCounterFunc func = args[0]; gpointer func_data = args[1]; stats_cluster_foreach_counter(sc, func, func_data); } void stats_foreach_counter(StatsForeachCounterFunc func, gpointer user_data) { gpointer args[] = { func, user_data }; g_assert(stats_locked); stats_foreach_cluster(_foreach_counter_helper, args); } void stats_registry_init(void) { stats_cluster_container.static_clusters = g_hash_table_new_full((GHashFunc) stats_cluster_hash, (GEqualFunc) stats_cluster_equal, NULL, (GDestroyNotify) stats_cluster_free); stats_cluster_container.dynamic_clusters = g_hash_table_new_full((GHashFunc) stats_cluster_hash, (GEqualFunc) stats_cluster_equal, NULL, (GDestroyNotify) stats_cluster_free); g_static_mutex_init(&stats_mutex); } void stats_registry_deinit(void) { g_hash_table_destroy(stats_cluster_container.static_clusters); g_hash_table_destroy(stats_cluster_container.dynamic_clusters); stats_cluster_container.static_clusters = NULL; stats_cluster_container.dynamic_clusters = NULL; g_static_mutex_free(&stats_mutex); } syslog-ng-syslog-ng-3.13.2/lib/stats/stats-registry.h000066400000000000000000000055321321171025300225230ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATS_REGISTRY_H_INCLUDED #define STATS_REGISTRY_H_INCLUDED 1 #include "stats/stats.h" #include "stats/stats-cluster.h" typedef void (*StatsForeachClusterFunc)(StatsCluster *sc, gpointer user_data); typedef gboolean (*StatsForeachClusterRemoveFunc)(StatsCluster *sc, gpointer user_data); void stats_lock(void); void stats_unlock(void); gboolean stats_check_level(gint level); StatsCluster *stats_register_counter(gint level, const StatsClusterKey *sc_key, gint type, StatsCounterItem **counter); StatsCluster *stats_register_counter_and_index(gint level, const StatsClusterKey *sc_key, gint type, StatsCounterItem **counter); StatsCluster *stats_register_dynamic_counter(gint stats_level, const StatsClusterKey *sc_key, gint type, StatsCounterItem **counter); void stats_register_and_increment_dynamic_counter(gint stats_level, const StatsClusterKey *sc_key, time_t timestamp); void stats_register_associated_counter(StatsCluster *handle, gint type, StatsCounterItem **counter); void stats_unregister_counter(const StatsClusterKey *sc_key, gint type, StatsCounterItem **counter); void stats_unregister_dynamic_counter(StatsCluster *handle, gint type, StatsCounterItem **counter); void save_counter_to_persistent_storage(GlobalConfig *cfg, StatsCounterItem *counter); void stats_foreach_counter(StatsForeachCounterFunc func, gpointer user_data); void stats_foreach_cluster(StatsForeachClusterFunc func, gpointer user_data); void stats_foreach_cluster_remove(StatsForeachClusterRemoveFunc func, gpointer user_data); void stats_registry_init(void); void stats_registry_deinit(void); void save_counter_to_persistent_storage(GlobalConfig *cfg, StatsCounterItem *counter); void load_counter_from_persistent_storage(GlobalConfig *cfg, StatsCounterItem *counter); gboolean stats_check_dynamic_clusters_limit(guint number_of_clusters); gint stats_number_of_dynamic_clusters_limit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/stats-syslog.c000066400000000000000000000070121321171025300221610ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stats/stats-syslog.h" #include "syslog-names.h" /* Static counters for severities and facilities */ /* LOG_DEBUG 0x7 */ #define SEVERITY_MAX (0x7 + 1) /* LOG_LOCAL7 23<<3, one additional slot for "everything-else" counter */ #define FACILITY_MAX (23 + 1 + 1) static StatsCounterItem *severity_counters[SEVERITY_MAX]; static StatsCounterItem *facility_counters[FACILITY_MAX]; void stats_syslog_process_message_pri(guint16 pri) { int lpri = LOG_FAC(pri); stats_counter_inc(severity_counters[LOG_PRI(pri)]); if (lpri > (FACILITY_MAX - 1)) { /* the large facilities (=facility.other) are collected in the last array item */ lpri = FACILITY_MAX - 1; } stats_counter_inc(facility_counters[lpri]); } void stats_syslog_reinit(void) { gchar name[11] = ""; gint i; StatsClusterKey sc_key; stats_lock(); if (stats_check_level(3)) { /* we need these counters, register them */ for (i = 0; i < SEVERITY_MAX; i++) { g_snprintf(name, sizeof(name), "%d", i); stats_cluster_logpipe_key_set(&sc_key, SCS_SEVERITY | SCS_SOURCE, NULL, name ); stats_register_counter(3, &sc_key, SC_TYPE_PROCESSED, &severity_counters[i]); } for (i = 0; i < FACILITY_MAX - 1; i++) { g_snprintf(name, sizeof(name), "%d", i); stats_cluster_logpipe_key_set(&sc_key, SCS_FACILITY | SCS_SOURCE, NULL, name ); stats_register_counter(3, &sc_key, SC_TYPE_PROCESSED, &facility_counters[i]); } stats_cluster_logpipe_key_set(&sc_key, SCS_FACILITY | SCS_SOURCE, NULL, "other" ); stats_register_counter(3, &sc_key, SC_TYPE_PROCESSED, &facility_counters[FACILITY_MAX - 1]); } else { /* no need for facility/severity counters, unregister them */ for (i = 0; i < SEVERITY_MAX; i++) { g_snprintf(name, sizeof(name), "%d", i); stats_cluster_logpipe_key_set(&sc_key, SCS_SEVERITY | SCS_SOURCE, NULL, name ); stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &severity_counters[i]); } for (i = 0; i < FACILITY_MAX - 1; i++) { g_snprintf(name, sizeof(name), "%d", i); stats_cluster_logpipe_key_set(&sc_key, SCS_FACILITY | SCS_SOURCE, NULL, name ); stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &facility_counters[i]); } stats_cluster_logpipe_key_set(&sc_key, SCS_FACILITY | SCS_SOURCE, NULL, "other" ); stats_unregister_counter(&sc_key, SC_TYPE_PROCESSED, &facility_counters[FACILITY_MAX - 1]); } stats_unlock(); } syslog-ng-syslog-ng-3.13.2/lib/stats/stats-syslog.h000066400000000000000000000022561321171025300221730ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATS_SYSLOG_H_INCLUDED #define STATS_SYSLOG_H_INCLUDED 1 #include "stats/stats-registry.h" void stats_syslog_process_message_pri(guint16 pri); void stats_syslog_reinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/stats.c000066400000000000000000000173401321171025300206500ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stats/stats-control.h" #include "stats/stats-log.h" #include "stats/stats-query.h" #include "stats/stats-registry.h" #include "stats/stats-syslog.h" #include "stats/stats.h" #include "timeutils.h" #include #include /* * The statistics module * * Various components of syslog-ng require counters to keep track of various * metrics, such as number of messages processed, dropped or stored in a * queue. For this purpose, this module provides an easy to use API to * register and keep track these counters, and also to publish them to * external programs via a UNIX domain socket. * * Counters are organized into clusters, as the same syslog-ng component * usually uses a set of related counters. Each counter is typed (see * SC_TYPE_XXX enums), the most common is SC_TYPE_PROCESSED, which is merely * counts the number of messages being processed by a source/destination/etc. * * Each cluster has the following properties: * * source component: enumerable type, that specifies the syslog-ng * component that the given counter belongs to, examples: * src.file, dst.file, center, src.socket, etc. * * * id: the unique identifier of the syslog-ng configuration item that * this counter belongs to. Named configuration elements (source, * destination, etc) use their "name" here. Other components without a * name use either an autogenerated ID (that can change when the * configuration file changes), or an explicit ID configured by the * administrator. * * * instance: each configuration element may track several sets of * counters. This field specifies an identifier that makes a group of * counters unique. For instance: * - source TCP drivers use the IP address of the client here * - destination file writers use the expanded filename * - for those which have no notion for instance, NULL is used * * * state: dynamic, active or orphaned, this indicates whether the given * counter is in use or in orphaned state * * * type: counter type (processed, dropped, stored, etc) * * Threading * * Registration and unregistration must be protected expicitly by invoking * stats_lock()/unlock(). Once registered, counters can be manipulated * without acquiring stats_lock(). * * Counters are updated atomically by the use of the stats_counter_inc/dec() * methods. */ static gboolean stats_cluster_is_expired(StatsOptions *options, StatsCluster *sc, time_t now) { time_t tstamp; /* check if dynamic entry, non-dynamic entries cannot be too large in * numbers, those are never pruned */ if (!sc->dynamic) return FALSE; /* this entry is being updated, cannot be too old */ if (sc->use_count > 0) return FALSE; /* check if timestamp is stored, no timestamp means we can't expire it. * All dynamic entries should have a timestamp. */ if ((sc->live_mask & (1 << SC_TYPE_STAMP)) == 0) return FALSE; tstamp = sc->counter_group.counters[SC_TYPE_STAMP].value; return (tstamp <= now - options->lifetime); } typedef struct _StatsTimerState { GTimeVal now; time_t oldest_counter; gint dropped_counters; EVTREC *stats_event; StatsOptions *options; } StatsTimerState; static gboolean stats_prune_counter(StatsCluster *sc, StatsTimerState *st) { gboolean expired; expired = stats_cluster_is_expired(st->options, sc, st->now.tv_sec); if (expired) { time_t tstamp = sc->counter_group.counters[SC_TYPE_STAMP].value; if ((st->oldest_counter) == 0 || st->oldest_counter > tstamp) st->oldest_counter = tstamp; st->dropped_counters++; } return expired; } static gboolean stats_format_and_prune_cluster(StatsCluster *sc, gpointer user_data) { StatsTimerState *st = (StatsTimerState *) user_data; if (st->stats_event) stats_log_format_cluster(sc, st->stats_event); return stats_prune_counter(sc, st); } void stats_publish_and_prune_counters(StatsOptions *options) { StatsTimerState st; gboolean publish = (options->log_freq > 0); st.oldest_counter = 0; st.dropped_counters = 0; st.stats_event = NULL; st.options = options; cached_g_current_time(&st.now); if (publish) st.stats_event = msg_event_create(EVT_PRI_INFO, "Log statistics", NULL); stats_lock(); stats_foreach_cluster_remove(stats_format_and_prune_cluster, &st); stats_unlock(); if (publish) msg_event_send(st.stats_event); if (st.dropped_counters > 0) { msg_notice("Pruning stats-counters have finished", evt_tag_int("dropped", st.dropped_counters), evt_tag_long("oldest-timestamp", (long) st.oldest_counter)); } } static void stats_timer_rearm(StatsOptions *options, struct iv_timer *timer) { gint freq; freq = options->log_freq; if (!freq) freq = options->lifetime <= 1 ? 1 : options->lifetime / 2; if (freq > 0) { /* arm the timer */ iv_validate_now(); timer->expires = iv_now; timespec_add_msec(&timer->expires, freq * 1000); iv_timer_register(timer); } } static void stats_timer_init(struct iv_timer *timer, void (*handler)(void *), StatsOptions *options) { IV_TIMER_INIT(timer); timer->handler = handler; timer->cookie = options; } static void stats_timer_kill(struct iv_timer *timer) { if (!timer->handler) return; if (iv_timer_registered(timer)) iv_timer_unregister(timer); } static struct iv_timer stats_timer; static void stats_timer_elapsed(gpointer st) { StatsOptions *options = (StatsOptions *) st; stats_publish_and_prune_counters(options); stats_timer_rearm(options, &stats_timer); } void stats_timer_reinit(StatsOptions *options) { stats_timer_kill(&stats_timer); stats_timer_init(&stats_timer, stats_timer_elapsed, options); stats_timer_rearm(options, &stats_timer); } static StatsOptions *stats_options; void stats_reinit(StatsOptions *options) { stats_options = options; stats_syslog_reinit(); stats_timer_reinit(options); } void stats_init(void) { stats_registry_init(); stats_query_init(); stats_register_control_commands(); } void stats_destroy(void) { stats_query_deinit(); stats_registry_deinit(); stats_unregister_control_commands(); } void stats_options_defaults(StatsOptions *options) { options->level = 0; options->log_freq = 600; options->lifetime = 600; options->max_dynamic = -1; } gboolean stats_check_level(gint level) { if (stats_options) return (stats_options->level >= level); else return level == 0; } gboolean stats_check_dynamic_clusters_limit(guint number_of_clusters) { if (!stats_options) return TRUE; if (stats_options->max_dynamic == -1) return TRUE; return (stats_options->max_dynamic > number_of_clusters); } gint stats_number_of_dynamic_clusters_limit() { if (!stats_options) return -1; return stats_options->max_dynamic; } syslog-ng-syslog-ng-3.13.2/lib/stats/stats.h000066400000000000000000000026661321171025300206620ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATS_H_INCLUDED #define STATS_H_INCLUDED #include "syslog-ng.h" #include "stats/stats-cluster.h" typedef struct _StatsOptions { gint log_freq; gint level; gint lifetime; gint max_dynamic; } StatsOptions; enum { STATS_LEVEL0 = 0, STATS_LEVEL1, STATS_LEVEL2, STATS_LEVEL3 }; void stats_reinit(StatsOptions *options); void stats_init(void); void stats_destroy(void); void stats_options_defaults(StatsOptions *options); #endif syslog-ng-syslog-ng-3.13.2/lib/stats/tests/000077500000000000000000000000001321171025300205035ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/stats/tests/Makefile.am000066400000000000000000000015011321171025300225340ustar00rootroot00000000000000lib_stats_tests_TESTS = \ lib/stats/tests/test_stats_cluster check_PROGRAMS += ${lib_stats_tests_TESTS} lib_stats_tests_test_stats_cluster_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/stats/tests lib_stats_tests_test_stats_cluster_LDADD = $(TEST_LDADD) lib_stats_tests_test_stats_cluster_SOURCES = \ lib/stats/tests/test_stats_cluster.c if ENABLE_CRITERION stats_test_extra_modules = \ $(PREOPEN_SYSLOGFORMAT) lib_stats_tests_TESTS += \ lib/stats/tests/test_stats_query \ lib/stats/tests/test_dynamic_ctr_reg lib_stats_tests_test_stats_query_CFLAGS = $(TEST_CFLAGS) lib_stats_tests_test_stats_query_LDADD = \ $(TEST_LDADD) $(stats_test_extra_modules) lib_stats_tests_test_dynamic_ctr_reg_CFLAGS = $(TEST_CFLAGS) lib_stats_tests_test_dynamic_ctr_reg_LDADD = \ $(TEST_LDADD) $(stats_test_extra_modules) endif syslog-ng-syslog-ng-3.13.2/lib/stats/tests/test_dynamic_ctr_reg.c000066400000000000000000000055571321171025300250530ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "apphook.h" #include "logmsg/logmsg.h" #include "stats/stats-cluster.h" #include "stats/stats-cluster-single.h" #include "stats/stats-counter.h" #include "stats/stats-query.h" #include "stats/stats-registry.h" #include "syslog-ng.h" #include #include #include #include TestSuite(stats_dynamic_clusters, .init = app_startup, .fini = app_shutdown); Test(stats_dynamic_clusters, unlimited_by_default) { StatsOptions stats_opts; stats_options_defaults(&stats_opts); stats_reinit(&stats_opts); cr_assert_eq(stats_check_dynamic_clusters_limit(0), TRUE); cr_assert_eq(stats_check_dynamic_clusters_limit(UINT_MAX), TRUE); } Test(stats_dynamic_clusters, limited) { StatsOptions stats_opts; stats_options_defaults(&stats_opts); stats_opts.max_dynamic = 2; stats_reinit(&stats_opts); cr_assert_eq(stats_check_dynamic_clusters_limit(0), TRUE); cr_assert_eq(stats_check_dynamic_clusters_limit(1), TRUE); cr_assert_eq(stats_check_dynamic_clusters_limit(2), FALSE); } Test(stats_dynamic_clusters, register_limited) { StatsOptions stats_opts; stats_options_defaults(&stats_opts); stats_opts.level = 3; stats_opts.max_dynamic = 2; stats_reinit(&stats_opts); stats_lock(); { StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_HOST | SCS_SENDER, NULL, "testhost1"); StatsCounterItem *counter = NULL; StatsCluster *sc = stats_register_dynamic_counter(1, &sc_key, SC_TYPE_PROCESSED, &counter); cr_assert_not_null(sc); stats_cluster_logpipe_key_set(&sc_key, SCS_HOST | SCS_SENDER, NULL, "testhost2"); sc = stats_register_dynamic_counter(1, &sc_key, SC_TYPE_PROCESSED, &counter); cr_assert_not_null(sc); stats_cluster_logpipe_key_set(&sc_key, SCS_HOST | SCS_SENDER, NULL, "testhost3"); sc = stats_register_dynamic_counter(1, &sc_key, SC_TYPE_PROCESSED, &counter); cr_assert_null(sc); } stats_unlock(); } syslog-ng-syslog-ng-3.13.2/lib/stats/tests/test_stats_cluster.c000066400000000000000000000213031321171025300246040ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "stats/stats-cluster.h" #include "stats/stats-cluster-single.h" #define STATS_CLUSTER_TESTCASE(x) x() static void test_stats_cluster_single(void) { StatsCluster *sc; StatsClusterKey sc_key; stats_cluster_single_key_set(&sc_key, SCS_GLOBAL, "logmsg_allocated_bytes", NULL); sc = stats_cluster_new(&sc_key); assert_string(sc->query_key, "global.logmsg_allocated_bytes", "Unexpected query key"); assert_gint(sc->counter_group.capacity, 1, "Invalid group capacity"); stats_cluster_free(sc); } static void test_stats_cluster_new_replaces_NULL_with_an_empty_string(void) { StatsCluster *sc; StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_SOURCE | SCS_FILE, NULL, NULL ); sc = stats_cluster_new(&sc_key); assert_string(sc->key.id, "", "StatsCluster->id is not properly defaulted to an empty string"); assert_string(sc->key.instance, "", "StatsCluster->instance is not properly defaulted to an empty string"); stats_cluster_free(sc); } static void assert_stats_cluster_equals(StatsCluster *sc1, StatsCluster *sc2) { assert_true(stats_cluster_equal(sc1, sc2), "unexpected unequal StatsClusters"); } static void assert_stats_cluster_mismatches(StatsCluster *sc1, StatsCluster *sc2) { assert_false(stats_cluster_equal(sc1, sc2), "unexpected equal StatsClusters"); } static void assert_stats_cluster_equals_and_free(StatsCluster *sc1, StatsCluster *sc2) { assert_stats_cluster_equals(sc1, sc2); stats_cluster_free(sc1); stats_cluster_free(sc2); } static void assert_stats_cluster_mismatches_and_free(StatsCluster *sc1, StatsCluster *sc2) { assert_stats_cluster_mismatches(sc1, sc2); stats_cluster_free(sc1); stats_cluster_free(sc2); } static void test_stats_cluster_equal_if_component_id_and_instance_are_the_same(void) { StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_SOURCE | SCS_FILE, "id", "instance" ); assert_stats_cluster_equals_and_free(stats_cluster_new(&sc_key), stats_cluster_new(&sc_key)); stats_cluster_logpipe_key_set(&sc_key, SCS_SOURCE | SCS_FILE, "id", "instance1" ); StatsClusterKey sc_key2; stats_cluster_logpipe_key_set(&sc_key2, SCS_SOURCE | SCS_FILE, "id", "instance2" ); assert_stats_cluster_mismatches_and_free(stats_cluster_new(&sc_key), stats_cluster_new(&sc_key2)); stats_cluster_logpipe_key_set(&sc_key, SCS_SOURCE | SCS_FILE, "id1", "instance" ); stats_cluster_logpipe_key_set(&sc_key2, SCS_SOURCE | SCS_FILE, "id2", "instance" ); assert_stats_cluster_mismatches_and_free(stats_cluster_new(&sc_key), stats_cluster_new(&sc_key2)); stats_cluster_logpipe_key_set(&sc_key, SCS_SOURCE | SCS_FILE, "id", "instance" ); stats_cluster_logpipe_key_set(&sc_key2, SCS_DESTINATION | SCS_FILE, "id", "instance" ); assert_stats_cluster_mismatches_and_free(stats_cluster_new(&sc_key), stats_cluster_new(&sc_key2)); } static void test_stats_cluster_key_not_equal_when_custom_tags_are_different(void) { StatsClusterKey sc_key1; StatsClusterKey sc_key2; stats_cluster_single_key_set_with_name(&sc_key1, SCS_SOURCE | SCS_FILE, "id", "instance", "name1"); stats_cluster_single_key_set_with_name(&sc_key2, SCS_SOURCE | SCS_FILE, "id", "instance", "name2"); assert_gboolean(stats_cluster_key_equal(&sc_key1, &sc_key2), FALSE, __FUNCTION__); } static void test_stats_cluster_key_equal_when_custom_tags_are_the_same(void) { StatsClusterKey sc_key1; StatsClusterKey sc_key2; stats_cluster_single_key_set_with_name(&sc_key1, SCS_SOURCE | SCS_FILE, "id", "instance", "name"); stats_cluster_single_key_set_with_name(&sc_key2, SCS_SOURCE | SCS_FILE, "id", "instance", "name"); assert_gboolean(stats_cluster_key_equal(&sc_key1, &sc_key2), TRUE, __FUNCTION__); } typedef struct _ValidateCountersState { gint type1; va_list types; gint validate_count; } ValidateCountersState; static void _validate_yielded_counters(StatsCluster *sc, gint type, StatsCounterItem *counter, gpointer user_data) { ValidateCountersState *st = (ValidateCountersState *) user_data; gint t; t = va_arg(st->types, gint); assert_true(t >= 0, "foreach counter returned a new counter, but we expected the end already"); assert_gint(type, t, "Counter type mismatch"); st->validate_count++; } static void assert_stats_foreach_yielded_counters_matches(StatsCluster *sc, ...) { ValidateCountersState st; va_list va; gint type_count = 0; gint t; va_start(va, sc); st.validate_count = 0; va_copy(st.types, va); t = va_arg(va, gint); while (t >= 0) { type_count++; t = va_arg(va, gint); } stats_cluster_foreach_counter(sc, _validate_yielded_counters, &st); va_end(va); assert_gint(type_count, st.validate_count, "the number of validated counters mismatch the expected size"); } static void test_stats_foreach_counter_yields_tracked_counters(void) { StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_SOURCE | SCS_FILE, "id", "instance" ); StatsCluster *sc = stats_cluster_new(&sc_key); assert_stats_foreach_yielded_counters_matches(sc, -1); stats_cluster_track_counter(sc, SC_TYPE_PROCESSED); assert_stats_foreach_yielded_counters_matches(sc, SC_TYPE_PROCESSED, -1); stats_cluster_track_counter(sc, SC_TYPE_STAMP); assert_stats_foreach_yielded_counters_matches(sc, SC_TYPE_PROCESSED, SC_TYPE_STAMP, -1); stats_cluster_free(sc); } static void test_stats_foreach_counter_never_forgets_untracked_counters(void) { StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_SOURCE | SCS_FILE, "id", "instance" ); StatsCluster *sc = stats_cluster_new(&sc_key); StatsCounterItem *processed, *stamp; processed = stats_cluster_track_counter(sc, SC_TYPE_PROCESSED); stamp = stats_cluster_track_counter(sc, SC_TYPE_STAMP); stats_cluster_untrack_counter(sc, SC_TYPE_PROCESSED, &processed); assert_stats_foreach_yielded_counters_matches(sc, SC_TYPE_PROCESSED, SC_TYPE_STAMP, -1); stats_cluster_untrack_counter(sc, SC_TYPE_STAMP, &stamp); assert_stats_foreach_yielded_counters_matches(sc, SC_TYPE_PROCESSED, SC_TYPE_STAMP, -1); stats_cluster_free(sc); } static void assert_stats_component_name(gint component, const gchar *expected) { gchar buf[32]; const gchar *name; StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, component, NULL, NULL ); StatsCluster *sc = stats_cluster_new(&sc_key); name = stats_cluster_get_component_name(sc, buf, sizeof(buf)); assert_string(name, expected, "component name mismatch"); stats_cluster_free(sc); } static void test_get_component_name_translates_component_to_name_properly(void) { assert_stats_component_name(SCS_SOURCE | SCS_FILE, "src.file"); assert_stats_component_name(SCS_DESTINATION | SCS_FILE, "dst.file"); assert_stats_component_name(SCS_GLOBAL, "global"); assert_stats_component_name(SCS_SOURCE | SCS_GROUP, "source"); assert_stats_component_name(SCS_DESTINATION | SCS_GROUP, "destination"); } static void test_stats_cluster(void) { STATS_CLUSTER_TESTCASE(test_stats_cluster_new_replaces_NULL_with_an_empty_string); STATS_CLUSTER_TESTCASE(test_stats_cluster_equal_if_component_id_and_instance_are_the_same); STATS_CLUSTER_TESTCASE(test_stats_foreach_counter_yields_tracked_counters); STATS_CLUSTER_TESTCASE(test_stats_foreach_counter_never_forgets_untracked_counters); STATS_CLUSTER_TESTCASE(test_get_component_name_translates_component_to_name_properly); STATS_CLUSTER_TESTCASE(test_stats_cluster_single); STATS_CLUSTER_TESTCASE(test_stats_cluster_key_not_equal_when_custom_tags_are_different); STATS_CLUSTER_TESTCASE(test_stats_cluster_key_equal_when_custom_tags_are_the_same); } int main(int argc, char *argv[]) { test_stats_cluster(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/stats/tests/test_stats_query.c000066400000000000000000000265751321171025300243100ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "apphook.h" #include "logmsg/logmsg.h" #include "stats/stats-cluster.h" #include "stats/stats-cluster-single.h" #include "stats/stats-counter.h" #include "stats/stats-query.h" #include "stats/stats-registry.h" #include "syslog-ng.h" #include #include #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) typedef struct _CounterHashContent { const gint component; const gchar *id; const gchar *instance; const gint type; } CounterHashContent; typedef struct _QueryTestCase { const gchar *pattern; const gchar *expected; } QueryTestCase; typedef void(*ClusterKeySet)(StatsClusterKey *, guint16, const gchar *, const gchar *); static void _add_two_to_value(GList *counters, StatsCounterItem **result) { StatsCounterItem *c = counters->data; stats_counter_set(*result, stats_counter_get(c) + 2); } static gchar * _construct_view_name(const gchar *counter_id) { GString *aliased_name = g_string_new(""); aliased_name = g_string_append(aliased_name, counter_id); aliased_name = g_string_append(aliased_name, ".aliased"); return g_string_free(aliased_name, FALSE); } static GList * _construct_view_query_list(const gchar *counter_instance) { GList *queries = NULL; GString *query = g_string_new("*"); query = g_string_append(query, counter_instance); query = g_string_append(query, ".*"); gchar *q = g_string_free(query, FALSE); queries = g_list_append(queries, q); return queries; } static void _register_counters(const CounterHashContent *counters, size_t n, ClusterKeySet key_set) { stats_lock(); for (size_t i = 0; i < n; i++) { StatsCounterItem *item = NULL; StatsClusterKey sc_key; key_set(&sc_key, counters[i].component, counters[i].id, counters[i].instance ); stats_register_counter(0, &sc_key, counters[i].type, &item); gchar *name = _construct_view_name(counters[i].id); GList *queries = _construct_view_query_list(counters[i].instance); stats_register_view(name, queries, _add_two_to_value); } stats_unlock(); } static void _register_single_counter_with_name(void) { stats_lock(); { StatsClusterKey sc_key; StatsCounterItem *ctr_item; stats_cluster_single_key_set_with_name(&sc_key, SCS_GLOBAL, "id", "instance", "name"); stats_register_counter(0, &sc_key, SC_TYPE_SINGLE_VALUE, &ctr_item); } stats_unlock(); } static void _initialize_counter_hash(void) { const CounterHashContent logpipe_cluster_counters[] = { {SCS_CENTER, "guba.polo", "frozen", SC_TYPE_SUPPRESSED}, {SCS_FILE | SCS_SOURCE, "guba", "processed", SC_TYPE_PROCESSED}, {SCS_GLOBAL, "guba.gumi.diszno", "frozen", SC_TYPE_SUPPRESSED}, {SCS_PIPE | SCS_SOURCE, "guba.gumi.disz", "frozen", SC_TYPE_SUPPRESSED}, {SCS_TCP | SCS_DESTINATION, "guba.labda", "received", SC_TYPE_DROPPED}, {SCS_TCP | SCS_SOURCE, "guba.frizbi", "left", SC_TYPE_QUEUED}, }; const CounterHashContent single_cluster_counters[] = { {SCS_GLOBAL, NULL, "guba", SC_TYPE_SINGLE_VALUE} }; app_startup(); _register_counters(logpipe_cluster_counters, ARRAY_SIZE(logpipe_cluster_counters), stats_cluster_logpipe_key_set); _register_counters(single_cluster_counters, ARRAY_SIZE(single_cluster_counters), stats_cluster_single_key_set); _register_single_counter_with_name(); } static gboolean _test_format_log_msg_get(StatsCounterItem *ctr, gpointer user_data) { gchar *name, *value; LogMessage *msg = (LogMessage *)user_data; name = g_strdup_printf("%s", stats_counter_get_name(ctr)); value = g_strdup_printf("%"G_GSIZE_FORMAT, stats_counter_get(ctr)); log_msg_set_value_by_name(msg, name, value, -1); g_free(name); g_free(value); return TRUE; } static gboolean _test_format_str_get(StatsCounterItem *ctr, gpointer user_data) { GString *str = (GString *)user_data; g_string_append_printf(str, "%s: %"G_GSIZE_FORMAT"\n", stats_counter_get_name(ctr), stats_counter_get(ctr)); return TRUE; } static gboolean _test_format_log_msg_get_sum(StatsCounterItem *ctr, gpointer user_data) { gchar *name, *value; gpointer *args = (gpointer *) user_data; LogMessage *msg = (LogMessage *) args[0]; gint *sum = (gint *) args[1]; name = g_strdup_printf("%s", stats_counter_get_name(ctr)); value = g_strdup_printf("%d", *sum); log_msg_set_value_by_name(msg, name, value, -1); g_free(name); g_free(value); return TRUE; } static gboolean _test_format_str_get_sum(StatsCounterItem *ctr, gpointer user_data) { gpointer *args = (gpointer *) user_data; GString *result = (GString *) args[0]; gint *sum = (gint *) args[1]; g_string_printf(result, "%d", *sum); return TRUE; } static gboolean _test_format_list(StatsCounterItem *ctr, gpointer user_data) { GString *str = (GString *)user_data; g_string_append_printf(str, "%s\n", stats_counter_get_name(ctr)); return TRUE; } TestSuite(cluster_query_key, .init = app_startup, .fini = app_shutdown); Test(cluster_query_key, test_global_key) { const gchar *expected_key = "dst.file.d_file.instance"; StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_DESTINATION|SCS_FILE, "d_file", "instance" ); StatsCluster *sc = stats_cluster_new(&sc_key); cr_assert_str_eq(sc->query_key, expected_key, "generated query key(%s) does not match to the expected key(%s)", sc->query_key, expected_key); } TestSuite(stats_query, .init = _initialize_counter_hash, .fini = app_shutdown); ParameterizedTestParameters(stats_query, test_stats_query_get_log_msg_out) { static QueryTestCase test_cases[] = { {"dst.tcp.guba.labda.received.dropped", "0"}, {"src.pipe.guba.gumi.disz.frozen.suppressed", "0"}, }; return cr_make_param_array(QueryTestCase, test_cases, sizeof(test_cases) / sizeof(test_cases[0])); } ParameterizedTest(QueryTestCase *test_cases, stats_query, test_stats_query_get_log_msg_out) { const gchar *actual; LogMessage *msg = log_msg_new_empty(); stats_query_get(test_cases->pattern, _test_format_log_msg_get, (gpointer)msg); actual = log_msg_get_value_by_name(msg, test_cases->pattern, NULL); cr_assert_str_eq(actual, test_cases->expected, "Counter: '%s'; expected number: '%s';, got: '%s';", test_cases->pattern, test_cases->expected, actual); log_msg_unref(msg); } ParameterizedTestParameters(stats_query, test_stats_query_get_str_out) { static QueryTestCase test_cases[] = { {"center.*.*", "center.guba.polo.frozen.suppressed: 0\n"}, {"cent*", "center.guba.polo.frozen.suppressed: 0\n"}, {"src.pipe.guba.gumi.disz.*.*", "src.pipe.guba.gumi.disz.frozen.suppressed: 0\n"}, {"src.pipe.guba.gumi.*.*", "src.pipe.guba.gumi.disz.frozen.suppressed: 0\n"}, {"src.pipe.guba.*.*", "src.pipe.guba.gumi.disz.frozen.suppressed: 0\n"}, {"src.pipe.*.*", "src.pipe.guba.gumi.disz.frozen.suppressed: 0\n"}, {"dst.*.*", "dst.tcp.guba.labda.received.dropped: 0\n"}, {"dst.*.*.*", "dst.tcp.guba.labda.received.dropped: 0\n"}, {"dst.*.*.*.*", "dst.tcp.guba.labda.received.dropped: 0\n"}, {"src.java.*.*", ""}, {"src.ja*.*.*", ""}, {"global.id.instance.name", "global.id.instance.name: 0\n"}, { "*.aliased", ".aliased: 2\n" "guba.frizbi.aliased: 2\n" "guba.gumi.diszno.aliased: 2\n" "guba.polo.aliased: 2\n" "guba.aliased: 2\n" "guba.gumi.disz.aliased: 2\n" "guba.labda.aliased: 2\n" }, }; return cr_make_param_array(QueryTestCase, test_cases, sizeof(test_cases) / sizeof(test_cases[0])); } ParameterizedTest(QueryTestCase *test_cases, stats_query, test_stats_query_get_str_out) { GString *result = g_string_new(""); stats_query_get(test_cases->pattern, _test_format_str_get, (gpointer)result); cr_assert_str_eq(result->str, test_cases->expected, "Pattern: '%s'; expected key and value: '%s';, got: '%s';", test_cases->pattern, test_cases->expected, result->str); g_string_free(result, TRUE); } ParameterizedTestParameters(stats_query, test_stats_query_get_sum_log_msg_out) { static QueryTestCase test_cases[] = { {"dst.tcp.guba.labda.received.dropped", "0"}, {"src.pipe.guba.gumi.disz.frozen.suppressed", "0"}, }; return cr_make_param_array(QueryTestCase, test_cases, sizeof(test_cases) / sizeof(test_cases[0])); } ParameterizedTest(QueryTestCase *test_cases, stats_query, test_stats_query_get_sum_log_msg_out) { const gchar *actual; LogMessage *msg = log_msg_new_empty(); stats_query_get_sum(test_cases->pattern, _test_format_log_msg_get_sum, (gpointer)msg); actual = log_msg_get_value_by_name(msg, test_cases->pattern, NULL); cr_assert_str_eq(actual, test_cases->expected, "Pattern: '%s'; expected number: '%s';, got: '%s';", test_cases->pattern, test_cases->expected, actual); log_msg_unref(msg); } ParameterizedTestParameters(stats_query, test_stats_query_get_sum_str_out) { static QueryTestCase test_cases[] = { {"*", "14"}, {"center.*.*", "0"}, {"cent*", "0"}, {"src.pipe.guba.gumi.disz.*.*", "0"}, {"*.tcp.guba.*.*", "0"}, {"*.guba.*i.*.*", "0"}, {"*.guba.gum?.*.*", "0"}, {"src.ja*.*.*", ""}, }; return cr_make_param_array(QueryTestCase, test_cases, sizeof(test_cases) / sizeof(test_cases[0])); } ParameterizedTest(QueryTestCase *test_cases, stats_query, test_stats_query_get_sum_str_out) { GString *result = g_string_new(""); stats_query_get_sum(test_cases->pattern, _test_format_str_get_sum, (gpointer)result); cr_assert_str_eq(result->str, test_cases->expected, "Pattern: '%s'; expected key and value: '%s';, got: '%s';", test_cases->pattern, test_cases->expected, result->str); g_string_free(result, TRUE); } ParameterizedTestParameters(stats_query, test_stats_query_list) { static QueryTestCase test_cases[] = { {"center.*.*", "center.guba.polo.frozen.suppressed\n"}, {"cent*", "center.guba.polo.frozen.suppressed\n"}, {"src.pipe.guba.gumi.disz.*.*", "src.pipe.guba.gumi.disz.frozen.suppressed\n"}, {"src.pipe.*.*", "src.pipe.guba.gumi.disz.frozen.suppressed\n"}, {"src.java.*.*", ""}, {"src.ja*.*.*", ""}, }; return cr_make_param_array(QueryTestCase, test_cases, sizeof(test_cases) / sizeof(test_cases[0])); } ParameterizedTest(QueryTestCase *test_cases, stats_query, test_stats_query_list) { GString *result = g_string_new(""); stats_query_list(test_cases->pattern, _test_format_list, (gpointer)result); cr_assert_str_eq(result->str, test_cases->expected, "Pattern: '%s'; expected key: '%s';, got: '%s';", test_cases->pattern, test_cases->expected, result->str); g_string_free(result, TRUE); } syslog-ng-syslog-ng-3.13.2/lib/str-format.c000066400000000000000000000323161321171025300204520ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "str-format.h" #include #include static gchar digits[] = "0123456789abcdef"; /* format 64 bit ints */ static inline gint format_uint64_base10_rev(gchar *result, gsize result_len, gint sign, guint64 value) { gchar *p; gboolean negative = FALSE; gboolean first = TRUE; if (sign && ((gint64) value) < 0) { value = -((gint64) value); negative = TRUE; } p = result; while (first || (result_len > 0 && value > 0)) { *p = digits[value % 10]; value /= 10; p++; result_len--; first = FALSE; } if (negative && result_len > 0) { *p = '-'; p++; } return p - result; } static inline gint format_uint64_base16_rev(gchar *result, gsize result_len, guint64 value) { gchar *p; p = result; while (result_len > 0 && value > 0) { *p = digits[value & 0x0F]; value >>= 4; p++; result_len--; } return p - result; } static inline gint format_uint64_base8_rev(gchar *result, gsize result_len, guint64 value) { gchar *p; gboolean first = TRUE; p = result; while (first || (result_len > 0 && value > 0)) { *p = digits[value & 0x07]; value >>= 3; p++; result_len--; first = FALSE; } return p - result; } static gint format_padded_int64(GString *result, gint field_len, gchar pad_char, gint sign, gint base, guint64 value) { gchar num[64]; gint len, i, pos; if (base == 10) len = format_uint64_base10_rev(num, sizeof(num), sign, value); else if (base == 16) len = format_uint64_base16_rev(num, sizeof(num), value); else if (base == 8) len = format_uint64_base8_rev(num, sizeof(num), value); else g_assert_not_reached(); if (field_len == 0 || field_len < len) field_len = len; pos = result->len; if (G_UNLIKELY(result->allocated_len < pos + field_len + 1)) { g_string_set_size(result, pos + field_len); } else { result->len += field_len; result->str[pos + field_len] = 0; } memset(result->str + pos, pad_char, field_len - len); for (i = 0; i < len; i++) { result->str[pos + field_len - i - 1] = num[i]; } return field_len; } gint format_uint64_padded(GString *result, gint field_len, gchar pad_char, gint base, guint64 value) { return format_padded_int64(result, field_len, pad_char, 0, base, value); } gint format_int64_padded(GString *result, gint field_len, gchar pad_char, gint base, gint64 value) { return format_padded_int64(result, field_len, pad_char, 1, base, value); } /* format 32 bit ints */ static inline gint format_uint32_base10_rev(gchar *result, gsize result_len, gint sign, guint32 value) { gchar *p; gboolean negative = 0; gboolean first = TRUE; if (sign && ((gint32) value) < 0) { value = -((gint32) value); negative = 1; } p = result; while (first || (result_len > 0 && value > 0)) { *p = digits[value % 10]; value /= 10; p++; result_len--; first = FALSE; } if (negative && result_len > 0) { *p = '-'; p++; } return p - result; } static inline gint format_uint32_base16_rev(gchar *result, gsize result_len, guint32 value) { gchar *p; gboolean first = TRUE; p = result; while (first || (result_len > 0 && value > 0)) { *p = digits[value & 0x0F]; value >>= 4; p++; result_len--; first = FALSE; } return p - result; } static inline gint format_uint32_base8_rev(gchar *result, gsize result_len, guint32 value) { gchar *p; gboolean first = TRUE; p = result; while (first || (result_len > 0 && value > 0)) { *p = digits[value & 0x07]; value >>= 3; p++; result_len--; first = FALSE; } return p - result; } static gint format_padded_int32(GString *result, gint field_len, gchar pad_char, gint sign, gint base, guint32 value) { gchar num[32]; gint len, i, pos; if (base == 10) len = format_uint32_base10_rev(num, sizeof(num), sign, value); else if (base == 16) len = format_uint32_base16_rev(num, sizeof(num), value); else if (base == 8) len = format_uint32_base8_rev(num, sizeof(num), value); else g_assert_not_reached(); if (field_len == 0 || field_len < len) field_len = len; pos = result->len; if (G_UNLIKELY(result->allocated_len < pos + field_len + 1)) { g_string_set_size(result, pos + field_len); } else { result->len += field_len; result->str[pos + field_len] = 0; } memset(result->str + pos, pad_char, field_len - len); for (i = 0; i < len; i++) { result->str[pos + field_len - i - 1] = num[i]; } return field_len; } gint format_uint32_padded(GString *result, gint field_len, gchar pad_char, gint base, guint32 value) { return format_padded_int32(result, field_len, pad_char, 0, base, value); } gint format_int32_padded(GString *result, gint field_len, gchar pad_char, gint base, gint32 value) { return format_padded_int32(result, field_len, pad_char, 1, base, value); } gchar * format_hex_string_with_delimiter(gpointer data, gsize data_len, gchar *result, gsize result_len, gchar delimiter) { gint i; gint pos = 0; guchar *str = (guchar *) data; for (i = 0; i < data_len && result_len - pos >= 3; i++) { if ( (delimiter != 0) && (i < data_len - 1)) { g_snprintf(result + pos, 4, "%02x%c", str[i], delimiter); pos += 3; } else { g_snprintf(result + pos, 3, "%02x", str[i]); pos += 2; } } return result; } gchar * format_hex_string(gpointer data, gsize data_len, gchar *result, gsize result_len) { return format_hex_string_with_delimiter(data, data_len, result, result_len, 0); } /* parse 32 bit ints */ gboolean scan_uint32(const gchar **buf, gint *left, gint field_width, guint32 *num) { guint32 result; result = 0; while (*left > 0 && field_width > 0) { if ((**buf) >= '0' && (**buf) <= '9') result = result * 10 + ((**buf) - '0'); else if (!isspace((int) **buf)) return FALSE; (*buf)++; (*left)--; field_width--; } if (field_width != 0) return FALSE; *num = result; return TRUE; } gboolean scan_int(const gchar **buf, gint *left, gint field_width, gint *num) { guint32 value; if (!scan_uint32(buf, left, field_width, &value)) return FALSE; *num = (gint) value; return TRUE; } gboolean scan_expect_char(const gchar **buf, gint *left, gchar value) { if (*left == 0) return FALSE; if ((**buf) != value) return FALSE; (*buf)++; (*left)--; return TRUE; } gboolean scan_expect_str(const gchar **buf, gint *left, const gchar *value) { const gchar *original_buf = *buf; gint original_left = *left; while (*value) { if (*left == 0 || *value != **buf) { *buf = original_buf; *left = original_left; return FALSE; } (*buf)++; (*left)--; value++; } return TRUE; } gboolean scan_day_abbrev(const gchar **buf, gint *left, gint *wday) { *wday = -1; if (*left < 3) return FALSE; switch (**buf) { case 'S': if (strncasecmp(*buf, "Sun", 3) == 0) *wday = 0; else if (strncasecmp(*buf, "Sat", 3) == 0) *wday = 6; break; case 'M': if (strncasecmp(*buf, "Mon", 3) == 0) *wday = 1; break; case 'T': if (strncasecmp(*buf, "Tue", 3) == 0) *wday = 2; else if (strncasecmp(*buf, "Thu", 3) == 0) *wday = 4; break; case 'W': if (strncasecmp(*buf, "Wed", 3) == 0) *wday = 3; break; case 'F': if (strncasecmp(*buf, "Fri", 3) == 0) *wday = 5; break; default: return FALSE; } (*buf) += 3; (*left) -= 3; return TRUE; } gboolean scan_month_abbrev(const gchar **buf, gint *left, gint *mon) { *mon = -1; if (*left < 3) return FALSE; switch (**buf) { case 'J': if (strncasecmp(*buf, "Jan", 3) == 0) *mon = 0; else if (strncasecmp(*buf, "Jun", 3) == 0) *mon = 5; else if (strncasecmp(*buf, "Jul", 3) == 0) *mon = 6; break; case 'F': if (strncasecmp(*buf, "Feb", 3) == 0) *mon = 1; break; case 'M': if (strncasecmp(*buf, "Mar", 3) == 0) *mon = 2; else if (strncasecmp(*buf, "May", 3) == 0) *mon = 4; break; case 'A': if (strncasecmp(*buf, "Apr", 3) == 0) *mon = 3; else if (strncasecmp(*buf, "Aug", 3) == 0) *mon = 7; break; case 'S': if (strncasecmp(*buf, "Sep", 3) == 0) *mon = 8; break; case 'O': if (strncasecmp(*buf, "Oct", 3) == 0) *mon = 9; break; case 'N': if (strncasecmp(*buf, "Nov", 3) == 0) *mon = 10; break; case 'D': if (strncasecmp(*buf, "Dec", 3) == 0) *mon = 11; break; default: return FALSE; } (*buf) += 3; (*left) -= 3; return TRUE; } /* this function parses the date/time portion of an ISODATE */ gboolean scan_iso_timestamp(const gchar **buf, gint *left, struct tm *tm) { /* YYYY-MM-DDTHH:MM:SS */ if (!scan_int(buf, left, 4, &tm->tm_year) || !scan_expect_char(buf, left, '-') || !scan_int(buf, left, 2, &tm->tm_mon) || !scan_expect_char(buf, left, '-') || !scan_int(buf, left, 2, &tm->tm_mday) || !scan_expect_char(buf, left, 'T') || !scan_int(buf, left, 2, &tm->tm_hour) || !scan_expect_char(buf, left, ':') || !scan_int(buf, left, 2, &tm->tm_min) || !scan_expect_char(buf, left, ':') || !scan_int(buf, left, 2, &tm->tm_sec)) return FALSE; tm->tm_year -= 1900; tm->tm_mon -= 1; return TRUE; } gboolean scan_pix_timestamp(const gchar **buf, gint *left, struct tm *tm) { /* PIX/ASA timestamp, expected format: MMM DD YYYY HH:MM:SS */ if (!scan_month_abbrev(buf, left, &tm->tm_mon) || !scan_expect_char(buf, left, ' ') || !scan_int(buf, left, 2, &tm->tm_mday) || !scan_expect_char(buf, left, ' ') || !scan_int(buf, left, 4, &tm->tm_year) || !scan_expect_char(buf, left, ' ') || !scan_int(buf, left, 2, &tm->tm_hour) || !scan_expect_char(buf, left, ':') || !scan_int(buf, left, 2, &tm->tm_min) || !scan_expect_char(buf, left, ':') || !scan_int(buf, left, 2, &tm->tm_sec)) return FALSE; tm->tm_year -= 1900; return TRUE; } gboolean scan_linksys_timestamp(const gchar **buf, gint *left, struct tm *tm) { /* LinkSys timestamp, expected format: MMM DD HH:MM:SS YYYY */ if (!scan_month_abbrev(buf, left, &tm->tm_mon) || !scan_expect_char(buf, left, ' ') || !scan_int(buf, left, 2, &tm->tm_mday) || !scan_expect_char(buf, left, ' ') || !scan_int(buf, left, 2, &tm->tm_hour) || !scan_expect_char(buf, left, ':') || !scan_int(buf, left, 2, &tm->tm_min) || !scan_expect_char(buf, left, ':') || !scan_int(buf, left, 2, &tm->tm_sec) || !scan_expect_char(buf, left, ' ') || !scan_int(buf, left, 4, &tm->tm_year)) return FALSE; tm->tm_year -= 1900; return TRUE; } gboolean scan_bsd_timestamp(const gchar **buf, gint *left, struct tm *tm) { /* RFC 3164 timestamp, expected format: MMM DD HH:MM:SS ... */ if (!scan_month_abbrev(buf, left, &tm->tm_mon) || !scan_expect_char(buf, left, ' ') || !scan_int(buf, left, 2, &tm->tm_mday) || !scan_expect_char(buf, left, ' ') || !scan_int(buf, left, 2, &tm->tm_hour) || !scan_expect_char(buf, left, ':') || !scan_int(buf, left, 2, &tm->tm_min) || !scan_expect_char(buf, left, ':') || !scan_int(buf, left, 2, &tm->tm_sec)) return FALSE; return TRUE; } gboolean scan_std_timestamp(const gchar **buf, gint *left, struct tm *tm) { /* YYYY-MM-DD HH:MM:SS */ if (!scan_int(buf, left, 4, &tm->tm_year) || !scan_expect_char(buf, left, '-') || !scan_int(buf, left, 2, &tm->tm_mon) || !scan_expect_char(buf, left, '-') || !scan_int(buf, left, 2, &tm->tm_mday) || !scan_expect_char(buf, left, ' ') || !scan_int(buf, left, 2, &tm->tm_hour) || !scan_expect_char(buf, left, ':') || !scan_int(buf, left, 2, &tm->tm_min) || !scan_expect_char(buf, left, ':') || !scan_int(buf, left, 2, &tm->tm_sec)) return FALSE; tm->tm_year -= 1900; tm->tm_mon -= 1; return TRUE; } syslog-ng-syslog-ng-3.13.2/lib/str-format.h000066400000000000000000000043021321171025300204510ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STR_FORMAT_H_INCLUDED #define STR_FORMAT_H_INCLUDED #include "syslog-ng.h" gint format_uint32_padded(GString *result, gint field_len, gchar pad_char, gint base, guint32 value); gint format_int32_padded(GString *result, gint field_len, gchar pad_char, gint base, gint32 value); gint format_uint64_padded(GString *result, gint field_len, gchar pad_char, gint base, guint64 value); gint format_int64_padded(GString *result, gint field_len, gchar pad_char, gint base, gint64 value); gchar *format_hex_string(gpointer str, gsize str_len, gchar *result, gsize result_len); gchar *format_hex_string_with_delimiter(gpointer str, gsize str_len, gchar *result, gsize result_len, gchar delimiter); gboolean scan_expect_char(const gchar **buf, gint *left, gchar value); gboolean scan_expect_str(const gchar **buf, gint *left, const gchar *value); gboolean scan_iso_timestamp(const gchar **buf, gint *left, struct tm *tm); gboolean scan_pix_timestamp(const gchar **buf, gint *left, struct tm *tm); gboolean scan_linksys_timestamp(const gchar **buf, gint *left, struct tm *tm); gboolean scan_bsd_timestamp(const gchar **buf, gint *left, struct tm *tm); gboolean scan_std_timestamp(const gchar **buf, gint *left, struct tm *tm); #endif syslog-ng-syslog-ng-3.13.2/lib/str-repr/000077500000000000000000000000001321171025300177615ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/str-repr/CMakeLists.txt000066400000000000000000000002471321171025300225240ustar00rootroot00000000000000set(STR_REPR_HEADERS str-repr/encode.h str-repr/decode.h PARENT_SCOPE) set(STR_REPR_SOURCES str-repr/encode.c str-repr/decode.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/str-repr/Makefile.am000066400000000000000000000003571321171025300220220ustar00rootroot00000000000000str_reprincludedir = ${pkgincludedir}/str-repr str_reprinclude_HEADERS = \ lib/str-repr/decode.h \ lib/str-repr/encode.h str_repr_sources = \ lib/str-repr/decode.c \ lib/str-repr/encode.c include lib/str-repr/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/str-repr/decode.c000066400000000000000000000156061321171025300213600ustar00rootroot00000000000000/* * Copyright (c) 2015-2016 Balabit * Copyright (c) 2015-2016 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "str-repr/decode.h" #include enum { KV_QUOTE_INITIAL = 0, KV_QUOTE_STRING, KV_QUOTE_BACKSLASH, KV_QUOTE_FINISH, KV_EXPECT_DELIMITER, KV_QUOTE_ERROR, KV_UNQUOTED_CHARACTERS, KV_FINISH_SUCCESS, KV_FINISH_FAILURE, }; static void _decode_backslash_escape(GString *value, gchar quote_char, gchar ch) { gchar control; switch (ch) { case 'b': control = '\b'; break; case 'f': control = '\f'; break; case 'n': control = '\n'; break; case 'r': control = '\r'; break; case 't': control = '\t'; break; case '\\': control = '\\'; break; default: if (quote_char != ch) g_string_append_c(value, '\\'); control = ch; break; } g_string_append_c(value, control); } typedef struct _StrReprDecodeState { GString *value; const gchar *cur; gchar quote_char; const StrReprDecodeOptions *options; } StrReprDecodeState; static gboolean _invoke_match_delimiter(StrReprDecodeState *state, const gchar **new_cur) { const StrReprDecodeOptions *options = state->options; if (options->delimiter_chars[0]) { if (*state->cur == options->delimiter_chars[0] || *state->cur == options->delimiter_chars[1] || *state->cur == options->delimiter_chars[2]) { if (options->match_delimiter) return options->match_delimiter(state->cur, new_cur, options->match_delimiter_data); else { *new_cur = state->cur + 1; return TRUE; } } } else { if (options->match_delimiter) return options->match_delimiter(state->cur, new_cur, options->match_delimiter_data); } return FALSE; } static gboolean _match_and_skip_delimiter(StrReprDecodeState *state) { const gchar *new_cur; if (_invoke_match_delimiter(state, &new_cur)) { state->cur = new_cur; return TRUE; } return FALSE; } static gint _process_initial_character(StrReprDecodeState *state) { if (_match_and_skip_delimiter(state)) { return KV_FINISH_SUCCESS; } else if (*state->cur == '\"' || *state->cur == '\'') { state->quote_char = *state->cur; return KV_QUOTE_STRING; } else { g_string_append_c(state->value, *state->cur); return KV_UNQUOTED_CHARACTERS; } } static gint _process_quoted_string_characters(StrReprDecodeState *state) { if (*state->cur == state->quote_char) return KV_EXPECT_DELIMITER; else if (*state->cur == '\\') return KV_QUOTE_BACKSLASH; g_string_append_c(state->value, *state->cur); return KV_QUOTE_STRING; } static gint _process_backslash_escaped_character_in_strings(StrReprDecodeState *state) { _decode_backslash_escape(state->value, state->quote_char, *state->cur); return KV_QUOTE_STRING; } static gint _process_delimiter_characters_after_a_quoted_string(StrReprDecodeState *state) { if (_match_and_skip_delimiter(state)) return KV_FINISH_SUCCESS; return KV_QUOTE_ERROR; } static gint _process_junk_after_closing_quote(StrReprDecodeState *state) { if (_match_and_skip_delimiter(state)) return KV_FINISH_FAILURE; return KV_QUOTE_ERROR; } static gint _process_unquoted_characters(StrReprDecodeState *state) { if (_match_and_skip_delimiter(state)) return KV_FINISH_SUCCESS; g_string_append_c(state->value, *state->cur); return KV_UNQUOTED_CHARACTERS; } static gboolean _is_an_ending_string_acceptable_in_this_state(gint quote_state) { return quote_state == KV_QUOTE_INITIAL || quote_state == KV_EXPECT_DELIMITER || quote_state == KV_UNQUOTED_CHARACTERS || quote_state == KV_FINISH_SUCCESS; } static gboolean _decode(StrReprDecodeState *state) { gint quote_state = KV_QUOTE_INITIAL; for (; *state->cur; state->cur++) { switch (quote_state) { case KV_QUOTE_INITIAL: quote_state = _process_initial_character(state); break; case KV_QUOTE_STRING: quote_state = _process_quoted_string_characters(state); break; case KV_QUOTE_BACKSLASH: quote_state = _process_backslash_escaped_character_in_strings(state); break; case KV_EXPECT_DELIMITER: quote_state = _process_delimiter_characters_after_a_quoted_string(state); break; case KV_QUOTE_ERROR: quote_state = _process_junk_after_closing_quote(state); break; case KV_UNQUOTED_CHARACTERS: quote_state = _process_unquoted_characters(state); break; } if (quote_state == KV_FINISH_SUCCESS || quote_state == KV_FINISH_FAILURE) break; } if (_is_an_ending_string_acceptable_in_this_state(quote_state)) return TRUE; return FALSE; } gboolean str_repr_decode_append_with_options(GString *value, const gchar *input, const gchar **end, const StrReprDecodeOptions *options) { StrReprDecodeState state = { .value = value, .cur = input, .quote_char = 0, .options = options, }; gsize initial_len = value->len; gboolean success = _decode(&state); *end = state.cur; if (!success) { g_string_truncate(value, initial_len); g_string_append_len(value, input, state.cur - input); return FALSE; } return TRUE; } gboolean str_repr_decode_append(GString *value, const gchar *input, const gchar **end) { StrReprDecodeOptions options = { 0, .delimiter_chars = " ", }; return str_repr_decode_append_with_options(value, input, end, &options); } gboolean str_repr_decode(GString *value, const gchar *input, const gchar **end) { g_string_truncate(value, 0); return str_repr_decode_append(value, input, end); } gboolean str_repr_decode_with_options(GString *value, const gchar *input, const gchar **end, const StrReprDecodeOptions *options) { g_string_truncate(value, 0); return str_repr_decode_append_with_options(value, input, end, options); } syslog-ng-syslog-ng-3.13.2/lib/str-repr/decode.h000066400000000000000000000034551321171025300213640ustar00rootroot00000000000000/* * Copyright (c) 2015-2016 Balabit * Copyright (c) 2015-2016 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef SYSLOG_NG_C_LITERAL_UNESCAPE_H_INCLUDED #define SYSLOG_NG_C_LITERAL_UNESCAPE_H_INCLUDED #include "syslog-ng.h" typedef gboolean (*MatchDelimiterFunc)(const gchar *cur, const gchar **new_cur, gpointer user_data); typedef struct _StrReprDecodeOptions { MatchDelimiterFunc match_delimiter; gpointer match_delimiter_data; gchar delimiter_chars[3]; } StrReprDecodeOptions; gboolean str_repr_decode(GString *value, const gchar *input, const gchar **end); gboolean str_repr_decode_append(GString *value, const gchar *input, const gchar **end); gboolean str_repr_decode_with_options(GString *value, const gchar *input, const gchar **end, const StrReprDecodeOptions *options); gboolean str_repr_decode_append_with_options(GString *value, const gchar *input, const gchar **end, const StrReprDecodeOptions *options); #endif syslog-ng-syslog-ng-3.13.2/lib/str-repr/encode.c000066400000000000000000000054561321171025300213740ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "str-repr/encode.h" #include "utf8utils.h" #include void str_repr_encode_append(GString *escaped_string, const gchar *str, gssize str_len, const gchar *forbidden_chars) { const gchar *apostrophe, *quote; if (str_len < 0) str_len = strlen(str); if (str_len == 0) { g_string_append_len(escaped_string, "\"\"", 2); return; } apostrophe = memchr(str, '\'', str_len); quote = memchr(str, '"', str_len); if (!apostrophe && !quote) { gboolean quoting_needed = FALSE; /* NOTE: for non-NUL terminated strings, this would go over the end of * the string until the first NUL character. It is not ideal at all, * but there's no strncspn() */ if ((strcspn(str, "\b\f\n\r\t\\ ")) < str_len || (forbidden_chars && strcspn(str, forbidden_chars) < str_len)) quoting_needed = TRUE; if (!quoting_needed) { g_string_append_len(escaped_string, str, str_len); return; } } if (!apostrophe && quote) { g_string_append_c(escaped_string, '\''); append_unsafe_utf8_as_escaped_binary(escaped_string, str, str_len, NULL); g_string_append_c(escaped_string, '\''); } else if (!quote && apostrophe) { g_string_append_c(escaped_string, '"'); append_unsafe_utf8_as_escaped_binary(escaped_string, str, str_len, NULL); g_string_append_c(escaped_string, '"'); } else { g_string_append_c(escaped_string, '"'); append_unsafe_utf8_as_escaped_binary(escaped_string, str, str_len, "\""); g_string_append_c(escaped_string, '"'); } } void str_repr_encode(GString *escaped_string, const gchar *str, gssize str_len, const gchar *forbidden_chars) { g_string_truncate(escaped_string, 0); str_repr_encode_append(escaped_string, str, str_len, forbidden_chars); } syslog-ng-syslog-ng-3.13.2/lib/str-repr/encode.h000066400000000000000000000025001321171025300213640ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef SYSLOG_NG_C_LITERAL_ESCAPE_INCLUDED #define SYSLOG_NG_C_LITERAL_ESCAPE_INCLUDED #include "syslog-ng.h" void str_repr_encode(GString *escaped_string, const gchar *str, gssize str_len, const gchar *forbidden_chars); void str_repr_encode_append(GString *escaped_string, const gchar *str, gssize str_len, const gchar *forbidden_chars); #endif syslog-ng-syslog-ng-3.13.2/lib/str-repr/tests/000077500000000000000000000000001321171025300211235ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/str-repr/tests/Makefile.am000066400000000000000000000005621321171025300231620ustar00rootroot00000000000000lib_str_repr_tests_TESTS = \ lib/str-repr/tests/test_decode \ lib/str-repr/tests/test_encode check_PROGRAMS += ${lib_str_repr_tests_TESTS} lib_str_repr_tests_test_decode_CFLAGS = $(TEST_CFLAGS) lib_str_repr_tests_test_decode_LDADD = \ $(TEST_LDADD) lib_str_repr_tests_test_encode_CFLAGS = $(TEST_CFLAGS) lib_str_repr_tests_test_encode_LDADD = \ $(TEST_LDADD) syslog-ng-syslog-ng-3.13.2/lib/str-repr/tests/test_decode.c000066400000000000000000000131261321171025300235540ustar00rootroot00000000000000/* * Copyright (c) 2015-2016 Balabit * Copyright (c) 2015-2016 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "str-repr/decode.h" #include "testutils.h" #define str_repr_decode_testcase_begin(func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ } \ while (0) #define str_repr_decode_testcase_end() \ do \ { \ testcase_end(); \ } \ while (0) #define STR_REPR_DECODE_TESTCASE(x, ...) \ do { \ str_repr_decode_testcase_begin(#x, #__VA_ARGS__); \ x(__VA_ARGS__); \ str_repr_decode_testcase_end(); \ } while(0) GString *value; static void assert_decode_equals(const gchar *input, const gchar *expected) { GString *str = g_string_new(""); const gchar *end; assert_true(str_repr_decode(str, input, &end), "Decode operation failed while success was expected, input=%s", input); assert_string(str->str, expected, "Decoded value does not match expected"); g_string_free(str, TRUE); } static void assert_decode_equals_and_fails(const gchar *input, const gchar *expected) { GString *str = g_string_new(""); const gchar *end; assert_false(str_repr_decode(str, input, &end), "Decode operation succeeded while failure was expected, input=%s", input); assert_string(str->str, expected, "Decoded value does not match expected"); g_string_free(str, TRUE); } static gboolean _match_three_tabs_as_delimiter(const gchar *cur, const gchar **new_cur, gpointer user_data) { *new_cur = cur + 3; return (strncmp(cur, "\t\t\t", 3) == 0); } static void assert_decode_with_three_tabs_as_delimiter_equals(const gchar *input, const gchar *expected) { StrReprDecodeOptions options = { 0, .match_delimiter = _match_three_tabs_as_delimiter, }; GString *str = g_string_new(""); const gchar *end; str_repr_decode_with_options(str, input, &end, &options); assert_string(str->str, expected, "Decoded value does not match expected"); g_string_free(str, TRUE); } static void test_decode_unquoted_strings(void) { assert_decode_equals("a", "a"); assert_decode_equals("alma", "alma"); assert_decode_equals("al ma", "al"); } static void test_decode_double_quoted_strings(void) { assert_decode_equals("\"al ma\"", "al ma"); /* embedded quote */ assert_decode_equals("\"\\\"value1\"", "\"value1"); /* control sequences */ assert_decode_equals("\"\\b \\f \\n \\r \\t \\\\\"", "\b \f \n \r \t \\"); /* unknown backslash escape is left as is */ assert_decode_equals("\"\\p\"", "\\p"); } static void test_decode_apostrophe_quoted_strings(void) { assert_decode_equals("'al ma'", "al ma"); /* embedded quote */ assert_decode_equals("'\\'value1'", "'value1"); /* control sequences */ assert_decode_equals("'\\b \\f \\n \\r \\t \\\\'", "\b \f \n \r \t \\"); /* unknown backslash escape is left as is */ assert_decode_equals("'\\p\'", "\\p"); } static void test_decode_malformed_strings(void) { assert_decode_equals_and_fails("'alma", "'alma"); assert_decode_equals_and_fails("\"alma", "\"alma"); assert_decode_equals("alma'", "alma'"); assert_decode_equals("alma\"", "alma\""); assert_decode_equals("alma\"korte", "alma\"korte"); assert_decode_equals("alma\"korte\"", "alma\"korte\""); assert_decode_equals_and_fails("'alma'@korte", "'alma'@korte"); } static void test_decode_delimited_strings(void) { assert_decode_with_three_tabs_as_delimiter_equals("alma\t\t\tkorte", "alma"); assert_decode_with_three_tabs_as_delimiter_equals("'alma\t\t\tkorte'", "alma\t\t\tkorte"); assert_decode_with_three_tabs_as_delimiter_equals("'alma\t\t\tkorte'\t\t", "'alma\t\t\tkorte'\t\t"); assert_decode_with_three_tabs_as_delimiter_equals("'alma\t\t\tkorte'\t\t\t", "alma\t\t\tkorte"); assert_decode_with_three_tabs_as_delimiter_equals("alma\t\t", "alma\t\t"); assert_decode_with_three_tabs_as_delimiter_equals("\t\t\tfoobar", ""); } int main(int argc, char *argv[]) { STR_REPR_DECODE_TESTCASE(test_decode_unquoted_strings); STR_REPR_DECODE_TESTCASE(test_decode_double_quoted_strings); STR_REPR_DECODE_TESTCASE(test_decode_apostrophe_quoted_strings); STR_REPR_DECODE_TESTCASE(test_decode_malformed_strings); STR_REPR_DECODE_TESTCASE(test_decode_delimited_strings); return 0; } syslog-ng-syslog-ng-3.13.2/lib/str-repr/tests/test_encode.c000066400000000000000000000115051321171025300235650ustar00rootroot00000000000000/* * Copyright (c) 2015-2016 Balabit * Copyright (c) 2015-2016 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "str-repr/encode.h" #include "testutils.h" #include "stopwatch.h" #define str_repr_encode_testcase_begin(func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ } \ while (0) #define str_repr_encode_testcase_end() \ do \ { \ testcase_end(); \ } \ while (0) #define STR_REPR_ENCODE_TESTCASE(x, ...) \ do { \ str_repr_encode_testcase_begin(#x, #__VA_ARGS__); \ x(__VA_ARGS__); \ str_repr_encode_testcase_end(); \ } while(0) GString *value; static void assert_encode_equals(const gchar *input, const gchar *expected) { GString *str = g_string_new(""); str_repr_encode(str, input, -1, NULL); assert_string(str->str, expected, "Encoded value does not match expected"); str_repr_encode(str, input, strlen(input), NULL); assert_string(str->str, expected, "Encoded value does not match expected"); gchar *space_ended_input = g_strdup_printf("%s ", input); str_repr_encode(str, space_ended_input, strlen(input), ","); assert_string(str->str, expected, "Encoded value does not match expected"); g_free(space_ended_input); g_string_free(str, TRUE); } static void assert_encode_with_forbidden_equals(const gchar *input, const gchar *forbidden_chars, const gchar *expected) { GString *str = g_string_new(""); str_repr_encode(str, input, -1, forbidden_chars); assert_string(str->str, expected, "Encoded value does not match expected"); g_string_free(str, TRUE); } static void test_encode_simple_strings(void) { assert_encode_equals("", "\"\""); assert_encode_equals("a", "a"); assert_encode_equals("alma", "alma"); assert_encode_equals("al\nma", "\"al\\nma\""); } static void test_encode_strings_that_need_quotation(void) { assert_encode_equals("foo bar", "\"foo bar\""); /* embedded quote */ assert_encode_equals("\"value1", "'\"value1'"); assert_encode_equals("'value1", "\"'value1\""); /* control sequences */ assert_encode_equals("\b \f \n \r \t \\", "\"\\b \\f \\n \\r \\t \\\\\""); } static void test_encode_strings_with_forbidden_chars(void) { assert_encode_with_forbidden_equals("foo,", ",", "\"foo,\""); assert_encode_with_forbidden_equals("\"'foo,", ",", "\"\\\"'foo,\""); } #define ITERATION_NUMBER 100000 static void _perftest(const gchar *value_to_encode) { gint iteration_index = 0; GString *result = g_string_sized_new(64); gsize value_len = strlen(value_to_encode); start_stopwatch(); for (iteration_index = 0; iteration_index < ITERATION_NUMBER; iteration_index++) { str_repr_encode(result, value_to_encode, value_len, ","); } stop_stopwatch_and_display_result(iteration_index, "%.64s...", value_to_encode); g_string_free(result, TRUE); } static void test_performance(void) { _perftest("This is a long value with spaces and control characters\n" " "); _perftest("This is 'a long' value with spaces and control characters\n"); _perftest("This is \"a long\" value with spaces and control characters\n"); } int main(int argc, char *argv[]) { STR_REPR_ENCODE_TESTCASE(test_encode_simple_strings); STR_REPR_ENCODE_TESTCASE(test_encode_strings_that_need_quotation); STR_REPR_ENCODE_TESTCASE(test_encode_strings_with_forbidden_chars); STR_REPR_ENCODE_TESTCASE(test_performance); return 0; } syslog-ng-syslog-ng-3.13.2/lib/str-utils.c000066400000000000000000000031271321171025300203200ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "str-utils.h" GString * g_string_assign_len(GString *s, const gchar *val, gint len) { g_string_truncate(s, 0); if (val && len) g_string_append_len(s, val, len); return s; } void g_string_steal(GString *s) { s->str = g_malloc0(1); s->allocated_len = 1; s->len = 0; } static gchar * str_replace_char(const gchar *str, const gchar from, const gchar to) { gchar *p; gchar *ret = g_strdup(str); p = ret; while (*p) { if (*p == from) *p = to; p++; } return ret; } gchar * __normalize_key(const gchar *buffer) { return str_replace_char(buffer, '-', '_'); } syslog-ng-syslog-ng-3.13.2/lib/str-utils.h000066400000000000000000000073351321171025300203320ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STR_UTILS_H_INCLUDED #define STR_UTILS_H_INCLUDED 1 #include "syslog-ng.h" #include /* functions that should be implemented by GLib but they aren't */ GString *g_string_assign_len(GString *s, const gchar *val, gint len); void g_string_steal(GString *s); static inline GString * g_string_append_unichar_optimized(GString *string, gunichar wc) { if (wc < 0x80) g_string_append_c(string, (gchar) wc); else g_string_append_unichar(string, wc); return string; } /* * DO NOT USE THIS MACRO UNLESS STRICTLY NECESSARY FOR PERFORMANCE REASONS. * * This macro tries hard to zero-terminate the string without moving it to a * new buffer. * * It is expected to be used at sites where the length is known and where * the input string is expected to be properly NUL terminated but not always. * * The macro checks if the string is indeed NUL terminated and if it is it * just assigns the original pointer to dest. If it's not, it allocates a * new string via g_alloca() so it is automatically freed when the current * scope exits. * * This does not work as an inline function as we use g_alloca() and that * would be freed when the inline function exits (e.g. when it is in fact * not inlined). */ #define APPEND_ZERO(dest, value, value_len) \ do { \ gchar *__buf; \ if (G_UNLIKELY(value[value_len] != 0)) \ { \ /* value is NOT zero terminated */ \ \ __buf = g_alloca(value_len + 1); \ memcpy(__buf, value, value_len); \ __buf[value_len] = 0; \ } \ else \ { \ /* value is zero terminated */ \ __buf = (gchar *) value; \ } \ dest = __buf; \ } while (0) gchar *__normalize_key(const gchar* buffer); /* This version of strchr() is optimized for cases where the string we are * looking up characters in is often zero or one character in length. In * those cases we can avoid the strchr() call, which can make a tight loop * doing a lot of strchr() calls a lot faster, especially as this function * is inlined. * * Naming: I originally wanted to use the original function as a prefix * (strchr), however that would potentially pollute the namespace of the * library that we are optimizing. So I've added an underscore prefix in * order not to clash, with that it is still obvious that it intends to * behave the same as strchr(). * * NOTE: don't use this unless strchr() really shows up in your profile. */ static inline char * _strchr_optimized_for_single_char_haystack(const char *str, int c) { if (str[0] == c) return (char *) str; else if (str[0] == '\0') return NULL; if (str[1] == '\0') { if (c != '\0') return NULL; else return (char *) &str[1]; } return strchr(str + 1, c); } #endif syslog-ng-syslog-ng-3.13.2/lib/string-list.c000066400000000000000000000046011321171025300206270ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "string-list.h" /* The aim of this module is to support the grammar to parse string lists * into simple linked lists. Items can contain special values denoted by * integers. We probably could find a _much_ nicer solution than this, I am * just extracting it from misc.c to its separate module. -- Bazsi */ /* * NOTE: pointer values below 0x1000 (4096) are taken as special values used * by the application code and are not duplicated, but assumed to be literal * tokens. */ GList * string_list_clone(GList *string_list) { GList *cloned = NULL; GList *l; for (l = string_list; l; l = l->next) cloned = g_list_append(cloned, GPOINTER_TO_UINT(l->data) > 4096 ? g_strdup(l->data) : l->data); return cloned; } GList * string_array_to_list(const gchar *strlist[]) { gint i; GList *l = NULL; for (i = 0; strlist[i]; i++) { l = g_list_prepend(l, g_strdup(strlist[i])); } return g_list_reverse(l); } /* * NOTE: pointer values below 0x1000 (4096) are taken as special * values used by the application code and are not freed. Since this * is the NULL page, this should not cause memory leaks. */ void string_list_free(GList *l) { while (l) { /* some of the string lists use invalid pointer values as special * items, see SQL "default" item */ if (GPOINTER_TO_UINT(l->data) > 4096) g_free(l->data); l = g_list_delete_link(l, l); } } syslog-ng-syslog-ng-3.13.2/lib/string-list.h000066400000000000000000000023211321171025300206310ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STRING_LIST_H_INCLUDED #define STRING_LIST_H_INCLUDED 1 #include "syslog-ng.h" GList *string_list_clone(GList *string_list); GList *string_array_to_list(const gchar *strlist[]); void string_list_free(GList *l); #endif syslog-ng-syslog-ng-3.13.2/lib/syslog-names.c000066400000000000000000000070431321171025300207740ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "syslog-names.h" #include "syslog-ng.h" #include #define LEVEL_CODE(n) ((n) & 7) #define FACILITY_CODE(n) ((n) << 3) struct sl_name sl_levels[] = { {"emerg", LEVEL_CODE(0) }, {"panic", LEVEL_CODE(0) }, {"alert", LEVEL_CODE(1) }, {"crit", LEVEL_CODE(2) }, {"err", LEVEL_CODE(3) }, {"error", LEVEL_CODE(3) }, {"warning", LEVEL_CODE(4) }, {"warn", LEVEL_CODE(4) }, {"notice", LEVEL_CODE(5) }, {"info", LEVEL_CODE(6) }, {"debug", LEVEL_CODE(7) }, {NULL, -1} }; struct sl_name sl_facilities[] = { {"kern", FACILITY_CODE(0) }, {"user", FACILITY_CODE(1) }, {"mail", FACILITY_CODE(2) }, {"daemon", FACILITY_CODE(3) }, {"auth", FACILITY_CODE(4) }, {"syslog", FACILITY_CODE(5) }, {"lpr", FACILITY_CODE(6) }, {"news", FACILITY_CODE(7) }, {"uucp", FACILITY_CODE(8) }, {"cron", FACILITY_CODE(9) }, {"authpriv", FACILITY_CODE(10) }, {"megasafe", FACILITY_CODE(10) }, /* DEC UNIX AdvFS logging */ {"ftp", FACILITY_CODE(11) }, {"ntp", FACILITY_CODE(12) }, {"security", FACILITY_CODE(13) }, {"console", FACILITY_CODE(14) }, {"solaris-cron", FACILITY_CODE(15) }, {"local0", FACILITY_CODE(16) }, {"local1", FACILITY_CODE(17) }, {"local2", FACILITY_CODE(18) }, {"local3", FACILITY_CODE(19) }, {"local4", FACILITY_CODE(20) }, {"local5", FACILITY_CODE(21) }, {"local6", FACILITY_CODE(22) }, {"local7", FACILITY_CODE(23) }, {NULL, -1} }; static inline int syslog_name_find_name(const char *name, struct sl_name names[]) { int i; for (i = 0; names[i].name; i++) { if (strcasecmp(name, names[i].name) == 0) { return i; } } return -1; } int syslog_name_lookup_id_by_name(const char *name, struct sl_name names[]) { return syslog_name_find_name(name, names); } int syslog_name_lookup_value_by_name(const char *name, struct sl_name names[]) { int i; i = syslog_name_find_name(name, names); if (i != -1) { return names[i].value; } return -1; } const char * syslog_name_lookup_name_by_value(int value, struct sl_name names[]) { int i; for (i = 0; names[i].name; i++) { if (names[i].value == value) { return names[i].name; } } return NULL; } guint32 syslog_make_range(guint32 value1, guint32 value2) { guint32 x; if (value1 > value2) { x = value2; value2 = value1; value1 = x; } return ((1 << (value2 + 1)) - 1) & ~((1 << value1) - 1); } syslog-ng-syslog-ng-3.13.2/lib/syslog-names.h000066400000000000000000000041551321171025300210020ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef __SYSLOG_NAMES_H_INCLUDED #define __SYSLOG_NAMES_H_INCLUDED #include "syslog-ng.h" #define LOG_FACMASK 0x03f8 /* mask to extract facility part */ /* facility of pri */ #define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) #ifndef LOG_PRIMASK #define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */ #endif /* extract priority */ #define LOG_PRI(p) ((p) & LOG_PRIMASK) struct sl_name { char *name; int value; }; extern struct sl_name sl_levels[]; extern struct sl_name sl_facilities[]; /* returns an index where this name is found */ int syslog_name_lookup_id_by_name(const char *name, struct sl_name names[]); int syslog_name_lookup_value_by_name(const char *name, struct sl_name names[]); const char *syslog_name_lookup_name_by_value(int value, struct sl_name names[]); guint32 syslog_make_range(guint32 r1, guint32 r2); static inline guint32 syslog_name_lookup_level_by_name(const gchar *name) { return syslog_name_lookup_value_by_name(name, sl_levels); } static inline guint32 syslog_name_lookup_facility_by_name(const gchar *name) { return syslog_name_lookup_value_by_name(name, sl_facilities); } #endif syslog-ng-syslog-ng-3.13.2/lib/syslog-ng.h000066400000000000000000000042341321171025300203010ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef SYSLOG_NG_H_INCLUDED #define SYSLOG_NG_H_INCLUDED #include #if SYSLOG_NG_ENABLE_DEBUG #undef YYDEBUG #define YYDEBUG 1 #endif #include "compat/glib.h" #include "versioning.h" #define PATH_SYSLOG_NG_CONF SYSLOG_NG_PATH_SYSCONFDIR "/syslog-ng.conf" #define PATH_INSTALL_DAT SYSLOG_NG_PATH_SYSCONFDIR "/install.dat" #define PATH_PIDFILE SYSLOG_NG_PATH_PIDFILEDIR "/syslog-ng.pid" #define PATH_CONTROL_SOCKET SYSLOG_NG_PATH_PIDFILEDIR "/syslog-ng.ctl" #if SYSLOG_NG_ENABLE_ENV_WRAPPER #define PATH_SYSLOGNG SYSLOG_NG_PATH_LIBEXECDIR "/syslog-ng" #endif #define PATH_PERSIST_CONFIG SYSLOG_NG_PATH_LOCALSTATEDIR "/syslog-ng.persist" typedef struct _LogPipe LogPipe; typedef struct _LogMessage LogMessage; typedef struct _GlobalConfig GlobalConfig; typedef struct _CfgLexer CfgLexer; typedef struct _PluginContext PluginContext; typedef struct _Bookmark Bookmark; typedef struct _AckTracker AckTracker; typedef struct _AckRecord AckRecord; typedef struct _StatsClusterKey StatsClusterKey; /* configuration being parsed, used by the bison generated code, NULL whenever parsing is finished. */ extern GlobalConfig *configuration; #endif syslog-ng-syslog-ng-3.13.2/lib/template/000077500000000000000000000000001321171025300200165ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/template/CMakeLists.txt000066400000000000000000000007551321171025300225650ustar00rootroot00000000000000set(TEMPLATE_HEADERS template/templates.h template/macros.h template/function.h template/simple-function.h template/repr.h template/compiler.h template/user-function.h template/escaping.h template/common-template-typedefs.h PARENT_SCOPE) set(TEMPLATE_SOURCES template/templates.c template/macros.c template/simple-function.c template/repr.c template/compiler.c template/user-function.c template/escaping.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/template/Makefile.am000066400000000000000000000011541321171025300220530ustar00rootroot00000000000000templateincludedir = ${pkgincludedir}/template templateinclude_HEADERS = \ lib/template/templates.h \ lib/template/macros.h \ lib/template/function.h \ lib/template/simple-function.h \ lib/template/repr.h \ lib/template/compiler.h \ lib/template/user-function.h \ lib/template/escaping.h \ lib/template/common-template-typedefs.h template_sources = \ lib/template/templates.c \ lib/template/macros.c \ lib/template/simple-function.c \ lib/template/repr.c \ lib/template/compiler.c \ lib/template/user-function.c \ lib/template/escaping.c include lib/template/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/template/common-template-typedefs.h000066400000000000000000000021441321171025300251120ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef COMMON_TYPEDEFS_H_INCLUDED #define COMMON_TYPEDEFS_H_INCLUDED typedef struct _LogTemplateOptions LogTemplateOptions; #endif syslog-ng-syslog-ng-3.13.2/lib/template/compiler.c000066400000000000000000000343341321171025300220030ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "template/compiler.h" #include "template/templates.h" #include "template/repr.h" #include "template/macros.h" #include "plugin.h" static void log_template_add_macro_elem(LogTemplateCompiler *self, guint macro, gchar *default_value) { LogTemplateElem *e; e = g_new0(LogTemplateElem, 1); e->type = LTE_MACRO; e->text_len = self->text ? self->text->len : 0; e->text = self->text ? g_strndup(self->text->str, self->text->len) : NULL; e->macro = macro; e->default_value = default_value; e->msg_ref = self->msg_ref; self->result = g_list_prepend(self->result, e); } static void log_template_add_value_elem(LogTemplateCompiler *self, gchar *value_name, gsize value_name_len, gchar *default_value) { LogTemplateElem *e; gchar *str; e = g_new0(LogTemplateElem, 1); e->type = LTE_VALUE; e->text_len = self->text ? self->text->len : 0; e->text = self->text ? g_strndup(self->text->str, self->text->len) : NULL; /* value_name is not NUL terminated */ str = g_strndup(value_name, value_name_len); e->value_handle = log_msg_get_value_handle(str); g_free(str); e->default_value = default_value; e->msg_ref = self->msg_ref; self->result = g_list_prepend(self->result, e); } static gboolean log_template_prepare_function_call(LogTemplateCompiler *self, Plugin *p, LogTemplateElem *e, gint argc, gchar *argv[], GError **error) { gchar *argv_copy[argc + 1]; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); e->func.ops = plugin_construct(p); e->func.state = e->func.ops->size_of_state > 0 ? g_malloc0(e->func.ops->size_of_state) : NULL; /* prepare may modify the argv array: remove and rearrange elements */ memcpy(argv_copy, argv, (argc + 1) * sizeof(argv[0])); if (!e->func.ops->prepare(e->func.ops, e->func.state, self->template, argc, argv_copy, error)) { if (e->func.state) { e->func.ops->free_state(e->func.state); g_free(e->func.state); } if (e->func.ops->free_fn) e->func.ops->free_fn(e->func.ops); return FALSE; } g_strfreev(argv); self->result = g_list_prepend(self->result, e); return TRUE; } static gboolean log_template_lookup_and_setup_function_call(LogTemplateCompiler *self, LogTemplateElem *e, gint argc, gchar *argv[], GError **error) { Plugin *p; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); p = cfg_find_plugin(self->template->cfg, LL_CONTEXT_TEMPLATE_FUNC, argv[0]); if (!p) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "Unknown template function \"%s\"", argv[0]); goto error; } if (!log_template_prepare_function_call(self, p, e, argc, argv, error)) goto error; return TRUE; error: return FALSE; } /* NOTE: this steals argv if successful */ static gboolean log_template_add_func_elem(LogTemplateCompiler *self, gint argc, gchar *argv[], GError **error) { LogTemplateElem *e; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); if (argc == 0) return TRUE; e = g_malloc0(sizeof(LogTemplateElem) + (argc - 1) * sizeof(LogTemplate *)); e->type = LTE_FUNC; e->text_len = self->text ? self->text->len : 0; e->text = self->text ? g_strndup(self->text->str, self->text->len) : NULL; e->msg_ref = self->msg_ref; if (!log_template_lookup_and_setup_function_call(self, e, argc, argv, error)) goto error; return TRUE; error: if (e->text) g_free(e->text); g_free(e); return FALSE; } static void parse_msg_ref(LogTemplateCompiler *self) { self->msg_ref = 0; if ((*self->cursor) == '@') { self->cursor++; if ((*self->cursor) >= '0' && (*self->cursor) <= '9') { /* syntax: ${name}@1 to denote the log message index in the correllation state */ while ((*self->cursor) >= '0' && (*self->cursor) <= '9') { self->msg_ref += self->msg_ref * 10 + ((*self->cursor) - '0'); self->cursor++; } self->msg_ref += 1; } else { if ((*self->cursor) != '@') { msg_warning("Non-numeric correlation state ID found, assuming a literal '@' character. To avoid confusion when using a literal '@' after a macro or template function, write '@@' in the template.", evt_tag_str("Template", self->template->template)); self->cursor--; } self->msg_ref = 0; } } } static void log_template_compiler_fill_compile_error(GError **error, const gchar *error_info, gint error_pos) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "%s, error_pos='%d'", error_info, error_pos); } static void log_template_compiler_append_and_increment(LogTemplateCompiler *self, GString *text) { g_string_append_c(text, *self->cursor); self->cursor++; } static gint log_template_compiler_get_macro_length(gchar *start, gchar *end, gchar **token) { gint result = 0; gchar *colon = memchr(start, ':', end - start - 1); if (colon) { result = colon - start; *token = colon < end ? colon + 1 : NULL; } else { result = end - start - 1; *token = NULL; } return result; } static gchar * log_template_compiler_get_default_value(LogTemplateCompiler *self, gchar *token) { g_assert(token); if (*token != '-') { return NULL; } return g_strndup(token + 1, self->cursor - token - 2); } static inline gboolean is_macro_name(gchar c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_') || (c >= '0' && c <= '9'); } #define STEP_BY_TRUE(p, x) while(x) p++; static void log_template_compiler_add_elem(LogTemplateCompiler *self, gchar *start, gint macro_len, gchar *default_value) { gint macro = log_macro_lookup(start, macro_len); if (macro == M_NONE) { log_template_add_value_elem(self, start, macro_len, default_value); } else { log_template_add_macro_elem(self, macro, default_value); } } static gboolean log_template_compiler_process_braced_template(LogTemplateCompiler *self, GError **error) { gint macro_len; gchar *default_value = NULL; gchar *start; gchar *end; gchar *token; self->cursor++; start = self->cursor; end = strchr(self->cursor, '}'); if (!end) { log_template_compiler_fill_compile_error(error, "Invalid macro, '}' is missing", strlen(self->template->template)); return FALSE; } self->cursor = end + 1; macro_len = log_template_compiler_get_macro_length(start, self->cursor, &token); if (token) { default_value = log_template_compiler_get_default_value(self, token); if (!default_value) { log_template_compiler_fill_compile_error(error, "Unknown substitution function", token - self->template->template); return FALSE; } } parse_msg_ref(self); log_template_compiler_add_elem(self, start, macro_len, default_value); return TRUE; } static gboolean log_template_compiler_add_quoted_string(LogTemplateCompiler *self, gboolean is_top_level, GString *result) { gchar *quote = self->cursor; gchar *end_of_quote = strchr(quote + 1, *quote); if (!end_of_quote) { return FALSE; } self->cursor = end_of_quote + 1; if (is_top_level) { /* skip the quote in top-level and don't skip in expressions enclosed in parens */ quote++; } else { end_of_quote++; } g_string_append_len(result, quote, end_of_quote - quote); return TRUE; } static gboolean log_template_compiler_process_arg_list(LogTemplateCompiler *self, GPtrArray *result) { GString *arg_buf = g_string_sized_new(32); gboolean arg_buf_has_a_value = FALSE; gint parens = 1; self->cursor++; while (*self->cursor && *self->cursor == ' ') self->cursor++; while(*self->cursor) { if (*self->cursor == '\\') { self->cursor++; } else if (*self->cursor == '(') { parens++; } else if (*self->cursor == ')') { parens--; if (parens == 0) { break; } } else if (*self->cursor == '"' || *self->cursor == '\'') { if (!log_template_compiler_add_quoted_string(self, parens == 1, arg_buf)) { g_ptr_array_add(result, NULL); g_string_free(arg_buf, TRUE); return FALSE; } arg_buf_has_a_value = TRUE; continue; } else if (parens == 1 && (*self->cursor == ' ' || *self->cursor == '\t')) { g_ptr_array_add(result, g_strndup(arg_buf->str, arg_buf->len)); g_string_truncate(arg_buf, 0); arg_buf_has_a_value = FALSE; while (*self->cursor && (*self->cursor == ' ' || *self->cursor == '\t')) self->cursor++; continue; } log_template_compiler_append_and_increment(self, arg_buf); arg_buf_has_a_value = TRUE; } if (arg_buf_has_a_value) { g_ptr_array_add(result, g_strndup(arg_buf->str, arg_buf->len)); } g_ptr_array_add(result, NULL); g_string_free(arg_buf, TRUE); return *self->cursor == ')'; } static gboolean log_template_compiler_process_template_function(LogTemplateCompiler *self, GError **error) { GPtrArray *strv = g_ptr_array_new(); if (!log_template_compiler_process_arg_list(self, strv)) { log_template_compiler_fill_compile_error(error, "Invalid template function reference, missing function name or inbalanced '('", self->cursor - self->template->template); goto error; } self->cursor++; parse_msg_ref(self); if (!log_template_add_func_elem(self, strv->len - 1, (gchar **) strv->pdata, error)) { goto error; } g_ptr_array_free(strv, FALSE); return TRUE; error: g_strfreev((gchar **)strv->pdata); g_ptr_array_free(strv, FALSE); return FALSE; } static void log_template_compiler_process_unbraced_template(LogTemplateCompiler *self) { gchar *start = self->cursor; gint macro_len; do { self->cursor++; } while (is_macro_name(*self->cursor)); macro_len = self->cursor - start; log_template_compiler_add_elem(self, start, macro_len, NULL); } static gboolean log_template_compiler_process_value(LogTemplateCompiler *self, GError **error) { gboolean finished = FALSE; gchar p; self->cursor++; p = *self->cursor; /* macro reference */ if (p == '{') { if (!log_template_compiler_process_braced_template(self, error)) { return FALSE; } finished = TRUE; } /* template function */ else if (p == '(') { if (!log_template_compiler_process_template_function(self, error)) { return FALSE; } finished = TRUE; } /* unbraced macro */ else if (is_macro_name(p)) { log_template_compiler_process_unbraced_template(self); finished = TRUE; } /* escaped value with dollar */ else { if (p != '$') { g_string_append_c(self->text, '$'); } if (p) { log_template_compiler_append_and_increment(self, self->text); } } if (finished) { g_string_truncate(self->text, 0); } return TRUE; } gboolean log_template_compiler_process_token(LogTemplateCompiler *self, GError **error) { self->msg_ref = 0; if (*self->cursor == '$') { return log_template_compiler_process_value(self, error); } if (*self->cursor == '\\') { if (cfg_is_config_version_older(self->template->cfg, 0x305)) { msg_warning("Template escaping changed in version 3.5. Use '$$' to specify a literal dollar sign instead of '\\$' and remove the escaping of the backslash character when you upgrade your configuration", evt_tag_str("Template", self->template->template)); self->cursor++; } } if (*self->cursor) { log_template_compiler_append_and_increment(self, self->text); } return TRUE; } static void log_template_compiler_free_result(LogTemplateCompiler *self) { log_template_elem_free_list(self->result); self->result = NULL; } gboolean log_template_compiler_compile(LogTemplateCompiler *self, GList **compiled_template, GError **error) { gboolean result = FALSE; while (*self->cursor) { if (!log_template_compiler_process_token(self, error)) { log_template_compiler_free_result(self); g_string_sprintf(self->text, "error in template: %s", self->template->template); log_template_add_macro_elem(self, M_NONE, NULL); goto error; } } if (self->text->len) { log_template_add_macro_elem(self, M_NONE, NULL); } result = TRUE; error: *compiled_template = g_list_reverse(self->result); self->result = NULL; return result; } void log_template_compiler_init(LogTemplateCompiler *self, LogTemplate *template) { memset(self, 0, sizeof(*self)); self->template = log_template_ref(template); self->cursor = self->template->template; self->text = g_string_sized_new(32); } void log_template_compiler_clear(LogTemplateCompiler *self) { log_template_unref(self->template); g_string_free(self->text, TRUE); } syslog-ng-syslog-ng-3.13.2/lib/template/compiler.h000066400000000000000000000027631321171025300220110ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TEMPLATE_COMPILER_H_INCLUDED #define TEMPLATE_COMPILER_H_INCLUDED #include "syslog-ng.h" #include "templates.h" typedef struct { LogTemplate *template; GList *result; gchar *cursor; GString *text; gint msg_ref; } LogTemplateCompiler; gboolean log_template_compiler_compile(LogTemplateCompiler *self, GList **compiled_template, GError **error); void log_template_compiler_init(LogTemplateCompiler *self, LogTemplate *template); void log_template_compiler_clear(LogTemplateCompiler *self); #endif syslog-ng-syslog-ng-3.13.2/lib/template/escaping.c000066400000000000000000000034411321171025300217550ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "template/escaping.h" #include "str-format.h" #include void result_append(GString *result, const gchar *sstr, gssize len, gboolean escape) { gint i; const guchar *ustr = (const guchar *) sstr; if (len < 0) len = strlen(sstr); if (escape) { for (i = 0; i < len; i++) { if (ustr[i] == '\'' || ustr[i] == '"' || ustr[i] == '\\') { g_string_append_c(result, '\\'); g_string_append_c(result, ustr[i]); } else if (ustr[i] < ' ') { g_string_append_c(result, '\\'); format_uint32_padded(result, 3, '0', 8, ustr[i]); } else g_string_append_c(result, ustr[i]); } } else g_string_append_len(result, sstr, len); } syslog-ng-syslog-ng-3.13.2/lib/template/escaping.h000066400000000000000000000022571321171025300217660ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TEMPLATE_ESCAPING_H_INCLUDED #define TEMPLATE_ESCAPING_H_INCLUDED 1 #include "syslog-ng.h" void result_append(GString *result, const gchar *sstr, gssize len, gboolean escape); #endif syslog-ng-syslog-ng-3.13.2/lib/template/function.h000066400000000000000000000106751321171025300220250ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TEMPLATE_FUNCTION_H_INCLUDED #define TEMPLATE_FUNCTION_H_INCLUDED #include "syslog-ng.h" #include "plugin-types.h" #include "common-template-typedefs.h" /* This structure contains the arguments for template-function * expansion. It is defined in a struct because otherwise a large * number of function arguments, that are passed around, possibly * several times. */ typedef struct _LogTemplateInvokeArgs { /* scratch buffers, stores GString *, elements are managed by the * function, storage/free is performed by the core. Can be used to * avoid allocating GString buffers in the fast-path. */ GPtrArray *bufs; /* context in case of correllation */ LogMessage **messages; gint num_messages; /* options for recursive template evaluation, inherited from the parent */ const LogTemplateOptions *opts; gint tz; gint seq_num; const gchar *context_id; } LogTemplateInvokeArgs; typedef struct _LogTemplateFunction LogTemplateFunction; struct _LogTemplateFunction { /* size of the state that carries information from parse-time to * runtime. Can be used to store the results of expensive * operations that don't need to be performed for all invocations */ gint size_of_state; /* called when parsing the arguments to be compiled into an internal * representation if necessary. Returns the compiled state in state */ gboolean (*prepare)(LogTemplateFunction *self, gpointer state, LogTemplate *parent, gint argc, gchar *argv[], GError **error); /* evaluate arguments, storing argument buffers in arg_bufs in case it * makes sense to reuse those buffers */ void (*eval)(LogTemplateFunction *self, gpointer state, const LogTemplateInvokeArgs *args); /* call the function */ void (*call)(LogTemplateFunction *self, gpointer state, const LogTemplateInvokeArgs *args, GString *result); /* free data in state */ void (*free_state)(gpointer s); /* free LogTemplateFunction instance (if not static) */ void (*free_fn)(LogTemplateFunction *self); /* generic argument that can be used to pass information from registration time */ gpointer arg; }; #define TEMPLATE_FUNCTION_PROTOTYPE(prefix) \ gpointer \ prefix ## _construct(Plugin *self) #define TEMPLATE_FUNCTION_DECLARE(prefix) \ TEMPLATE_FUNCTION_PROTOTYPE(prefix); /* helper macros for template function plugins */ #define TEMPLATE_FUNCTION(state_struct, prefix, prepare, eval, call, free_state, arg) \ TEMPLATE_FUNCTION_PROTOTYPE(prefix) \ { \ static LogTemplateFunction func = { \ sizeof(state_struct), \ prepare, \ eval, \ call, \ free_state, \ NULL, \ arg \ }; \ return &func; \ } #define TEMPLATE_FUNCTION_PLUGIN(x, tf_name) \ { \ .type = LL_CONTEXT_TEMPLATE_FUNC, \ .name = tf_name, \ .construct = x ## _construct, \ } #endif syslog-ng-syslog-ng-3.13.2/lib/template/macros.c000066400000000000000000000440041321171025300214500ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "template/macros.h" #include "template/escaping.h" #include "timeutils.h" #include "logstamp.h" #include "messages.h" #include "str-format.h" #include "run-id.h" #include "host-id.h" #include "rcptid.h" #include "logmsg/logmsg.h" #include "syslog-names.h" #include "hostname.h" #include "template/templates.h" #include "cfg.h" #include LogMacroDef macros[] = { { "FACILITY", M_FACILITY }, { "FACILITY_NUM", M_FACILITY_NUM }, { "PRIORITY", M_LEVEL }, { "LEVEL", M_LEVEL }, { "LEVEL_NUM", M_LEVEL_NUM }, { "TAG", M_TAG }, { "TAGS", M_TAGS }, { "BSDTAG", M_BSDTAG }, { "PRI", M_PRI }, { "DATE", M_DATE }, { "FULLDATE", M_FULLDATE }, { "ISODATE", M_ISODATE }, { "STAMP", M_STAMP }, { "YEAR", M_YEAR }, { "YEAR_DAY", M_YEAR_DAY }, { "MONTH", M_MONTH }, { "MONTH_WEEK", M_MONTH_WEEK }, { "MONTH_ABBREV", M_MONTH_ABBREV }, { "MONTH_NAME", M_MONTH_NAME }, { "DAY", M_DAY }, { "HOUR", M_HOUR }, { "HOUR12", M_HOUR12 }, { "MIN", M_MIN }, { "SEC", M_SEC }, { "USEC", M_USEC }, { "MSEC", M_MSEC }, { "AMPM", M_AMPM }, { "WEEKDAY", M_WEEK_DAY_ABBREV }, /* deprecated */ { "WEEK_DAY", M_WEEK_DAY }, { "WEEK_DAY_ABBREV",M_WEEK_DAY_ABBREV }, { "WEEK_DAY_NAME", M_WEEK_DAY_NAME }, { "WEEK", M_WEEK }, { "TZOFFSET", M_TZOFFSET }, { "TZ", M_TZ }, { "SYSUPTIME", M_SYSUPTIME }, { "UNIXTIME", M_UNIXTIME }, { "R_DATE", M_RECVD_OFS + M_DATE }, { "R_FULLDATE", M_RECVD_OFS + M_FULLDATE }, { "R_ISODATE", M_RECVD_OFS + M_ISODATE }, { "R_STAMP", M_RECVD_OFS + M_STAMP }, { "R_YEAR", M_RECVD_OFS + M_YEAR }, { "R_YEAR_DAY", M_RECVD_OFS + M_YEAR_DAY }, { "R_MONTH", M_RECVD_OFS + M_MONTH }, { "R_MONTH_WEEK", M_RECVD_OFS + M_MONTH_WEEK }, { "R_MONTH_ABBREV", M_RECVD_OFS + M_MONTH_ABBREV }, { "R_MONTH_NAME", M_RECVD_OFS + M_MONTH_NAME }, { "R_DAY", M_RECVD_OFS + M_DAY }, { "R_HOUR", M_RECVD_OFS + M_HOUR }, { "R_HOUR12", M_RECVD_OFS + M_HOUR12 }, { "R_MIN", M_RECVD_OFS + M_MIN }, { "R_SEC", M_RECVD_OFS + M_SEC }, { "R_MSEC", M_RECVD_OFS + M_MSEC }, { "R_USEC", M_RECVD_OFS + M_USEC }, { "R_AMPM", M_RECVD_OFS + M_AMPM }, { "R_WEEKDAY", M_RECVD_OFS + M_WEEK_DAY_ABBREV }, /* deprecated */ { "R_WEEK_DAY", M_RECVD_OFS + M_WEEK_DAY }, { "R_WEEK_DAY_ABBREV",M_RECVD_OFS + M_WEEK_DAY_ABBREV }, { "R_WEEK_DAY_NAME", M_RECVD_OFS + M_WEEK_DAY_NAME }, { "R_WEEK", M_RECVD_OFS + M_WEEK }, { "R_TZOFFSET", M_RECVD_OFS + M_TZOFFSET }, { "R_TZ", M_RECVD_OFS + M_TZ }, { "R_UNIXTIME", M_RECVD_OFS + M_UNIXTIME }, { "S_DATE", M_STAMP_OFS + M_DATE }, { "S_FULLDATE", M_STAMP_OFS + M_FULLDATE }, { "S_ISODATE", M_STAMP_OFS + M_ISODATE }, { "S_STAMP", M_STAMP_OFS + M_STAMP }, { "S_YEAR", M_STAMP_OFS + M_YEAR }, { "S_YEAR_DAY", M_STAMP_OFS + M_YEAR_DAY }, { "S_MONTH", M_STAMP_OFS + M_MONTH }, { "S_MONTH_WEEK", M_STAMP_OFS + M_MONTH_WEEK }, { "S_MONTH_ABBREV", M_STAMP_OFS + M_MONTH_ABBREV }, { "S_MONTH_NAME", M_STAMP_OFS + M_MONTH_NAME }, { "S_DAY", M_STAMP_OFS + M_DAY }, { "S_HOUR", M_STAMP_OFS + M_HOUR }, { "S_HOUR12", M_STAMP_OFS + M_HOUR12 }, { "S_MIN", M_STAMP_OFS + M_MIN }, { "S_SEC", M_STAMP_OFS + M_SEC }, { "S_MSEC", M_STAMP_OFS + M_MSEC }, { "S_USEC", M_STAMP_OFS + M_USEC }, { "S_AMPM", M_STAMP_OFS + M_AMPM }, { "S_WEEKDAY", M_STAMP_OFS + M_WEEK_DAY_ABBREV }, /* deprecated */ { "S_WEEK_DAY", M_STAMP_OFS + M_WEEK_DAY }, { "S_WEEK_DAY_ABBREV",M_STAMP_OFS + M_WEEK_DAY_ABBREV }, { "S_WEEK_DAY_NAME", M_STAMP_OFS + M_WEEK_DAY_NAME }, { "S_WEEK", M_STAMP_OFS + M_WEEK }, { "S_TZOFFSET", M_STAMP_OFS + M_TZOFFSET }, { "S_TZ", M_STAMP_OFS + M_TZ }, { "S_UNIXTIME", M_STAMP_OFS + M_UNIXTIME }, { "C_DATE", M_CSTAMP_OFS + M_DATE }, { "C_FULLDATE", M_CSTAMP_OFS + M_FULLDATE }, { "C_ISODATE", M_CSTAMP_OFS + M_ISODATE }, { "C_STAMP", M_CSTAMP_OFS + M_STAMP }, { "C_YEAR", M_CSTAMP_OFS + M_YEAR }, { "C_YEAR_DAY", M_CSTAMP_OFS + M_YEAR_DAY }, { "C_MONTH", M_CSTAMP_OFS + M_MONTH }, { "C_MONTH_WEEK", M_CSTAMP_OFS + M_MONTH_WEEK }, { "C_MONTH_ABBREV", M_CSTAMP_OFS + M_MONTH_ABBREV }, { "C_MONTH_NAME", M_CSTAMP_OFS + M_MONTH_NAME }, { "C_DAY", M_CSTAMP_OFS + M_DAY }, { "C_HOUR", M_CSTAMP_OFS + M_HOUR }, { "C_MIN", M_CSTAMP_OFS + M_MIN }, { "C_SEC", M_CSTAMP_OFS + M_SEC }, { "C_WEEKDAY", M_CSTAMP_OFS + M_WEEK_DAY_ABBREV }, /* deprecated */ { "C_WEEK_DAY", M_CSTAMP_OFS + M_WEEK_DAY }, { "C_WEEK_DAY_ABBREV",M_CSTAMP_OFS + M_WEEK_DAY_ABBREV }, { "C_WEEK_DAY_NAME", M_CSTAMP_OFS + M_WEEK_DAY_NAME }, { "C_WEEK", M_CSTAMP_OFS + M_WEEK }, { "C_TZOFFSET", M_CSTAMP_OFS + M_TZOFFSET }, { "C_TZ", M_CSTAMP_OFS + M_TZ }, { "C_UNIXTIME", M_CSTAMP_OFS + M_UNIXTIME }, { "SDATA", M_SDATA }, { "MSGHDR", M_MSGHDR }, { "SOURCEIP", M_SOURCE_IP }, { "SEQNUM", M_SEQNUM }, { "CONTEXT_ID", M_CONTEXT_ID }, { "_", M_CONTEXT_ID }, { "RCPTID", M_RCPTID }, { "RUNID", M_RUNID }, { "HOSTID", M_HOSTID }, { "UNIQID", M_UNIQID }, /* values that have specific behaviour with older syslog-ng config versions */ { "MSG", M_MESSAGE }, { "MESSAGE", M_MESSAGE }, { "HOST", M_HOST }, /* message independent macros */ { "LOGHOST", M_LOGHOST }, { NULL, 0 } }; static GTimeVal app_uptime; static GHashTable *macro_hash; static LogTemplateOptions template_options_for_macro_expand; static void _result_append_value(GString *result, const LogMessage *lm, NVHandle handle, gboolean escape) { const gchar *str; gssize len = 0; str = log_msg_get_value(lm, handle, &len); result_append(result, str, len, escape); } static gboolean _is_message_source_an_ip_address(const LogMessage *msg) { if (!msg->saddr) return FALSE; if (g_sockaddr_inet_check(msg->saddr)) return TRUE; #if SYSLOG_NG_ENABLE_IPV6 if (g_sockaddr_inet6_check(msg->saddr)) return TRUE; #endif return FALSE; } gboolean log_macro_expand(GString *result, gint id, gboolean escape, const LogTemplateOptions *opts, gint tz, gint32 seq_num, const gchar *context_id, const LogMessage *msg) { switch (id) { case M_FACILITY: { /* facility */ const char *n; n = syslog_name_lookup_name_by_value(msg->pri & LOG_FACMASK, sl_facilities); if (n) { g_string_append(result, n); } else { format_uint32_padded(result, 0, 0, 16, (msg->pri & LOG_FACMASK) >> 3); } break; } case M_FACILITY_NUM: { format_uint32_padded(result, 0, 0, 10, (msg->pri & LOG_FACMASK) >> 3); break; } case M_LEVEL: { /* level */ const char *n; n = syslog_name_lookup_name_by_value(msg->pri & LOG_PRIMASK, sl_levels); if (n) { g_string_append(result, n); } else { format_uint32_padded(result, 0, 0, 10, msg->pri & LOG_PRIMASK); } break; } case M_LEVEL_NUM: { format_uint32_padded(result, 0, 0, 10, msg->pri & LOG_PRIMASK); break; } case M_TAG: { format_uint32_padded(result, 2, '0', 16, msg->pri); break; } case M_TAGS: { log_msg_print_tags(msg, result); break; } case M_BSDTAG: { format_uint32_padded(result, 0, 0, 10, (msg->pri & LOG_PRIMASK)); g_string_append_c(result, (((msg->pri & LOG_FACMASK) >> 3) + 'A')); break; } case M_PRI: { format_uint32_padded(result, 0, 0, 10, msg->pri); break; } case M_HOST: { if (msg->flags & LF_CHAINED_HOSTNAME) { /* host */ const gchar *p1, *p2; int remaining, length; gssize host_len; const gchar *host = log_msg_get_value(msg, LM_V_HOST, &host_len); p1 = memchr(host, '@', host_len); if (p1) p1++; else p1 = host; remaining = host_len - (p1 - host); p2 = memchr(p1, '/', remaining); length = p2 ? p2 - p1 : host_len - (p1 - host); result_append(result, p1, length, escape); } else { _result_append_value(result, msg, LM_V_HOST, escape); } break; } case M_SDATA: if (escape) { GString *sdstr = g_string_sized_new(0); log_msg_append_format_sdata(msg, sdstr, seq_num); result_append(result, sdstr->str, sdstr->len, TRUE); g_string_free(sdstr, TRUE); } else { log_msg_append_format_sdata(msg, result, seq_num); } break; case M_MSGHDR: { gssize len; const gchar *p; p = log_msg_get_value(msg, LM_V_LEGACY_MSGHDR, &len); if (len > 0) result_append(result, p, len, escape); else { /* message, complete with program name and pid */ len = result->len; _result_append_value(result, msg, LM_V_PROGRAM, escape); if (len != result->len) { const gchar *pid = log_msg_get_value(msg, LM_V_PID, &len); if (len > 0) { result_append(result, "[", 1, FALSE); result_append(result, pid, len, escape); result_append(result, "]", 1, FALSE); } result_append(result, ": ", 2, FALSE); } } break; } case M_MESSAGE: _result_append_value(result, msg, LM_V_MESSAGE, escape); break; case M_SOURCE_IP: { gchar *ip; if(_is_message_source_an_ip_address(msg)) { gchar buf[MAX_SOCKADDR_STRING]; g_sockaddr_format(msg->saddr, buf, sizeof(buf), GSA_ADDRESS_ONLY); ip = buf; } else { ip = "127.0.0.1"; } result_append(result, ip, strlen(ip), escape); break; } case M_SEQNUM: { if (seq_num) { format_uint32_padded(result, 0, 0, 10, seq_num); } break; } case M_CONTEXT_ID: { if (context_id) { result_append(result, context_id, strlen(context_id), escape); } break; } case M_RCPTID: { rcptid_append_formatted_id(result, msg->rcptid); break; } case M_RUNID: { run_id_append_formatted_id(result); break; } case M_HOSTID: { host_id_append_formatted_id(result, msg->host_id); break; } case M_UNIQID: { if (msg->rcptid) { host_id_append_formatted_id(result, msg->host_id); g_string_append(result, "@"); format_uint64_padded(result, 16, '0', 16, msg->rcptid); break; } break; } case M_LOGHOST: { const gchar *hname = get_local_hostname_fqdn(); result_append(result, hname, -1, escape); break; } case M_SYSUPTIME: { GTimeVal ct; g_get_current_time(&ct); format_uint64_padded(result, 0, 0, 10, g_time_val_diff(&ct, &app_uptime) / 1000 / 10); break; } default: { /* year, month, day */ struct tm *tm, tm_storage; gchar buf[64]; gint length; time_t t; const LogStamp *stamp; LogStamp sstamp; glong zone_ofs; guint tmp_hour; if (id >= M_TIME_FIRST && id <= M_TIME_LAST) { stamp = &msg->timestamps[LM_TS_STAMP]; } else if (id >= M_TIME_FIRST + M_RECVD_OFS && id <= M_TIME_LAST + M_RECVD_OFS) { id -= M_RECVD_OFS; stamp = &msg->timestamps[LM_TS_RECVD]; } else if (id >= M_TIME_FIRST + M_STAMP_OFS && id <= M_TIME_LAST + M_STAMP_OFS) { id -= M_STAMP_OFS; stamp = &msg->timestamps[LM_TS_STAMP]; } else if (id >= M_TIME_FIRST + M_CSTAMP_OFS && id <= M_TIME_LAST + M_CSTAMP_OFS) { GTimeVal tv; id -= M_CSTAMP_OFS; cached_g_current_time(&tv); sstamp.tv_sec = tv.tv_sec; sstamp.tv_usec = tv.tv_usec; sstamp.zone_offset = -1; stamp = &sstamp; } else { g_assert_not_reached(); break; } /* try to use the following zone values in order: * destination specific timezone, if one is specified * message specific timezone, if one is specified * local timezone */ zone_ofs = (opts->time_zone_info[tz] != NULL ? time_zone_info_get_offset(opts->time_zone_info[tz], stamp->tv_sec) : stamp->zone_offset); if (zone_ofs == -1) zone_ofs = stamp->zone_offset; t = stamp->tv_sec + zone_ofs; cached_gmtime(&t, &tm_storage); tm = &tm_storage; switch (id) { case M_WEEK_DAY_ABBREV: g_string_append_len(result, weekday_names_abbrev[tm->tm_wday], 3); break; case M_WEEK_DAY_NAME: g_string_append(result, weekday_names[tm->tm_wday]); break; case M_WEEK_DAY: format_uint32_padded(result, 0, 0, 10, tm->tm_wday + 1); break; case M_WEEK: format_uint32_padded(result, 2, '0', 10, (tm->tm_yday - (tm->tm_wday - 1 + 7) % 7 + 7) / 7); break; case M_YEAR: format_uint32_padded(result, 4, '0', 10, tm->tm_year + 1900); break; case M_YEAR_DAY: format_uint32_padded(result, 3, '0', 10, tm->tm_yday + 1); break; case M_MONTH: format_uint32_padded(result, 2, '0', 10, tm->tm_mon + 1); break; case M_MONTH_WEEK: format_uint32_padded(result, 0, 0, 10, ((tm->tm_mday / 7) + ((tm->tm_wday > 0) && ((tm->tm_mday % 7) >= tm->tm_wday)))); break; case M_MONTH_ABBREV: g_string_append_len(result, month_names_abbrev[tm->tm_mon], 3); break; case M_MONTH_NAME: g_string_append(result, month_names[tm->tm_mon]); break; case M_DAY: format_uint32_padded(result, 2, '0', 10, tm->tm_mday); break; case M_HOUR: format_uint32_padded(result, 2, '0', 10, tm->tm_hour); break; case M_HOUR12: if (tm->tm_hour < 12) tmp_hour = tm->tm_hour; else tmp_hour = tm->tm_hour - 12; if (tmp_hour == 0) tmp_hour = 12; format_uint32_padded(result, 2, '0', 10, tmp_hour); break; case M_MIN: format_uint32_padded(result, 2, '0', 10, tm->tm_min); break; case M_SEC: format_uint32_padded(result, 2, '0', 10, tm->tm_sec); break; case M_MSEC: format_uint32_padded(result, 3, '0', 10, stamp->tv_usec/1000); break; case M_USEC: format_uint32_padded(result, 6, '0', 10, stamp->tv_usec); break; case M_AMPM: g_string_append(result, tm->tm_hour < 12 ? "AM" : "PM"); break; case M_DATE: case M_STAMP: case M_ISODATE: case M_FULLDATE: case M_UNIXTIME: { gint format = id == M_DATE ? TS_FMT_BSD : id == M_ISODATE ? TS_FMT_ISO : id == M_FULLDATE ? TS_FMT_FULL : id == M_UNIXTIME ? TS_FMT_UNIX : opts->ts_format; log_stamp_append_format(stamp, result, format, zone_ofs, opts->frac_digits); break; } case M_TZ: case M_TZOFFSET: length = format_zone_info(buf, sizeof(buf), zone_ofs); g_string_append_len(result, buf, length); break; } break; } } return TRUE; } gboolean log_macro_expand_simple(GString *result, gint id, const LogMessage *msg) { return log_macro_expand(result, id, FALSE, &template_options_for_macro_expand, LTZ_LOCAL, 0, NULL, msg); } guint log_macro_lookup(gchar *macro, gint len) { gchar buf[256]; gint macro_id; g_assert(macro_hash); g_strlcpy(buf, macro, MIN(sizeof(buf), len+1)); macro_id = GPOINTER_TO_INT(g_hash_table_lookup(macro_hash, buf)); return macro_id; } void log_macros_global_init(void) { gint i; /* init the uptime (SYSUPTIME macro) */ g_get_current_time(&app_uptime); log_template_options_defaults(&template_options_for_macro_expand); macro_hash = g_hash_table_new(g_str_hash, g_str_equal); for (i = 0; macros[i].name; i++) { g_hash_table_insert(macro_hash, macros[i].name, GINT_TO_POINTER(macros[i].id)); } return; } void log_macros_global_deinit(void) { g_hash_table_destroy(macro_hash); macro_hash = NULL; } syslog-ng-syslog-ng-3.13.2/lib/template/macros.h000066400000000000000000000055731321171025300214650ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TEMPLATE_MACROS_H_INCLUDED #define TEMPLATE_MACROS_H_INCLUDED #include "syslog-ng.h" #include "common-template-typedefs.h" /* macro IDs */ enum { M_NONE, M_FACILITY, M_FACILITY_NUM, M_LEVEL, M_LEVEL_NUM, M_TAG, M_TAGS, M_BSDTAG, M_PRI, M_HOST, M_SDATA, M_MSGHDR, M_MESSAGE, M_SOURCE_IP, M_SEQNUM, M_CONTEXT_ID, M_LOGHOST, M_SYSUPTIME, M_RCPTID, M_RUNID, M_HOSTID, M_UNIQID, /* only touch this section if you want to add three macros, one w/o * prefix, and a R_ and S_ prefixed macro that relates one of the * timestamps of the log message. */ M_DATE, M_FULLDATE, M_ISODATE, M_STAMP, M_YEAR, M_YEAR_DAY, M_MONTH, M_MONTH_WEEK, M_MONTH_ABBREV, M_MONTH_NAME, M_DAY, M_HOUR, M_HOUR12, M_MIN, M_SEC, M_USEC, M_MSEC, M_AMPM, M_WEEK_DAY, M_WEEK_DAY_ABBREV, M_WEEK_DAY_NAME, M_WEEK, M_TZOFFSET, M_TZ, M_UNIXTIME, M_TIME_FIRST = M_DATE, M_TIME_LAST = M_UNIXTIME, M_TIME_MACROS_MAX = M_UNIXTIME - M_DATE + 1, M_RECVD_OFS = M_TIME_MACROS_MAX, M_STAMP_OFS = 2 * M_TIME_MACROS_MAX, M_CSTAMP_OFS = 3 * M_TIME_MACROS_MAX, }; /* macros (not NV pairs!) that syslog-ng knows about. This was the * earliest mechanism for inserting message-specific information into * texts. It is now superseeded by name-value pairs where the value is * text, but remains to be used for time and other metadata. */ typedef struct _LogMacroDef { char *name; int id; } LogMacroDef; extern LogMacroDef macros[]; /* low level macro functions */ guint log_macro_lookup(gchar *macro, gint len); gboolean log_macro_expand(GString *result, gint id, gboolean escape, const LogTemplateOptions *opts, gint tz, gint32 seq_num, const gchar *context_id, const LogMessage *msg); gboolean log_macro_expand_simple(GString *result, gint id, const LogMessage *msg); void log_macros_global_init(void); void log_macros_global_deinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/template/repr.c000066400000000000000000000031651321171025300211370ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "template/repr.h" void log_template_elem_free(LogTemplateElem *e) { switch (e->type) { case LTE_FUNC: if (e->func.state) { e->func.ops->free_state(e->func.state); g_free(e->func.state); } if (e->func.ops && e->func.ops->free_fn) e->func.ops->free_fn(e->func.ops); break; } if (e->default_value) g_free(e->default_value); if (e->text) g_free(e->text); g_free(e); } void log_template_elem_free_list(GList *l) { GList *el = l; for (; el; el = el->next) { log_template_elem_free((LogTemplateElem *) el->data); } g_list_free(l); } syslog-ng-syslog-ng-3.13.2/lib/template/repr.h000066400000000000000000000027621321171025300211460ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TEMPLATE_REPR_H_INCLUDED #define TEMPLATE_REPR_H_INCLUDED #include "template/function.h" #include "logmsg/logmsg.h" enum { LTE_MACRO, LTE_VALUE, LTE_FUNC }; typedef struct _LogTemplateElem { gsize text_len; gchar *text; gchar *default_value; guint16 msg_ref; guint8 type; union { guint macro; NVHandle value_handle; struct { LogTemplateFunction *ops; gpointer state; } func; }; } LogTemplateElem; void log_template_elem_free_list(GList *el); #endif syslog-ng-syslog-ng-3.13.2/lib/template/simple-function.c000066400000000000000000000065221321171025300233030ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "template/simple-function.h" #include "template/templates.h" void log_template_append_format_recursive(LogTemplate *self, const LogTemplateInvokeArgs *args, GString *result) { log_template_append_format_with_context(self, args->messages, args->num_messages, args->opts, args->tz, args->seq_num, args->context_id, result); } /* simple template functions which take templates as arguments */ gboolean tf_simple_func_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent, gint argc, gchar *argv[], GError **error) { TFSimpleFuncState *state = (TFSimpleFuncState *) s; gint i; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); state->argv = g_malloc(sizeof(LogTemplate *) * (argc - 1)); /* NOTE: the argv argument contains the function name as argv[0], * but the LogTemplate array doesn't. Thus the index is shifted by * one. */ for (i = 0; i < argc - 1; i++) { state->argv[i] = log_template_new(parent->cfg, NULL); log_template_set_escape(state->argv[i], parent->escape); if (!log_template_compile(state->argv[i], argv[i + 1], error)) goto error; } state->argc = argc - 1; return TRUE; error: return FALSE; } void tf_simple_func_eval(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args) { TFSimpleFuncState *state = (TFSimpleFuncState *) s; gint i; for (i = 0; i < state->argc; i++) { GString **arg; if (args->bufs->len <= i) g_ptr_array_add(args->bufs, g_string_sized_new(256)); arg = (GString **) &g_ptr_array_index(args->bufs, i); g_string_truncate(*arg, 0); log_template_append_format_recursive(state->argv[i], args, *arg); } } void tf_simple_func_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { TFSimpleFunc simple_func = (TFSimpleFunc) self->arg; TFSimpleFuncState *state = (TFSimpleFuncState *) s; simple_func(args->messages[args->num_messages-1], state->argc, (GString **) args->bufs->pdata, result); } void tf_simple_func_free_state(gpointer s) { TFSimpleFuncState *state = (TFSimpleFuncState *) s; gint i; for (i = 0; i < state->argc; i++) { if (state->argv[i]) log_template_unref(state->argv[i]); } g_free(state->argv); } syslog-ng-syslog-ng-3.13.2/lib/template/simple-function.h000066400000000000000000000036411321171025300233070ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TEMPLATE_SIMPLE_FUNCTION_H_INCLUDED #define TEMPLATE_SIMPLE_FUNCTION_H_INCLUDED #include "template/function.h" /* function pointers for template functions */ typedef struct _TFSimpleFuncState { gint argc; LogTemplate **argv; } TFSimpleFuncState; typedef void (*TFSimpleFunc)(LogMessage *msg, gint argc, GString *argv[], GString *result); gboolean tf_simple_func_prepare(LogTemplateFunction *self, gpointer state, LogTemplate *parent, gint argc, gchar *argv[], GError **error); void tf_simple_func_eval(LogTemplateFunction *self, gpointer state, const LogTemplateInvokeArgs *args); void tf_simple_func_call(LogTemplateFunction *self, gpointer state, const LogTemplateInvokeArgs *args, GString *result); void tf_simple_func_free_state(gpointer state); #define TEMPLATE_FUNCTION_SIMPLE(x) TEMPLATE_FUNCTION(TFSimpleFuncState, x, tf_simple_func_prepare, tf_simple_func_eval, tf_simple_func_call, tf_simple_func_free_state, x) #endif syslog-ng-syslog-ng-3.13.2/lib/template/templates.c000066400000000000000000000250611321171025300221640ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "template/templates.h" #include "template/repr.h" #include "template/compiler.h" #include "template/macros.h" #include "template/escaping.h" #include "cfg.h" static void log_template_reset_compiled(LogTemplate *self) { log_template_elem_free_list(self->compiled_template); self->compiled_template = NULL; } gboolean log_template_compile(LogTemplate *self, const gchar *template, GError **error) { LogTemplateCompiler compiler; gboolean result; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); log_template_reset_compiled(self); if (self->template) g_free(self->template); self->template = g_strdup(template); log_template_compiler_init(&compiler, self); result = log_template_compiler_compile(&compiler, &self->compiled_template, error); log_template_compiler_clear(&compiler); return result; } void log_template_set_escape(LogTemplate *self, gboolean enable) { self->escape = enable; } gboolean log_template_set_type_hint(LogTemplate *self, const gchar *type_hint, GError **error) { g_return_val_if_fail(error == NULL || *error == NULL, FALSE); return type_hint_parse(type_hint, &self->type_hint, error); } void log_template_append_format_with_context(LogTemplate *self, LogMessage **messages, gint num_messages, const LogTemplateOptions *opts, gint tz, gint32 seq_num, const gchar *context_id, GString *result) { GList *p; LogTemplateElem *e; if (!opts) opts = &self->cfg->template_options; for (p = self->compiled_template; p; p = g_list_next(p)) { gint msg_ndx; e = (LogTemplateElem *) p->data; if (e->text) { g_string_append_len(result, e->text, e->text_len); } /* NOTE: msg_ref is 1 larger than the index specified by the user in * order to make it distinguishable from the zero value. Therefore * the '>' instead of '>=' * * msg_ref == 0 means that the user didn't specify msg_ref * msg_ref >= 1 means that the user supplied the given msg_ref, 1 is equal to @0 */ if (e->msg_ref > num_messages) continue; msg_ndx = num_messages - e->msg_ref; /* value and macro can't understand a context, assume that no msg_ref means @0 */ if (e->msg_ref == 0) msg_ndx--; switch (e->type) { case LTE_VALUE: { const gchar *value = NULL; gssize value_len = -1; value = log_msg_get_value(messages[msg_ndx], e->value_handle, &value_len); if (value && value[0]) result_append(result, value, value_len, self->escape); else if (e->default_value) result_append(result, e->default_value, -1, self->escape); break; } case LTE_MACRO: { gint len = result->len; if (e->macro) { log_macro_expand(result, e->macro, self->escape, opts ? opts : &self->cfg->template_options, tz, seq_num, context_id, messages[msg_ndx]); if (len == result->len && e->default_value) g_string_append(result, e->default_value); } break; } case LTE_FUNC: { g_static_mutex_lock(&self->arg_lock); if (!self->arg_bufs) self->arg_bufs = g_ptr_array_sized_new(0); if (1) { LogTemplateInvokeArgs args = { self->arg_bufs, e->msg_ref ? &messages[msg_ndx] : messages, e->msg_ref ? 1 : num_messages, opts, tz, seq_num, context_id }; /* if a function call is called with an msg_ref, we only * pass that given logmsg to argument resolution, otherwise * we pass the whole set so the arguments can individually * specify which message they want to resolve from */ if (e->func.ops->eval) e->func.ops->eval(e->func.ops, e->func.state, &args); e->func.ops->call(e->func.ops, e->func.state, &args, result); } g_static_mutex_unlock(&self->arg_lock); break; } } } } void log_template_format_with_context(LogTemplate *self, LogMessage **messages, gint num_messages, const LogTemplateOptions *opts, gint tz, gint32 seq_num, const gchar *context_id, GString *result) { g_string_truncate(result, 0); log_template_append_format_with_context(self, messages, num_messages, opts, tz, seq_num, context_id, result); } void log_template_append_format(LogTemplate *self, LogMessage *lm, const LogTemplateOptions *opts, gint tz, gint32 seq_num, const gchar *context_id, GString *result) { log_template_append_format_with_context(self, &lm, 1, opts, tz, seq_num, context_id, result); } void log_template_format(LogTemplate *self, LogMessage *lm, const LogTemplateOptions *opts, gint tz, gint32 seq_num, const gchar *context_id, GString *result) { g_string_truncate(result, 0); log_template_append_format(self, lm, opts, tz, seq_num, context_id, result); } /* NOTE: we should completely get rid off the name property of templates, * we basically use it at two locations: * * 1) dbparser uses it to store SyntheticMessages, there the "name" of a * value is stored here * * 2) we reuse the LogTemplate structure (which represents a compiled * template) to store a template {} statement in the configuration, * which apart from a compiled template, also sports a name. This was * the original reason the name attribute was introduced. This basically * blends two unrelated purposes in the same struct. * * Other call sites pass a dummy value, which is probably never used in any * meaningful way. * * Both usages and the dummy call-sites should be removed, and the entire * thing replaced by another struct that contains a LogTemplate. * * I saw this to cause confusion numerous times already. * -- * Bazsi. */ void log_template_set_name(LogTemplate *self, const gchar *name) { if (self->name) g_free(self->name); self->name = g_strdup(name); } /* NOTE: the name parameter should not be used, please pass a NULL until it is eliminated */ LogTemplate * log_template_new(GlobalConfig *cfg, const gchar *name) { LogTemplate *self = g_new0(LogTemplate, 1); log_template_set_name(self, name); self->ref_cnt = 1; self->cfg = cfg; g_static_mutex_init(&self->arg_lock); return self; } static void log_template_free(LogTemplate *self) { if (self->arg_bufs) { gint i; for (i = 0; i < self->arg_bufs->len; i++) g_string_free(g_ptr_array_index(self->arg_bufs, i), TRUE); g_ptr_array_free(self->arg_bufs, TRUE); } log_template_reset_compiled(self); g_free(self->name); g_free(self->template); g_static_mutex_free(&self->arg_lock); g_free(self); } LogTemplate * log_template_ref(LogTemplate *s) { if (s) { g_assert(s->ref_cnt > 0); s->ref_cnt++; } return s; } void log_template_unref(LogTemplate *s) { if (s) { g_assert(s->ref_cnt > 0); if (--s->ref_cnt == 0) log_template_free(s); } } /* NOTE: _init needs to be idempotent when called multiple times w/o invoking _destroy */ void log_template_options_init(LogTemplateOptions *options, GlobalConfig *cfg) { gint i; if (options->initialized) return; if (options->ts_format == -1) options->ts_format = cfg->template_options.ts_format; for (i = 0; i < LTZ_MAX; i++) { if (options->time_zone[i] == NULL) options->time_zone[i] = g_strdup(cfg->template_options.time_zone[i]); if (options->time_zone_info[i] == NULL) options->time_zone_info[i] = time_zone_info_new(options->time_zone[i]); } if (options->frac_digits == -1) options->frac_digits = cfg->template_options.frac_digits; if (options->on_error == -1) options->on_error = cfg->template_options.on_error; options->initialized = TRUE; } void log_template_options_destroy(LogTemplateOptions *options) { gint i; for (i = 0; i < LTZ_MAX; i++) { if (options->time_zone[i]) g_free(options->time_zone[i]); if (options->time_zone_info[i]) time_zone_info_free(options->time_zone_info[i]); } options->initialized = FALSE; } void log_template_options_defaults(LogTemplateOptions *options) { memset(options, 0, sizeof(LogTemplateOptions)); options->frac_digits = -1; options->ts_format = -1; options->on_error = -1; } GQuark log_template_error_quark(void) { return g_quark_from_static_string("log-template-error-quark"); } void log_template_global_init(void) { log_macros_global_init(); } void log_template_global_deinit(void) { log_macros_global_deinit(); } gboolean log_template_on_error_parse(const gchar *strictness, gint *out) { const gchar *p = strictness; gboolean silently = FALSE; if (!strictness) { *out = ON_ERROR_DROP_MESSAGE; return TRUE; } if (strncmp(strictness, "silently-", strlen("silently-")) == 0) { silently = TRUE; p = strictness + strlen("silently-"); } if (strcmp(p, "drop-message") == 0) *out = ON_ERROR_DROP_MESSAGE; else if (strcmp(p, "drop-property") == 0) *out = ON_ERROR_DROP_PROPERTY; else if (strcmp(p, "fallback-to-string") == 0) *out = ON_ERROR_FALLBACK_TO_STRING; else return FALSE; if (silently) *out |= ON_ERROR_SILENT; return TRUE; } void log_template_options_set_on_error(LogTemplateOptions *options, gint on_error) { options->on_error = on_error; } syslog-ng-syslog-ng-3.13.2/lib/template/templates.h000066400000000000000000000104221321171025300221640ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TEMPLATES_H_INCLUDED #define TEMPLATES_H_INCLUDED #include "syslog-ng.h" #include "common-template-typedefs.h" #include "timeutils.h" #include "type-hinting.h" #define LTZ_LOCAL 0 #define LTZ_SEND 1 #define LTZ_MAX 2 #define LOG_TEMPLATE_ERROR log_template_error_quark() GQuark log_template_error_quark(void); enum LogTemplateError { LOG_TEMPLATE_ERROR_FAILED, LOG_TEMPLATE_ERROR_COMPILE, }; typedef enum { ON_ERROR_DROP_MESSAGE = 0x01, ON_ERROR_DROP_PROPERTY = 0x02, ON_ERROR_FALLBACK_TO_STRING = 0x04, /* Valid for type hinting only! */ ON_ERROR_SILENT = 0x08 } LogTemplateOnError; /* structure that represents an expandable syslog-ng template */ typedef struct _LogTemplate { gint ref_cnt; gchar *name; gchar *template; GList *compiled_template; gboolean escape; gboolean def_inline; GlobalConfig *cfg; GStaticMutex arg_lock; GPtrArray *arg_bufs; TypeHint type_hint; } LogTemplate; /* template expansion options that can be influenced by the user and * is static throughout the runtime for a given configuration. There * are call-site specific options too, those are specified as * arguments to log_template_format() */ struct _LogTemplateOptions { gboolean initialized; /* timestamp format as specified by ts_format() */ gint ts_format; /* number of digits in the fraction of a second part, specified using frac_digits() */ gint frac_digits; /* timezone for LTZ_LOCAL/LTZ_SEND settings */ gchar *time_zone[LTZ_MAX]; TimeZoneInfo *time_zone_info[LTZ_MAX]; /* Template error handling settings */ gint on_error; }; /* appends the formatted output into result */ void log_template_set_escape(LogTemplate *self, gboolean enable); gboolean log_template_set_type_hint(LogTemplate *self, const gchar *hint, GError **error); gboolean log_template_compile(LogTemplate *self, const gchar *template, GError **error); void log_template_format(LogTemplate *self, LogMessage *lm, const LogTemplateOptions *opts, gint tz, gint32 seq_num, const gchar *context_id, GString *result); void log_template_append_format(LogTemplate *self, LogMessage *lm, const LogTemplateOptions *opts, gint tz, gint32 seq_num, const gchar *context_id, GString *result); void log_template_append_format_with_context(LogTemplate *self, LogMessage **messages, gint num_messages, const LogTemplateOptions *opts, gint tz, gint32 seq_num, const gchar *context_id, GString *result); void log_template_format_with_context(LogTemplate *self, LogMessage **messages, gint num_messages, const LogTemplateOptions *opts, gint tz, gint32 seq_num, const gchar *context_id, GString *result); void log_template_set_name(LogTemplate *self, const gchar *name); LogTemplate *log_template_new(GlobalConfig *cfg, const gchar *name); LogTemplate *log_template_ref(LogTemplate *s); void log_template_unref(LogTemplate *s); void log_template_options_init(LogTemplateOptions *options, GlobalConfig *cfg); void log_template_options_destroy(LogTemplateOptions *options); void log_template_options_defaults(LogTemplateOptions *options); void log_template_global_init(void); void log_template_global_deinit(void); gboolean log_template_on_error_parse(const gchar *on_error, gint *out); void log_template_options_set_on_error(LogTemplateOptions *options, gint on_error); #endif syslog-ng-syslog-ng-3.13.2/lib/template/tests/000077500000000000000000000000001321171025300211605ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/template/tests/Makefile.am000066400000000000000000000014201321171025300232110ustar00rootroot00000000000000lib_template_tests_TESTS = \ lib/template/tests/test_template_compile \ lib/template/tests/test_template_on_error \ lib/template/tests/test_template \ lib/template/tests/test_template_speed check_PROGRAMS += ${lib_template_tests_TESTS} lib_template_tests_test_template_compile_CFLAGS = \ $(TEST_CFLAGS) lib_template_tests_test_template_compile_LDADD = \ $(TEST_LDADD) lib_template_tests_test_template_on_error_CFLAGS = \ $(TEST_CFLAGS) lib_template_tests_test_template_on_error_LDADD = \ $(TEST_LDADD) lib_template_tests_test_template_CFLAGS = $(TEST_CFLAGS) lib_template_tests_test_template_LDADD = \ $(TEST_LDADD) \ $(PREOPEN_SYSLOGFORMAT) \ $(PREOPEN_BASICFUNCS) lib_template_tests_test_template_speed_LDADD = \ $(TEST_LDADD) $(PREOPEN_SYSLOGFORMAT) syslog-ng-syslog-ng-3.13.2/lib/template/tests/test_template.c000066400000000000000000000263111321171025300242010ustar00rootroot00000000000000/* * Copyright (c) 2007-2014 Balabit * Copyright (c) 2007-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "syslog-ng.h" #include "template_lib.h" #include "logmsg/logmsg.h" #include "template/templates.h" #include "template/user-function.h" #include "apphook.h" #include "cfg.h" #include "timeutils.h" #include "plugin.h" #include #include #include #include GCond *thread_ping; GMutex *thread_lock; gboolean thread_start; static gpointer format_template_thread(gpointer s) { gpointer *args = (gpointer *) s; LogMessage *msg = args[0]; LogTemplate *templ = args[1]; const gchar *expected = args[2]; GString *result; gint i; g_mutex_lock(thread_lock); while (!thread_start) g_cond_wait(thread_ping, thread_lock); g_mutex_unlock(thread_lock); result = g_string_sized_new(0); for (i = 0; i < 10000; i++) { log_template_format(templ, msg, NULL, LTZ_SEND, 5555, NULL, result); assert_string(result->str, expected, "multi-threaded formatting yielded invalid result (iteration: %d)", i); } g_string_free(result, TRUE); return NULL; } static void assert_template_format_multi_thread(const gchar *template, const gchar *expected) { LogTemplate *templ; LogMessage *msg; gpointer args[3]; GThread *threads[16]; gint i; msg = create_sample_message(); templ = compile_template(template, FALSE); args[0] = msg; args[1] = templ; args[2] = (gpointer) expected; thread_start = FALSE; thread_ping = g_cond_new(); thread_lock = g_mutex_new(); args[1] = templ; for (i = 0; i < 16; i++) { threads[i] = g_thread_create(format_template_thread, args, TRUE, NULL); } thread_start = TRUE; g_mutex_lock(thread_lock); g_cond_broadcast(thread_ping); g_mutex_unlock(thread_lock); for (i = 0; i < 16; i++) { g_thread_join(threads[i]); } g_cond_free(thread_ping); g_mutex_free(thread_lock); log_template_unref(templ); log_msg_unref(msg); } static void test_macros(void) { /* pri 3, fac 19 == local3 */ assert_template_format("$FACILITY", "local3"); assert_template_format("$FACILITY_NUM", "19"); assert_template_format("$PRIORITY", "err"); assert_template_format("$LEVEL", "err"); assert_template_format("$LEVEL_NUM", "3"); assert_template_format("$TAG", "9b"); assert_template_format("$TAGS", "alma,korte,citrom,\"tag,containing,comma\""); assert_template_format("$PRI", "155"); assert_template_format("$DATE", "Feb 11 10:34:56.000"); assert_template_format("$FULLDATE", "2006 Feb 11 10:34:56.000"); assert_template_format("$ISODATE", "2006-02-11T10:34:56.000+01:00"); assert_template_format("$STAMP", "Feb 11 10:34:56.000"); assert_template_format("$YEAR", "2006"); assert_template_format("$YEAR_DAY", "042"); assert_template_format("$MONTH", "02"); assert_template_format("$MONTH_WEEK", "1"); assert_template_format("$MONTH_ABBREV", "Feb"); assert_template_format("$MONTH_NAME", "February"); assert_template_format("$DAY", "11"); assert_template_format("$HOUR", "10"); assert_template_format("$MIN", "34"); assert_template_format("$SEC", "56"); assert_template_format("$WEEKDAY", "Sat"); assert_template_format("$WEEK_DAY", "7"); assert_template_format("$WEEK_DAY_NAME", "Saturday"); assert_template_format("$WEEK_DAY_ABBREV", "Sat"); assert_template_format("$WEEK", "06"); assert_template_format("$UNIXTIME", "1139650496.000"); assert_template_format("$TZOFFSET", "+01:00"); assert_template_format("$TZ", "+01:00"); assert_template_format("$R_DATE", "Feb 11 19:58:35.639"); assert_template_format("$R_FULLDATE", "2006 Feb 11 19:58:35.639"); assert_template_format("$R_ISODATE", "2006-02-11T19:58:35.639+01:00"); assert_template_format("$R_STAMP", "Feb 11 19:58:35.639"); assert_template_format("$R_YEAR", "2006"); assert_template_format("$R_YEAR_DAY", "042"); assert_template_format("$R_MONTH", "02"); assert_template_format("$R_MONTH_WEEK", "1"); assert_template_format("$R_MONTH_ABBREV", "Feb"); assert_template_format("$R_MONTH_NAME", "February"); assert_template_format("$R_DAY", "11"); assert_template_format("$R_HOUR", "19"); assert_template_format("$R_MIN", "58"); assert_template_format("$R_SEC", "35"); assert_template_format("$R_WEEKDAY", "Sat"); assert_template_format("$R_WEEK_DAY", "7"); assert_template_format("$R_WEEK_DAY_NAME", "Saturday"); assert_template_format("$R_WEEK_DAY_ABBREV", "Sat"); assert_template_format("$R_WEEK", "06"); assert_template_format("$R_UNIXTIME", "1139684315.639"); assert_template_format("$R_TZOFFSET", "+01:00"); assert_template_format("$R_TZ", "+01:00"); assert_template_format("$S_DATE", "Feb 11 10:34:56.000"); assert_template_format("$S_FULLDATE", "2006 Feb 11 10:34:56.000"); assert_template_format("$S_ISODATE", "2006-02-11T10:34:56.000+01:00"); assert_template_format("$S_STAMP", "Feb 11 10:34:56.000"); assert_template_format("$S_YEAR", "2006"); assert_template_format("$S_YEAR_DAY", "042"); assert_template_format("$S_MONTH", "02"); assert_template_format("$S_MONTH_WEEK", "1"); assert_template_format("$S_MONTH_ABBREV", "Feb"); assert_template_format("$S_MONTH_NAME", "February"); assert_template_format("$S_DAY", "11"); assert_template_format("$S_HOUR", "10"); assert_template_format("$S_MIN", "34"); assert_template_format("$S_SEC", "56"); assert_template_format("$S_WEEKDAY", "Sat"); assert_template_format("$S_WEEK_DAY", "7"); assert_template_format("$S_WEEK_DAY_NAME", "Saturday"); assert_template_format("$S_WEEK_DAY_ABBREV", "Sat"); assert_template_format("$S_WEEK", "06"); assert_template_format("$S_UNIXTIME", "1139650496.000"); assert_template_format("$S_TZOFFSET", "+01:00"); assert_template_format("$S_TZ", "+01:00"); assert_template_format("$HOST_FROM", "kismacska"); assert_template_format("$FULLHOST_FROM", "kismacska"); assert_template_format("$HOST", "bzorp"); assert_template_format("$FULLHOST", "bzorp"); assert_template_format("$PROGRAM", "syslog-ng"); assert_template_format("$PID", "23323"); assert_template_format("$MSGHDR", "syslog-ng[23323]:"); assert_template_format("$MSG", "árvíztűrőtükörfúrógép"); assert_template_format("$MESSAGE", "árvíztűrőtükörfúrógép"); assert_template_format("$SOURCEIP", "10.11.12.13"); assert_template_format("$RCPTID", "555"); assert_template_format("$SEQNUM", "999"); assert_template_format("$CONTEXT_ID", "test-context-id"); assert_template_format("$UNIQID", "cafebabe@000000000000022b"); } static void test_nvpairs(void) { assert_template_format("$PROGRAM/var/log/messages/$HOST/$HOST_FROM/$MONTH$DAY${QQQQQ}valami", "syslog-ng/var/log/messages/bzorp/kismacska/0211valami"); assert_template_format("${APP.VALUE}", "value"); assert_template_format("${APP.VALUE:-ures}", "value"); assert_template_format("${APP.VALUE99:-ures}", "ures"); assert_template_format("${1}", "first-match"); assert_template_format("$1", "first-match"); assert_template_format("$$$1$$", "$first-match$"); } static void test_template_functions(void) { /* template functions */ assert_template_format("$(echo $HOST $PID)", "bzorp 23323"); assert_template_format("$(echo \"$(echo $HOST)\" $PID)", "bzorp 23323"); assert_template_format("$(echo \"$(echo '$(echo $HOST)')\" $PID)", "bzorp 23323"); assert_template_format("$(echo \"$(echo '$(echo $HOST)')\" $PID)", "bzorp 23323"); assert_template_format("$(echo '\"$(echo $(echo $HOST))\"' $PID)", "\"bzorp\" 23323"); } static void test_message_refs(void) { /* message refs */ assert_template_format_with_context("$(echo ${HOST}@0 ${PID}@1)", "bzorp 23323"); assert_template_format_with_context("$(echo $HOST $PID)@0", "bzorp 23323"); } static void test_syntax_errors(void) { /* template syntax errors */ assert_template_failure("${unbalanced_brace", "'}' is missing"); assert_template_format("$unbalanced_brace}", "}"); assert_template_format("$}", "$}"); assert_template_failure("$(unbalanced_paren", "missing function name or inbalanced '('"); assert_template_format("$unbalanced_paren)", ")"); } static void test_multi_thread(void) { /* name-value pair */ assert_template_format_multi_thread("alma $HOST bela", "alma bzorp bela"); assert_template_format_multi_thread("kukac $DATE mukac", "kukac Feb 11 10:34:56.000 mukac"); assert_template_format_multi_thread("dani $(echo $HOST $DATE $(echo huha)) balint", "dani bzorp Feb 11 10:34:56.000 huha balint"); } static void test_escaping(void) { assert_template_format_with_escaping("${APP.QVALUE}", FALSE, "\"value\""); assert_template_format_with_escaping("${APP.QVALUE}", TRUE, "\\\"value\\\""); assert_template_format_with_escaping("$(if (\"${APP.VALUE}\" == \"value\") \"${APP.QVALUE}\" \"${APP.QVALUE}\")", FALSE, "\"value\""); assert_template_format_with_escaping("$(if (\"${APP.VALUE}\" == \"value\") \"${APP.QVALUE}\" \"${APP.QVALUE}\")", TRUE, "\\\"value\\\""); } static void test_user_template_function(void) { LogTemplate *template; template = compile_template("this is a user-defined template function $DATE", FALSE); user_template_function_register(configuration, "dummy", template); assert_template_format("$(dummy)", "this is a user-defined template function Feb 11 10:34:56.000"); assert_template_failure("$(dummy arg)", "User defined template function $(dummy) cannot have arguments"); log_template_unref(template); } static void test_template_function_args(void) { assert_template_format("$(echo foo bar)", "foo bar"); assert_template_format("$(echo 'foobar' \"barfoo\")", "foobar barfoo"); assert_template_format("$(echo foo '' bar)", "foo bar"); assert_template_format("$(echo foo '')", "foo "); } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { app_startup(); init_template_tests(); cfg_load_module(configuration, "basicfuncs"); configuration->template_options.frac_digits = 3; configuration->template_options.time_zone_info[LTZ_LOCAL] = time_zone_info_new(NULL); putenv("TZ=MET-1METDST"); tzset(); test_macros(); test_nvpairs(); test_template_functions(); test_message_refs(); test_syntax_errors(); test_multi_thread(); test_escaping(); test_template_function_args(); test_user_template_function(); /* multi-threaded expansion */ deinit_template_tests(); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/template/tests/test_template_compile.c000066400000000000000000000435261321171025300257200ustar00rootroot00000000000000/* * Copyright (c) 2013-2014 Balabit * Copyright (c) 2013-2014 Balázs Scheidler * Copyright (c) 2013 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "template/templates.c" #include "template/simple-function.h" #include "logmsg/logmsg.h" #include "testutils.h" #include "cfg.h" #include "plugin.h" static void hello(LogMessage *msg, int argc, GString *argv[], GString *result) { return; } TEMPLATE_FUNCTION_SIMPLE(hello); Plugin hello_plugin = TEMPLATE_FUNCTION_PLUGIN(hello, "hello"); #define assert_common_element(expected) \ assert_string(current_elem->text, expected.text, ASSERTION_ERROR("Bad compiled template text")); \ if (expected.default_value) \ { \ assert_string(current_elem->default_value, expected.default_value, ASSERTION_ERROR("Bad compiled template default value")); \ } \ else \ { \ assert_gpointer(current_elem->default_value, NULL, ASSERTION_ERROR("Bad compiled template default value")); \ } \ assert_gint(current_elem->msg_ref, expected.msg_ref, ASSERTION_ERROR("Bad compiled template msg_ref")); #define fill_expected_template_element(element, text, default_value, spec, type, msg_ref) {\ element.text; \ element.default_value; \ element.spec; \ element.type; \ element.msg_ref; } #define assert_compiled_template(text, default_value, spec, type, msg_ref) \ do { \ LogTemplateElem expected_elem; \ \ fill_expected_template_element(expected_elem, text, default_value, spec, type, msg_ref); \ assert_gint((current_elem->type), (expected_elem.type), ASSERTION_ERROR("Bad compiled template type")); \ assert_common_element(expected_elem); \ if ((expected_elem.type) == LTE_MACRO) assert_gint(current_elem->macro, expected_elem.macro, ASSERTION_ERROR("Bad compiled template macro")); \ if ((expected_elem.type) == LTE_VALUE) assert_gint(current_elem->value_handle, expected_elem.value_handle, ASSERTION_ERROR("Bad compiled template macro")); \ if ((expected_elem.type) == LTE_FUNC) assert_gpointer(current_elem->func.ops, expected_elem.func.ops, ASSERTION_ERROR("Bad compiled template macro")); \ } while (0) #define TEMPLATE_TESTCASE(x, ...) do { template_testcase_begin(#x, #__VA_ARGS__); x(__VA_ARGS__); template_testcase_end(); } while(0) #define template_testcase_begin(func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ template = log_template_new(configuration, NULL); \ start_grabbing_messages(); \ } \ while (0) #define template_testcase_end() \ do \ { \ log_template_unref(template); \ template = NULL; \ testcase_end(); \ } \ while (0) static LogTemplate *template; static GList *current_elem_list; static LogTemplateElem *current_elem; static void select_current_element(void) { current_elem = (LogTemplateElem *) current_elem_list->data; } static void select_first_element(void) { current_elem_list = template->compiled_template; select_current_element(); } static void select_next_element(void) { current_elem_list = current_elem_list->next; select_current_element(); } static inline void assert_template_compile(const gchar *template_string) { GError *error = NULL; assert_true(log_template_compile(template, template_string, &error), ASSERTION_ERROR("Can't compile template")); assert_string(template->template, template_string, ASSERTION_ERROR("Bad stored template")); select_first_element(); } static inline void assert_failed_template_compile(const gchar *template_string, const gchar *expected_error_message) { GError *error = NULL; assert_false(log_template_compile(template, template_string, &error), ASSERTION_ERROR("Can compile bad template")); assert_string(error->message, expected_error_message, ASSERTION_ERROR("Bad error message")); g_clear_error(&error); select_first_element(); } static gpointer get_template_function_ops(const gchar *name) { Plugin *plugin; plugin = cfg_find_plugin(configuration, LL_CONTEXT_TEMPLATE_FUNC, name); assert_not_null(plugin, "Template function %s is not found", name); if (plugin) return plugin->construct(plugin); return NULL; } static void test_simple_string_literal(void) { gchar *text = "Test String"; assert_template_compile(text); assert_compiled_template(text = text, default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_simple_macro(void) { assert_template_compile("${MESSAGE}"); assert_compiled_template(text = "", default_value = NULL, macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 0); } static void test_macro_and_text(void) { assert_template_compile("${MESSAGE}test value"); assert_compiled_template(text = "", default_value = NULL, macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 0); select_next_element(); assert_compiled_template(text = "test value", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_macro_without_braces(void) { assert_template_compile("$MESSAGE"); assert_compiled_template(text = "", default_value = NULL, macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 0); } static void test_macro_name_without_braces_are_terminated_with_non_identifier_characters(void) { /* macro names consist of [A-Z0-9_] */ assert_template_compile("$MESSAGE test value"); assert_compiled_template(text = "", default_value = NULL, macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 0); select_next_element(); assert_compiled_template(text = " test value", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_macro_without_at_records_that_no_msgref_was_present_by_msgref_zero(void) { assert_template_compile("${MESSAGE}"); assert_compiled_template(text = "", default_value = NULL, macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 0); } static void test_macro_with_at_references_a_single_msg_in_the_context_stack_by_setting_msgref(void) { assert_template_compile("${MESSAGE}@0"); assert_compiled_template(text = "", default_value = NULL, macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 1); assert_template_compile("${MESSAGE}@1"); assert_compiled_template(text = "", default_value = NULL, macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 2); } static void test_macro_with_invalid_msgref_are_recognized_as_the_top_element_in_the_stack(void) { assert_template_compile("${MESSAGE}@gmail.com"); assert_compiled_template(text = "", default_value = NULL, macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 0); select_next_element(); assert_compiled_template(text = "@gmail.com", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_dollar_prefixed_with_backslash_is_a_literal_dollar(void) { cfg_set_version(configuration, 0x304); assert_template_compile("Test \\$STRING"); assert_compiled_template(text = "Test $STRING", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); cfg_set_version(configuration, 0x305); assert_template_compile("Test \\$STRING"); assert_compiled_template(text = "Test \\", default_value = NULL, value_handle = log_msg_get_value_handle("STRING"), type = LTE_VALUE, msg_ref = 0); } static void test_colon_dash_in_braces_is_parsed_as_default_value(void) { assert_template_compile("${MESSAGE:-default value}"); assert_compiled_template(text = "", default_value = "default value", macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 0); assert_template_compile("${MESSAGE:-}"); assert_compiled_template(text = "", default_value = "", macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 0); } static void test_double_dollars_is_a_literal_dollar(void) { assert_template_compile("$$VALUE_NAME"); assert_compiled_template(text = "$VALUE_NAME", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); assert_template_compile("$${VALUE_NAME}"); assert_compiled_template(text = "${VALUE_NAME}", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_dollar_with_an_invalid_macro_name_without_braces_is_parsed_as_a_literal_dollar(void) { assert_template_compile("$:VALUE_NAME"); assert_compiled_template(text = "$:VALUE_NAME", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); assert_template_compile("$"); assert_compiled_template(text = "$", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_backslash_without_finishing_the_escape_sequence_is_ignored(void) { cfg_set_version(configuration, 0x304); assert_template_compile("foo\\"); assert_compiled_template(text = "foo", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); cfg_set_version(configuration, 0x305); assert_template_compile("foo\\"); assert_compiled_template(text = "foo\\", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_double_at_is_a_literal_at(void) { assert_template_compile("${MESSAGE}@@12"); assert_compiled_template(text = "", default_value = NULL, macro = M_MESSAGE, type = LTE_MACRO, msg_ref = 0); select_next_element(); assert_compiled_template(text = "@12", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_template_compile_macro(void) { TEMPLATE_TESTCASE(test_simple_string_literal); TEMPLATE_TESTCASE(test_simple_macro); TEMPLATE_TESTCASE(test_macro_and_text); TEMPLATE_TESTCASE(test_macro_without_braces); TEMPLATE_TESTCASE(test_macro_name_without_braces_are_terminated_with_non_identifier_characters); TEMPLATE_TESTCASE(test_macro_without_at_records_that_no_msgref_was_present_by_msgref_zero); TEMPLATE_TESTCASE(test_macro_with_at_references_a_single_msg_in_the_context_stack_by_setting_msgref); TEMPLATE_TESTCASE(test_macro_with_invalid_msgref_are_recognized_as_the_top_element_in_the_stack); TEMPLATE_TESTCASE(test_dollar_prefixed_with_backslash_is_a_literal_dollar); TEMPLATE_TESTCASE(test_colon_dash_in_braces_is_parsed_as_default_value); TEMPLATE_TESTCASE(test_double_dollars_is_a_literal_dollar); TEMPLATE_TESTCASE(test_dollar_with_an_invalid_macro_name_without_braces_is_parsed_as_a_literal_dollar); TEMPLATE_TESTCASE(test_backslash_without_finishing_the_escape_sequence_is_ignored); TEMPLATE_TESTCASE(test_double_at_is_a_literal_at); } static void test_simple_value(void) { assert_template_compile("${VALUE_NAME}"); assert_compiled_template(text = "", default_value = NULL, value_handle = log_msg_get_value_handle("VALUE_NAME"), type = LTE_VALUE, msg_ref = 0); } static void test_value_without_braces(void) { assert_template_compile("$VALUE_NAME"); assert_compiled_template(text = "", default_value = NULL, value_handle = log_msg_get_value_handle("VALUE_NAME"), type = LTE_VALUE, msg_ref = 0); } static void test_backslash_within_braces_is_taken_literally(void) { assert_template_compile("${VALUE\\}NAME}"); assert_compiled_template(text = "", default_value = NULL, value_handle = log_msg_get_value_handle("VALUE\\"), type = LTE_VALUE, msg_ref = 0); } static void test_value_name_can_be_the_empty_string_when_referenced_using_braces(void) { assert_template_compile("${}"); assert_compiled_template(text = "", default_value = NULL, value_handle = log_msg_get_value_handle(""), type = LTE_VALUE, msg_ref = 0); } static void test_template_compile_value(void) { TEMPLATE_TESTCASE(test_simple_value); TEMPLATE_TESTCASE(test_value_without_braces); TEMPLATE_TESTCASE(test_backslash_within_braces_is_taken_literally); TEMPLATE_TESTCASE(test_value_name_can_be_the_empty_string_when_referenced_using_braces); } static void test_simple_template_function(void) { assert_template_compile("$(hello)"); assert_compiled_template(text = "", default_value = NULL, func.ops = get_template_function_ops("hello"), type = LTE_FUNC, msg_ref = 0); } static void test_complicated_template_function(void) { assert_template_compile("$( hello \\tes\t\t\t value(xyz) \"value with spaces\" 'test value with spa\"ces')@2"); assert_compiled_template(text = "", default_value = NULL, func.ops = get_template_function_ops("hello"), type = LTE_FUNC, msg_ref = 3); } static void test_simple_template_function_with_additional_text(void) { assert_template_compile("$(hello)test value"); assert_compiled_template(text = "", default_value = NULL, func.ops = get_template_function_ops("hello"), type = LTE_FUNC, msg_ref = 0); select_next_element(); assert_compiled_template(text = "test value", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_qouted_string_in_name_template_function(void) { assert_template_compile("$(he\"ll\"o)"); assert_compiled_template(text = "", default_value = NULL, func.ops = get_template_function_ops("hello"), type = LTE_FUNC, msg_ref = 0); } static void test_template_compile_func(void) { TEMPLATE_TESTCASE(test_simple_template_function); TEMPLATE_TESTCASE(test_complicated_template_function); TEMPLATE_TESTCASE(test_simple_template_function_with_additional_text); TEMPLATE_TESTCASE(test_qouted_string_in_name_template_function); } static void test_invalid_macro(void) { assert_failed_template_compile("${MESSAGE", "Invalid macro, '}' is missing, error_pos='9'"); assert_compiled_template(text = "error in template: ${MESSAGE", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_invalid_subst(void) { assert_failed_template_compile("${MESSAGE:1}", "Unknown substitution function, error_pos='10'"); assert_compiled_template(text = "error in template: ${MESSAGE:1}", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_template_function_bad1(void) { assert_failed_template_compile("$( hello \\tes\t\t\t value(xyz \"value with spaces\" 'test value with spa\"ces')", "Invalid template function reference, missing function name or inbalanced '(', error_pos='73'"); assert_compiled_template(text = "error in template: $( hello \\tes\t\t\t value(xyz \"value with spaces\" 'test value with spa\"ces')", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_template_function_bad2(void) { assert_failed_template_compile("$( hello \\tes\t\t\t value xyz \"value with spaces\" 'test value with spa\"ces'", "Invalid template function reference, missing function name or inbalanced '(', error_pos='72'"); assert_compiled_template(text = "error in template: $( hello \\tes\t\t\t value xyz \"value with spaces\" 'test value with spa\"ces'", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_template_function_bad3(void) { assert_failed_template_compile("$(hello \"This is an unclosed quoted string)", "Invalid template function reference, missing function name or inbalanced '(', error_pos='8'"); assert_compiled_template(text = "error in template: $(hello \"This is an unclosed quoted string)", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_unknown_function(void) { assert_failed_template_compile("$(unknown function)", "Unknown template function \"unknown\""); assert_compiled_template(text = "error in template: $(unknown function)", default_value = NULL, macro = M_NONE, type = LTE_MACRO, msg_ref = 0); } static void test_template_compile_negativ_tests(void) { TEMPLATE_TESTCASE(test_invalid_macro); TEMPLATE_TESTCASE(test_invalid_subst); TEMPLATE_TESTCASE(test_template_function_bad1); TEMPLATE_TESTCASE(test_template_function_bad2); TEMPLATE_TESTCASE(test_template_function_bad3); TEMPLATE_TESTCASE(test_unknown_function); } int main(int argc, char **argv) { msg_init(FALSE); configuration = cfg_new_snippet(); log_msg_registry_init(); log_template_global_init(); plugin_register(&configuration->plugin_context, &hello_plugin, 1); test_template_compile_macro(); test_template_compile_value(); test_template_compile_func(); test_template_compile_negativ_tests(); log_msg_registry_deinit(); msg_deinit(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/template/tests/test_template_on_error.c000066400000000000000000000061371321171025300261120ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include "template/templates.h" #include "testutils.h" #include "apphook.h" #define assert_on_error_parse(on_error,expected) \ do \ { \ gint r; \ \ assert_true(log_template_on_error_parse(on_error, &r), \ "Parsing '%s' works", on_error); \ assert_gint32(r, expected, "'%s' parses down to '%s'", \ on_error, #expected); \ } while(0) #define assert_on_error_parse_fails(on_error) \ do \ { \ gint r; \ \ assert_false(log_template_on_error_parse(on_error, &r), \ "Parsing '%s' works", on_error); \ } while(0) static void test_template_on_error(void) { testcase_begin("Testing LogTemplate on-error parsing"); assert_on_error_parse("drop-message", ON_ERROR_DROP_MESSAGE); assert_on_error_parse("silently-drop-message", ON_ERROR_DROP_MESSAGE | ON_ERROR_SILENT); assert_on_error_parse("drop-property", ON_ERROR_DROP_PROPERTY); assert_on_error_parse("silently-drop-property", ON_ERROR_DROP_PROPERTY | ON_ERROR_SILENT); assert_on_error_parse("fallback-to-string", ON_ERROR_FALLBACK_TO_STRING); assert_on_error_parse("silently-fallback-to-string", ON_ERROR_FALLBACK_TO_STRING | ON_ERROR_SILENT); assert_on_error_parse_fails("do-what-i-mean"); testcase_end(); } int main (void) { app_startup(); test_template_on_error(); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/template/tests/test_template_speed.c000066400000000000000000000046061321171025300253640ustar00rootroot00000000000000/* * Copyright (c) 2009-2014 Balabit * Copyright (c) 2009-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "syslog-ng.h" #include "logmsg/logmsg.h" #include "template/templates.h" #include "apphook.h" #include "cfg.h" #include "timeutils.h" #include "plugin.h" #include "libtest/template_lib.h" #include "libtest/stopwatch.h" #include #include #include #include gboolean success = TRUE; int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { app_startup(); init_template_tests(); putenv("TZ=MET-1METDST"); tzset(); cfg_load_module(configuration, "syslogformat"); cfg_load_module(configuration, "basicfuncs"); perftest_template("$DATE\n"); perftest_template("<$PRI>$DATE $HOST $MSGHDR$MSG\n"); perftest_template("$DATE\n"); perftest_template("$DATE $HOST\n"); perftest_template("$DATE $HOST $MSGHDR\n"); perftest_template("$DATE $HOST $MSGHDR$MSG\n"); perftest_template("$DATE $HOST $MSGHDR$MSG value\n"); perftest_template("$DATE $HOST $MSGHDR$MSG ${APP.VALUE}\n"); perftest_template("$MSG\n"); perftest_template("$TAGS\n"); perftest_template("$(echo $MSG)\n"); perftest_template("$(+ $FACILITY_NUM $FACILITY_NUM)\n"); perftest_template("$DATE $FACILITY.$PRIORITY $HOST $MSGHDR$MSG $SEQNO\n"); perftest_template("${APP.VALUE} ${APP.VALUE2}\n"); perftest_template("$DATE ${HOST:--} ${PROGRAM:--} ${PID:--} ${MSGID:--} ${SDATA:--} $MSG\n"); app_shutdown(); if (success) return 0; return 1; } syslog-ng-syslog-ng-3.13.2/lib/template/user-function.c000066400000000000000000000074551321171025300227760ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "template/function.h" #include "plugin.h" typedef struct _UserTemplateFunction { LogTemplateFunction super; gchar *name; LogTemplate *template; } UserTemplateFunction; static gboolean user_template_function_prepare(LogTemplateFunction *s, gpointer state, LogTemplate *parent, gint argc, gchar *argv[], GError **error) { UserTemplateFunction *self = (UserTemplateFunction *) s; g_return_val_if_fail(error == NULL || (*error) == NULL, FALSE); if (argc != 1) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "User defined template function $(%s) cannot have arguments", self->name); return FALSE; } return TRUE; } static void user_template_function_call(LogTemplateFunction *s, gpointer state, const LogTemplateInvokeArgs *args, GString *result) { UserTemplateFunction *self = (UserTemplateFunction *) s; log_template_append_format_with_context(self->template, args->messages, args->num_messages, args->opts, args->tz, args->seq_num, args->context_id, result); } static void user_template_function_free(LogTemplateFunction *s) { UserTemplateFunction *self = (UserTemplateFunction *) s; g_free(self->name); log_template_unref(self->template); g_free(self); } LogTemplateFunction * user_template_function_new(const gchar *name, LogTemplate *template) { UserTemplateFunction *self; self = g_new0(UserTemplateFunction, 1); self->super.size_of_state = 0; self->super.prepare = user_template_function_prepare; self->super.call = user_template_function_call; self->super.free_fn = user_template_function_free; self->template = log_template_ref(template); self->name = g_strdup(name); return &self->super; } typedef struct _UserTemplateFunctionPlugin { Plugin super; LogTemplate *template; } UserTemplateFunctionPlugin; static gpointer user_template_function_construct(Plugin *s) { UserTemplateFunctionPlugin *self = (UserTemplateFunctionPlugin *) s; return user_template_function_new(self->super.name, self->template); } static void user_template_function_plugin_free(Plugin *s) { UserTemplateFunctionPlugin *plugin = (UserTemplateFunctionPlugin *) s; g_free((gchar *) plugin->super.name); log_template_unref(plugin->template); g_free(s); } void user_template_function_register(GlobalConfig *cfg, const gchar *name, LogTemplate *template) { UserTemplateFunctionPlugin *plugin; plugin = g_new0(UserTemplateFunctionPlugin, 1); plugin->super.type = LL_CONTEXT_TEMPLATE_FUNC; plugin->super.name = g_strdup(name); plugin->super.parser = NULL; plugin->super.construct = user_template_function_construct; plugin->super.free_fn = user_template_function_plugin_free; plugin->template = log_template_ref(template); plugin_register(&cfg->plugin_context, &plugin->super, 1); } syslog-ng-syslog-ng-3.13.2/lib/template/user-function.h000066400000000000000000000022741321171025300227750ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TEMPLATE_FUNCTION_H_INCLUDED #define TEMPLATE_FUNCTION_H_INCLUDED #include "syslog-ng.h" void user_template_function_register(GlobalConfig *cfg, const gchar *name, LogTemplate *template); #endif syslog-ng-syslog-ng-3.13.2/lib/tests/000077500000000000000000000000001321171025300173455ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/tests/Makefile.am000066400000000000000000000052301321171025300214010ustar00rootroot00000000000000lib_tests_TESTS = \ lib/tests/test_cfg_lexer_subst \ lib/tests/test_cfg_tree \ lib/tests/test_type_hints \ lib/tests/test_parse_number \ lib/tests/test_reloc \ lib/tests/test_hostname \ lib/tests/test_rcptid \ lib/tests/test_lexer \ lib/tests/test_str_format \ lib/tests/test_string_list \ lib/tests/test_runid \ lib/tests/test_pathutils \ lib/tests/test_utf8utils \ lib/tests/test_userdb \ lib/tests/test_str-utils check_PROGRAMS += ${lib_tests_TESTS} noinst_PROGRAMS = \ lib/tests/test_host_resolve lib_tests_test_cfg_lexer_subst_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_cfg_lexer_subst_LDADD = \ $(TEST_LDADD) lib_tests_test_cfg_tree_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_cfg_tree_LDADD = \ $(TEST_LDADD) lib_tests_test_type_hints_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_type_hints_LDADD = \ $(TEST_LDADD) lib_tests_test_parse_number_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_parse_number_LDADD = \ $(TEST_LDADD) lib_tests_test_reloc_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_reloc_LDADD = \ $(TEST_LDADD) lib_tests_test_hostname_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_hostname_LDADD = \ $(TEST_LDADD) lib_tests_test_host_resolve_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_host_resolve_LDADD = \ $(TEST_LDADD) lib_tests_test_rcptid_CFLAGS = $(TEST_CFLAGS) lib_tests_test_rcptid_LDADD = \ $(TEST_LDADD) lib_tests_test_lexer_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_lexer_LDADD = \ $(TEST_LDADD) lib_tests_test_runid_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_runid_LDADD = \ $(TEST_LDADD) lib_tests_test_str_format_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_str_format_LDADD = \ $(TEST_LDADD) lib_tests_test_string_list_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_string_list_LDADD = \ $(TEST_LDADD) lib_tests_test_pathutils_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_pathutils_LDADD = \ $(TEST_LDADD) lib_tests_test_utf8utils_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_utf8utils_LDADD = \ $(TEST_LDADD) lib_tests_test_str_utils_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_str_utils_LDADD = \ $(TEST_LDADD) CLEANFILES += \ test_values.persist \ test_values.persist- \ test_run_id.persist \ test_run_id.persist- lib_tests_test_userdb_LDADD = \ $(TEST_LDADD) if ENABLE_CRITERION lib_tests_TESTS += \ lib/tests/test_cache \ lib/tests/test_scratch_buffers \ lib/tests/test_timeutils lib_tests_test_cache_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_cache_LDADD = \ $(TEST_LDADD) lib_tests_test_timeutils_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_timeutils_LDADD = \ $(TEST_LDADD) lib_tests_test_scratch_buffers_CFLAGS = \ $(TEST_CFLAGS) lib_tests_test_scratch_buffers_LDADD = \ $(TEST_LDADD) endif syslog-ng-syslog-ng-3.13.2/lib/tests/test_cache.c000066400000000000000000000055331321171025300216210ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cache.h" #include gint fetch_count; gint free_fn_count; void * fetch(CacheResolver *self, const gchar *key) { fetch_count++; return g_strdup_printf("almafa_%s", key); } void free_fn(CacheResolver *self) { free_fn_count++; return; } CacheResolver * dummy_cache_resolver(void) { CacheResolver *self = g_new0(CacheResolver, 1); self->resolve_elem = fetch; self->free_elem = g_free; self->free_fn = free_fn; return self; } static void assert_cache_lookup(Cache *c, const gchar *key) { gchar *value; gchar *expected_value = g_strdup_printf("almafa_%s", key); value = cache_lookup(c, key); cr_assert_str_eq(value, expected_value, "Lookup key: %s, Expected value: %s, Actual value: %s", key, value, expected_value); g_free(expected_value); } static void assert_cache_lookup_uncached(Cache *c, const gchar *key) { fetch_count = 0; assert_cache_lookup(c, key); cr_assert_eq(fetch_count, 1, "Cache lookup expected when looking up uncached elements, but one didn't arrive key=\"%s\"", key); } static void assert_cache_lookup_cached(Cache *c, const gchar *key) { fetch_count = 0; assert_cache_lookup(c, key); cr_assert_eq(fetch_count, 0, "Cache lookup unexpected when looking up cached elements, but one did arrive key=\"%s\"", key); } Test(cache, test_write_and_read) { Cache *c; c = cache_new(dummy_cache_resolver()); assert_cache_lookup_uncached(c, "key"); assert_cache_lookup_cached(c, "key"); assert_cache_lookup_uncached(c, "key2"); assert_cache_lookup_cached(c, "key2"); assert_cache_lookup_cached(c, "key"); assert_cache_lookup_cached(c, "key2"); cache_free(c); } Test(cache, test_free_calls_resolver_free_fn) { Cache *c; free_fn_count = 0; c = cache_new(dummy_cache_resolver()); cache_free(c); cr_assert_eq(free_fn_count, 1, "cache_free call the free_fn %d times", free_fn_count); } syslog-ng-syslog-ng-3.13.2/lib/tests/test_cfg_lexer_subst.c000066400000000000000000000266271321171025300237430ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-lexer-subst.h" #include "testutils.h" #include "apphook.h" #include #define SUBST_TESTCASE(x, ...) do { subst_testcase_begin(#x, #__VA_ARGS__); x(__VA_ARGS__); subst_testcase_end(); } while(0) #define subst_testcase_begin(func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ } \ while (0) #define subst_testcase_end() \ do \ { \ testcase_end(); \ } \ while (0) static CfgArgs * construct_cfg_args_for_args(const gchar *additional_values[]) { CfgArgs *args = cfg_args_new(); gint i; cfg_args_set(args, "arg", "arg_value"); cfg_args_set(args, "simple_string", "\"simple_string_value\""); cfg_args_set(args, "simple_qstring", "'simple_qstring_value'"); cfg_args_set(args, "escaped_string", "\"escaped_string\\\"\\r\\n\""); for (i = 0; additional_values && additional_values[i] && additional_values[i + 1]; i += 2) { cfg_args_set(args, additional_values[i], additional_values[i + 1]); } return args; } static CfgArgs * construct_cfg_args_for_defaults(void) { CfgArgs *args = cfg_args_new(); cfg_args_set(args, "arg", "default_for_arg"); cfg_args_set(args, "def", "default_for_def"); return args; } static CfgArgs * construct_cfg_args_for_globals(void) { CfgArgs *args = cfg_args_new(); cfg_args_set(args, "arg", "global_for_arg"); cfg_args_set(args, "def", "global_for_def"); cfg_args_set(args, "globl", "global_for_globl"); return args; } static CfgLexerSubst * construct_object_with_values(const gchar *additional_values[]) { return cfg_lexer_subst_new(construct_cfg_args_for_globals(), construct_cfg_args_for_defaults(), construct_cfg_args_for_args(additional_values)); } static CfgLexerSubst * construct_object(void) { return construct_object_with_values(NULL); } static gchar * duplicate_string_without_with_trailing_nonzero_bytes(const gchar *input) { gsize input_len = strlen(input); const gint canary_size = 10; gchar *input_dup = malloc(input_len + canary_size); memcpy(input_dup, input, input_len); memset(input_dup + input_len, 'A', canary_size - 1); input_dup[input_len + canary_size - 1] = 0; return input_dup; } static void _assert_invoke_result(CfgLexerSubst *subst, gchar *input_dup, gssize input_len, const gchar *expected_output) { gchar *result; gsize result_len; GError *error = NULL; result = cfg_lexer_subst_invoke(subst, input_dup, input_len, &result_len, &error); assert_true(error == NULL, "Error value is non-null while no error is expected"); assert_true(result != NULL, "value substitution returned an unexpected failure"); assert_string(result, expected_output, "value substitution is broken"); assert_guint64(result_len, strlen(expected_output), "length returned by invoke_result is invalid"); g_free(result); } static void assert_invoke_result_with_input_length_explicit(CfgLexerSubst *subst, const gchar *input, const gchar *expected_output) { gchar *input_dup; input_dup = duplicate_string_without_with_trailing_nonzero_bytes(input); _assert_invoke_result(subst, input_dup, strlen(input), expected_output); g_free(input_dup); } static void assert_invoke_result_with_zero_terminated_input(CfgLexerSubst *subst, const gchar *input, const gchar *expected_output) { gchar *input_dup; input_dup = strdup(input); _assert_invoke_result(subst, input_dup, -1, expected_output); g_free(input_dup); } static void assert_invoke_result(CfgLexerSubst *subst, const gchar *input, const gchar *expected_output) { assert_invoke_result_with_input_length_explicit(subst, input, expected_output); assert_invoke_result_with_zero_terminated_input(subst, input, expected_output); } static void assert_invoke_failure(CfgLexerSubst *subst, const gchar *input, const gchar *expected_error) { gchar *result; gsize result_len; gchar *input_dup = g_strdup(input); GError *error = NULL; result = cfg_lexer_subst_invoke(subst, input_dup, strlen(input), &result_len, &error); assert_true(result == NULL, "expected failure for value substitution, but success was returned"); assert_true(error != NULL, "expected a non-NULL error object for failure"); assert_string(error->message, expected_error, "error message mismatch"); g_free(input_dup); } static void test_double_backtick_replaced_with_a_single_one(void) { CfgLexerSubst *subst = construct_object(); assert_invoke_result(subst, "``", "`"); cfg_lexer_subst_free(subst); } static void test_single_backtick_causes_an_error(void) { CfgLexerSubst *subst = construct_object(); assert_invoke_failure(subst, "foo ` bar", "missing closing backtick (`) character"); cfg_lexer_subst_free(subst); } static void test_backtick_after_quoted_character_succeeds(void) { CfgLexerSubst *subst = construct_object(); assert_invoke_result(subst, "foo \"string \\n`arg`\" bar", "foo \"string \\narg_value\" bar"); cfg_lexer_subst_free(subst); } static void test_backtick_as_a_quoted_character_in_a_string_results_in_failure(void) { CfgLexerSubst *subst = construct_object(); assert_invoke_failure(subst, "foo \"string \\`arg`\" bar", "cannot subsitute backticked values right after a string quote character"); cfg_lexer_subst_free(subst); } static void test_value_in_normal_text_replaced_with_its_literal_value(void) { CfgLexerSubst *subst = construct_object(); assert_invoke_result(subst, "foo `arg` bar", "foo arg_value bar"); assert_invoke_result(subst, "foo `simple_string` bar", "foo \"simple_string_value\" bar"); assert_invoke_result(subst, "foo `simple_qstring` bar", "foo 'simple_qstring_value' bar"); assert_invoke_result(subst, "foo `escaped_string` bar", "foo \"escaped_string\\\"\\r\\n\" bar"); cfg_lexer_subst_free(subst); } static void test_values_are_resolution_order_args_defaults_globals_env(void) { CfgLexerSubst *subst = construct_object(); putenv("env=env_for_env"); assert_invoke_result(subst, "foo `arg` bar", "foo arg_value bar"); assert_invoke_result(subst, "foo `def` bar", "foo default_for_def bar"); assert_invoke_result(subst, "foo `globl` bar", "foo global_for_globl bar"); assert_invoke_result(subst, "foo `env` bar", "foo env_for_env bar"); cfg_lexer_subst_free(subst); } static void test_values_are_inserted_within_strings(void) { CfgLexerSubst *subst = construct_object(); assert_invoke_result(subst, "foo \"`arg`\" bar", "foo \"arg_value\" bar"); assert_invoke_result(subst, "foo '`arg`' bar", "foo 'arg_value' bar"); cfg_lexer_subst_free(subst); } static void test_string_literals_are_inserted_into_strings_without_quotes(void) { const gchar *additional_values[] = { "simple_string_with_whitespace", " \"string_with_whitespace\" ", NULL, NULL }; CfgLexerSubst *subst = construct_object_with_values(additional_values); /* double quotes */ assert_invoke_result(subst, "foo \"x `simple_string` y\" bar", "foo \"x simple_string_value y\" bar"); /* apostrophes */ assert_invoke_result(subst, "foo 'x `simple_string` y' bar", "foo 'x simple_string_value y' bar"); assert_invoke_result(subst, "foo \"x `simple_string_with_whitespace` y\" bar", "foo \"x string_with_whitespace y\" bar"); cfg_lexer_subst_free(subst); } static void test_incorrect_strings_and_multiple_tokens_are_inserted_verbatim(void) { const gchar *additional_values[] = { "half_string", "\"halfstring", "tokens_that_start_with_string", "\"str\", token", "tokens_enclosed_in_strings", "\"str1\", token, \"str2\"", NULL, NULL }; CfgLexerSubst *subst = construct_object_with_values(additional_values); assert_invoke_result(subst, "foo \"x `simple_string` y\" bar", "foo \"x simple_string_value y\" bar"); assert_invoke_result(subst, "foo \"x `half_string` y\" bar", "foo \"x \"halfstring y\" bar"); assert_invoke_result(subst, "foo \"x `tokens_that_start_with_string` y\" bar", "foo \"x \"str\", token y\" bar"); assert_invoke_result(subst, "foo \"x `tokens_enclosed_in_strings` y\" bar", "foo \"x \"str1\", token, \"str2\" y\" bar"); cfg_lexer_subst_free(subst); } static void test_strings_with_special_chars_are_properly_encoded_in_strings(void) { const gchar *additional_values[] = { "string_with_characters_that_need_quoting", "\"quote: \\\", newline: \\r\\n, backslash: \\\\\"", NULL, NULL }; CfgLexerSubst *subst = construct_object_with_values(additional_values); assert_invoke_result(subst, "foo \"x `string_with_characters_that_need_quoting` y\" bar", "foo \"x quote: \\\", newline: \\r\\n, backslash: \\\\ y\" bar"); cfg_lexer_subst_free(subst); } static void test_strings_with_embedded_apostrophe_cause_an_error_when_encoding_in_qstring(void) { const gchar *additional_values[] = { "string_with_apostrophe", "\"'foo'\"", NULL, NULL }; CfgLexerSubst *subst = construct_object_with_values(additional_values); assert_invoke_result(subst, "foo \"x `string_with_apostrophe` y\" bar", "foo \"x 'foo' y\" bar"); assert_invoke_failure(subst, "foo 'x `string_with_apostrophe` y' bar", "cannot represent apostrophes within apostroph-enclosed string"); cfg_lexer_subst_free(subst); } static void test_cfg_lexer_subst(void) { SUBST_TESTCASE(test_double_backtick_replaced_with_a_single_one); SUBST_TESTCASE(test_single_backtick_causes_an_error); SUBST_TESTCASE(test_backtick_after_quoted_character_succeeds); SUBST_TESTCASE(test_backtick_as_a_quoted_character_in_a_string_results_in_failure); SUBST_TESTCASE(test_value_in_normal_text_replaced_with_its_literal_value); SUBST_TESTCASE(test_values_are_resolution_order_args_defaults_globals_env); SUBST_TESTCASE(test_values_are_inserted_within_strings); SUBST_TESTCASE(test_string_literals_are_inserted_into_strings_without_quotes); SUBST_TESTCASE(test_incorrect_strings_and_multiple_tokens_are_inserted_verbatim); SUBST_TESTCASE(test_strings_with_special_chars_are_properly_encoded_in_strings); SUBST_TESTCASE(test_strings_with_embedded_apostrophe_cause_an_error_when_encoding_in_qstring); } int main(void) { app_startup(); test_cfg_lexer_subst(); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/tests/test_cfg_tree.c000066400000000000000000000133501321171025300223300ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-tree.h" #include "testutils.h" #include "apphook.h" #include "logpipe.h" /* * The Always Pipe. Always returns the same thing at init time. */ typedef struct { LogPipe super; gboolean return_value; gboolean init_called; gboolean deinit_called; } AlmightyAlwaysPipe; static gboolean almighty_always_pipe_init (LogPipe *s) { AlmightyAlwaysPipe *self = (AlmightyAlwaysPipe *)s; self->init_called = TRUE; return self->return_value; } static gboolean almighty_always_pipe_deinit (LogPipe *s) { AlmightyAlwaysPipe *self = (AlmightyAlwaysPipe *)s; self->deinit_called = TRUE; return TRUE; } static LogPipe * almighty_always_pipe_new (gboolean return_value) { AlmightyAlwaysPipe *self; self = g_new0 (AlmightyAlwaysPipe, 1); log_pipe_init_instance (&self->super, NULL); self->super.init = almighty_always_pipe_init; self->super.deinit = almighty_always_pipe_deinit; self->return_value = return_value; return &self->super; } /* * Helper functions */ static AlmightyAlwaysPipe * create_and_attach_almighty_pipe (CfgTree *tree, gboolean pipe_value) { AlmightyAlwaysPipe *pipe; pipe = (AlmightyAlwaysPipe *)almighty_always_pipe_new (pipe_value); cfg_tree_add_object (tree, log_expr_node_new_pipe (&pipe->super, NULL)); return pipe; } static void assert_almighty_always_pipe (gboolean always_pipe_value, gboolean tree_start_expected, gboolean tree_stop_expected, gboolean was_init_called, gboolean was_deinit_called) { CfgTree tree; AlmightyAlwaysPipe *pipe; cfg_tree_init_instance (&tree, NULL); pipe = create_and_attach_almighty_pipe (&tree, always_pipe_value); assert_gboolean (cfg_tree_start (&tree), tree_start_expected, "cfg_tree_start() did not return the expected value"); assert_gboolean (cfg_tree_stop (&tree), tree_stop_expected, "cfg_tree_stop() did not return the epxected value"); assert_gboolean (pipe->init_called, was_init_called, "->init was called state"); assert_gboolean (pipe->deinit_called, was_deinit_called, "->deinit was called state"); cfg_tree_free_instance (&tree); } /* * Test cases */ static void test_pipe_init_success (void) { testcase_begin ("A pipe that always succeeds, results in a startable tree"); assert_almighty_always_pipe (TRUE, TRUE, TRUE, TRUE, TRUE); testcase_end (); } static void test_pipe_init_fail (void) { testcase_begin ("A pipe that always fails, results in an unstartable tree"); assert_almighty_always_pipe (FALSE, FALSE, TRUE, TRUE, FALSE); testcase_end (); } static void test_pipe_init_multi_success (void) { CfgTree tree; testcase_begin ("A pipe of all good nodes will start & stop properly"); cfg_tree_init_instance (&tree, NULL); create_and_attach_almighty_pipe (&tree, TRUE); create_and_attach_almighty_pipe (&tree, TRUE); create_and_attach_almighty_pipe (&tree, TRUE); assert_true (cfg_tree_start (&tree), "Starting a tree of all-good nodes works"); assert_true (cfg_tree_stop (&tree), "Stopping a tree of all-good nodes works"); cfg_tree_free_instance (&tree); testcase_end (); } static void test_pipe_init_multi_with_bad_node (void) { AlmightyAlwaysPipe *pipe1, *pipe2, *pipe3; CfgTree tree; testcase_begin ("A pipe of some bad nodes will not start, but cleans up nicely."); cfg_tree_init_instance (&tree, NULL); pipe1 = create_and_attach_almighty_pipe (&tree, TRUE); pipe2 = create_and_attach_almighty_pipe (&tree, FALSE); pipe3 = create_and_attach_almighty_pipe (&tree, TRUE); assert_false (cfg_tree_start (&tree), "Starting a tree of all-good nodes works"); assert_true (cfg_tree_stop (&tree), "Stopping a tree of all-good nodes works"); assert_true (pipe1->init_called, "The initializer of the first good pipe is called"); assert_true (pipe2->init_called, "The initializer of the bad pipe is called"); assert_false (pipe3->init_called, "The initializer of the second good pipe is NOT called"); assert_true (pipe1->deinit_called, "The deinitializer of the first good pipe is called"); assert_false (pipe2->deinit_called, "The deinitializer of the bad pipe is NOT called"); assert_false (pipe3->deinit_called, "The deinitializer of the second good pipe is NOT called"); cfg_tree_free_instance (&tree); testcase_end (); } /* * The main program. */ int main (void) { app_startup (); test_pipe_init_success (); test_pipe_init_fail (); test_pipe_init_multi_success (); test_pipe_init_multi_with_bad_node (); app_shutdown (); return 0; } syslog-ng-syslog-ng-3.13.2/lib/tests/test_host_resolve.c000066400000000000000000000245601321171025300232730ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ /* NOTE: this is not run automatically in make check as it relies on DNS, * you have to invoke it manually if your workstation has internet * connectivity. */ #include "host-resolve.h" #include "testutils.h" #include "apphook.h" #include "dnscache.h" #include "gsocket.h" #include "hostname.h" #include "cfg.h" #include #define HOST_RESOLVE_TESTCASE(x, ...) do { host_resolve_testcase_begin(domain_override, #x, #__VA_ARGS__); x(__VA_ARGS__); host_resolve_testcase_end(); } while(0) #define host_resolve_testcase_begin(domain_override, func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ dns_caching_thread_init(); \ host_resolve_options_defaults(&host_resolve_options); \ host_resolve_options_init(&host_resolve_options, &configuration->host_resolve_options); \ hostname_reinit(NULL); \ } \ while (0) #define host_resolve_testcase_end() \ do \ { \ host_resolve_options_destroy(&host_resolve_options); \ dns_caching_thread_deinit(); \ testcase_end(); \ } \ while (0) static HostResolveOptions host_resolve_options; static void assert_sockaddr_to_hostname(GSockAddr *sa, const gchar *expected) { const gchar *result; gsize result_len = 9999; result = resolve_sockaddr_to_hostname(&result_len, sa, &host_resolve_options); g_sockaddr_unref(sa); assert_string(result, expected, "resolved name mismatch"); assert_gint(result_len, strlen(result), "returned length is not true"); } static void assert_ip_to_short_hostname(const gchar *ip, const gchar *expected) { host_resolve_options.use_fqdn = FALSE; assert_sockaddr_to_hostname(g_sockaddr_inet_new(ip, 0), expected); } static void assert_ip_to_fqdn_hostname(const gchar *ip, const gchar *expected) { host_resolve_options.use_fqdn = TRUE; assert_sockaddr_to_hostname(g_sockaddr_inet_new(ip, 0), expected); } #if SYSLOG_NG_ENABLE_IPV6 static void assert_ip6_to_short_hostname(const gchar *ip, const gchar *expected) { host_resolve_options.use_fqdn = FALSE; assert_sockaddr_to_hostname(g_sockaddr_inet6_new(ip, 0), expected); } static void assert_ip6_to_fqdn_hostname(const gchar *ip, const gchar *expected) { host_resolve_options.use_fqdn = TRUE; assert_sockaddr_to_hostname(g_sockaddr_inet6_new(ip, 0), expected); } #else static void assert_ip6_to_short_hostname(const gchar *ip, const gchar *expected) { } static void assert_ip6_to_fqdn_hostname(const gchar *ip, const gchar *expected) { } #endif static void assert_hostname_to_sockaddr(gint family, const gchar *hostname, const gchar *expected_ip) { GSockAddr *sa = NULL; gchar ip[64]; gboolean result; result = resolve_hostname_to_sockaddr(&sa, family, hostname); if (sa) { g_sockaddr_format(sa, ip, sizeof(ip), GSA_ADDRESS_ONLY); g_sockaddr_unref(sa); } assert_true(result, "unexpected error return"); assert_true(sa != NULL, "sockaddr can't be NULL for successful returns"); assert_string(ip, expected_ip, "resolved address mismatch"); } static void assert_hostname_to_sockaddr_fails(gint family, const gchar *hostname) { GSockAddr *sa = NULL; gboolean result; result = resolve_hostname_to_sockaddr(&sa, family, hostname); g_sockaddr_unref(sa); assert_null(sa, "returned sockaddr is non-NULL"); assert_false(result, "unexpected success returned"); } static void assert_hostname_to_hostname_len(gsize buflen, const gchar *hostname, const gchar *expected) { const gchar *result; gsize result_len = 9999; result = resolve_hostname_to_hostname(&result_len, hostname, &host_resolve_options); assert_string(result, expected, "hostname to hostname result mismatch"); assert_gint(result_len, strlen(result), "returned length is not true"); } static void assert_hostname_to_hostname(const gchar *hostname, const gchar *expected) { assert_hostname_to_hostname_len(256, hostname, expected); } #define for_all_resolve_cases() \ for (host_resolve_options.use_dns_cache = 0; host_resolve_options.use_dns_cache < 2; host_resolve_options.use_dns_cache++) \ for (host_resolve_options.normalize_hostnames = 0; host_resolve_options.normalize_hostnames < 2; host_resolve_options.normalize_hostnames++) static void test_resolvable_ip_results_in_hostname(void) { host_resolve_options.use_dns = TRUE; for_all_resolve_cases() { /* a.root-servers.net, will probably not go away as its IP is registered to bind hints file */ assert_ip_to_short_hostname("198.41.0.4", "a"); assert_ip_to_fqdn_hostname("198.41.0.4", "a.root-servers.net"); assert_ip6_to_short_hostname("2001:503:ba3e::2:30", "a"); assert_ip6_to_fqdn_hostname("2001:503:ba3e::2:30", "a.root-servers.net"); } } static void test_unresolvable_ip_results_in_ip(void) { fprintf(stderr, "The testcase %s takes a lot of time, it is advisable to turn it\n" "off for short iterations and reenable it at the end of the session.\n" "The easiest way to disable it is to comment out its invocation that\n" "looks like HOST_RESOLVE_TESTCASE(test_unresolvable_ip_results_in_ip);\n" "But please, please, please don't commit the disabling of that testcase.\n", __FUNCTION__); host_resolve_options.use_dns = TRUE; for_all_resolve_cases() { /* 198.41.0.251 is on the same network as a.root-servers.net, but is * not resolvable as of now. It is a good candidate for the negative tests * as it responds quite fast. * * NOTE: this might become resolve once in the future, in that case * this testcase will fail. Search for an IP address that has a * responding DNS server but has no A record. */ assert_ip_to_short_hostname("198.41.0.251", "198.41.0.251"); assert_ip_to_fqdn_hostname("198.41.0.251", "198.41.0.251"); assert_ip6_to_short_hostname("2001:503:ba3e::2:31", "2001:503:ba3e::2:31"); assert_ip6_to_fqdn_hostname("2001:503:ba3e::2:31", "2001:503:ba3e::2:31"); } } static void test_sockaddr_without_dns_resolution_results_in_ip(void) { host_resolve_options.use_dns = FALSE; for_all_resolve_cases() { /* a.root-servers.net, will probably not go away as its IP is registered to bind hints file */ assert_ip_to_short_hostname("198.41.0.4", "198.41.0.4"); assert_ip_to_fqdn_hostname("198.41.0.4", "198.41.0.4"); assert_ip6_to_short_hostname("2001:503:ba3e::2:30", "2001:503:ba3e::2:30"); assert_ip6_to_fqdn_hostname("2001:503:ba3e::2:30", "2001:503:ba3e::2:30"); } } static void test_unix_domain_sockaddr_results_in_the_local_hostname(void) { const gchar *local_host; host_resolve_options.use_fqdn = TRUE; local_host = get_local_hostname_fqdn(); assert_sockaddr_to_hostname(g_sockaddr_unix_new(NULL), local_host); assert_sockaddr_to_hostname(NULL, local_host); } static void test_resolve_sockaddr_to_hostname(void) { HOST_RESOLVE_TESTCASE(test_resolvable_ip_results_in_hostname); HOST_RESOLVE_TESTCASE(test_unresolvable_ip_results_in_ip); HOST_RESOLVE_TESTCASE(test_sockaddr_without_dns_resolution_results_in_ip); HOST_RESOLVE_TESTCASE(test_unix_domain_sockaddr_results_in_the_local_hostname); } static void test_resolvable_hostname_results_in_sockaddr(void) { assert_hostname_to_sockaddr(AF_INET, "a.root-servers.net", "198.41.0.4"); assert_hostname_to_sockaddr(AF_INET, "", "0.0.0.0"); #if SYSLOG_NG_ENABLE_IPV6 assert_hostname_to_sockaddr(AF_INET6, "a.root-servers.net", "2001:503:ba3e::2:30"); assert_hostname_to_sockaddr(AF_INET6, "", "::"); #endif } static void test_unresolvable_hostname_results_in_error(void) { assert_hostname_to_sockaddr_fails(AF_INET, "foo.bar.baz"); } static void test_resolve_hostname_to_sockaddr(void) { HOST_RESOLVE_TESTCASE(test_resolvable_hostname_results_in_sockaddr); HOST_RESOLVE_TESTCASE(test_unresolvable_hostname_results_in_error); } static void test_short_hostname_is_converted_to_fqdn_if_use_fqdn_is_set(void) { host_resolve_options.use_fqdn = TRUE; /* force the use of custom domain to make asserts easier. the * non-custom-domain case is tested by test-hostname.c */ hostname_reinit("bardomain"); assert_hostname_to_hostname("foo", "foo.bardomain"); } static void test_fqdn_hostname_is_converted_to_short_if_use_fqdn_is_unset(void) { host_resolve_options.use_fqdn = FALSE; assert_hostname_to_hostname("foo.bardomain", "foo"); } static void test_hostname_is_normalized_if_normalize_hostnames_is_set(void) { host_resolve_options.use_fqdn = TRUE; host_resolve_options.normalize_hostnames = TRUE; assert_hostname_to_hostname("Foo.BarDomain", "foo.bardomain"); } static void test_resolve_hostname_to_hostname(void) { HOST_RESOLVE_TESTCASE(test_short_hostname_is_converted_to_fqdn_if_use_fqdn_is_set); HOST_RESOLVE_TESTCASE(test_fqdn_hostname_is_converted_to_short_if_use_fqdn_is_unset); HOST_RESOLVE_TESTCASE(test_hostname_is_normalized_if_normalize_hostnames_is_set); } int main(int argc, char *argv[]) { app_startup(); configuration = cfg_new_snippet(); test_resolve_hostname_to_hostname(); test_resolve_hostname_to_sockaddr(); test_resolve_sockaddr_to_hostname(); cfg_free(configuration); return 0; } syslog-ng-syslog-ng-3.13.2/lib/tests/test_hostname.c000066400000000000000000000177431321171025300224020ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "hostname.h" #include "testutils.h" #include "apphook.h" #include #include /* * NOTE: on WRAP_GETHOSTNAME below * * If WRAP_GETHOSTNAME is 1, this test will mock the gethostname() call in * order to run on all systems. When gethostname() is mocked, it will * always return an FQDN as a hostname. This in turn means, that the use of * DNS in detecting the FQDN is completely avoided. * * This means, that if WRAP_GETHOSTNAME is set to 1, it will run on all * systems, but some of the production code will not be tested. If it is * set to 0, it'll only run on a host whose name is "bzorp.balabit", which * happens to be my notebook. * * I was thinking of mocking the DNS calls too, but that gets more and more * difficult, so I was left with this macro that I can change whenever I'm * working on the DNS related parts of the hostname.c file. */ #define WRAP_GETHOSTNAME 1 #ifdef WRAP_GETHOSTNAME static int (*__wrap_gethostname)(char *buf, size_t buflen); #define gethostname __wrap_gethostname #include "hostname.c" #undef gethostname static int __fqdn_gethostname(char *buf, size_t buflen) { strncpy(buf, "bzorp.balabit", buflen); return 0; } #else #include "hostname.c" #endif static void assert_hostname_fqdn(const gchar *expected) { const gchar *host; host = get_local_hostname_fqdn(); assert_string(host, expected, "hostname values mismatch"); } static void assert_hostname_short(const gchar *expected) { const gchar *host; host = get_local_hostname_short(); assert_string(host, expected, "hostname values mismatch"); } static void assert_fqdn_conversion(gchar *hostname, const gchar *expected) { gchar buf[256]; g_strlcpy(buf, hostname, sizeof(buf)); convert_hostname_to_fqdn(buf, sizeof(buf)); assert_string(buf, expected, "hostname values mismatch"); } static void assert_short_conversion(gchar *hostname, const gchar *expected) { gchar buf[256]; g_strlcpy(buf, hostname, sizeof(buf)); convert_hostname_to_short_hostname(buf, sizeof(buf)); assert_string(buf, expected, "hostname values mismatch"); } #define HOSTNAME_TESTCASE_WITH_DOMAIN(domain_override, x, ...) do { hostname_testcase_begin(domain_override, #x, #__VA_ARGS__); x(__VA_ARGS__); hostname_testcase_end(); } while(0) #define HOSTNAME_TESTCASE(x, ...) HOSTNAME_TESTCASE_WITH_DOMAIN(NULL, x, __VA_ARGS__) #ifdef WRAP_GETHOSTNAME #define wrap_gethostname() (__wrap_gethostname = __fqdn_gethostname) #else #define wrap_gethostname() #endif #define hostname_testcase_begin(domain_override, func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ wrap_gethostname(); \ hostname_reinit(domain_override); \ } \ while (0) #define hostname_testcase_end() \ do \ { \ testcase_end(); \ } \ while (0) static void test_without_domain_override_the_domain_in_the_hostname_is_used(void) { assert_fqdn_conversion("foo.bar", "foo.bar"); } static void test_without_domain_override_the_local_domain_is_used_when_converting_a_short_hostname_to_fqdn(void) { assert_fqdn_conversion("foo", "foo.balabit"); } static void test_without_domain_override_short_conversion_removes_any_domain_name(void) { assert_short_conversion("foo", "foo"); assert_short_conversion("foo.bar", "foo"); assert_short_conversion("foo.bardomain", "foo"); } static void test_domain_override_short_conversion_removes_any_domain_name(void) { assert_short_conversion("foo", "foo"); assert_short_conversion("foo.bar", "foo"); assert_short_conversion("foo.bardomain", "foo"); } static void test_system_host_and_domain_name_are_detected_properly(void) { assert_hostname_fqdn("bzorp.balabit"); assert_hostname_short("bzorp"); assert_fqdn_conversion("bzorp", "bzorp.balabit"); assert_fqdn_conversion("bzorp.balabit", "bzorp.balabit"); } static void test_domain_override_replaces_domain_detected_on_the_system(void) { assert_hostname_fqdn("bzorp.bardomain"); assert_hostname_short("bzorp"); assert_fqdn_conversion("bzorp", "bzorp.bardomain"); assert_fqdn_conversion("bzorp.balabit", "bzorp.bardomain"); assert_fqdn_conversion("foo", "foo.bardomain"); assert_fqdn_conversion("foo.bar", "foo.bardomain"); } /* this is hostname-unix specific and will probably be made conditional once the win32 bits are in */ /* NOTE: we are testing a private function */ static const gchar * _invoke_extract_fqdn_from_hostent(gchar *primary_host, gchar **aliases) { struct hostent hostent; memset(&hostent, 0, sizeof(hostent)); hostent.h_name = primary_host; hostent.h_aliases = aliases; return _extract_fqdn_from_hostent(&hostent); } static void assert_extract_fqdn_from_hostent(gchar *primary_host, gchar **aliases, const gchar *expected) { assert_string(_invoke_extract_fqdn_from_hostent(primary_host, aliases), expected, "_extract_fqdn didn't return the requested hostname"); } static void assert_extract_fqdn_from_hostent_fails(gchar *primary_host, gchar **aliases) { assert_null(_invoke_extract_fqdn_from_hostent(primary_host, aliases), "_extract_fqdn returned non-NULL when we expected failure"); } static void test_extract_fqdn_from_hostent_uses_primary_name_if_it_is_an_fqdn(void) { gchar *aliases[] = { "bzorp", "bzorp.lan", NULL }; assert_extract_fqdn_from_hostent("bzorp.balabit", aliases, "bzorp.balabit"); } static void test_extract_fqdn_from_hostent_finds_the_first_fqdn_in_aliases_if_primary_is_short(void) { gchar *aliases[] = { "bzorp", "bzorp.lan", NULL }; assert_extract_fqdn_from_hostent("bzorp", aliases, "bzorp.lan"); } static void test_extract_fqdn_from_hostent_returns_NULL_when_no_fqdn_is_found(void) { gchar *aliases[] = { "bzorp", "foobar", NULL }; assert_extract_fqdn_from_hostent_fails("bzorp", aliases); } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { HOSTNAME_TESTCASE(test_without_domain_override_the_domain_in_the_hostname_is_used); HOSTNAME_TESTCASE(test_without_domain_override_the_local_domain_is_used_when_converting_a_short_hostname_to_fqdn); HOSTNAME_TESTCASE(test_without_domain_override_short_conversion_removes_any_domain_name); HOSTNAME_TESTCASE_WITH_DOMAIN("bardomain", test_domain_override_short_conversion_removes_any_domain_name); HOSTNAME_TESTCASE(test_system_host_and_domain_name_are_detected_properly); HOSTNAME_TESTCASE_WITH_DOMAIN("bardomain", test_domain_override_replaces_domain_detected_on_the_system); HOSTNAME_TESTCASE(test_extract_fqdn_from_hostent_uses_primary_name_if_it_is_an_fqdn); HOSTNAME_TESTCASE(test_extract_fqdn_from_hostent_finds_the_first_fqdn_in_aliases_if_primary_is_short); HOSTNAME_TESTCASE(test_extract_fqdn_from_hostent_returns_NULL_when_no_fqdn_is_found); return 0; } syslog-ng-syslog-ng-3.13.2/lib/tests/test_lexer.c000066400000000000000000000215211321171025300216700ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "cfg-lexer.h" #include "cfg-grammar.h" typedef struct { YYSTYPE *yylval; YYLTYPE *yylloc; CfgLexer *lexer; } TestParser; static void test_parser_clear_token(TestParser *self) { if (self->yylval->type) cfg_lexer_free_token(self->yylval); self->yylval->type = 0; } static void test_parser_next_token(TestParser *self) { test_parser_clear_token(self); cfg_lexer_lex(self->lexer, self->yylval, self->yylloc); } static void test_parser_input(TestParser *self, const gchar *buffer) { if (self->lexer) cfg_lexer_free(self->lexer); self->lexer = cfg_lexer_new_buffer(configuration, buffer, strlen(buffer)); } TestParser * test_parser_new(void) { TestParser *self = g_new0(TestParser, 1); self->yylval = g_new0(YYSTYPE, 1); self->yylloc = g_new0(YYLTYPE, 1); self->yylval->type = LL_CONTEXT_ROOT; self->yylloc->first_column = 1; self->yylloc->first_line = 1; self->yylloc->last_column = 1; self->yylloc->last_line = 1; self->yylloc->level = &self->lexer->include_stack[0]; return self; } void test_parser_free(TestParser *self) { test_parser_clear_token(self); if (self->lexer) cfg_lexer_free(self->lexer); g_free(self->yylval); g_free(self->yylloc); g_free(self); } #define LEXER_TESTCASE(x, ...) do { lexer_testcase_begin(#x, #__VA_ARGS__); x(__VA_ARGS__); lexer_testcase_end(); } while(0) TestParser *parser = NULL; #define lexer_testcase_begin(func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ parser = test_parser_new(); \ } \ while (0) #define lexer_testcase_end() \ do \ { \ test_parser_free(parser); \ testcase_end(); \ } \ while (0) static void _input(const gchar *input) { test_parser_input(parser, input); } static void _next_token(void) { test_parser_next_token(parser); } static YYSTYPE * _current_token(void) { return parser->yylval; } static YYLTYPE * _current_lloc(void) { return parser->yylloc; } #define assert_token_type(expected) \ assert_gint(_current_token()->type, expected, "Bad token type at %s:%d", __FUNCTION__, __LINE__); #define assert_parser_string(expected) \ _next_token(); \ assert_token_type(LL_STRING); \ assert_string(_current_token()->cptr, expected, "Bad parsed string at %s:%d", __FUNCTION__, __LINE__); \ #define assert_parser_block(expected) \ _next_token(); \ assert_token_type(LL_BLOCK); \ assert_string(_current_token()->cptr, expected, "Bad parsed string at %s:%d", __FUNCTION__, __LINE__); #define assert_parser_block_bad(parser) \ _next_token(); \ assert_token_type(LL_ERROR); #define assert_parser_pragma(parser) \ _next_token(); \ assert_token_type(LL_PRAGMA); #define assert_parser_number(expected) \ _next_token(); \ assert_token_type(LL_NUMBER); \ assert_gint(_current_token()->num, expected, "Bad parsed value at %s:%d", __FUNCTION__, __LINE__); #define assert_parser_float(expected) \ _next_token(); \ assert_token_type(LL_FLOAT); \ assert_true(_current_token()->fnum == expected, "Bad parsed value at %s:%d", __FUNCTION__, __LINE__); #define assert_parser_identifier(expected) \ _next_token(); \ assert_token_type(LL_IDENTIFIER); \ assert_string(_current_token()->cptr, expected, "Bad parsed value at %s:%d", __FUNCTION__, __LINE__); #define assert_parser_char(expected) \ _next_token(); \ assert_gint(_current_token()->type, expected, "Bad character value at %s:%d", __FUNCTION__, __LINE__); #define assert_location(line, column) \ assert_gint(_current_lloc()->first_line, line, \ "The line number in the location information " \ "does not match the expected value at %s:%d", __FUNCTION__, __LINE__); \ assert_gint(_current_lloc()->first_column, column, \ "The column number in the location information " \ "does not match the expected value at %s:%d", __FUNCTION__, __LINE__); static gchar * _format_location_tag_message(void) { EVTCONTEXT *ctx; EVTREC *rec; char *msg; ctx = evt_ctx_init("test", EVT_FAC_USER); rec = evt_rec_init(ctx, EVT_PRI_WARNING, "test"); evt_rec_add_tag(rec, cfg_lexer_format_location_tag(parser->lexer, _current_lloc())); msg = evt_format(rec); evt_rec_free(rec); evt_ctx_free(ctx); return msg; } #define assert_location_tag(expected) \ ({ \ char *msg = _format_location_tag_message(); \ const gchar *tag_repr; \ tag_repr = strstr(msg, "; "); \ assert_string(tag_repr ? tag_repr + 2 : NULL, expected, "Formatted location tag does not match"); \ free(msg); \ \ }) static void test_lexer_string(void) { _input("\"test\""); assert_parser_string("test"); _input("\"test\\x0a\""); assert_parser_string("test\n"); _input("\"test\\o011\""); assert_parser_string("test\t"); _input("\"test\\n\\r\\a\\t\\v\\c\""); assert_parser_string("test\n\r\a\t\vc"); } static void test_lexer_qstring(void) { _input("'test'"); assert_parser_string("test"); _input("'\"test\\n\\r\"'"); assert_parser_string("\"test\\n\\r\""); } #define TEST_BLOCK " {'hello world' \"test value\" {other_block} other\text}" #define TEST_BAD_BLOCK "this is a bad block starting " TEST_BLOCK static void test_lexer_block(void) { _input(TEST_BLOCK); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block("'hello world' \"test value\" {other_block} other\text"); _input(TEST_BAD_BLOCK); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block_bad(parser); } static void test_lexer_others(void) { _input("#This is a full line comment\nfoobar"); assert_parser_identifier("foobar"); _input("@version"); assert_parser_pragma(parser); assert_parser_identifier("version"); _input("():;{}|"); assert_parser_char('('); assert_parser_char(')'); assert_parser_char(':'); assert_parser_char(';'); assert_parser_char('{'); assert_parser_char('}'); assert_parser_char('|'); _input("4.2 12 0x50 011 +12 -12 -4.2 +4.2"); assert_parser_float(4.2); assert_parser_number(12); assert_parser_number(80 /*0x50*/); assert_parser_number(9 /*011 */); assert_parser_number(12); assert_parser_number(-12); assert_parser_float(-4.2); assert_parser_float(4.2); _input("test_value"); assert_parser_identifier("test_value"); } static void test_location_tracking(void) { _input("test another\nfoo\nbar\n"); _next_token(); assert_location(1, 1); _next_token(); assert_location(1, 6); _next_token(); assert_location(2, 1); _next_token(); assert_location(3, 1); assert_location_tag("location='#buffer:3:1'"); } int main(int argc, char **argv) { LEXER_TESTCASE(test_lexer_string); LEXER_TESTCASE(test_lexer_qstring); LEXER_TESTCASE(test_lexer_block); LEXER_TESTCASE(test_lexer_others); LEXER_TESTCASE(test_location_tracking); return 0; } syslog-ng-syslog-ng-3.13.2/lib/tests/test_parse_number.c000066400000000000000000000103621321171025300232340ustar00rootroot00000000000000/* * Copyright (c) 2013-2014 Balabit * Copyright (c) 2013 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include "testutils.h" #include "parse-number.h" static void assert_parse_with_suffix(const gchar *str, gint64 expected) { gint64 n; gboolean res; res = parse_number_with_suffix(str, &n); assert_gboolean(res, TRUE, "Parsing (w/ suffix) %s failed", str); assert_gint64(n, expected, "Parsing (w/ suffix) %s failed", str); } static void assert_parse_with_suffix_fails(const gchar *str) { gint64 n; gboolean res; res = parse_number_with_suffix(str, &n); assert_gboolean(res, FALSE, "Parsing (w/ suffix) %s succeeded, while expecting failure", str); } static void assert_parse(const gchar *str, gint64 expected) { gint64 n; gboolean res; res = parse_number(str, &n); assert_gboolean(res, TRUE, "Parsing (w/o suffix) %s failed", str); assert_gint64(n, expected, "Parsing (w/o suffix) %s failed", str); } static void assert_parse_fails(const gchar *str) { gint64 n; gboolean res; res = parse_number(str, &n); assert_gboolean(res, FALSE, "Parsing (w/o suffix) %s succeeded, while expecting failure", str); } static void test_simple_numbers_are_parsed_properly(void) { assert_parse_with_suffix("1234", 1234); assert_parse_with_suffix("+1234", 1234); assert_parse_with_suffix("-1234", -1234); assert_parse("1234", 1234); } static void test_c_like_prefixes_select_base(void) { assert_parse("0x20", 32); assert_parse("020", 16); assert_parse("20", 20); assert_parse_with_suffix("0x20kiB", 32 * 1024); } static void test_exponent_suffix_is_parsed_properly(void) { assert_parse_with_suffix("1K", 1000); assert_parse_with_suffix("1k", 1000); assert_parse_with_suffix("1m", 1000 * 1000); assert_parse_with_suffix("1M", 1000 * 1000); assert_parse_with_suffix("1G", 1000 * 1000 * 1000); assert_parse_with_suffix("1g", 1000 * 1000 * 1000); } static void test_byte_units_are_accepted(void) { assert_parse_with_suffix("1b", 1); assert_parse_with_suffix("1B", 1); assert_parse_with_suffix("1Kb", 1000); assert_parse_with_suffix("1kB", 1000); assert_parse_with_suffix("1mb", 1000 * 1000); assert_parse_with_suffix("1MB", 1000 * 1000); assert_parse_with_suffix("1Gb", 1000 * 1000 * 1000); assert_parse_with_suffix("1gB", 1000 * 1000 * 1000); } static void test_base2_is_selected_by_an_i_modifier(void) { assert_parse_with_suffix("1Kib", 1024); assert_parse_with_suffix("1kiB", 1024); assert_parse_with_suffix("1Ki", 1024); assert_parse_with_suffix("1kI", 1024); assert_parse_with_suffix("1mib", 1024 * 1024); assert_parse_with_suffix("1MiB", 1024 * 1024); assert_parse_with_suffix("1Gib", 1024 * 1024 * 1024); assert_parse_with_suffix("1giB", 1024 * 1024 * 1024); assert_parse_with_suffix("1024giB", 1024LL * 1024LL * 1024LL * 1024LL); } static void test_invalid_formats_are_not_accepted(void) { assert_parse_with_suffix_fails("1234Z"); assert_parse_with_suffix_fails("1234kZ"); assert_parse_with_suffix_fails("1234kdZ"); assert_parse_with_suffix_fails("1234kiZ"); assert_parse_fails("1234kiZ"); } int main(int argc, char *argv[]) { test_simple_numbers_are_parsed_properly(); test_exponent_suffix_is_parsed_properly(); test_byte_units_are_accepted(); test_base2_is_selected_by_an_i_modifier(); test_invalid_formats_are_not_accepted(); test_c_like_prefixes_select_base(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/tests/test_pathutils.c000066400000000000000000000032151321171025300225660ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "pathutils.h" #include #include #include #include "libtest/testutils.h" #include void test_is_directory_return_false_in_case_of_regular_file(void) { int fd = open("test.file", O_CREAT | O_RDWR, 0644); assert_false(fd < 0, "open error"); ssize_t done = write(fd, "a", 1); assert_false(done != 1, "write error"); int error = close(fd); assert_false(error, "close error"); assert_false(is_file_directory("test.file"), "File is not a directory!"); error = unlink("test.file"); assert_false(error, "unlink error"); } int main(void) { test_is_directory_return_false_in_case_of_regular_file(); } syslog-ng-syslog-ng-3.13.2/lib/tests/test_rcptid.c000066400000000000000000000066741321171025300220520ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 2013 Viktor Juhasz * Copyright (c) 2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "syslog-ng.h" #include "apphook.h" #include "rcptid.h" #include "libtest/persist_lib.h" #include gboolean verbose = FALSE; PersistState *state; void setup_persist_id_test(void) { state = clean_and_create_persist_state_for_test("test_values.persist"); rcptid_init(state, TRUE); } void teardown_persist_id_test(void) { commit_and_destroy_persist_state(state); rcptid_deinit(); } static void test_rcptid_is_persistent_across_persist_backend_reinits(void) { guint64 rcptid; setup_persist_id_test(); rcptid_set_id(0xFFFFFFFFFFFFFFFE); rcptid = rcptid_generate_id(); assert_guint64(rcptid, 0xFFFFFFFFFFFFFFFE, "Rcptid initialization to specific value failed!"); state = restart_persist_state(state); rcptid_deinit(); rcptid_init(state, TRUE); rcptid = rcptid_generate_id(); assert_guint64(rcptid, 0xFFFFFFFFFFFFFFFF, "Rcptid did not persisted across persist backend reinit!"); teardown_persist_id_test(); } static void test_rcptid_overflows_at_64bits_and_is_reset_to_one(void) { guint64 rcptid; setup_persist_id_test(); rcptid_set_id(0xFFFFFFFFFFFFFFFF); rcptid = rcptid_generate_id(); rcptid = rcptid_generate_id(); assert_guint64(rcptid, (guint64) 1, "Rcptid counter overflow handling did not work!"); teardown_persist_id_test(); } static void test_rcptid_is_formatted_as_a_number_when_nonzero(void) { GString *formatted_rcptid = g_string_sized_new(0); setup_persist_id_test(); rcptid_append_formatted_id(formatted_rcptid, 1); assert_string(formatted_rcptid->str, "1", "RCPTID macro formatting for non-zero number failed!"); teardown_persist_id_test(); g_string_free(formatted_rcptid, TRUE); } static void test_rcptid_is_an_empty_string_when_zero(void) { GString *formatted_rcptid = g_string_sized_new(0); setup_persist_id_test(); rcptid_append_formatted_id(formatted_rcptid, 0); assert_string(formatted_rcptid->str, "", "RCPTID macro formatting for zero value failed!"); teardown_persist_id_test(); g_string_free(formatted_rcptid, TRUE); } static void rcptid_test_case(void) { test_rcptid_is_persistent_across_persist_backend_reinits(); test_rcptid_overflows_at_64bits_and_is_reset_to_one(); test_rcptid_is_formatted_as_a_number_when_nonzero(); test_rcptid_is_an_empty_string_when_zero(); } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { if (argc > 1) verbose = TRUE; app_startup(); rcptid_test_case(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/tests/test_reloc.c000066400000000000000000000046621321171025300216640ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "reloc.h" CacheResolver *path_resolver; Cache *path_cache; static void assert_install_path(const gchar *template, const gchar *expected) { const gchar *expanded_path; expanded_path = cache_lookup(path_cache, template); assert_string(expanded_path, expected, "Expanded install path doesn't match expected value"); } static void test_absolute_dirs_remain_unchanged(void) { assert_install_path("/opt/syslog-ng", "/opt/syslog-ng"); } static void test_configure_variables_are_resolved(void) { assert_install_path("${prefix}/bin", "/test/bin"); } static void test_configure_variables_are_resolved_recursively(void) { path_resolver_add_configure_variable(path_resolver, "${foo}", "/foo"); path_resolver_add_configure_variable(path_resolver, "${bar}", "${foo}"); assert_install_path("${foo}/bin", "/foo/bin"); assert_install_path("${bar}/bin", "/foo/bin"); } static void test_confiure_variables_are_resolved_in_the_middle(void) { assert_install_path("/foo/${prefix}/bar", "/foo//test/bar"); } static void init_path_cache(void) { path_resolver = path_resolver_new("/test"); path_cache = cache_new(path_resolver); } static void free_path_cache(void) { cache_free(path_cache); } int main(int argc, char *argv[]) { init_path_cache(); test_absolute_dirs_remain_unchanged(); test_configure_variables_are_resolved(); test_configure_variables_are_resolved_recursively(); test_confiure_variables_are_resolved_in_the_middle(); free_path_cache(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/tests/test_runid.c000066400000000000000000000076771321171025300217120ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 2013 Viktor Juhasz * Copyright (c) 2013 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "libtest/testutils.h" #include "libtest/persist_lib.h" #include "lib/run-id.h" #include "lib/apphook.h" #include #define RUN_ID_FIRST 1 PersistState * create_persist_state(void) { return clean_and_create_persist_state_for_test("test_run_id.persist"); }; PersistState * restart_persist_state_with_cancel(PersistState *state) { PersistState *new_state; persist_state_cancel(state); persist_state_free(state); new_state = create_persist_state_for_test("test_run_id.persist"); return new_state; }; void destroy_persist_state(PersistState *state) { cancel_and_destroy_persist_state(state); }; void test_run_id__first_run__run_id_is_one(void) { PersistState *state; state = create_persist_state(); run_id_init(state); assert_gint(run_id_get(), RUN_ID_FIRST, "Newly initialized run id is not the first id!"); destroy_persist_state(state); }; void test_run_id__second_run__run_id_is_two(void) { PersistState *state; state = create_persist_state(); run_id_init(state); state = restart_persist_state(state); run_id_init(state); assert_gint(run_id_get(), RUN_ID_FIRST + 1, "Running run_id_init twice is not the second id!"); destroy_persist_state(state); }; void test_run_id__second_run_but_with_non_commit__run_id_is_one(void) { PersistState *state; state = create_persist_state(); run_id_init(state); state = restart_persist_state_with_cancel(state); run_id_init(state); assert_gint(run_id_get(), RUN_ID_FIRST, "Not committing persist state still increases run_id"); destroy_persist_state(state); }; void test_run_id__is_same_run__differs_when_not_same_run(void) { PersistState *state; state = create_persist_state(); run_id_init(state); int prev_run_id = run_id_get(); state = restart_persist_state(state); run_id_init(state); assert_false(run_id_is_same_run(prev_run_id), "Run_id_is_same_run returned true when the run differs"); destroy_persist_state(state); }; void test_run_id_macro__macro_has_the_same_value_as_run_id(void) { PersistState *state; GString *res = g_string_sized_new(0); state = create_persist_state(); run_id_init(state); run_id_append_formatted_id(res); assert_string(res->str, "1", "Run id is formatted incorrectly"); destroy_persist_state(state); g_string_free(res, TRUE); }; void test_run_id_macro__macro_is_empty_if_run_id_is_not_inited(void) { GString *res = g_string_sized_new(0); run_id_deinit(); run_id_append_formatted_id(res); assert_string(res->str, "", "Run id is not empty if it is not inited"); g_string_free(res, TRUE); }; int main(void) { app_startup(); test_run_id__first_run__run_id_is_one(); test_run_id__second_run__run_id_is_two(); test_run_id__second_run_but_with_non_commit__run_id_is_one(); test_run_id__is_same_run__differs_when_not_same_run(); test_run_id_macro__macro_has_the_same_value_as_run_id(); test_run_id_macro__macro_is_empty_if_run_id_is_not_inited(); app_shutdown(); return 0; }; syslog-ng-syslog-ng-3.13.2/lib/tests/test_scratch_buffers.c000066400000000000000000000124041321171025300237140ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "scratch-buffers.h" #include "stats/stats-registry.h" #include #include #define ITERATIONS 10 #define DEFAULT_ALLOC_SIZE 256L static void _do_something_with_a_gstring(GString *str) { g_string_assign(str, "foobar"); g_string_append(str, "len"); g_string_truncate(str, 0); } Test(scratch_buffers, alloc_returns_a_gstring_instance) { GString *str = scratch_buffers_alloc(); cr_assert_not_null(str); _do_something_with_a_gstring(str); cr_assert_eq(scratch_buffers_get_local_usage_count(), 1); } Test(scratch_buffers, reclaim_allocations_drops_all_allocs) { for (gint i = 0; i < ITERATIONS; i++) { GString *str = scratch_buffers_alloc(); cr_assert_not_null(str); _do_something_with_a_gstring(str); } cr_assert_eq(scratch_buffers_get_local_usage_count(), ITERATIONS); scratch_buffers_reclaim_allocations(); cr_assert_eq(scratch_buffers_get_local_usage_count(), 0); } Test(scratch_buffers, reclaim_marked_allocs) { ScratchBuffersMarker marker; GString *str; str = scratch_buffers_alloc(); cr_assert_not_null(str); _do_something_with_a_gstring(str); scratch_buffers_mark(&marker); for (gint i = 0; i < ITERATIONS; i++) { str = scratch_buffers_alloc(); cr_assert_not_null(str); _do_something_with_a_gstring(str); } cr_assert_eq(scratch_buffers_get_local_usage_count(), ITERATIONS + 1); scratch_buffers_reclaim_marked(marker); cr_assert_eq(scratch_buffers_get_local_usage_count(), 1); } Test(scratch_buffers, reclaim_up_to_a_marked_alloc) { ScratchBuffersMarker marker; GString *str; str = scratch_buffers_alloc(); cr_assert_not_null(str); _do_something_with_a_gstring(str); str = scratch_buffers_alloc_and_mark(&marker); cr_assert_not_null(str); _do_something_with_a_gstring(str); for (gint i = 0; i < ITERATIONS; i++) { str = scratch_buffers_alloc(); cr_assert_not_null(str); _do_something_with_a_gstring(str); } cr_assert_eq(scratch_buffers_get_local_usage_count(), ITERATIONS + 2); scratch_buffers_reclaim_marked(marker); cr_assert_eq(scratch_buffers_get_local_usage_count(), 1); } Test(scratch_buffers, local_usage_metrics_measure_allocs) { GString *str; str = scratch_buffers_alloc(); cr_assert_not_null(str); _do_something_with_a_gstring(str); cr_assert_eq(scratch_buffers_get_local_usage_count(), 1); cr_assert_eq(scratch_buffers_get_local_allocation_bytes(), DEFAULT_ALLOC_SIZE); str = scratch_buffers_alloc(); cr_assert_not_null(str); _do_something_with_a_gstring(str); cr_assert_eq(scratch_buffers_get_local_usage_count(), 2); cr_assert_eq(scratch_buffers_get_local_allocation_bytes(), 2*DEFAULT_ALLOC_SIZE); } /* not published via the header */ extern StatsCounterItem *stats_scratch_buffers_count; extern StatsCounterItem *stats_scratch_buffers_bytes; Test(scratch_buffers, stats_counters_are_updated) { GString *str; for (gint count = 1; count <= ITERATIONS; count++) { str = scratch_buffers_alloc(); cr_assert_not_null(str); /* check through accessor functions */ cr_assert(scratch_buffers_get_local_usage_count() == count, "get_local_usage_count() not returning proper value, value=%d, expected=%d", scratch_buffers_get_local_usage_count(), count); cr_assert(scratch_buffers_get_local_allocation_bytes() == count * DEFAULT_ALLOC_SIZE, "get_local_allocation_bytes() not returning proper value, value=%ld, expected=%ld", scratch_buffers_get_local_allocation_bytes(), count * DEFAULT_ALLOC_SIZE); /* check through metrics */ cr_assert(stats_counter_get(stats_scratch_buffers_count) == count, "Statistic scratch_buffers_count is not updated properly, value=%d, expected=%d", (gint) stats_counter_get(stats_scratch_buffers_count), count); /* check if byte counter is updated */ scratch_buffers_update_stats(); cr_assert_eq(stats_counter_get(stats_scratch_buffers_bytes), count * DEFAULT_ALLOC_SIZE); } } static void setup(void) { g_thread_init(NULL); stats_init(); scratch_buffers_global_init(); scratch_buffers_allocator_init(); } static void teardown(void) { scratch_buffers_allocator_deinit(); scratch_buffers_global_deinit(); stats_destroy(); } TestSuite(scratch_buffers, .init = setup, .fini = teardown); syslog-ng-syslog-ng-3.13.2/lib/tests/test_str-utils.c000066400000000000000000000054021321171025300225170ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "str-utils.h" /* this macro defines which strchr() implementation we are testing. It is * extracted as a macro in order to make it easy to switch strchr() * implementation, provided there would be more. */ #define strchr_under_test _strchr_optimized_for_single_char_haystack static void assert_strchr_is_null(const gchar *str, int c) { assert_null(strchr_under_test(str, c), "expected a NULL return"); } static void assert_strchr_finds_character_at(const gchar *str, int c, int ofs) { char *result = strchr_under_test(str, c); assert_not_null(result, "expected a non-NULL return"); assert_true(result - str <= strlen(str), "Expected the strchr() return value to point into the input string or the terminating NUL, it points past the NUL"); assert_true(result >= str, "Expected the strchr() return value to point into the input string or the terminating NUL, it points before the start of the string"); assert_gint((result - str), ofs, "Expected the strchr() return value to point right to the specified offset"); } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { assert_strchr_is_null("", 'x'); assert_strchr_is_null("\0x", 'x'); assert_strchr_is_null("a", 'x'); assert_strchr_is_null("abc", 'x'); assert_strchr_finds_character_at("", '\0', 0); assert_strchr_finds_character_at("a", 'a', 0); assert_strchr_finds_character_at("a", '\0', 1); assert_strchr_finds_character_at("abc", 'a', 0); assert_strchr_finds_character_at("abc", 'b', 1); assert_strchr_finds_character_at("abc", 'c', 2); assert_strchr_finds_character_at("abc", '\0', 3); assert_strchr_finds_character_at("0123456789abcdef", '0', 0); assert_strchr_finds_character_at("0123456789abcdef", '7', 7); assert_strchr_finds_character_at("0123456789abcdef", 'f', 15); return 0; } syslog-ng-syslog-ng-3.13.2/lib/tests/test_str_format.c000066400000000000000000000056721321171025300227420ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Balázs Scheidler * Copyright (c) 2014 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "str-format.h" #include "testutils.h" void test_format_hex_string__single_byte__perfect(void) { gchar expected_output[3] = "40"; gchar output[3]; gchar input[1] = "@"; //Act format_hex_string(input, sizeof(input), output, sizeof(output)); //Assert assert_nstring(output, sizeof(output), expected_output, sizeof(expected_output), "format_hex_string output does not match!", NULL); } void test_format_hex_string__two_bytes__perfect(void) { gchar expected_output[5] = "4041"; gchar output[5]; gchar input[2] = "@A"; //Act format_hex_string(input, sizeof(input), output, sizeof(output)); //Assert assert_nstring(output, sizeof(output), expected_output, sizeof(expected_output), "format_hex_string output does not match with two bytes!", NULL); } void test_format_hex_string_with_delimiter__single_byte__perfect(void) { gchar expected_output[3] = "40"; gchar output[3]; gchar input[1] = "@"; //Act format_hex_string_with_delimiter(input, sizeof(input), output, sizeof(output), ' '); //Assert assert_nstring(output, sizeof(output), expected_output, sizeof(expected_output), "format_hex_string_with_delimiter output does not match!", NULL); } void test_format_hex_string_with_delimiter__two_bytes__perfect(void) { gchar expected_output[6] = "40 41"; gchar output[6]; gchar input[2] = "@A"; //Act format_hex_string_with_delimiter(input, sizeof(input), output, sizeof(output), ' '); //Assert assert_nstring(output, sizeof(output), expected_output, sizeof(expected_output), "format_hex_string_with_delimiter output does not match in case of two bytes!", NULL); } int main(void) { test_format_hex_string__single_byte__perfect(); test_format_hex_string__two_bytes__perfect(); test_format_hex_string_with_delimiter__single_byte__perfect(); test_format_hex_string_with_delimiter__two_bytes__perfect(); } syslog-ng-syslog-ng-3.13.2/lib/tests/test_string_list.c000066400000000000000000000053171321171025300231170ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "string-list.h" #include "testutils.h" static void test_string_array_to_list_converts_to_an_equivalent_glist(void) { const gchar *arr[] = { "foo", "bar", "baz", NULL }; GList *l; l = string_array_to_list(arr); assert_gint(g_list_length(l), 3, "converted list is not the expected length"); assert_string(l->data, "foo", "first element is expected to be foo"); assert_string(l->next->data, "bar", "second element is expected to be bar"); assert_string(l->next->next->data, "baz", "third element is expected to be baz"); string_list_free(l); } static void test_clone_string_array_duplicates_elements_while_leaving_token_values_intact(void) { const gchar *arr[] = { "foo", "bar", "baz", NULL }; GList *l, *l2; l = string_array_to_list(arr); l = g_list_append(l, GUINT_TO_POINTER(1)); l = g_list_append(l, GUINT_TO_POINTER(2)); l2 = string_list_clone(l); string_list_free(l); assert_gint(g_list_length(l2), 5, "converted list is not the expected length"); assert_string(l2->data, "foo", "first element is expected to be foo"); assert_string(l2->next->data, "bar", "second element is expected to be bar"); assert_string(l2->next->next->data, "baz", "third element is expected to be baz"); assert_gint(GPOINTER_TO_UINT(l2->next->next->next->data), 1, "fourth element is expected to be a token, with a value of 1"); assert_gint(GPOINTER_TO_UINT(l2->next->next->next->next->data), 2, "fifth element is expected to be a token, with a value of 2"); string_list_free(l2); } int main(int argc, char *argv[]) { test_string_array_to_list_converts_to_an_equivalent_glist(); test_clone_string_array_duplicates_elements_while_leaving_token_values_intact(); } syslog-ng-syslog-ng-3.13.2/lib/tests/test_timeutils.c000066400000000000000000000041271321171025300225730ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include #include #include "timeutils.h" TheoryDataPoints(msgparse, test_year_calculation_for_bsd_format_regular_months) = { DataPoints(int, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), DataPoints(int, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), }; Theory((int lhs, int rhs), msgparse, test_year_calculation_for_bsd_format_regular_months) { /* For regular months, the year will be the actual year, independently of the current month. */ cr_assume(lhs != 11 || rhs != 0); cr_assume(lhs != 0 || rhs != 11); struct tm *tm; time_t t; time(&t); tm = localtime(&t); tm->tm_mon = rhs; cr_assert_eq(tm->tm_year, determine_year_for_month(lhs, tm)); } Test(msgparse, test_bsd_year_calculation_near_to_end_of_the_year) { struct tm *tm; time_t t; time(&t); tm = localtime(&t); /* Current month is January, the given month is December => last year */ tm->tm_mon = 0; cr_assert_eq(tm->tm_year - 1, determine_year_for_month(11, tm)); /* Current month is December, the given month is January => next year */ tm->tm_mon = 11; cr_assert_eq(tm->tm_year + 1, determine_year_for_month(0, tm)); } syslog-ng-syslog-ng-3.13.2/lib/tests/test_type_hints.c000066400000000000000000000167621321171025300227520ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "type-hinting.h" #include "apphook.h" #include #include #include #define assert_type_hint(hint,expected) \ do \ { \ TypeHint t; \ GError *e = NULL; \ \ assert_true(type_hint_parse(hint, &t, &e), \ "Parsing '%s' as type hint", hint); \ \ assert_gint(t, expected, \ "Parsing '%s' as type hint results in correct type", hint); \ } while(0) \ static void assert_error(GError *error, gint code, const gchar *expected_message) { assert_not_null(error, "GError expected to be non-NULL"); assert_gint(error->code, code, "GError error code is as expected"); if (expected_message) assert_string(error->message, expected_message, "GError error message is as expected"); } static void test_type_hint_parse(void) { testcase_begin("Testing type hint parsing"); assert_type_hint(NULL, TYPE_HINT_STRING); assert_type_hint("string", TYPE_HINT_STRING); assert_type_hint("literal", TYPE_HINT_LITERAL); assert_type_hint("boolean", TYPE_HINT_BOOLEAN); assert_type_hint("int", TYPE_HINT_INT32); assert_type_hint("int32", TYPE_HINT_INT32); assert_type_hint("int64", TYPE_HINT_INT64); assert_type_hint("double", TYPE_HINT_DOUBLE); assert_type_hint("datetime", TYPE_HINT_DATETIME); assert_type_hint("default", TYPE_HINT_DEFAULT); TypeHint t; GError *e = NULL; assert_false(type_hint_parse("invalid-hint", &t, &e), "Parsing an invalid hint results in an error."); assert_error(e, TYPE_HINTING_INVALID_TYPE, "Unknown type specified in type hinting: invalid-hint"); testcase_end(); } #define assert_type_cast(target,value,out) \ do \ { \ assert_true(type_cast_to_##target(value, out, &error), \ "Casting '%s' to %s works", value, #target); \ assert_no_error(error, "Successful casting returns no error"); \ } while(0) #define assert_type_cast_fail(target,value,out) \ do \ { \ assert_false(type_cast_to_##target(value, out, &error), \ "Casting '%s' to %s fails", value, #target); \ assert_error(error, TYPE_HINTING_INVALID_CAST, NULL); \ error = NULL; \ } while(0) #define assert_bool_cast(value,expected) \ do \ { \ gboolean ob; \ assert_type_cast(boolean, value, &ob); \ assert_gboolean(ob, expected, "'%s' casted to boolean is %s", \ value, #expected); \ } while(0) #define assert_double_cast(value,expected) \ do \ { \ gdouble od; \ assert_type_cast(double, value, &od); \ assert_gdouble(od, expected, "'%s' casted to double is %s", \ value, #expected); \ } while(0) #define assert_int_cast(value,width,expected) \ do \ { \ gint##width i; \ assert_type_cast(int##width, value, &i); \ assert_gint##width(i, expected, "'%s' casted to int%s is %u", \ value, expected); \ } while(0) \ static void test_type_cast(void) { GError *error = NULL; gint32 i32; gint64 i64; guint64 dt; gdouble d; testcase_begin("Testing type casting"); /* Boolean */ assert_bool_cast("True", TRUE); assert_bool_cast("true", TRUE); assert_bool_cast("1", TRUE); assert_bool_cast("totally true", TRUE); assert_bool_cast("False", FALSE); assert_bool_cast("false", FALSE); assert_bool_cast("0", FALSE); assert_bool_cast("fatally false", FALSE); { gboolean ob; assert_type_cast_fail(boolean, "booyah", &ob); } /* int32 */ assert_int_cast("12345", 32, 12345); assert_type_cast_fail(int32, "12345a", &i32); /* int64 */ assert_int_cast("12345", 64, 12345); assert_type_cast_fail(int64, "12345a", &i64); /* double */ assert_double_cast("1.0", 1.0); assert_type_cast_fail(double, "2.0bad", &d); assert_type_cast_fail(double, "bad", &d); assert_type_cast_fail(double, "", &d); assert_type_cast_fail(double, "1e1000000", &d); assert_type_cast_fail(double, "-1e1000000", &d); assert_double_cast("1e-100000000", 0.0); #ifdef INFINITY assert_double_cast("INF", INFINITY); #endif /* datetime */ assert_type_cast(datetime_int, "12345", &dt); assert_guint64(dt, 12345000, "Casting '12345' to datetime works"); assert_type_cast(datetime_int, "12345.5", &dt); assert_guint64(dt, 12345500, "Casting '12345.5' to datetime works"); assert_type_cast(datetime_int, "12345.54", &dt); assert_guint64(dt, 12345540, "Casting '12345.54' to datetime works"); assert_type_cast(datetime_int, "12345.543", &dt); assert_guint64(dt, 12345543, "Casting '12345.543' to datetime works"); assert_type_cast(datetime_int, "12345.54321", &dt); assert_guint64(dt, 12345543, "Casting '12345.54321' to datetime works"); assert_type_cast_fail(datetime_int, "invalid", &dt); testcase_end(); } int main (void) { app_startup(); test_type_hint_parse(); test_type_cast(); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/tests/test_userdb.c000066400000000000000000000027611321171025300220420ustar00rootroot00000000000000/* * Copyright (c) 2010 Balabit * Copyright (c) 2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "userdb.h" int main(void) { gint uid; gint gid; if (!resolve_user("root", &uid)) return 1; if (!resolve_user("0", &uid) || uid != 0) return 1; if (!resolve_user("-1", &uid) || uid != -1) return 1; if (resolve_group("nincsily", &gid)) return 1; if (!resolve_group("0", &gid) || gid != 0) return 1; if (!resolve_group("-1", &gid) || gid != -1) return 1; if (!resolve_group("sys", &gid)) return 1; if (resolve_group("nincsily", &gid)) return 1; return 0; } syslog-ng-syslog-ng-3.13.2/lib/tests/test_utf8utils.c000066400000000000000000000102331321171025300225160ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "utf8utils.h" void assert_escaped_binary_with_unsafe_chars_with_len(const gchar *str, gssize str_len, const gchar *expected_escaped_str, const gchar *unsafe_chars) { GString *escaped_str = g_string_sized_new(64); append_unsafe_utf8_as_escaped_binary(escaped_str, str, str_len, unsafe_chars); assert_string(escaped_str->str, expected_escaped_str, "Escaped UTF-8 string is not expected"); g_string_free(escaped_str, TRUE); } void assert_escaped_binary_with_unsafe_chars(const gchar *str, const gchar *expected_escaped_str, const gchar *unsafe_chars) { assert_escaped_binary_with_unsafe_chars_with_len(str, -1, expected_escaped_str, unsafe_chars); } void assert_escaped_binary(const gchar *str, const gchar *expected_escaped_str) { assert_escaped_binary_with_unsafe_chars(str, expected_escaped_str, NULL); } void assert_escaped_binary_with_len(const gchar *str, gssize str_len, const gchar *expected_escaped_str) { assert_escaped_binary_with_unsafe_chars_with_len(str, str_len, expected_escaped_str, NULL); } void assert_escaped_text_with_unsafe_chars(const gchar *str, const gchar *expected_escaped_str, const gchar *unsafe_chars) { gchar *escaped_str = convert_unsafe_utf8_to_escaped_text(str, -1, unsafe_chars); assert_string(escaped_str, expected_escaped_str, "Escaped UTF-8 string is not expected"); g_free(escaped_str); } void assert_escaped_text(const gchar *str, const gchar *expected_escaped_str) { assert_escaped_text_with_unsafe_chars(str, expected_escaped_str, NULL); } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { assert_escaped_binary("", ""); assert_escaped_binary("\n", "\\n"); assert_escaped_binary("\b \f \n \r \t", "\\b \\f \\n \\r \\t"); assert_escaped_binary("\\", "\\\\"); assert_escaped_binary("árvíztűrőtükörfúrógép", "árvíztűrőtükörfúrógép"); assert_escaped_binary("árvíztűrőtükörfúrógép\n", "árvíztűrőtükörfúrógép\\n"); assert_escaped_binary("\x41", "A"); assert_escaped_binary("\x7", "\\x07"); assert_escaped_binary("\xad", "\\xad"); assert_escaped_binary("Á\xadÉ", "Á\\xadÉ"); assert_escaped_binary("\xc3\x00\xc1""", "\\xc3"); assert_escaped_binary_with_len("\xc3""\xa1 non zero terminated", 1, "\\xc3"); assert_escaped_binary_with_len("\xc3""\xa1 non zero terminated", 2, "á"); assert_escaped_binary_with_unsafe_chars("\"text\"", "\\\"text\\\"", "\""); assert_escaped_binary_with_unsafe_chars("\"text\"", "\\\"te\\xt\\\"", "\"x"); assert_escaped_text("", ""); assert_escaped_text("\n", "\\n"); assert_escaped_text("\b \f \n \r \t", "\\b \\f \\n \\r \\t"); assert_escaped_text("\\", "\\\\"); assert_escaped_text("árvíztűrőtükörfúrógép", "árvíztűrőtükörfúrógép"); assert_escaped_text("árvíztűrőtükörfúrógép\n", "árvíztűrőtükörfúrógép\\n"); assert_escaped_text("\x41", "A"); assert_escaped_text("\x7", "\\u0007"); assert_escaped_text("\xad", "\\\\xad"); assert_escaped_text("Á\xadÉ", "Á\\\\xadÉ"); assert_escaped_text_with_unsafe_chars("\"text\"", "\\\"text\\\"", "\""); assert_escaped_text_with_unsafe_chars("\"text\"", "\\\"te\\xt\\\"", "\"x"); return 0; } syslog-ng-syslog-ng-3.13.2/lib/thread-utils.h000066400000000000000000000026671321171025300207740ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #ifndef THREAD_UTILS_H_INCLUDED #define THREAD_UTILS_H_INCLUDED #include "syslog-ng.h" #include #ifdef _WIN32 typedef DWORD ThreadId; #else typedef pthread_t ThreadId; #endif static inline ThreadId get_thread_id(void) { #ifndef _WIN32 return pthread_self(); #else return GetCurrentThreadId(); #endif } static inline int threads_equal(ThreadId thread_a, ThreadId thread_b) { #ifndef _WIN32 return pthread_equal(thread_a, thread_b); #else return thread_a == thread_b; #endif } #endif syslog-ng-syslog-ng-3.13.2/lib/timeutils.c000066400000000000000000000616321321171025300203760ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "timeutils.h" #include "messages.h" #include "tls-support.h" #include "reloc.h" #include "pathutils.h" #include #include #include const char *month_names_abbrev[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; const char *month_names[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; const char *weekday_names_abbrev[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; const char *weekday_names[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; #define TZCACHE_SIZE 4 #define TZCACHE_SIZE_MASK (TZCACHE_SIZE - 1) #define TZ_MAGIC "TZif" const gint64 LOWEST_TIME32 = (gint64)((gint32)0x80000000); static const gchar *time_zone_path_list[] = { #ifdef PATH_TIMEZONEDIR PATH_TIMEZONEDIR, /* search the user specified dir */ #endif SYSLOG_NG_PATH_PREFIX "/share/zoneinfo/", /* then local installation first */ "/usr/share/zoneinfo/", /* linux */ "/usr/share/lib/zoneinfo/", /* solaris, AIX */ NULL, }; static const gchar *time_zone_basedir = NULL; typedef struct _TimeCache { time_t when; struct tm tm; } TimeCache; static const gchar * get_time_zone_basedir(void) { int i = 0; if (!time_zone_basedir) { for (i = 0; time_zone_path_list[i] != NULL && !is_file_directory(get_installation_path_for(time_zone_path_list[i])); i++) ; time_zone_basedir = time_zone_path_list[i]; } return time_zone_basedir; } TLS_BLOCK_START { GTimeVal current_time_value; struct iv_task invalidate_time_task; TimeCache local_time_cache[64]; TimeCache gm_time_cache[64]; struct tm mktime_prev_tm; time_t mktime_prev_time; } TLS_BLOCK_END; #define current_time_value __tls_deref(current_time_value) #define invalidate_time_task __tls_deref(invalidate_time_task) #define local_time_cache __tls_deref(local_time_cache) #define gm_time_cache __tls_deref(gm_time_cache) #define mktime_prev_tm __tls_deref(mktime_prev_tm) #define mktime_prev_time __tls_deref(mktime_prev_time) #if !defined(SYSLOG_NG_HAVE_LOCALTIME_R) || !defined(SYSLOG_NG_HAVE_GMTIME_R) static GStaticMutex localtime_lock = G_STATIC_MUTEX_INIT; #endif void invalidate_cached_time(void) { current_time_value.tv_sec = 0; } /* * this shuld replace the g_get_current_time and the g_source_get_current_time calls in the main thread * (log_msg_init, afinter_postpone_mark) */ void cached_g_current_time(GTimeVal *result) { if (current_time_value.tv_sec == 0) { g_get_current_time(¤t_time_value); } *result = current_time_value; if (iv_inited()) { if (invalidate_time_task.handler == NULL) { IV_TASK_INIT(&invalidate_time_task); invalidate_time_task.handler = (void (*)(void *)) invalidate_cached_time; } if (!iv_task_registered(&invalidate_time_task)) iv_task_register(&invalidate_time_task); } else { invalidate_cached_time(); } } time_t cached_g_current_time_sec(void) { GTimeVal now; cached_g_current_time(&now); return now.tv_sec; } time_t cached_mktime(struct tm *tm) { time_t result; if (G_LIKELY(tm->tm_sec == mktime_prev_tm.tm_sec && tm->tm_min == mktime_prev_tm.tm_min && tm->tm_hour == mktime_prev_tm.tm_hour && tm->tm_mday == mktime_prev_tm.tm_mday && tm->tm_mon == mktime_prev_tm.tm_mon && tm->tm_year == mktime_prev_tm.tm_year)) { result = mktime_prev_time; return result; } result = mktime(tm); mktime_prev_tm = *tm; mktime_prev_time = result; return result; } void cached_localtime(time_t *when, struct tm *tm) { guchar i = 0; i = *when & 0x3F; if (G_LIKELY(*when == local_time_cache[i].when)) { *tm = local_time_cache[i].tm; return; } else { #ifdef SYSLOG_NG_HAVE_LOCALTIME_R localtime_r(when, tm); #else struct tm *ltm; g_static_mutex_lock(&localtime_lock); ltm = localtime(when); *tm = *ltm; g_static_mutex_unlock(&localtime_lock); #endif local_time_cache[i].tm = *tm; local_time_cache[i].when = *when; } } void cached_gmtime(time_t *when, struct tm *tm) { guchar i = 0; i = *when & 0x3F; if (G_LIKELY(*when == gm_time_cache[i].when && *when != 0)) { *tm = gm_time_cache[i].tm; return; } else { #ifdef SYSLOG_NG_HAVE_GMTIME_R gmtime_r(when, tm); #else struct tm *ltm; g_static_mutex_lock(&localtime_lock); ltm = gmtime(when); *tm = *ltm; g_static_mutex_unlock(&localtime_lock); #endif gm_time_cache[i].tm = *tm; gm_time_cache[i].when = *when; } } /** * get_local_timezone_ofs: * @when: time in UTC * * Return the zone offset (measured in seconds) of @when expressed in local * time. The function also takes care about daylight saving. **/ long get_local_timezone_ofs(time_t when) { #ifdef SYSLOG_NG_HAVE_STRUCT_TM_TM_GMTOFF struct tm ltm; cached_localtime(&when, <m); return ltm.tm_gmtoff; #else struct tm gtm; struct tm ltm; long tzoff; cached_localtime(&when, <m); cached_gmtime(&when, >m); tzoff = (ltm.tm_hour - gtm.tm_hour) * 3600; tzoff += (ltm.tm_min - gtm.tm_min) * 60; tzoff += ltm.tm_sec - gtm.tm_sec; if (tzoff > 0 && (ltm.tm_year < gtm.tm_year || ltm.tm_mon < gtm.tm_mon || ltm.tm_mday < gtm.tm_mday)) tzoff -= 86400; else if (tzoff < 0 && (ltm.tm_year > gtm.tm_year || ltm.tm_mon > gtm.tm_mon || ltm.tm_mday > gtm.tm_mday)) tzoff += 86400; return tzoff; #endif /* SYSLOG_NG_HAVE_STRUCT_TM_TM_GMTOFF */ } void clean_time_cache(void) { memset(&gm_time_cache, 0, sizeof(gm_time_cache)); memset(&local_time_cache, 0, sizeof(local_time_cache)); } int format_zone_info(gchar *buf, size_t buflen, glong gmtoff) { return g_snprintf(buf, buflen, "%c%02ld:%02ld", gmtoff < 0 ? '-' : '+', (gmtoff < 0 ? -gmtoff : gmtoff) / 3600, ((gmtoff < 0 ? -gmtoff : gmtoff) % 3600) / 60); } /** * check_nanosleep: * * Check if nanosleep() is accurate enough for sub-millisecond sleeping. If * it is not good enough, we're skipping the minor sleeps in LogReader to * balance the cost of returning to the main loop (e.g. we're always going * to return to the main loop, instead of trying to wait for the writer). **/ gboolean check_nanosleep(void) { struct timespec start, stop, sleep_amount; glong diff; gint attempts; for (attempts = 0; attempts < 3; attempts++) { clock_gettime(CLOCK_MONOTONIC, &start); sleep_amount.tv_sec = 0; /* 0.1 msec */ sleep_amount.tv_nsec = 1e5; while (nanosleep(&sleep_amount, &sleep_amount) < 0) ; clock_gettime(CLOCK_MONOTONIC, &stop); diff = timespec_diff_nsec(&stop, &start); if (diff < 5e5) return TRUE; } return FALSE; } /** * g_time_val_diff: * @t1: time value t1 * @t2: time value t2 * * Calculates the time difference between t1 and t2 in microseconds. * The result is positive if t1 is later than t2. * * Returns: * Time difference in microseconds */ glong g_time_val_diff(GTimeVal *t1, GTimeVal *t2) { g_assert(t1); g_assert(t2); return (t1->tv_sec - t2->tv_sec) * G_USEC_PER_SEC + (t1->tv_usec - t2->tv_usec); } void timespec_add_msec(struct timespec *ts, glong msec) { ts->tv_sec += msec / 1000; msec = msec % 1000; ts->tv_nsec += msec * 1e6; if (ts->tv_nsec > 1e9) { ts->tv_nsec -= 1e9; ts->tv_sec++; } } glong timspec_diff_msec(struct timespec *t1, struct timespec *t2) { return (t1->tv_sec - t2->tv_sec) * 1e3 + (t1->tv_nsec - t2->tv_nsec) / 1e6; } glong timespec_diff_nsec(struct timespec *t1, struct timespec *t2) { return (t1->tv_sec - t2->tv_sec) * 1e9 + (t1->tv_nsec - t2->tv_nsec); } /* Determine (guess) the year for the month. * * It can be used for BSD logs, where year is missing. */ gint determine_year_for_month(gint month, const struct tm *now) { if (month == 11 && now->tm_mon == 0) return now->tm_year - 1; else if (month == 0 && now->tm_mon == 11) return now->tm_year + 1; else return now->tm_year; } /** Time zone file parser code **/ /* ** TZ file header ** * * struct tzhead * { * char tzh_magic[4]; TZ_MAGIC "TZif" * char tzh_version[1]; '\0' or '2' as of 2005 * char tzh_reserved[15]; reserved--must be zero * char tzh_ttisgmtcnt[4]; coded number of trans. time flags * char tzh_ttisstdcnt[4]; coded number of trans. time flags * char tzh_leapcnt[4]; coded number of leap seconds * char tzh_timecnt[4]; coded number of transition times * char tzh_typecnt[4]; coded number of local time types * char tzh_charcnt[4]; coded number of abbr. chars * }; * ** TZ file body part ** * * tzh_timecnt (char [4])s coded transition times a la time(2) * tzh_timecnt (unsigned char)s types of local time starting at above * tzh_typecnt repetitions of * one (char [4]) coded UTC offset in seconds * one (unsigned char) used to set tm_isdst * one (unsigned char) that's an abbreviation list index * tzh_charcnt (char)s '\0'-terminated zone abbreviations * tzh_leapcnt repetitions of * one (char [4]) coded leap second transition times * one (char [4]) total correction after above * tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition time is standard time, if FALSE, transition time is wall clock time if absent, * transition times are assumed to be wall clock time * tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition time is UTC, if FALSE, transition time is local time if absent, * transition times are assumed to be local time */ /* * A transition from one ZoneType to another * Minimal size = 5 bytes (4+1) */ typedef struct _Transition { gint64 time; /* seconds, 1970 epoch */ gint32 gmtoffset; /* raw seconds offset from GMT */ } Transition; /* A collection of transitions from one zone_type to another, together * with a list of the zone_types. A zone_info object may have a long * list of transitions between a smaller list of zone_types. * * This object represents the contents of a single zic-created * zoneinfo file. */ struct _ZoneInfo { Transition *transitions; gint64 timecnt; gint32 last_transitions_index; }; struct _TimeZoneInfo { ZoneInfo *zone; ZoneInfo *zone64; glong zone_offset; }; /* Read zic-coded 32-bit integer from file*/ static gint64 readcoded32(unsigned char **input, gint64 minv, gint64 maxv) { unsigned char buf[4]; /* must be UNSIGNED */ gint64 val = 0; gint32 i = 0; gint32 shift = 0; memcpy (buf, *input, sizeof(buf)); *input += 4; for (i = 0, shift = 24; i < 4; ++i, shift -= 8) val |= buf[i] << shift; if (val < minv || val > maxv) { msg_error("Error while processing the time zone file", evt_tag_str("message", "oded value out-of-range"), evt_tag_int("value", val), evt_tag_printf("expected", "[%"G_GINT64_FORMAT", %"G_GINT64_FORMAT"]", minv, maxv)); g_assert_not_reached(); } return val; } /* Read zic-coded 64-bit integer from file */ static gint64 readcoded64(unsigned char **input, gint64 minv, gint64 maxv) { unsigned char buf[8]; /* must be UNSIGNED */ gint64 val = 0; gint32 i = 0; gint32 shift = 0; memcpy (buf, *input, sizeof(buf)); *input += 8; for (i = 0, shift = 56; i < 8; ++i, shift -= 8) val |= (gint64)buf[i] << shift; if (val < minv || val > maxv) { msg_error("Error while processing the time zone file", evt_tag_str("message", "Coded value out-of-range"), evt_tag_int("value", val), evt_tag_printf("expected", "[%"G_GINT64_FORMAT", %"G_GINT64_FORMAT"]", minv, maxv)); g_assert_not_reached(); } return val; } /* Read a booleanean value */ static gboolean readbool(unsigned char **input) { gchar c; c = **input; *input += 1; if (c!=0 && c!=1) { msg_error("Error while processing the time zone file", evt_tag_str("message", "Boolean value out-of-range"), evt_tag_int("value", c)); g_assert_not_reached(); } return (c != 0); } /* Read a character value */ static gchar readchar(unsigned char **input) { unsigned char c; c = **input; *input += 1; return c; } static ZoneInfo * zone_info_new(gint64 timecnt) { ZoneInfo *self = g_new0(ZoneInfo, 1); self->transitions = g_new0(Transition, timecnt); self->timecnt = timecnt; self->last_transitions_index = -1; return self; } static void zone_info_free(ZoneInfo *self) { if (!self) return; g_free(self->transitions); g_free(self); } /** * Parse the zoneinfo file structure (see tzfile.h) into a ZoneInfo */ static ZoneInfo * zone_info_parser(unsigned char **input, gboolean is64bitData, gint *version) { gint32 i = 0; unsigned char *buf = NULL; ZoneInfo *info = NULL; gint64 *transition_times = NULL; guint8 *transition_types = NULL; gint32 *gmt_offsets = NULL; gint64 isgmtcnt, isdstcnt, leapcnt, timecnt, typecnt, charcnt; gboolean insertInitial = FALSE; buf = *input; *input += 4; if (strncmp((gchar *)buf, TZ_MAGIC, 4) != 0) { msg_error("Error while processing the time zone file", evt_tag_str("message", TZ_MAGIC" signature is missing")); goto error; } /* read the version byte */ buf = *input; *input += 1; /* * if '\0', we have just one copy of data, * if '2', there is additional 64 bit version at the end. */ if (buf[0] != 0 && buf[0] != '2' && buf[0] != '3') { msg_error("Error in the time zone file", evt_tag_str("message", "Bad Olson version info")); goto error; } else { if (buf[0] != 0) *version = buf[0] - '0'; else *version = 0; } /* Read reserved bytes */ *input += 15; /* Read array sizes */ isgmtcnt = readcoded32(input, 0, G_MAXINT64); isdstcnt = readcoded32(input, 0, G_MAXINT64); leapcnt = readcoded32(input, 0, G_MAXINT64); timecnt = readcoded32(input, 0, G_MAXINT64); typecnt = readcoded32(input, 0, G_MAXINT64); charcnt = readcoded32(input, 0, G_MAXINT64); /* * Confirm sizes that we assume to be equal. These assumptions * are drawn from a reading of the zic source (2003a), so they * should hold unless the zic source changes. */ if (isgmtcnt != typecnt || isdstcnt != typecnt) { msg_warning("Error in the time zone file", evt_tag_str("message", "Count mismatch between tzh_ttisgmtcnt, tzh_ttisdstcnt, tth_typecnt")); } /* * Used temporarily to store transition times and types. We need * to do this because the times and types are stored in two * separate arrays. */ transition_times = g_new0(gint64, timecnt); transition_types = g_new0(guint8, timecnt); gmt_offsets = g_new0(gint32, typecnt); /* Read transition times */ for (i = 0; i < timecnt; ++i) { if (is64bitData) { transition_times[i] = readcoded64(input, G_MININT64, G_MAXINT64); } else { transition_times[i] = readcoded32(input, G_MININT64, G_MAXINT64); } } /* Read transition types */ for (i = 0; i < timecnt; ++i) { guint8 t = (guint8)readchar(input); if (t >= typecnt) { msg_warning("Error in the time zone file", evt_tag_str("message", "Illegal type number"), evt_tag_printf("val", "%ld", (long) t), evt_tag_printf("expected", "[0, %" G_GINT64_FORMAT "]", typecnt-1)); goto error; } transition_types[i] = t; } /* Read types (except for the isstd and isgmt flags, which come later (why??)) */ for (i = 0; i offs * 60 * 60 || gmt_offsets[i] < -1 * offs * 60 * 60) { msg_warning("Error in the time zone file", evt_tag_str("message", "Illegal gmtoffset number"), evt_tag_int("val", gmt_offsets[i]), evt_tag_printf("expected", "[%d, %d]", -1 * offs * 60 * 60, offs * 60 * 60)); goto error; } /* ignore isdst flag */ readbool(input); /* ignore abbr index */ readchar(input); } /* allocate a new ZoneInfo structure */ if (typecnt > 0 && timecnt == 0) { /* only one type info is in the time zone file so add it with 1901 */ info = zone_info_new(1); info->transitions[0].time = LOWEST_TIME32; info->transitions[0].gmtoffset = gmt_offsets[0]; } else { info = zone_info_new(timecnt); } /* Build transitions vector out of corresponding times and types. */ insertInitial = FALSE; if (is64bitData) { if (timecnt > 0) { gint32 minidx = -1; gint32 last_transition_index = 0; for (i = 0; i < timecnt; ++i) { if (transition_times[i] < LOWEST_TIME32) { if (minidx == -1 || transition_times[i] > transition_times[minidx]) { /* Preserve the latest transition before the 32bit minimum time */ minidx = i; } } else { info->transitions[last_transition_index].time = transition_times[i]; info->transitions[last_transition_index].gmtoffset = gmt_offsets[transition_types[i]]; last_transition_index++; } } if (minidx != -1) { /* * If there are any transitions before the 32bit minimum time, * put the type information with the 32bit minimum time */ memmove(&info->transitions[1], &info->transitions[0], sizeof(Transition) * (timecnt-1)); info->transitions[0].time = LOWEST_TIME32; info->transitions[0].gmtoffset = gmt_offsets[transition_types[minidx]]; info->timecnt -= minidx; } else { /* Otherwise, we need insert the initial type later */ insertInitial = TRUE; } } } else { for (i = 0; i < timecnt; ++i) { info->transitions[i].time = transition_times[i]; info->transitions[i].gmtoffset = gmt_offsets[transition_types[i]]; } } if (insertInitial) { g_assert(timecnt > 0); g_assert(typecnt > 0); /* reallocate the transitions vector to be able to store a new entry */ info->timecnt ++; timecnt ++; info->transitions = g_renew(Transition, info->transitions, timecnt); /* Add the initial type associated with the lowest int32 time */ memmove(&info->transitions[1], &info->transitions[0], sizeof(Transition) * (timecnt-1)); info->transitions[0].time = LOWEST_TIME32; info->transitions[0].gmtoffset = gmt_offsets[0]; } /* ignore the abbreviation string */ if (charcnt) *input += charcnt; /* ignore leap second info, if any */ for (i=0; itransitions == NULL) return 0; if (self->last_transitions_index != -1 && self->last_transitions_index < (self->timecnt - 1) && self->transitions[self->last_transitions_index].time < timestamp && self->transitions[self->last_transitions_index + 1].time > timestamp) { return self->transitions[ self->last_transitions_index ].gmtoffset; } else { for (i = 0; i < (self->timecnt - 1); i++) if (self->transitions[i].time < timestamp && self->transitions[i+1].time > timestamp) break; self->last_transitions_index = i; } return self->transitions[self->last_transitions_index].gmtoffset; } static gboolean zone_info_read(const gchar *zonename, ZoneInfo **zone, ZoneInfo **zone64) { unsigned char *buff = NULL; gchar *filename = NULL; int byte_read = 0; int version; GError *error = NULL; GMappedFile *file_map = NULL; *zone = NULL; *zone64 = NULL; filename = g_build_path(G_DIR_SEPARATOR_S, get_time_zone_basedir(), zonename, NULL); file_map = g_mapped_file_new(filename, FALSE, &error); if (!file_map) { msg_error("Failed to open the time zone file", evt_tag_str("filename", filename), evt_tag_str("message", error->message)); g_error_free(error); g_free(filename); return FALSE; } byte_read = g_mapped_file_get_length(file_map); buff = (unsigned char *)g_mapped_file_get_contents(file_map); if (byte_read == -1) { msg_error("Failed to read the time zone file", evt_tag_str("filename", filename)); g_mapped_file_unref(file_map); g_free(filename); return FALSE; } msg_debug("Processing the time zone file (32bit part)", evt_tag_str("filename", filename)); *zone = zone_info_parser(&buff, FALSE, &version); if (version == 2) { msg_debug("Processing the time zone file (64bit part)", evt_tag_str("filename", filename)); *zone64 = zone_info_parser(&buff, TRUE, &version); } g_mapped_file_unref(file_map); g_free(filename); return *zone != NULL || *zone64 != NULL; } gint32 time_zone_info_get_offset(const TimeZoneInfo *self, time_t stamp) { if (self == NULL) return -1; if (self->zone_offset != -1) return self->zone_offset; if (self->zone64) return zone_info_get_offset(self->zone64, stamp); if (self->zone) return zone_info_get_offset(self->zone, stamp); return -1; } TimeZoneInfo * time_zone_info_new(const gchar *tz) { TimeZoneInfo *self = g_new0(TimeZoneInfo,1); self->zone_offset = -1; /* if no time zone was specified return with an empty TimeZoneInfo pointer */ if (!tz) return self; if ((*tz == '+' || *tz == '-') && strlen(tz) == 6 && isdigit((int) *(tz+1)) && isdigit((int) *(tz+2)) && (*(tz+3) == ':') && isdigit((int) *(tz+4)) && isdigit((int) *(tz+5))) { /* timezone offset */ gint sign = *tz == '-' ? -1 : 1; gint hours, mins; tz++; hours = (*tz - '0') * 10 + *(tz+1) - '0'; mins = (*(tz+3) - '0') * 10 + *(tz+4) - '0'; if ((hours < 24 && mins <= 60) || (hours == 24 && mins == 0)) { self->zone_offset = sign * (hours * 3600 + mins * 60); return self; } } else if (zone_info_read(tz, &self->zone, &self->zone64)) { return self; } time_zone_info_free(self); /* failed to read time zone data */ msg_error("Bogus timezone spec, must be in the format [+-]HH:MM, offset must be less than 24:00", evt_tag_str("value", tz)); return NULL; } void time_zone_info_free(TimeZoneInfo *self) { g_assert(self); zone_info_free(self->zone); zone_info_free(self->zone64); g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/timeutils.h000066400000000000000000000043341321171025300203770ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TIMEUTILS_H_INCLUDED #define TIMEUTILS_H_INCLUDED #include "syslog-ng.h" #include "compat/time.h" time_t cached_mktime(struct tm *tm); void cached_localtime(time_t *when, struct tm *tm); void cached_gmtime(time_t *when, struct tm *tm); long get_local_timezone_ofs(time_t when); void clean_time_cache(void); void invalidate_cached_time(void); void cached_g_current_time(GTimeVal *result); time_t cached_g_current_time_sec(void); gboolean check_nanosleep(void); int format_zone_info(gchar *buf, size_t buflen, long gmtoff); glong g_time_val_diff(GTimeVal *t1, GTimeVal *t2); void timespec_add_msec(struct timespec *ts, glong msec); glong timespec_diff_msec(struct timespec *t1, struct timespec *t2); glong timespec_diff_nsec(struct timespec *t1, struct timespec *t2); gint determine_year_for_month(gint month, const struct tm *now); typedef struct _ZoneInfo ZoneInfo; typedef struct _TimeZoneInfo TimeZoneInfo; gint32 time_zone_info_get_offset(const TimeZoneInfo *self, time_t stamp); TimeZoneInfo* time_zone_info_new(const gchar *tz); void time_zone_info_free(TimeZoneInfo *self); extern const char *month_names_abbrev[]; extern const char *month_names[]; extern const char *weekday_names_abbrev[]; extern const char *weekday_names[]; #endif syslog-ng-syslog-ng-3.13.2/lib/tls-support.h000066400000000000000000000052111321171025300206670ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #ifndef TLS_SUPPORT_H_INCLUDED #define TLS_SUPPORT_H_INCLUDED /* this header is about Thread Local Storage and not about Transport Layer Security */ #include #ifndef SYSLOG_NG_HAVE_THREAD_KEYWORD #include #include static struct __tls_variables * __tls_init_thread(pthread_key_t key, size_t size) { struct __tls_variables *ptr; ptr = calloc(1, size); if (!ptr) abort(); pthread_setspecific(key, ptr); return ptr; } static inline struct __tls_variables *__tls_deref_helper(pthread_key_t key, size_t size) { struct __tls_variables *ptr; ptr = pthread_getspecific(key); if (!ptr) ptr = __tls_init_thread(key, size); return ptr; } #define TLS_BLOCK_START \ static pthread_key_t __tls_key; \ static void __attribute__((constructor)) __tls_init_key(void) \ { \ pthread_key_create(&__tls_key, free); \ } \ \ struct __tls_variables #define TLS_BLOCK_END #define __tls_deref(var) (*({ struct __tls_variables *__ptr = __tls_deref_helper(__tls_key, sizeof(struct __tls_variables)); &__ptr->var; })) #define __thread # #else /* SYSLOG_NG_HAVE_TLS */ #define TLS_BLOCK_START \ struct __tls_variables #define TLS_BLOCK_END \ ; \ static __thread struct __tls_variables __tls #define __tls_deref(var) (__tls.var) #endif #endif syslog-ng-syslog-ng-3.13.2/lib/tlscontext.c000066400000000000000000000632361321171025300205700ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "tlscontext.h" #include "str-utils.h" #include "messages.h" #include "compat/openssl_support.h" #include #include #include #include #include #include #include #include #include #include struct _TLSContext { TLSMode mode; gint verify_mode; gchar *key_file; gchar *cert_file; gchar *dhparam_file; gchar *pkcs12_file; gchar *ca_dir; gchar *crl_dir; gchar *cipher_suite; gchar *ecdh_curve_list; SSL_CTX *ssl_ctx; GList *trusted_fingerpint_list; GList *trusted_dn_list; gint ssl_options; }; gboolean tls_get_x509_digest(X509 *x, GString *hash_string) { gint j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; g_assert(hash_string); if (!X509_digest(x, EVP_sha1(), md, &n)) return FALSE; g_string_append(hash_string, "SHA1:"); for (j = 0; j < (int) n; j++) g_string_append_printf(hash_string, "%02X%c", md[j], (j + 1 == (int) n) ?'\0' : ':'); return TRUE; } int tls_session_verify_fingerprint(X509_STORE_CTX *ctx) { SSL *ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); TLSSession *self = SSL_get_app_data(ssl); GList *current_fingerprint = self->ctx->trusted_fingerpint_list; GString *hash; gboolean match = FALSE; X509 *cert = X509_STORE_CTX_get_current_cert(ctx); if (!current_fingerprint) { return TRUE; } if (!cert) return match; hash = g_string_sized_new(EVP_MAX_MD_SIZE * 3); if (tls_get_x509_digest(cert, hash)) { do { if (strcmp((const gchar *)(current_fingerprint->data), hash->str) == 0) { match = TRUE; break; } } while ((current_fingerprint = g_list_next(current_fingerprint)) != NULL); } g_string_free(hash, TRUE); return match; } void tls_x509_format_dn(X509_NAME *name, GString *dn) { BIO *bio; gchar *buf; long len; bio = BIO_new(BIO_s_mem()); X509_NAME_print_ex(bio, name, 0, ASN1_STRFLGS_ESC_2253 | ASN1_STRFLGS_UTF8_CONVERT | XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_DN_REV); len = BIO_get_mem_data(bio, &buf); g_string_assign_len(dn, buf, len); BIO_free(bio); } int tls_session_verify_dn(X509_STORE_CTX *ctx) { SSL *ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); TLSSession *self = SSL_get_app_data(ssl); gboolean match = FALSE; GList *current_dn = self->ctx->trusted_dn_list; X509 *cert = X509_STORE_CTX_get_current_cert(ctx); GString *dn; if (!current_dn || !cert) return TRUE; dn = g_string_sized_new(128); tls_x509_format_dn(X509_get_subject_name(cert), dn); do { if (g_pattern_match_simple((const gchar *) current_dn->data, dn->str)) { match = TRUE; break; } } while ((current_dn = g_list_next(current_dn)) != NULL); return match; } int tls_session_verify(TLSSession *self, int ok, X509_STORE_CTX *ctx) { /* untrusted means that we have to accept the certificate even if it is untrusted */ if (self->ctx->verify_mode & TVM_UNTRUSTED) return 1; int ctx_error_depth = X509_STORE_CTX_get_error_depth(ctx); /* accept certificate if its fingerprint matches, again regardless whether x509 certificate validation was successful */ if (ok && ctx_error_depth == 0 && !tls_session_verify_fingerprint(ctx)) { msg_notice("Certificate valid, but fingerprint constraints were not met, rejecting"); return 0; } X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx); if (ok && ctx_error_depth != 0 && (X509_get_extension_flags(current_cert) & EXFLAG_CA) == 0) { msg_notice("Invalid certificate found in chain, basicConstraints.ca is unset in non-leaf certificate"); X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA); return 0; } /* reject certificate if it is valid, but its DN is not trusted */ if (ok && ctx_error_depth == 0 && !tls_session_verify_dn(ctx)) { msg_notice("Certificate valid, but DN constraints were not met, rejecting"); X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_UNTRUSTED); return 0; } /* if the crl_dir is set in the configuration file but the directory is empty ignore this error */ if (!ok && X509_STORE_CTX_get_error(ctx) == X509_V_ERR_UNABLE_TO_GET_CRL) { msg_notice("CRL directory is set but no CRLs found"); return 1; } if (!ok && X509_STORE_CTX_get_error(ctx) == X509_V_ERR_INVALID_PURPOSE) { msg_warning("Certificate valid, but purpose is invalid"); return 1; } return ok; } int tls_session_verify_callback(int ok, X509_STORE_CTX *ctx) { SSL *ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); TLSSession *self = SSL_get_app_data(ssl); /* NOTE: Sometimes libssl calls this function with no current_cert. This happens when some global error is happen. At this situation we do not need to call any other check and callback */ if (X509_STORE_CTX_get_current_cert(ctx) == NULL) { int ctx_error = X509_STORE_CTX_get_error(ctx); switch (ctx_error) { case X509_V_ERR_NO_EXPLICIT_POLICY: /* NOTE: Because we set the CHECK_POLICY_FLAG if the certificate contains ExplicitPolicy constraint we would get this error. But this error is because we do not set the policy what we want to check for. */ ok = 1; break; default: msg_notice("Error occured during certificate validation", evt_tag_int("error", X509_STORE_CTX_get_error(ctx))); break; } } else { ok = tls_session_verify(self, ok, ctx); tls_log_certificate_validation_progress(ok, ctx); if (self->verify_func) return self->verify_func(ok, ctx, self->verify_data); } return ok; } void tls_session_set_trusted_fingerprints(TLSContext *self, GList *fingerprints) { g_assert(fingerprints); self->trusted_fingerpint_list = fingerprints; } void tls_session_set_trusted_dn(TLSContext *self, GList *dn) { g_assert(dn); self->trusted_dn_list = dn; } void tls_session_set_verify(TLSSession *self, TLSSessionVerifyFunc verify_func, gpointer verify_data, GDestroyNotify verify_destroy) { self->verify_func = verify_func; self->verify_data = verify_data; self->verify_data_destroy = verify_destroy; } void tls_session_info_callback(const SSL *ssl, int where, int ret) { TLSSession *self = (TLSSession *)SSL_get_app_data(ssl); if( !self->peer_info.found && where == (SSL_ST_ACCEPT|SSL_CB_LOOP) ) { X509 *cert = SSL_get_peer_certificate(ssl); if(cert) { self->peer_info.found = 1; /* mark this found so we don't keep checking on every callback */ X509_NAME *name = X509_get_subject_name(cert); X509_NAME_get_text_by_NID( name, NID_commonName, self->peer_info.cn, X509_MAX_CN_LEN ); X509_NAME_get_text_by_NID( name, NID_organizationName, self->peer_info.o, X509_MAX_O_LEN ); X509_NAME_get_text_by_NID( name, NID_organizationalUnitName, self->peer_info.ou, X509_MAX_OU_LEN ); X509_free(cert); } } } static TLSSession * tls_session_new(SSL *ssl, TLSContext *ctx) { TLSSession *self = g_new0(TLSSession, 1); self->ssl = ssl; self->ctx = ctx; /* to set verify callback */ tls_session_set_verify(self, NULL, NULL, NULL); SSL_set_info_callback(ssl, tls_session_info_callback); return self; } void tls_session_free(TLSSession *self) { if (self->verify_data && self->verify_data_destroy) self->verify_data_destroy(self->verify_data); SSL_free(self->ssl); g_free(self); } static gboolean file_exists(const gchar *fname) { if (!fname) return FALSE; if (access(fname, R_OK) < 0) { msg_error("Error opening TLS file", evt_tag_str("filename", fname), evt_tag_errno("error", errno)); return FALSE; } return TRUE; } static void _print_and_clear_tls_session_error(void) { gulong ssl_error = ERR_get_error(); msg_error("Error setting up TLS session context", evt_tag_printf("tls_error", "%s:%s:%s", ERR_lib_error_string(ssl_error), ERR_func_error_string(ssl_error), ERR_reason_error_string(ssl_error))); ERR_clear_error(); } static void tls_context_setup_verify_mode(TLSContext *self) { gint verify_mode = 0; switch (self->verify_mode) { case TVM_NONE: verify_mode = SSL_VERIFY_NONE; break; case TVM_OPTIONAL | TVM_UNTRUSTED: verify_mode = SSL_VERIFY_NONE; break; case TVM_OPTIONAL | TVM_TRUSTED: verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; break; case TVM_REQUIRED | TVM_UNTRUSTED: verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; break; case TVM_REQUIRED | TVM_TRUSTED: verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; break; default: g_assert_not_reached(); } SSL_CTX_set_verify(self->ssl_ctx, verify_mode, tls_session_verify_callback); } static void tls_context_setup_ssl_options(TLSContext *self) { if (self->ssl_options != TSO_NONE) { glong ssl_options = 0; if(self->ssl_options & TSO_NOSSLv2) ssl_options |= SSL_OP_NO_SSLv2; if(self->ssl_options & TSO_NOSSLv3) ssl_options |= SSL_OP_NO_SSLv3; if(self->ssl_options & TSO_NOTLSv1) ssl_options |= SSL_OP_NO_TLSv1; #ifdef SSL_OP_NO_TLSv1_2 if(self->ssl_options & TSO_NOTLSv11) ssl_options |= SSL_OP_NO_TLSv1_1; if(self->ssl_options & TSO_NOTLSv12) ssl_options |= SSL_OP_NO_TLSv1_2; #endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE if (self->mode == TM_SERVER) ssl_options |= SSL_OP_CIPHER_SERVER_PREFERENCE; #endif SSL_CTX_set_options(self->ssl_ctx, ssl_options); } else { msg_debug("empty ssl options"); } } static gboolean _set_optional_ecdh_curve_list(SSL_CTX *ctx, const gchar *ecdh_curve_list) { #if OPENSSL_VERSION_NUMBER >= 0x10002000L if (ecdh_curve_list && !SSL_CTX_set1_curves_list(ctx, ecdh_curve_list)) { msg_error("Error setting up TLS session context, invalid curve name in list", evt_tag_str("ecdh_curve_list", ecdh_curve_list)); return FALSE; } #endif return TRUE; } static gboolean _is_dh_valid(DH *dh) { if (!dh) return FALSE; gint check_flags; if (!DH_check(dh, &check_flags)) return FALSE; gboolean error_flag_is_set = check_flags & (DH_CHECK_P_NOT_PRIME | DH_UNABLE_TO_CHECK_GENERATOR | DH_CHECK_P_NOT_SAFE_PRIME | DH_NOT_SUITABLE_GENERATOR); return !error_flag_is_set; } static DH * _load_dh_from_file(const gchar *dhparam_file) { if (!file_exists(dhparam_file)) return NULL; BIO *bio = BIO_new_file(dhparam_file, "r"); if (!bio) return NULL; DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); if (!_is_dh_valid(dh)) { msg_error("Error setting up TLS session context, invalid DH parameters", evt_tag_str("dhparam_file", dhparam_file), NULL); DH_free(dh); return NULL; } return dh; } static DH * _load_dh_fallback(void) { DH *dh = DH_new(); if (!dh) return NULL; /* * "2048-bit MODP Group" from RFC3526, Section 3. * * The prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } * * RFC3526 specifies a generator of 2. */ BIGNUM *g = NULL; BN_dec2bn(&g, "2"); if (!DH_set0_pqg(dh, get_rfc3526_prime_2048(NULL), NULL, g)) { BN_free(g); DH_free(dh); return NULL; } return dh; } static gboolean tls_context_setup_ecdh(TLSContext *self) { /* server only */ if (self->mode != TM_SERVER) return TRUE; if (!_set_optional_ecdh_curve_list(self->ssl_ctx, self->ecdh_curve_list)) return FALSE; openssl_ctx_setup_ecdh(self->ssl_ctx); return TRUE; } static gboolean tls_context_setup_dh(TLSContext *self) { DH *dh = self->dhparam_file ? _load_dh_from_file(self->dhparam_file) : _load_dh_fallback(); if (!dh) return FALSE; gboolean ctx_dh_success = SSL_CTX_set_tmp_dh(self->ssl_ctx, dh); DH_free(dh); return ctx_dh_success; } static PKCS12 * _load_pkcs12_file(const gchar *pkcs12_file) { if (!file_exists(pkcs12_file)) return NULL; FILE *p12_file = fopen(pkcs12_file, "rb"); if (!p12_file) return NULL; PKCS12 *pkcs12 = d2i_PKCS12_fp(p12_file, NULL); fclose(p12_file); return pkcs12; } static gboolean _extract_pkcs12_content(PKCS12 *pkcs12, EVP_PKEY **private_key, X509 **cert, STACK_OF(X509) **ca_list) { return PKCS12_parse(pkcs12, "", private_key, cert, ca_list); } static gboolean tls_context_add_certs(TLSContext *self, STACK_OF(X509) *ca_list) { for (gint ca_index = 0; ca_index < sk_X509_num(ca_list); ++ca_index) { X509 *current_ca = sk_X509_value(ca_list, ca_index); if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(self->ssl_ctx), current_ca)) return FALSE; if (self->mode == TM_SERVER && !SSL_CTX_add_client_CA(self->ssl_ctx, current_ca)) return FALSE; } return TRUE; } static gboolean tls_context_load_pkcs12(TLSContext *self) { PKCS12 *pkcs12 = _load_pkcs12_file(self->pkcs12_file); if (!pkcs12) return FALSE; EVP_PKEY *private_key; X509 *cert; STACK_OF(X509) *ca_list = NULL; if (!_extract_pkcs12_content(pkcs12, &private_key, &cert, &ca_list)) { PKCS12_free(pkcs12); return FALSE; } PKCS12_free(pkcs12); if (ca_list && !tls_context_add_certs(self, ca_list)) return FALSE; return SSL_CTX_use_certificate(self->ssl_ctx, cert) && SSL_CTX_use_PrivateKey(self->ssl_ctx, private_key) && SSL_CTX_check_private_key(self->ssl_ctx); } static gboolean tls_context_load_key_and_cert(TLSContext *self) { if (file_exists(self->key_file) && !SSL_CTX_use_PrivateKey_file(self->ssl_ctx, self->key_file, SSL_FILETYPE_PEM)) return FALSE; if (file_exists(self->cert_file) && !SSL_CTX_use_certificate_chain_file(self->ssl_ctx, self->cert_file)) return FALSE; if (self->key_file && self->cert_file && !SSL_CTX_check_private_key(self->ssl_ctx)) return FALSE; return TRUE; } gboolean tls_context_setup_context(TLSContext *self) { gint verify_flags = X509_V_FLAG_POLICY_CHECK; if (!self->ssl_ctx) goto error; if (self->pkcs12_file) { if (self->cert_file || self->key_file) msg_warning("WARNING: pkcs12-file() is specified, key-file() and cert-file() will be omitted"); if (!tls_context_load_pkcs12(self)) goto error; } else { if (!tls_context_load_key_and_cert(self)) goto error; } if (file_exists(self->ca_dir) && !SSL_CTX_load_verify_locations(self->ssl_ctx, NULL, self->ca_dir)) goto error; if (file_exists(self->crl_dir) && !SSL_CTX_load_verify_locations(self->ssl_ctx, NULL, self->crl_dir)) goto error; if (self->crl_dir) verify_flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL; X509_VERIFY_PARAM_set_flags(SSL_CTX_get0_param(self->ssl_ctx), verify_flags); tls_context_setup_verify_mode(self); tls_context_setup_ssl_options(self); if (!tls_context_setup_ecdh(self)) { SSL_CTX_free(self->ssl_ctx); self->ssl_ctx = NULL; return FALSE; } if (!tls_context_setup_dh(self)) goto error; if (self->cipher_suite) { if (!SSL_CTX_set_cipher_list(self->ssl_ctx, self->cipher_suite)) goto error; } return TRUE; error: _print_and_clear_tls_session_error(); if (self->ssl_ctx) { SSL_CTX_free(self->ssl_ctx); self->ssl_ctx = NULL; } return FALSE; } TLSSession * tls_context_setup_session(TLSContext *self) { if (!self->ssl_ctx) return NULL; SSL *ssl = SSL_new(self->ssl_ctx); if (self->mode == TM_CLIENT) SSL_set_connect_state(ssl); else SSL_set_accept_state(ssl); TLSSession *session = tls_session_new(ssl, self); SSL_set_app_data(ssl, session); return session; } TLSContext * tls_context_new(TLSMode mode) { TLSContext *self = g_new0(TLSContext, 1); self->mode = mode; self->verify_mode = TVM_REQUIRED | TVM_TRUSTED; self->ssl_options = TSO_NOSSLv2; if (self->mode == TM_CLIENT) self->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); else self->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); return self; } void tls_context_free(TLSContext *self) { SSL_CTX_free(self->ssl_ctx); g_list_foreach(self->trusted_fingerpint_list, (GFunc) g_free, NULL); g_list_foreach(self->trusted_dn_list, (GFunc) g_free, NULL); g_free(self->key_file); g_free(self->pkcs12_file); g_free(self->cert_file); g_free(self->dhparam_file); g_free(self->ca_dir); g_free(self->crl_dir); g_free(self->cipher_suite); g_free(self->ecdh_curve_list); g_free(self); } gboolean tls_context_set_verify_mode_by_name(TLSContext *self, const gchar *mode_str) { if (strcasecmp(mode_str, "none") == 0) self->verify_mode = TVM_NONE; else if (strcasecmp(mode_str, "optional-trusted") == 0 || strcasecmp(mode_str, "optional_trusted") == 0) self->verify_mode = TVM_OPTIONAL | TVM_TRUSTED; else if (strcasecmp(mode_str, "optional-untrusted") == 0 || strcasecmp(mode_str, "optional_untrusted") == 0) self->verify_mode = TVM_OPTIONAL | TVM_UNTRUSTED; else if (strcasecmp(mode_str, "required-trusted") == 0 || strcasecmp(mode_str, "required_trusted") == 0) self->verify_mode = TVM_REQUIRED | TVM_TRUSTED; else if (strcasecmp(mode_str, "required-untrusted") == 0 || strcasecmp(mode_str, "required_untrusted") == 0) self->verify_mode = TVM_REQUIRED | TVM_UNTRUSTED; else return FALSE; return TRUE; } gboolean tls_context_set_ssl_options_by_name(TLSContext *self, GList *options) { self->ssl_options = TSO_NONE; GList *l; for (l=options; l != NULL; l=l->next) { if (strcasecmp(l->data, "no-sslv2") == 0 || strcasecmp(l->data, "no_sslv2") == 0) self->ssl_options |= TSO_NOSSLv2; else if (strcasecmp(l->data, "no-sslv3") == 0 || strcasecmp(l->data, "no_sslv3") == 0) self->ssl_options |= TSO_NOSSLv3; else if (strcasecmp(l->data, "no-tlsv1") == 0 || strcasecmp(l->data, "no_tlsv1") == 0) self->ssl_options |= TSO_NOTLSv1; #ifdef SSL_OP_NO_TLSv1_2 else if (strcasecmp(l->data, "no-tlsv11") == 0 || strcasecmp(l->data, "no_tlsv11") == 0) self->ssl_options |= TSO_NOTLSv11; else if (strcasecmp(l->data, "no-tlsv12") == 0 || strcasecmp(l->data, "no_tlsv12") == 0) self->ssl_options |= TSO_NOTLSv12; #endif else return FALSE; } return TRUE; } gint tls_context_get_verify_mode(const TLSContext *self) { return self->verify_mode; } void tls_context_set_verify_mode(TLSContext *self, gint verify_mode) { self->verify_mode = verify_mode; } void tls_context_set_key_file(TLSContext *self, const gchar *key_file) { g_free(self->key_file); self->key_file = g_strdup(key_file); } void tls_context_set_cert_file(TLSContext *self, const gchar *cert_file) { g_free(self->cert_file); self->cert_file = g_strdup(cert_file); } void tls_context_set_pkcs12_file(TLSContext *self, const gchar *pkcs12_file) { g_free(self->pkcs12_file); self->pkcs12_file = g_strdup(pkcs12_file); } void tls_context_set_ca_dir(TLSContext *self, const gchar *ca_dir) { g_free(self->ca_dir); self->ca_dir = g_strdup(ca_dir); } void tls_context_set_crl_dir(TLSContext *self, const gchar *crl_dir) { g_free(self->crl_dir); self->crl_dir = g_strdup(crl_dir); } void tls_context_set_cipher_suite(TLSContext *self, const gchar *cipher_suite) { g_free(self->cipher_suite); self->cipher_suite = g_strdup(cipher_suite); } void tls_context_set_ecdh_curve_list(TLSContext *self, const gchar *ecdh_curve_list) { g_free(self->ecdh_curve_list); self->ecdh_curve_list = g_strdup(ecdh_curve_list); } void tls_context_set_dhparam_file(TLSContext *self, const gchar *dhparam_file) { g_free(self->dhparam_file); self->dhparam_file = g_strdup(dhparam_file); } void tls_log_certificate_validation_progress(int ok, X509_STORE_CTX *ctx) { X509 *xs; GString *subject_name, *issuer_name; xs = X509_STORE_CTX_get_current_cert(ctx); subject_name = g_string_sized_new(128); issuer_name = g_string_sized_new(128); tls_x509_format_dn(X509_get_subject_name(xs), subject_name); tls_x509_format_dn(X509_get_issuer_name(xs), issuer_name); if (ok) { msg_debug("Certificate validation progress", evt_tag_str("subject", subject_name->str), evt_tag_str("issuer", issuer_name->str)); } else { gint errnum, errdepth; errnum = X509_STORE_CTX_get_error(ctx); errdepth = X509_STORE_CTX_get_error_depth(ctx); msg_error("Certificate validation failed", evt_tag_str("subject", subject_name->str), evt_tag_str("issuer", issuer_name->str), evt_tag_str("error", X509_verify_cert_error_string(errnum)), evt_tag_int("depth", errdepth)); } g_string_free(subject_name, TRUE); g_string_free(issuer_name, TRUE); } static gboolean tls_wildcard_match(const gchar *host_name, const gchar *pattern) { gchar **pattern_parts, **hostname_parts; gboolean success = FALSE; gchar *lower_pattern = NULL; gchar *lower_hostname = NULL; gint i; pattern_parts = g_strsplit(pattern, ".", 0); hostname_parts = g_strsplit(host_name, ".", 0); for (i = 0; pattern_parts[i]; i++) { if (!hostname_parts[i]) { /* number of dot separated entries is not the same in the hostname and the pattern spec */ goto exit; } lower_pattern = g_ascii_strdown(pattern_parts[i],-1); lower_hostname = g_ascii_strdown(hostname_parts[i],-1); if (!g_pattern_match_simple(lower_pattern, lower_hostname)) goto exit; } success = TRUE; exit: g_free(lower_pattern); g_free(lower_hostname); g_strfreev(pattern_parts); g_strfreev(hostname_parts); return success; } gboolean tls_verify_certificate_name(X509 *cert, const gchar *host_name) { gchar pattern_buf[256]; gint ext_ndx; gboolean found = FALSE, result = FALSE; ext_ndx = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1); if (ext_ndx >= 0) { /* ok, there's a subjectAltName extension, check that */ X509_EXTENSION *ext; STACK_OF(GENERAL_NAME) *alt_names; GENERAL_NAME *gen_name; ext = X509_get_ext(cert, ext_ndx); alt_names = X509V3_EXT_d2i(ext); if (alt_names) { gint num, i; num = sk_GENERAL_NAME_num(alt_names); for (i = 0; !result && i < num; i++) { gen_name = sk_GENERAL_NAME_value(alt_names, i); if (gen_name->type == GEN_DNS) { const guchar *dnsname = ASN1_STRING_get0_data(gen_name->d.dNSName); guint dnsname_len = ASN1_STRING_length(gen_name->d.dNSName); if (dnsname_len > sizeof(pattern_buf) - 1) { found = TRUE; result = FALSE; break; } memcpy(pattern_buf, dnsname, dnsname_len); pattern_buf[dnsname_len] = 0; /* we have found a DNS name as alternative subject name */ found = TRUE; result = tls_wildcard_match(host_name, pattern_buf); } else if (gen_name->type == GEN_IPADD) { char *dotted_ip = inet_ntoa(*(struct in_addr *) gen_name->d.iPAddress->data); g_strlcpy(pattern_buf, dotted_ip, sizeof(pattern_buf)); found = TRUE; result = strcasecmp(host_name, pattern_buf) == 0; } } sk_GENERAL_NAME_free(alt_names); } } if (!found) { /* hmm. there was no subjectAltName (this is deprecated, but still * widely used), look up the Subject, most specific CN */ X509_NAME *name; name = X509_get_subject_name(cert); if (X509_NAME_get_text_by_NID(name, NID_commonName, pattern_buf, sizeof(pattern_buf)) != -1) { result = tls_wildcard_match(host_name, pattern_buf); } } if (!result) { msg_error("Certificate subject does not match configured hostname", evt_tag_str("hostname", host_name), evt_tag_str("certificate", pattern_buf)); } else { msg_verbose("Certificate subject matches configured hostname", evt_tag_str("hostname", host_name), evt_tag_str("certificate", pattern_buf)); } return result; } syslog-ng-syslog-ng-3.13.2/lib/tlscontext.h000066400000000000000000000070401321171025300205640ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #ifndef TLSCONTEXT_H_INCLUDED #define TLSCONTEXT_H_INCLUDED #include "syslog-ng.h" #include typedef enum { TM_CLIENT, TM_SERVER, TM_MAX } TLSMode; typedef enum { TVM_NONE, TVM_TRUSTED=0x0001, TVM_UNTRUSTED=0x0002, TVM_OPTIONAL=0x0010, TVM_REQUIRED=0x0020, } TLSVerifyMode; typedef enum { TSO_NONE, TSO_NOSSLv2=0x0001, TSO_NOSSLv3=0x0002, TSO_NOTLSv1=0x0004, TSO_NOTLSv11=0x0008, TSO_NOTLSv12=0x0010, } TLSSslOptions; typedef gint (*TLSSessionVerifyFunc)(gint ok, X509_STORE_CTX *ctx, gpointer user_data); typedef struct _TLSContext TLSContext; #define X509_MAX_CN_LEN 64 #define X509_MAX_O_LEN 64 #define X509_MAX_OU_LEN 32 typedef struct _TLSSession { SSL *ssl; TLSContext *ctx; TLSSessionVerifyFunc verify_func; gpointer verify_data; GDestroyNotify verify_data_destroy; struct { int found; gchar o[X509_MAX_O_LEN]; gchar ou[X509_MAX_OU_LEN]; gchar cn[X509_MAX_CN_LEN]; } peer_info; } TLSSession; void tls_session_set_verify(TLSSession *self, TLSSessionVerifyFunc verify_func, gpointer verify_data, GDestroyNotify verify_destroy); void tls_session_free(TLSSession *self); gboolean tls_context_setup_context(TLSContext *self); TLSSession *tls_context_setup_session(TLSContext *self); void tls_session_set_trusted_fingerprints(TLSContext *self, GList *fingerprints); void tls_session_set_trusted_dn(TLSContext *self, GList *dns); TLSContext *tls_context_new(TLSMode mode); void tls_context_free(TLSContext *s); gboolean tls_context_set_verify_mode_by_name(TLSContext *self, const gchar *mode_str); gboolean tls_context_set_ssl_options_by_name(TLSContext *self, GList *options); gint tls_context_get_verify_mode(const TLSContext *self); void tls_context_set_verify_mode(TLSContext *self, gint verify_mode); void tls_context_set_key_file(TLSContext *self, const gchar *key_file); void tls_context_set_cert_file(TLSContext *self, const gchar *cert_file); void tls_context_set_pkcs12_file(TLSContext *self, const gchar *pkcs12_file); void tls_context_set_ca_dir(TLSContext *self, const gchar *ca_dir); void tls_context_set_crl_dir(TLSContext *self, const gchar *crl_dir); void tls_context_set_cipher_suite(TLSContext *self, const gchar *cipher_suite); void tls_context_set_ecdh_curve_list(TLSContext *self, const gchar *ecdh_curve_list); void tls_context_set_dhparam_file(TLSContext *self, const gchar *dhparam_file); void tls_log_certificate_validation_progress(int ok, X509_STORE_CTX *ctx); gboolean tls_verify_certificate_name(X509 *cert, const gchar *hostname); void tls_x509_format_dn(X509_NAME *name, GString *dn); #endif syslog-ng-syslog-ng-3.13.2/lib/transport/000077500000000000000000000000001321171025300202375ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/transport/CMakeLists.txt000066400000000000000000000007131321171025300230000ustar00rootroot00000000000000set(TRANSPORT_HEADERS transport/logtransport.h transport/transport-aux-data.h transport/transport-tls.h transport/transport-file.h transport/transport-pipe.h transport/transport-socket.h PARENT_SCOPE) set(TRANSPORT_SOURCES transport/logtransport.c transport/transport-aux-data.c transport/transport-file.c transport/transport-pipe.c transport/transport-socket.c transport/transport-tls.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/transport/Makefile.am000066400000000000000000000011071321171025300222720ustar00rootroot00000000000000transportincludedir = ${pkgincludedir}/transport transportinclude_HEADERS = \ lib/transport/logtransport.h \ lib/transport/transport-aux-data.h \ lib/transport/transport-tls.h \ lib/transport/transport-file.h \ lib/transport/transport-pipe.h \ lib/transport/transport-socket.h transport_sources = \ lib/transport/logtransport.c \ lib/transport/transport-aux-data.c \ lib/transport/transport-file.c \ lib/transport/transport-pipe.c \ lib/transport/transport-socket.c transport_crypto_sources = \ lib/transport/transport-tls.c include lib/transport/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/transport/logtransport.c000066400000000000000000000027401321171025300231440ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logtransport.h" #include "messages.h" #include void log_transport_free_method(LogTransport *s) { if (s->fd != -1) { msg_verbose("Closing log transport fd", evt_tag_int("fd", s->fd)); close(s->fd); } } void log_transport_init_instance(LogTransport *self, gint fd) { self->fd = fd; self->cond = 0; self->free_fn = log_transport_free_method; } void log_transport_free(LogTransport *self) { self->free_fn(self); g_free(self); } syslog-ng-syslog-ng-3.13.2/lib/transport/logtransport.h000066400000000000000000000035561321171025300231570ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOGTRANSPORT_H_INCLUDED #define LOGTRANSPORT_H_INCLUDED #include "syslog-ng.h" #include "transport/transport-aux-data.h" typedef struct _LogTransport LogTransport; struct _LogTransport { gint fd; GIOCondition cond; gssize (*read)(LogTransport *self, gpointer buf, gsize count, LogTransportAuxData *aux); gssize (*write)(LogTransport *self, const gpointer buf, gsize count); void (*free_fn)(LogTransport *self); }; static inline gssize log_transport_write(LogTransport *self, const gpointer buf, gsize count) { return self->write(self, buf, count); } static inline gssize log_transport_read(LogTransport *self, gpointer buf, gsize count, LogTransportAuxData *aux) { return self->read(self, buf, count, aux); } void log_transport_init_instance(LogTransport *s, gint fd); void log_transport_free_method(LogTransport *s); void log_transport_free(LogTransport *s); #endif syslog-ng-syslog-ng-3.13.2/lib/transport/tests/000077500000000000000000000000001321171025300214015ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/transport/tests/Makefile.am000066400000000000000000000005501321171025300234350ustar00rootroot00000000000000lib_transport_tests_TESTS = \ lib/transport/tests/test_aux_data check_PROGRAMS += ${lib_transport_tests_TESTS} lib_transport_tests_test_aux_data_CFLAGS = $(TEST_CFLAGS) \ -I${top_srcdir}/lib/transport/tests lib_transport_tests_test_aux_data_LDADD = $(TEST_LDADD) lib_transport_tests_test_aux_data_SOURCES = \ lib/transport/tests/test_aux_data.c syslog-ng-syslog-ng-3.13.2/lib/transport/tests/test_aux_data.c000066400000000000000000000130521321171025300243730ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "testutils.h" #include "transport/transport-aux-data.h" #define AUX_DATA_TESTCASE(x, ...) do { aux_data_testcase_begin(#x, #__VA_ARGS__); x(__VA_ARGS__); aux_data_testcase_end(); } while(0) #define aux_data_testcase_begin(func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ } \ while (0) #define aux_data_testcase_end() \ do \ { \ testcase_end(); \ } \ while (0) static LogTransportAuxData * construct_empty_aux(void) { LogTransportAuxData *aux = g_new(LogTransportAuxData, 1); log_transport_aux_data_init(aux); return aux; } static void free_aux(LogTransportAuxData *aux) { log_transport_aux_data_destroy(aux); g_free(aux); } static LogTransportAuxData * construct_aux_with_some_data(void) { LogTransportAuxData *aux = construct_empty_aux(); /* set peer_addr twice to validate that peer_addr is correctly reference counted */ log_transport_aux_data_set_peer_addr_ref(aux, g_sockaddr_inet_new("1.2.3.4", 5555)); log_transport_aux_data_set_peer_addr_ref(aux, g_sockaddr_inet_new("1.2.3.4", 5555)); log_transport_aux_data_add_nv_pair(aux, "foo", "bar"); return aux; } static void test_aux_data_reinit_returns_aux_into_initial_state_without_leaks(void) { LogTransportAuxData *aux = construct_aux_with_some_data(); log_transport_aux_data_reinit(aux); assert_null(aux->peer_addr, "aux->peer_addr is not NULL after reinit"); free_aux(aux); } static void _concat_nvpairs_helper(const gchar *name, const gchar *value, gsize value_len, gpointer user_data) { GString *concatenated = (GString *) user_data; g_string_sprintfa(concatenated, "%s=%s\n", name, value); assert_gint(value_len, strlen(value), "foreach() length mismatch"); } static gchar * _concat_nvpairs(LogTransportAuxData *aux) { GString *concatenated = g_string_sized_new(0); log_transport_aux_data_foreach(aux, _concat_nvpairs_helper, concatenated); return g_string_free(concatenated, FALSE); } static void assert_concatenated_nvpairs(LogTransportAuxData *aux, const gchar *expected) { gchar *concatenated = _concat_nvpairs(aux);; assert_string(concatenated, expected, "foreach() didn't return all-added nvpairs"); g_free(concatenated); } static void test_aux_data_added_nvpairs_are_returned_by_foreach_in_order(void) { LogTransportAuxData *aux = construct_aux_with_some_data(); log_transport_aux_data_add_nv_pair(aux, "super", "lativus"); assert_concatenated_nvpairs(aux, "foo=bar\nsuper=lativus\n"); free_aux(aux); } static void test_aux_data_copy_creates_an_identical_copy(void) { LogTransportAuxData *aux = construct_aux_with_some_data(); LogTransportAuxData aux_copy; gchar *orig, *copy; log_transport_aux_data_copy(&aux_copy, aux); orig = _concat_nvpairs(aux); copy = _concat_nvpairs(&aux_copy); assert_string(orig, copy, "copy incorrectly copied aux->nvpairs"); g_free(orig); g_free(copy); log_transport_aux_data_destroy(&aux_copy); free_aux(aux); } static void test_aux_data_copy_separates_the_copies(void) { LogTransportAuxData *aux = construct_aux_with_some_data(); LogTransportAuxData aux_copy; gchar *orig, *copy; log_transport_aux_data_copy(&aux_copy, aux); log_transport_aux_data_add_nv_pair(aux, "super", "lativus"); orig = _concat_nvpairs(aux); copy = _concat_nvpairs(&aux_copy); assert_false(strcmp(orig, copy) == 0, "copy incorrectly copied aux->nvpairs as change to one of them affected the other, orig=%s, copy=%s", orig, copy); g_free(orig); g_free(copy); log_transport_aux_data_destroy(&aux_copy); free_aux(aux); } static void test_add_nv_pair_to_a_NULL_aux_data_will_do_nothing(void) { log_transport_aux_data_add_nv_pair(NULL, "foo", "bar"); } static void test_aux_data(void) { AUX_DATA_TESTCASE(test_aux_data_reinit_returns_aux_into_initial_state_without_leaks); AUX_DATA_TESTCASE(test_aux_data_added_nvpairs_are_returned_by_foreach_in_order); AUX_DATA_TESTCASE(test_aux_data_copy_creates_an_identical_copy); AUX_DATA_TESTCASE(test_aux_data_copy_separates_the_copies); AUX_DATA_TESTCASE(test_add_nv_pair_to_a_NULL_aux_data_will_do_nothing); } int main(void) { test_aux_data(); return 0; } syslog-ng-syslog-ng-3.13.2/lib/transport/transport-aux-data.c000066400000000000000000000047121321171025300241450ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "transport-aux-data.h" #include "messages.h" #include void log_transport_aux_data_add_nv_pair(LogTransportAuxData *self, const gchar *name, const gchar *value) { if (!self) return; gsize name_len = strlen(name); gsize value_len = strlen(value); if (self->end_ptr + name_len + 1 + value_len + 1 + 1 < sizeof(self->data)) { /* copy NUL too */ memcpy(&self->data[self->end_ptr], name, name_len + 1); self->end_ptr += name_len + 1; memcpy(&self->data[self->end_ptr], value, value_len + 1); self->end_ptr += value_len + 1; /* append final NULL that indicates the end of name-value pairs */ self->data[self->end_ptr] = 0; } else { static gboolean warned = FALSE; if (!warned) { msg_notice("Transport aux data overflow, some fields may not be associated with the message, please increase aux buffer size", evt_tag_int("aux_size", sizeof(self->data))); warned = TRUE; } } } void log_transport_aux_data_foreach(LogTransportAuxData *self, void (*func)(const gchar *, const gchar *, gsize, gpointer), gpointer user_data) { const gchar *p; p = self->data; while (*p) { const gchar *name = p; gsize name_len = strlen(p); const gchar *value = name + name_len + 1; gsize value_len = strlen(value); func(name, value, value_len, user_data); p = value + value_len + 1; } } syslog-ng-syslog-ng-3.13.2/lib/transport/transport-aux-data.h000066400000000000000000000045411321171025300241520ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #ifndef TRANSPORT_TRANSPORT_AUX_DATA_H_INCLUDED #define TRANSPORT_TRANSPORT_AUX_DATA_H_INCLUDED #include "gsockaddr.h" #include typedef struct _LogTransportAuxData { GSockAddr *peer_addr; gchar data[1024]; gsize end_ptr; } LogTransportAuxData; static inline void log_transport_aux_data_init(LogTransportAuxData *self) { self->peer_addr = NULL; self->end_ptr = 0; self->data[0] = 0; } static inline void log_transport_aux_data_destroy(LogTransportAuxData *self) { g_sockaddr_unref(self->peer_addr); } static inline void log_transport_aux_data_reinit(LogTransportAuxData *self) { log_transport_aux_data_destroy(self); log_transport_aux_data_init(self); } static inline void log_transport_aux_data_copy(LogTransportAuxData *dst, LogTransportAuxData *src) { gsize data_to_copy = sizeof(*src) - sizeof(src->data) + src->end_ptr; memcpy(dst, src, data_to_copy); g_sockaddr_ref(dst->peer_addr); } static inline void log_transport_aux_data_set_peer_addr_ref(LogTransportAuxData *self, GSockAddr *peer_addr) { if (self->peer_addr) g_sockaddr_unref(self->peer_addr); self->peer_addr = peer_addr; } void log_transport_aux_data_add_nv_pair(LogTransportAuxData *self, const gchar *name, const gchar *value); void log_transport_aux_data_foreach(LogTransportAuxData *self, void (*func)(const gchar *, const gchar *, gsize, gpointer), gpointer user_data); #endif syslog-ng-syslog-ng-3.13.2/lib/transport/transport-file.c000066400000000000000000000043401321171025300233550ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "transport-file.h" #include #include gssize log_transport_file_read_method(LogTransport *self, gpointer buf, gsize buflen, LogTransportAuxData *aux) { gint rc; do { rc = read(self->fd, buf, buflen); } while (rc == -1 && errno == EINTR); return rc; } gssize log_transport_file_read_and_ignore_eof_method(LogTransport *self, gpointer buf, gsize buflen, LogTransportAuxData *aux) { gint rc; rc = log_transport_file_read_method(self, buf, buflen, aux); if (rc == 0) { rc = -1; errno = EAGAIN; } return rc; } gssize log_transport_file_write_method(LogTransport *self, const gpointer buf, gsize buflen) { gint rc; do { rc = write(self->fd, buf, buflen); } while (rc == -1 && errno == EINTR); return rc; } void log_transport_file_init_instance(LogTransportFile *self, gint fd) { log_transport_init_instance(&self->super, fd); self->super.read = log_transport_file_read_method; self->super.write = log_transport_file_write_method; self->super.free_fn = log_transport_free_method; } LogTransport * log_transport_file_new(gint fd) { LogTransportFile *self = g_new0(LogTransportFile, 1); log_transport_file_init_instance(self, fd); return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/transport/transport-file.h000066400000000000000000000033341321171025300233640ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TRANSPORT_TRANSPORT_FILE_H_INCLUDED #define TRANSPORT_TRANSPORT_FILE_H_INCLUDED 1 #include "transport/logtransport.h" /* log transport that simply sends messages to an fd */ typedef struct _LogTransportFile LogTransportFile; struct _LogTransportFile { LogTransport super; }; gssize log_transport_file_read_method(LogTransport *self, gpointer buf, gsize buflen, LogTransportAuxData *aux); gssize log_transport_file_read_and_ignore_eof_method(LogTransport *self, gpointer buf, gsize buflen, LogTransportAuxData *aux); gssize log_transport_file_write_method(LogTransport *self, const gpointer buf, gsize buflen); void log_transport_file_init_instance(LogTransportFile *self, gint fd); LogTransport *log_transport_file_new(gint fd); #endif syslog-ng-syslog-ng-3.13.2/lib/transport/transport-pipe.c000066400000000000000000000050741321171025300234000ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "transport/transport-pipe.h" #include "transport/transport-file.h" #include #include gssize log_transport_pipe_write_method(LogTransport *s, const gpointer buf, gsize buflen) { LogTransportFile *self = (LogTransportFile *) s; gint rc; do { /* NOTE: this loop is needed because of the funny semantics that * pipe() uses. A pipe has a buffer (sized PIPE_BUF), which * determines how much data it can buffer. If the data to be * written would overflow the buffer, it may reject it with * rc == -1 and errno set to EAGAIN. * * The issue is worse as AIX may indicate in poll() that the * pipe is writable, and then the pipe may flat out reject our * write() operation, resulting in a busy loop. * * The work around is to try to write the data in * ever-decreasing size, and only accept EAGAIN if a single byte * write is refused as well. * * Most UNIX platforms behaves better than that, but the AIX * implementation is still conforming, for now we only enable it * on AIX. */ do { rc = write(self->super.fd, buf, buflen); } #ifdef __aix__ while ((buflen >>= 1) && rc < 0 && errno == EAGAIN); #else while (0); #endif } while (rc == -1 && errno == EINTR); return rc; } LogTransport * log_transport_pipe_new(gint fd) { LogTransportFile *self = g_new0(LogTransportFile, 1); log_transport_file_init_instance(self, fd); self->super.write = log_transport_pipe_write_method; return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/transport/transport-pipe.h000066400000000000000000000023651321171025300234050ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TRANSPORT_TRANSPORT_PIPE_H_INCLUDED #define TRANSPORT_TRANSPORT_PIPE_H_INCLUDED 1 #include "logtransport.h" gssize log_transport_pipe_write_method(LogTransport *s, const gpointer buf, gsize buflen); LogTransport *log_transport_pipe_new(gint fd); #endif syslog-ng-syslog-ng-3.13.2/lib/transport/transport-socket.c000066400000000000000000000105031321171025300237240ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "transport-socket.h" #include #include static gssize log_transport_dgram_socket_read_method(LogTransport *s, gpointer buf, gsize buflen, LogTransportAuxData *aux) { LogTransportSocket *self = (LogTransportSocket *) s; gint rc; struct sockaddr_storage ss; socklen_t salen = sizeof(ss); do { rc = recvfrom(self->super.fd, buf, buflen, 0, (struct sockaddr *) &ss, &salen); } while (rc == -1 && errno == EINTR); if (rc != -1 && salen && aux) log_transport_aux_data_set_peer_addr_ref(aux, g_sockaddr_new((struct sockaddr *) &ss, salen)); if (rc == 0) { /* DGRAM sockets should never return EOF, they just need to be read again */ rc = -1; errno = EAGAIN; } return rc; } static gssize log_transport_dgram_socket_write_method(LogTransport *s, const gpointer buf, gsize buflen) { LogTransportSocket *self = (LogTransportSocket *) s; gint rc; do { rc = send(self->super.fd, buf, buflen, 0); } while (rc == -1 && errno == EINTR); /* NOTE: FreeBSD returns ENOBUFS on send() failure instead of indicating * this conditions via poll(). The return of ENOBUFS actually is a send * error and is calulated in IP statistics, so the best is to handle it as * a success. The only alternative would be to return EAGAIN, which could * cause syslog-ng to spin as long as buffer space is unavailable. Since * I'm not sure how much time that would take and I think spinning the CPU * is not a good idea in general, I just drop the packet in this case. * UDP is lossy anyway */ if (rc < 0 && errno == ENOBUFS) return buflen; return rc; } void log_transport_dgram_socket_init_instance(LogTransportSocket *self, gint fd) { log_transport_init_instance(&self->super, fd); self->super.read = log_transport_dgram_socket_read_method; self->super.write = log_transport_dgram_socket_write_method; } LogTransport * log_transport_dgram_socket_new(gint fd) { LogTransportSocket *self = g_new0(LogTransportSocket, 1); log_transport_dgram_socket_init_instance(self, fd); return &self->super; } static gssize log_transport_stream_socket_read_method(LogTransport *s, gpointer buf, gsize buflen, LogTransportAuxData *aux) { LogTransportSocket *self = (LogTransportSocket *) s; gint rc; do { rc = recv(self->super.fd, buf, buflen, 0); } while (rc == -1 && errno == EINTR); return rc; } static gssize log_transport_stream_socket_write_method(LogTransport *s, const gpointer buf, gsize buflen) { LogTransportSocket *self = (LogTransportSocket *) s; gint rc; do { rc = send(self->super.fd, buf, buflen, 0); } while (rc == -1 && errno == EINTR); return rc; } static void log_transport_stream_socket_free_method(LogTransport *s) { shutdown(s->fd, SHUT_RDWR); log_transport_free_method(s); } void log_transport_stream_socket_init_instance(LogTransportSocket *self, gint fd) { log_transport_init_instance(&self->super, fd); self->super.read = log_transport_stream_socket_read_method; self->super.write = log_transport_stream_socket_write_method; self->super.free_fn = log_transport_stream_socket_free_method; } LogTransport * log_transport_stream_socket_new(gint fd) { LogTransportSocket *self = g_new0(LogTransportSocket, 1); log_transport_stream_socket_init_instance(self, fd); return &self->super; } syslog-ng-syslog-ng-3.13.2/lib/transport/transport-socket.h000066400000000000000000000027621321171025300237410ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TRANSPORT_TRANSPORT_SOCKET_H_INCLUDED #define TRANSPORT_TRANSPORT_SOCKET_H_INCLUDED 1 #include "logtransport.h" typedef struct _LogTransportSocket LogTransportSocket; struct _LogTransportSocket { LogTransport super; }; void log_transport_dgram_socket_init_instance(LogTransportSocket *self, gint fd); LogTransport *log_transport_dgram_socket_new(gint fd); void log_transport_stream_socket_init_instance(LogTransportSocket *self, gint fd); LogTransport *log_transport_stream_socket_new(gint fd); #endif syslog-ng-syslog-ng-3.13.2/lib/transport/transport-tls.c000066400000000000000000000120371321171025300232420ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "transport/transport-tls.h" #include "messages.h" #include #include #include typedef struct _LogTransportTLS { LogTransport super; TLSSession *tls_session; } LogTransportTLS; static gssize log_transport_tls_read_method(LogTransport *s, gpointer buf, gsize buflen, LogTransportAuxData *aux) { LogTransportTLS *self = (LogTransportTLS *) s; gint ssl_error; gint rc; /* assume that we need to poll our input for reading unless * SSL_ERROR_WANT_WRITE is specified by libssl */ self->super.cond = G_IO_IN; /* if we have found the peer has a certificate */ if( self->tls_session->peer_info.found ) { log_transport_aux_data_add_nv_pair(aux, ".tls.x509_cn", self->tls_session->peer_info.cn ); log_transport_aux_data_add_nv_pair(aux, ".tls.x509_o", self->tls_session->peer_info.o ); log_transport_aux_data_add_nv_pair(aux, ".tls.x509_ou", self->tls_session->peer_info.ou ); } do { rc = SSL_read(self->tls_session->ssl, buf, buflen); if (rc < 0) { ssl_error = SSL_get_error(self->tls_session->ssl, rc); switch (ssl_error) { case SSL_ERROR_WANT_READ: errno = EAGAIN; break; case SSL_ERROR_WANT_WRITE: /* although we are writing this fd, libssl wants to write. This * happens during renegotiation for example */ self->super.cond = G_IO_OUT; errno = EAGAIN; break; case SSL_ERROR_SYSCALL: /* errno is set accordingly */ break; default: goto tls_error; } } } while (rc == -1 && errno == EINTR); return rc; tls_error: ssl_error = ERR_get_error(); msg_error("SSL error while reading stream", evt_tag_printf("tls_error", "%s:%s:%s", ERR_lib_error_string(ssl_error), ERR_func_error_string(ssl_error), ERR_reason_error_string(ssl_error))); ERR_clear_error(); errno = ECONNRESET; return -1; } static gssize log_transport_tls_write_method(LogTransport *s, const gpointer buf, gsize buflen) { LogTransportTLS *self = (LogTransportTLS *) s; gint ssl_error; gint rc; /* assume that we need to poll our output for writing unless * SSL_ERROR_WANT_READ is specified by libssl */ self->super.cond = G_IO_OUT; rc = SSL_write(self->tls_session->ssl, buf, buflen); if (rc < 0) { ssl_error = SSL_get_error(self->tls_session->ssl, rc); switch (ssl_error) { case SSL_ERROR_WANT_READ: /* although we are writing this fd, libssl wants to read. This * happens during renegotiation for example */ self->super.cond = G_IO_IN; errno = EAGAIN; break; case SSL_ERROR_WANT_WRITE: errno = EAGAIN; break; case SSL_ERROR_SYSCALL: /* errno is set accordingly */ break; default: goto tls_error; } } return rc; tls_error: ssl_error = ERR_get_error(); msg_error("SSL error while writing stream", evt_tag_printf("tls_error", "%s:%s:%s", ERR_lib_error_string(ssl_error), ERR_func_error_string(ssl_error), ERR_reason_error_string(ssl_error))); ERR_clear_error(); errno = EPIPE; return -1; } static void log_transport_tls_free_method(LogTransport *s); LogTransport * log_transport_tls_new(TLSSession *tls_session, gint fd) { LogTransportTLS *self = g_new0(LogTransportTLS, 1); log_transport_init_instance(&self->super, fd); self->super.cond = G_IO_IN | G_IO_OUT; self->super.read = log_transport_tls_read_method; self->super.write = log_transport_tls_write_method; self->super.free_fn = log_transport_tls_free_method; self->tls_session = tls_session; SSL_set_fd(self->tls_session->ssl, fd); return &self->super; } static void log_transport_tls_free_method(LogTransport *s) { LogTransportTLS *self = (LogTransportTLS *) s; tls_session_free(self->tls_session); log_transport_free_method(s); } syslog-ng-syslog-ng-3.13.2/lib/transport/transport-tls.h000066400000000000000000000022701321171025300232450ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #ifndef TLSTRANSPORT_H_INCLUDED #define TLSTRANSPORT_H_INCLUDED #include "transport/logtransport.h" #include "tlscontext.h" LogTransport *log_transport_tls_new(TLSSession *tls_session, gint fd); #endif syslog-ng-syslog-ng-3.13.2/lib/type-hinting.c000066400000000000000000000125761321171025300210010ustar00rootroot00000000000000/* * Copyright (c) 2012-2014 Balabit * Copyright (c) 2012-2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "messages.h" #include "type-hinting.h" #include "template/templates.h" #include #include #include #include GQuark type_hinting_error_quark(void) { return g_quark_from_static_string("type-hinting-error-quark"); } gboolean type_hint_parse(const gchar *hint, TypeHint *out_type, GError **error) { if (hint == NULL) { *out_type = TYPE_HINT_STRING; return TRUE; } if (strcmp(hint, "string") == 0) *out_type = TYPE_HINT_STRING; else if (strcmp(hint, "literal") == 0) *out_type = TYPE_HINT_LITERAL; else if (strcmp(hint, "int32") == 0 || strcmp(hint, "int") == 0) *out_type = TYPE_HINT_INT32; else if (strcmp(hint, "int64") == 0) *out_type = TYPE_HINT_INT64; else if (strcmp(hint, "double") == 0) *out_type = TYPE_HINT_DOUBLE; else if (strcmp(hint, "datetime") == 0) *out_type = TYPE_HINT_DATETIME; else if (strcmp(hint, "boolean") == 0) *out_type = TYPE_HINT_BOOLEAN; else if (strcmp(hint, "default") == 0) *out_type = TYPE_HINT_DEFAULT; else { g_set_error(error, TYPE_HINTING_ERROR, TYPE_HINTING_INVALID_TYPE, "Unknown type specified in type hinting: %s", hint); return FALSE; } return TRUE; } gboolean type_cast_drop_helper(gint drop_flags, const gchar *value, const gchar *type_hint) { if (!(drop_flags & ON_ERROR_SILENT)) { msg_error("Casting error", evt_tag_str("value", value), evt_tag_str("type-hint", type_hint)); } return drop_flags & ON_ERROR_DROP_MESSAGE; } gboolean type_cast_to_boolean(const gchar *value, gboolean *out, GError **error) { if (value[0] == 'T' || value[0] == 't' || value[0] == '1') *out = TRUE; else if (value[0] == 'F' || value[0] == 'f' || value[0] == '0') *out = FALSE; else { if (error) g_set_error(error, TYPE_HINTING_ERROR, TYPE_HINTING_INVALID_CAST, "boolean(%s)", value); return FALSE; } return TRUE; } gboolean type_cast_to_int32(const gchar *value, gint32 *out, GError **error) { gchar *endptr; *out = (gint32)strtol(value, &endptr, 10); if (endptr[0] != '\0') { if (error) g_set_error(error, TYPE_HINTING_ERROR, TYPE_HINTING_INVALID_CAST, "int32(%s)", value); return FALSE; } return TRUE; } gboolean type_cast_to_int64(const gchar *value, gint64 *out, GError **error) { gchar *endptr; *out = (gint64)strtoll(value, &endptr, 10); if (endptr[0] != '\0') { if (error) g_set_error(error, TYPE_HINTING_ERROR, TYPE_HINTING_INVALID_CAST, "int64(%s)", value); return FALSE; } return TRUE; } gboolean type_cast_to_double(const gchar *value, gdouble *out, GError **error) { gchar *endptr = NULL; gboolean success = TRUE; errno = 0; *out = strtod(value, &endptr); if (errno == ERANGE && (*out == HUGE_VAL || *out == -HUGE_VAL)) success = FALSE; if (*out == 0 && endptr == value) success = FALSE; if (endptr[0] != '\0') success = FALSE; if (!success && error) { g_set_error(error, TYPE_HINTING_ERROR, TYPE_HINTING_INVALID_CAST, "double(%s)", value); } return success; } gboolean type_cast_to_datetime_int(const gchar *value, guint64 *out, GError **error) { gchar *endptr; *out = (gint64)strtoll(value, &endptr, 10) * 1000; if (endptr[0] == '.') { gsize len = strlen(endptr) - 1, p; gchar *e, tmp[4]; glong i; if (len > 3) len = 3; memcpy(tmp, endptr + 1, len); tmp[len] = '\0'; i = strtoll(tmp, &e, 10); if (e[0] != '\0') { if (error) g_set_error(error, TYPE_HINTING_ERROR, TYPE_HINTING_INVALID_CAST, "datetime(%s)", value); return FALSE; } for (p = 3 - len; p > 0; p--) i *= 10; *out += i; } else if (endptr[0] != '\0') { if (error) g_set_error(error, TYPE_HINTING_ERROR, TYPE_HINTING_INVALID_CAST, "datetime(%s)", value); return FALSE; } return TRUE; } gboolean type_cast_to_datetime_str(const gchar *value, const char *format, gchar **out, GError **error) { if (error) g_set_error(error, TYPE_HINTING_ERROR, TYPE_HINTING_INVALID_CAST, "datetime_str is not supported yet"); return FALSE; } syslog-ng-syslog-ng-3.13.2/lib/type-hinting.h000066400000000000000000000042601321171025300207750ustar00rootroot00000000000000/* * Copyright (c) 2012-2014 Balabit * Copyright (c) 2012-2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TYPE_HINTING_H #define TYPE_HINTING_H #include "syslog-ng.h" #define TYPE_HINTING_ERROR type_hinting_error_quark() GQuark type_hinting_error_quark(void); enum TypeHintingError { TYPE_HINTING_INVALID_TYPE, TYPE_HINTING_INVALID_CAST, }; typedef enum { TYPE_HINT_STRING, TYPE_HINT_LITERAL, TYPE_HINT_BOOLEAN, TYPE_HINT_INT32, TYPE_HINT_INT64, TYPE_HINT_DOUBLE, TYPE_HINT_DATETIME, TYPE_HINT_DEFAULT, } TypeHint; gboolean type_hint_parse(const gchar *hint, TypeHint *out_hint, GError **error); gboolean type_cast_drop_helper(gint drop_flags, const gchar *value, const gchar *type_hint); gboolean type_cast_to_boolean(const gchar *value, gboolean *out, GError **error); gboolean type_cast_to_int32(const gchar *value, gint32 *out, GError **error); gboolean type_cast_to_int64(const gchar *value, gint64 *out, GError **error); gboolean type_cast_to_double(const gchar *value, gdouble *out, GError **error); gboolean type_cast_to_datetime_int(const gchar *value, guint64 *out, GError **error); gboolean type_cast_to_datetime_str(const gchar *value, const char *format, gchar **out, GError **error); #endif syslog-ng-syslog-ng-3.13.2/lib/userdb.c000066400000000000000000000037641321171025300176450ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "userdb.h" #include #include #include #include #include gboolean resolve_user(const char *user, gint *uid) { struct passwd *pw; gchar *endptr; *uid = 0; if (!(*user)) return FALSE; *uid = strtol(user, &endptr, 0); if (*endptr) { pw = getpwnam(user); if (!pw) return FALSE; *uid = pw->pw_uid; } return TRUE; } gboolean resolve_group(const char *group, gint *gid) { struct group *gr; gchar *endptr; *gid = 0; if (!(*group)) return FALSE; *gid = strtol(group, &endptr, 0); if (*endptr) { gr = getgrnam(group); if (!gr) return FALSE; *gid = gr->gr_gid; } return TRUE; } gboolean resolve_user_group(char *arg, gint *uid, gint *gid) { char *user, *group; *uid = 0; user = strtok(arg, ":."); group = strtok(NULL, ""); if (user && !resolve_user(user, uid)) return FALSE; if (group && !resolve_group(group, gid)) return FALSE; return TRUE; } syslog-ng-syslog-ng-3.13.2/lib/userdb.h000066400000000000000000000025031321171025300176400ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef USERDB_H_INCLUDED #define USERDB_H_INCLUDED 1 #include "syslog-ng.h" /* deliberately using gint here as the extremal values may not fit into uid_t/gid_t */ gboolean resolve_user(const char *user, gint *uid); gboolean resolve_group(const char *group, gint *gid); gboolean resolve_user_group(char *arg, gint *uid, gint *gid); #endif syslog-ng-syslog-ng-3.13.2/lib/utf8utils.c000066400000000000000000000221121321171025300203140ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "utf8utils.h" #include "str-utils.h" static inline gboolean _is_character_unsafe(gunichar uchar, const gchar *unsafe_chars) { /* These G_LIKELY/UNLIKELY clauses assume that most characters are in the * ASCII range and that unsafe characters are not specified. Since this function * is called for each and every character generated by format-json/format-welf * it does make a difference. */ if (G_UNLIKELY(uchar >= 256)) return FALSE; if (G_LIKELY(!unsafe_chars)) return FALSE; return _strchr_optimized_for_single_char_haystack(unsafe_chars, (gchar) uchar) != NULL; } /** * This function escapes an unsanitized input (e.g. that can contain binary * characters, and produces an escaped format that can be deescaped in need, * which is guaranteed to be utf8 clean. The major difference between * "binary" and "text" form is that the receiver is able to cope with \xXX * sequences that can incorporate invalid utf8 sequences when decoded. With * "text" format, we never embed anything that would become not valid utf8 * when decoded. * * Here are the rules that the routine follows: * - well-known control characters are escaped (0x0a as \n and so on) * - other control characters as per control_format * - backslash is escaped as \\ * - any additional characters (only ASCII is supported) as \ * - invalid utf8 sequences are converted as per invalid_format * - utf8 characters are reproduced as is */ static gsize _append_escaped_utf8_character(GString *escaped_output, const gchar **raw, gssize raw_len, const gchar *unsafe_chars, const gchar *control_format, const gchar *invalid_format) { const gchar *char_ptr = *raw; gunichar uchar = g_utf8_get_char_validated(char_ptr, raw_len); if (G_UNLIKELY(uchar == (gunichar) -1 || uchar == (gunichar) -2)) { g_string_append_printf(escaped_output, invalid_format, *(guint8 *) char_ptr); (*raw)++; return 1; } else if (G_UNLIKELY(uchar < 32 || uchar == '\\')) { switch (uchar) { case '\b': g_string_append(escaped_output, "\\b"); break; case '\f': g_string_append(escaped_output, "\\f"); break; case '\n': g_string_append(escaped_output, "\\n"); break; case '\r': g_string_append(escaped_output, "\\r"); break; case '\t': g_string_append(escaped_output, "\\t"); break; case '\\': g_string_append(escaped_output, "\\\\"); break; default: g_string_append_printf(escaped_output, control_format, uchar); break; } } else if (G_UNLIKELY(_is_character_unsafe(uchar, unsafe_chars))) g_string_append_printf(escaped_output, "\\%c", (gchar) uchar); else g_string_append_unichar_optimized(escaped_output, uchar); *raw = g_utf8_next_char(char_ptr); return *raw - char_ptr; } static void _append_unsafe_utf8_as_escaped_with_specific_length(GString *escaped_output, const gchar *raw, gsize raw_len, const gchar *unsafe_chars, const gchar *control_format, const gchar *invalid_format) { const gchar *raw_end = raw + raw_len; while (raw < raw_end) _append_escaped_utf8_character(escaped_output, &raw, raw_end - raw, unsafe_chars, control_format, invalid_format); } static void _append_unsafe_utf8_as_escaped_nul_terminated(GString *escaped_output, const gchar *raw, const gchar *unsafe_chars, const gchar *control_format, const gchar *invalid_format) { _append_unsafe_utf8_as_escaped_with_specific_length(escaped_output, raw, strlen(raw), unsafe_chars, control_format, invalid_format); } /** * @see _append_escaped_utf8_character() */ static void _append_unsafe_utf8_as_escaped(GString *escaped_output, const gchar *raw, gssize raw_len, const gchar *unsafe_chars, const gchar *control_format, const gchar *invalid_format) { if (raw_len < 0) _append_unsafe_utf8_as_escaped_nul_terminated(escaped_output, raw, unsafe_chars, control_format, invalid_format); else _append_unsafe_utf8_as_escaped_with_specific_length(escaped_output, raw, raw_len, unsafe_chars, control_format, invalid_format); } /** * This function escapes an unsanitized input (e.g. that can contain binary * characters, and produces an escaped format that can be deescaped in need, * which is guaranteed to be utf8 clean. The major difference between * "binary" and "text" form is that the receiver is able to cope with \xXX * sequences that can incorporate invalid utf8 sequences when decoded. With * "text" format, we never embed anything that would become not valid utf8 * when decoded. * * Here are the rules that the routine follows: * - well-known control characters are escaped (0x0a as \n and so on) * - other control characters as per control_format (\xXX) * - backslash is escaped as \\ * - any additional characters (only ASCII is supported) as \ * - invalid utf8 sequences are converted as per invalid_format (\xXX) * - utf8 characters are reproduced as is * * This is basically meant to be used when sending data to * 8 bit clean receivers, e.g. syslog-ng or WELF. * @see _append_unsafe_utf8_as_escaped() */ void append_unsafe_utf8_as_escaped_binary(GString *escaped_string, const gchar *str, gssize str_len, const gchar *unsafe_chars) { _append_unsafe_utf8_as_escaped(escaped_string, str, str_len, unsafe_chars, "\\x%02x", "\\x%02x"); } gchar * convert_unsafe_utf8_to_escaped_binary(const gchar *str, gssize str_len, const gchar *unsafe_chars) { if (str_len < 0) str_len = strlen(str); GString *escaped_string = g_string_sized_new(str_len); append_unsafe_utf8_as_escaped_binary(escaped_string, str, str_len, unsafe_chars); return g_string_free(escaped_string, FALSE); } /** * This function escapes an unsanitized input (e.g. that can contain binary * characters, and produces an escaped format that can be deescaped in need, * which is guaranteed to be utf8 clean. The major difference between * "binary" and "text" form is that the receiver is able to cope with \xXX * sequences that can incorporate invalid utf8 sequences when decoded. With * "text" format, we never embed anything that would become not valid utf8 * when decoded. * * Here are the rules that the routine follows: * - well-known control characters are escaped (0x0a as \n and so on) * - other control characters as per control_format (\u00XX) * - backslash is escaped as \\ * - any additional characters (only ASCII is supported) as \ * - invalid utf8 sequences are converted as per invalid_format (\\xXX) * - utf8 characters are reproduced as is * * This is basically meant to be used when sending data to * utf8 only receivers, e.g. JSON. * @see _append_unsafe_utf8_as_escaped() */ void append_unsafe_utf8_as_escaped_text(GString *escaped_string, const gchar *str, gssize str_len, const gchar *unsafe_chars) { _append_unsafe_utf8_as_escaped(escaped_string, str, str_len, unsafe_chars, "\\u%04x", "\\\\x%02x"); } gchar * convert_unsafe_utf8_to_escaped_text(const gchar *str, gssize str_len, const gchar *unsafe_chars) { if (str_len < 0) str_len = strlen(str); GString *escaped_string = g_string_sized_new(str_len); append_unsafe_utf8_as_escaped_text(escaped_string, str, str_len, unsafe_chars); return g_string_free(escaped_string, FALSE); } syslog-ng-syslog-ng-3.13.2/lib/utf8utils.h000066400000000000000000000032741321171025300203310ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef UTF8UTILS_H_INCLUDED #define UTF8UTILS_H_INCLUDED #include "syslog-ng.h" void append_unsafe_utf8_as_escaped_binary(GString *escaped_string, const gchar *str, gssize str_len, const gchar *unsafe_chars); gchar *convert_unsafe_utf8_to_escaped_binary(const gchar *str, gssize str_len, const gchar *unsafe_chars); void append_unsafe_utf8_as_escaped_text(GString *escaped_string, const gchar *str, gssize str_len, const gchar *unsafe_chars); gchar *convert_unsafe_utf8_to_escaped_text(const gchar *str, gssize str_len, const gchar *unsafe_chars); #endif syslog-ng-syslog-ng-3.13.2/lib/uuid.c000066400000000000000000000036441321171025300173240ustar00rootroot00000000000000/* * Copyright (c) 2010-2012 Balabit * Copyright (c) 2010-2012 Balázs Scheidler * Copyright (c) 2012 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "uuid.h" #include #include void uuid_gen_random(gchar *buf, gsize buflen) { union { struct { guint32 time_low; guint16 time_mid; guint16 time_hi_and_version; guint8 clk_seq_hi_res; guint8 clk_seq_low; guint8 node[6]; guint16 node_low; guint32 node_hi; }; guchar __rnd[16]; } uuid; RAND_bytes(uuid.__rnd, sizeof(uuid)); uuid.clk_seq_hi_res = (uuid.clk_seq_hi_res & ~0xC0) | 0x80; uuid.time_hi_and_version = htons((uuid.time_hi_and_version & ~0xF000) | 0x4000); g_snprintf(buf, buflen, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, uuid.clk_seq_hi_res, uuid.clk_seq_low, uuid.node[0], uuid.node[1], uuid.node[2], uuid.node[3], uuid.node[4], uuid.node[5]); } syslog-ng-syslog-ng-3.13.2/lib/uuid.h000066400000000000000000000022461321171025300173260ustar00rootroot00000000000000/* * Copyright (c) 2010-2012 Balabit * Copyright (c) 2010-2012 Balázs Scheidler * Copyright (c) 2012 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #ifndef UUID_H_INCLUDED #define UUID_H_INCLUDED 1 #include "syslog-ng.h" void uuid_gen_random(gchar *buf, gsize buflen); #endif syslog-ng-syslog-ng-3.13.2/lib/value-pairs/000077500000000000000000000000001321171025300204335ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/value-pairs/CMakeLists.txt000066400000000000000000000004611321171025300231740ustar00rootroot00000000000000set(VALUE_PAIRS_HEADERS value-pairs/value-pairs.h value-pairs/transforms.h value-pairs/cmdline.h value-pairs/evttag.h PARENT_SCOPE) set(VALUE_PAIRS_SOURCES value-pairs/value-pairs.c value-pairs/transforms.c value-pairs/cmdline.c value-pairs/evttag.c PARENT_SCOPE) syslog-ng-syslog-ng-3.13.2/lib/value-pairs/Makefile.am000066400000000000000000000006211321171025300224660ustar00rootroot00000000000000value_pairsincludedir = ${pkgincludedir}/value-pairs value_pairsinclude_HEADERS = \ lib/value-pairs/value-pairs.h \ lib/value-pairs/transforms.h \ lib/value-pairs/cmdline.h \ lib/value-pairs/evttag.h value_pairs_sources = \ lib/value-pairs/value-pairs.c \ lib/value-pairs/transforms.c \ lib/value-pairs/cmdline.c \ lib/value-pairs/evttag.c include lib/value-pairs/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/lib/value-pairs/cmdline.c000066400000000000000000000270001321171025300222110ustar00rootroot00000000000000/* * Copyright (c) 2011-2015 Balabit * Copyright (c) 2011-2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "value-pairs/cmdline.h" #include #include #include /******************************************************************************* * Command line parser *******************************************************************************/ static void vp_cmdline_parse_rekey_finish (gpointer data) { gpointer *args = (gpointer *) data; ValuePairs *vp = (ValuePairs *) args[1]; ValuePairsTransformSet *vpts = (ValuePairsTransformSet *) args[2]; if (vpts) value_pairs_add_transforms (vp, args[2]); args[2] = NULL; g_free(args[3]); args[3] = NULL; } static void vp_cmdline_start_key(gpointer data, const gchar *key) { gpointer *args = (gpointer *) data; vp_cmdline_parse_rekey_finish (data); args[3] = g_strdup(key); } static ValuePairsTransformSet * vp_cmdline_rekey_verify (gchar *key, ValuePairsTransformSet *vpts, gpointer data) { gpointer *args = (gpointer *)data; if (!vpts) { if (!key) return NULL; vpts = value_pairs_transform_set_new (key); vp_cmdline_parse_rekey_finish (data); args[2] = vpts; return vpts; } return vpts; } /* parse a value-pair specification from a command-line like environment */ static gboolean vp_cmdline_parse_scope(const gchar *option_name, const gchar *value, gpointer data, GError **error) { gpointer *args = (gpointer *) data; ValuePairs *vp = (ValuePairs *) args[1]; gchar **scopes; gint i; vp_cmdline_parse_rekey_finish (data); scopes = g_strsplit (value, ",", -1); for (i = 0; scopes[i] != NULL; i++) { if (!value_pairs_add_scope (vp, scopes[i])) { g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Error parsing value-pairs: unknown scope %s", scopes[i]); g_strfreev (scopes); return FALSE; } } g_strfreev (scopes); return TRUE; } static gboolean vp_cmdline_parse_exclude(const gchar *option_name, const gchar *value, gpointer data, GError **error) { gpointer *args = (gpointer *) data; ValuePairs *vp = (ValuePairs *) args[1]; gchar **excludes; gint i; vp_cmdline_parse_rekey_finish (data); excludes = g_strsplit(value, ",", -1); for (i = 0; excludes[i] != NULL; i++) value_pairs_add_glob_pattern(vp, excludes[i], FALSE); g_strfreev(excludes); return TRUE; } static gboolean vp_cmdline_parse_key(const gchar *option_name, const gchar *value, gpointer data, GError **error) { gpointer *args = (gpointer *) data; ValuePairs *vp = (ValuePairs *) args[1]; gchar **keys; gint i; vp_cmdline_start_key(data, value); keys = g_strsplit(value, ",", -1); for (i = 0; keys[i] != NULL; i++) value_pairs_add_glob_pattern(vp, keys[i], TRUE); g_strfreev(keys); return TRUE; } static gboolean vp_cmdline_parse_rekey(const gchar *option_name, const gchar *value, gpointer data, GError **error) { vp_cmdline_start_key(data, value); return TRUE; } static void value_pairs_parse_type(gchar *spec, gchar **value, gchar **type) { char *sp, *ep; *type = NULL; sp = spec; while (g_ascii_isalnum(*sp) || (*sp) == '_') sp++; while (*sp == ' ' || *sp == '\t') sp++; if (*sp != '(' || !((g_ascii_toupper(spec[0]) >= 'A' && g_ascii_toupper(spec[0]) <= 'Z') || spec[0] == '_')) { *value = spec; return; } ep = strchr(sp, ')'); if (ep == NULL || ep[1] != '\0') { *value = spec; return; } *value = sp + 1; *type = spec; sp[0] = '\0'; ep[0] = '\0'; } static gboolean vp_cmdline_parse_pair (const gchar *option_name, const gchar *value, gpointer data, GError **error) { gpointer *args = (gpointer *) data; ValuePairs *vp = (ValuePairs *) args[1]; GlobalConfig *cfg = (GlobalConfig *) args[0]; gchar **kv, *v, *t; gboolean res = FALSE; LogTemplate *template; vp_cmdline_parse_rekey_finish (data); if (strchr(value, '=') == NULL) { g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Error parsing value-pairs: expected an equal sign in key=value pair"); return FALSE; } kv = g_strsplit(value, "=", 2); value_pairs_parse_type(kv[1], &v, &t); template = log_template_new(cfg, NULL); if (!log_template_compile(template, v, error)) goto error; if (!log_template_set_type_hint(template, t, error)) goto error; value_pairs_add_pair(vp, kv[0], template); res = TRUE; error: log_template_unref(template); g_strfreev(kv); return res; } static gboolean vp_cmdline_parse_pair_or_key (const gchar *option_name, const gchar *value, gpointer data, GError **error) { if (strchr(value, '=') == NULL) return vp_cmdline_parse_key(option_name, value, data, error); else return vp_cmdline_parse_pair(option_name, value, data, error); } static gboolean vp_cmdline_parse_subkeys(const gchar *option_name, const gchar *value, gpointer data, GError **error) { gpointer *args = (gpointer *) data; ValuePairs *vp = (ValuePairs *) args[1]; ValuePairsTransformSet *vpts = (ValuePairsTransformSet *) args[2]; if (!value[0]) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, "Error parsing value-pairs: --subkeys requires a non-empty argument"); return FALSE; } GString *prefix = g_string_new(value); g_string_append_c(prefix, '*'); value_pairs_add_glob_pattern(vp, prefix->str, TRUE); vp_cmdline_start_key(data, prefix->str); vpts = vp_cmdline_rekey_verify(prefix->str, vpts, data); if (!vpts) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, "Error parsing value-pairs: --subkeys failed to create key"); g_string_free(prefix, TRUE); return FALSE; } value_pairs_transform_set_add_func (vpts, value_pairs_new_transform_replace_prefix(value, "")); g_string_free(prefix, TRUE); return TRUE; } static gboolean vp_cmdline_parse_rekey_replace_prefix (const gchar *option_name, const gchar *value, gpointer data, GError **error) { gpointer *args = (gpointer *) data; ValuePairsTransformSet *vpts = (ValuePairsTransformSet *) args[2]; gchar *key = (gchar *) args[3]; gchar **kv; vpts = vp_cmdline_rekey_verify (key, vpts, data); if (!vpts) { g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, "Error parsing value-pairs: --replace-prefix used without --key or --rekey"); return FALSE; } if (!g_strstr_len (value, strlen (value), "=")) { g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Error parsing value-pairs: rekey replace-prefix construct should be in the format string=replacement"); return FALSE; } kv = g_strsplit(value, "=", 2); value_pairs_transform_set_add_func (vpts, value_pairs_new_transform_replace_prefix (kv[0], kv[1])); g_free (kv[0]); g_free (kv[1]); g_free (kv); return TRUE; } static gboolean vp_cmdline_parse_rekey_add_prefix (const gchar *option_name, const gchar *value, gpointer data, GError **error) { gpointer *args = (gpointer *) data; ValuePairsTransformSet *vpts = (ValuePairsTransformSet *) args[2]; gchar *key = (gchar *) args[3]; vpts = vp_cmdline_rekey_verify (key, vpts, data); if (!vpts) { g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, "Error parsing value-pairs: --add-prefix used without --key or --rekey"); return FALSE; } value_pairs_transform_set_add_func (vpts, value_pairs_new_transform_add_prefix (value)); return TRUE; } static gboolean vp_cmdline_parse_rekey_shift (const gchar *option_name, const gchar *value, gpointer data, GError **error) { gpointer *args = (gpointer *) data; ValuePairsTransformSet *vpts = (ValuePairsTransformSet *) args[2]; gchar *key = (gchar *) args[3]; vpts = vp_cmdline_rekey_verify (key, vpts, data); if (!vpts) { g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, "Error parsing value-pairs: --shift used without --key or --rekey"); return FALSE; } value_pairs_transform_set_add_func (vpts, value_pairs_new_transform_shift (atoi (value))); return TRUE; } ValuePairs * value_pairs_new_from_cmdline (GlobalConfig *cfg, gint *argc, gchar ***argv, gboolean ignore_unknown_options, GError **error) { ValuePairs *vp; GOptionContext *ctx; GOptionEntry vp_options[] = { { "scope", 's', 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_scope, NULL, NULL }, { "exclude", 'x', 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_exclude, NULL, NULL }, { "key", 'k', 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_key, NULL, NULL }, { "rekey", 'r', 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_rekey, NULL, NULL }, { "pair", 'p', 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_pair, NULL, NULL }, { "shift", 'S', 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_rekey_shift, NULL, NULL }, { "add-prefix", 'A', 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_rekey_add_prefix, NULL, NULL }, { "replace-prefix", 'R', 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_rekey_replace_prefix, NULL, NULL }, { "replace", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_rekey_replace_prefix, NULL, NULL }, { "subkeys", 0, 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_subkeys, NULL, NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_CALLBACK, vp_cmdline_parse_pair_or_key, NULL, NULL }, { NULL } }; GOptionGroup *og; gpointer user_data_args[4]; gboolean success; vp = value_pairs_new(); user_data_args[0] = cfg; user_data_args[1] = vp; user_data_args[2] = NULL; user_data_args[3] = NULL; ctx = g_option_context_new("value-pairs"); og = g_option_group_new(NULL, NULL, NULL, user_data_args, NULL); g_option_group_add_entries(og, vp_options); g_option_context_set_main_group(ctx, og); g_option_context_set_ignore_unknown_options(ctx, ignore_unknown_options); success = g_option_context_parse(ctx, argc, argv, error); vp_cmdline_parse_rekey_finish(user_data_args); g_option_context_free(ctx); if (!success) { value_pairs_unref(vp); vp = NULL; } return vp; } syslog-ng-syslog-ng-3.13.2/lib/value-pairs/cmdline.h000066400000000000000000000024271321171025300222240ustar00rootroot00000000000000/* * Copyright (c) 2011-2015 Balabit * Copyright (c) 2011-2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef VALUE_PAIRS_CMDLINE_H_INCLUDED #define VALUE_PAIRS_CMDLINE_H_INCLUDED 1 #include "value-pairs/value-pairs.h" ValuePairs *value_pairs_new_from_cmdline(GlobalConfig *cfg, gint *argc, gchar ***argv, gboolean ignore_unknown_options, GError **error); #endif syslog-ng-syslog-ng-3.13.2/lib/value-pairs/evttag.c000066400000000000000000000033421321171025300220730ustar00rootroot00000000000000/* * Copyright (c) 2011-2015 Balabit * Copyright (c) 2011-2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "value-pairs/evttag.h" static gboolean _append_pair_to_debug_string(const gchar *name, TypeHint type, const gchar *value, gsize value_len, gpointer user_data) { GString *text = (GString *) user_data; g_string_append_printf(text, "%s=%s ",name, value); return FALSE; } EVTTAG * evt_tag_value_pairs(const char *key, ValuePairs *vp, LogMessage *msg, gint32 seq_num, gint time_zone_mode, LogTemplateOptions *template_options) { GString *debug_text = g_string_new(""); EVTTAG *result; value_pairs_foreach(vp, _append_pair_to_debug_string, msg, seq_num, time_zone_mode, template_options, debug_text); result = evt_tag_str(key, debug_text->str); g_string_free(debug_text, TRUE); return result; } syslog-ng-syslog-ng-3.13.2/lib/value-pairs/evttag.h000066400000000000000000000024361321171025300221030ustar00rootroot00000000000000/* * Copyright (c) 2011-2015 Balabit * Copyright (c) 2011-2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef VALUE_PAIRS_EVTTAG_H_INCLUDED #define VALUE_PAIRS_EVTTAG_H_INCLUDED 1 #include "value-pairs.h" #include "messages.h" EVTTAG *evt_tag_value_pairs(const char* key, ValuePairs *vp, LogMessage *msg, gint32 seq_num, gint time_zone_mode, LogTemplateOptions *template_options); #endif syslog-ng-syslog-ng-3.13.2/lib/value-pairs/tests/000077500000000000000000000000001321171025300215755ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/lib/value-pairs/tests/Makefile.am000066400000000000000000000006031321171025300236300ustar00rootroot00000000000000lib_value_pairs_tests_TESTS = \ lib/value-pairs/tests/test_value_pairs \ lib/value-pairs/tests/test_value_pairs_walk check_PROGRAMS += \ ${lib_value_pairs_tests_TESTS} lib_value_pairs_tests_test_value_pairs_LDADD = $(TEST_LDADD) lib_value_pairs_tests_test_value_pairs_LDFLAGS = $(PREOPEN_SYSLOGFORMAT) lib_value_pairs_tests_test_value_pairs_walk_LDADD = \ $(TEST_LDADD) syslog-ng-syslog-ng-3.13.2/lib/value-pairs/tests/test_value_pairs.c000066400000000000000000000235731321171025300253240ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Laszlo Budai * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "value-pairs/value-pairs.h" #include "logmsg/logmsg.h" #include "apphook.h" #include "cfg.h" #include "plugin.h" #include gboolean success = TRUE; gboolean vp_keys_foreach(const gchar *name, TypeHint type, const gchar *value, gsize value_len, gpointer user_data) { gpointer *args = (gpointer *) user_data; GList **keys = (GList **) args[0]; gboolean *test_key_found = (gboolean *) args[1]; if (strcmp(name, "test.key") != 0) *keys = g_list_insert_sorted(*keys, g_strdup(name), (GCompareFunc) strcmp); else *test_key_found = TRUE; return FALSE; } void cat_keys_foreach(const gchar *name, gpointer user_data) { GString *res = (GString *) user_data; if (res->len > 0) g_string_append_c(res, ','); g_string_append(res, name); } MsgFormatOptions parse_options; LogTemplateOptions template_options; LogMessage * create_message(void) { LogMessage *msg; const gchar *text = "<134>1 2009-10-16T11:51:56+02:00 exchange.macartney.esbjerg MSExchange_ADAccess 20208 _MSGID_ [origin ip=\"exchange.macartney.esbjerg\"][meta sequenceId=\"191732\" sysUpTime=\"68807696\"][EventData@18372.4 Data=\"MSEXCHANGEOWAAPPPOOL.CONFIG\\\" -W \\\"\\\" -M 1 -AP \\\"MSEXCHANGEOWAAPPPOOL5244fileserver.macartney.esbjerg CDG 1 7 7 1 0 1 1 7 1 mail.macartney.esbjerg CDG 1 7 7 1 0 1 1 7 1 maindc.macartney.esbjerg CD- 1 6 6 0 0 1 1 6 1 \"][Keywords@18372.4 Keyword=\"Classic\"] ApplicationMSExchangeADAccess: message"; const gchar *unset_nvpair = "unset_value"; msg = log_msg_new(text, strlen(text), NULL, &parse_options); log_msg_set_tag_by_name(msg, "almafa"); log_msg_set_value_by_name(msg, unset_nvpair, "value that has been unset", -1); log_msg_unset_value_by_name(msg, unset_nvpair); return msg; } static LogTemplate * create_template(const gchar *type_hint_string, const gchar *template_string) { LogTemplate *template; template = log_template_new(configuration, NULL); log_template_compile(template, template_string, NULL); log_template_set_type_hint(template, type_hint_string, NULL); return template; } void testcase(const gchar *scope, const gchar *exclude, const gchar *expected, GPtrArray *transformers) { ValuePairs *vp; GList *vp_keys_list = NULL; GString *vp_keys; LogMessage *msg = create_message(); gpointer args[2]; gboolean test_key_found = FALSE; LogTemplate *template; vp_keys = g_string_sized_new(0); vp = value_pairs_new(); value_pairs_add_scope(vp, scope); if (exclude) value_pairs_add_glob_pattern(vp, exclude, FALSE); template = create_template("string", "$MESSAGE"); value_pairs_add_pair(vp, "test.key", template); log_template_unref(template); if (transformers) { gint i; ValuePairsTransformSet *vpts = value_pairs_transform_set_new("*"); for (i = 0; i < transformers->len; i++) value_pairs_transform_set_add_func(vpts, g_ptr_array_index(transformers, i)); value_pairs_add_transforms(vp, vpts); } args[0] = &vp_keys_list; args[1] = &test_key_found; value_pairs_foreach(vp, vp_keys_foreach, msg, 11, LTZ_LOCAL, &template_options, args); g_list_foreach(vp_keys_list, (GFunc) cat_keys_foreach, vp_keys); if (strcmp(vp_keys->str, expected) != 0) { fprintf(stderr, "Scope keys mismatch, scope=[%s], exclude=[%s], value=[%s], expected=[%s]\n", scope, exclude ? exclude : "(none)", vp_keys->str, expected); success = FALSE; } if (!test_key_found) { fprintf(stderr, "test.key is not found in the result set\n"); success = FALSE; } g_list_foreach(vp_keys_list, (GFunc) g_free, NULL); g_list_free(vp_keys_list); g_string_free(vp_keys, TRUE); log_msg_unref(msg); value_pairs_unref(vp); } int main(int argc, char *argv[]) { GPtrArray *transformers; GlobalConfig *cfg; app_startup(); putenv("TZ=MET-1METDST"); tzset(); cfg = cfg_new_snippet(); cfg_load_module(cfg, "syslogformat"); msg_format_options_defaults(&parse_options); msg_format_options_init(&parse_options, cfg); parse_options.flags |= LP_SYSLOG_PROTOCOL; testcase("rfc3164", NULL, "DATE,FACILITY,HOST,MESSAGE,PID,PRIORITY,PROGRAM", NULL); testcase("core", NULL, "DATE,FACILITY,HOST,MESSAGE,PID,PRIORITY,PROGRAM", NULL); testcase("base", NULL, "DATE,FACILITY,HOST,MESSAGE,PID,PRIORITY,PROGRAM", NULL); testcase("rfc5424", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,DATE,FACILITY,HOST,MESSAGE,MSGID,PID,PRIORITY,PROGRAM", NULL); testcase("syslog-proto", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,DATE,FACILITY,HOST,MESSAGE,MSGID,PID,PRIORITY,PROGRAM", NULL); testcase("selected-macros", NULL, "DATE,FACILITY,HOST,MESSAGE,PID,PRIORITY,PROGRAM,SEQNUM,SOURCEIP,TAGS", NULL); testcase("nv-pairs", NULL, "HOST,MESSAGE,MSGID,PID,PROGRAM", NULL); testcase("dot-nv-pairs", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip", NULL); testcase("sdata", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip", NULL); testcase("all-nv-pairs", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,HOST,MESSAGE,MSGID,PID,PROGRAM", NULL); testcase("everything", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,AMPM,BSDTAG,C_DATE,C_DAY,C_FULLDATE,C_HOUR,C_ISODATE,C_MIN,C_MONTH,C_MONTH_ABBREV,C_MONTH_NAME,C_MONTH_WEEK,C_SEC,C_STAMP,C_TZ,C_TZOFFSET,C_UNIXTIME,C_WEEK,C_WEEKDAY,C_WEEK_DAY,C_WEEK_DAY_ABBREV,C_WEEK_DAY_NAME,C_YEAR,C_YEAR_DAY,DATE,DAY,FACILITY,FACILITY_NUM,FULLDATE,HOST,HOSTID,HOUR,HOUR12,ISODATE,LEVEL,LEVEL_NUM,LOGHOST,MESSAGE,MIN,MONTH,MONTH_ABBREV,MONTH_NAME,MONTH_WEEK,MSEC,MSG,MSGHDR,MSGID,PID,PRI,PRIORITY,PROGRAM,R_AMPM,R_DATE,R_DAY,R_FULLDATE,R_HOUR,R_HOUR12,R_ISODATE,R_MIN,R_MONTH,R_MONTH_ABBREV,R_MONTH_NAME,R_MONTH_WEEK,R_MSEC,R_SEC,R_STAMP,R_TZ,R_TZOFFSET,R_UNIXTIME,R_USEC,R_WEEK,R_WEEKDAY,R_WEEK_DAY,R_WEEK_DAY_ABBREV,R_WEEK_DAY_NAME,R_YEAR,R_YEAR_DAY,SDATA,SEC,SEQNUM,SOURCEIP,STAMP,SYSUPTIME,S_AMPM,S_DATE,S_DAY,S_FULLDATE,S_HOUR,S_HOUR12,S_ISODATE,S_MIN,S_MONTH,S_MONTH_ABBREV,S_MONTH_NAME,S_MONTH_WEEK,S_MSEC,S_SEC,S_STAMP,S_TZ,S_TZOFFSET,S_UNIXTIME,S_USEC,S_WEEK,S_WEEKDAY,S_WEEK_DAY,S_WEEK_DAY_ABBREV,S_WEEK_DAY_NAME,S_YEAR,S_YEAR_DAY,TAG,TAGS,TZ,TZOFFSET,UNIXTIME,USEC,WEEK,WEEKDAY,WEEK_DAY,WEEK_DAY_ABBREV,WEEK_DAY_NAME,YEAR,YEAR_DAY", NULL); testcase("nv-pairs", ".SDATA.*", "HOST,MESSAGE,MSGID,PID,PROGRAM", NULL); /* tests that the exclude patterns do not affect explicitly added * keys. The testcase function adds a "test.key" and then checks if * it is indeed present. Even if it would be excluded it still has * to be in the result set. */ testcase("rfc3164", "test.*", "DATE,FACILITY,HOST,MESSAGE,PID,PRIORITY,PROGRAM", NULL); /* tests that excluding works even when the key would be in the * default set. */ testcase("nv-pairs", "MESSAGE", "HOST,MSGID,PID,PROGRAM", NULL); /* test the value-pair transformators */ transformers = g_ptr_array_new(); g_ptr_array_add(transformers, value_pairs_new_transform_add_prefix("__")); g_ptr_array_add(transformers, value_pairs_new_transform_shift(2)); g_ptr_array_add(transformers, value_pairs_new_transform_replace_prefix("C_", "CC_")); testcase("everything", NULL, ".SDATA.EventData@18372.4.Data,.SDATA.Keywords@18372.4.Keyword,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,AMPM,BSDTAG,CC_DATE,CC_DAY,CC_FULLDATE,CC_HOUR,CC_ISODATE,CC_MIN,CC_MONTH,CC_MONTH_ABBREV,CC_MONTH_NAME,CC_MONTH_WEEK,CC_SEC,CC_STAMP,CC_TZ,CC_TZOFFSET,CC_UNIXTIME,CC_WEEK,CC_WEEKDAY,CC_WEEK_DAY,CC_WEEK_DAY_ABBREV,CC_WEEK_DAY_NAME,CC_YEAR,CC_YEAR_DAY,DATE,DAY,FACILITY,FACILITY_NUM,FULLDATE,HOST,HOSTID,HOUR,HOUR12,ISODATE,LEVEL,LEVEL_NUM,LOGHOST,MESSAGE,MIN,MONTH,MONTH_ABBREV,MONTH_NAME,MONTH_WEEK,MSEC,MSG,MSGHDR,MSGID,PID,PRI,PRIORITY,PROGRAM,R_AMPM,R_DATE,R_DAY,R_FULLDATE,R_HOUR,R_HOUR12,R_ISODATE,R_MIN,R_MONTH,R_MONTH_ABBREV,R_MONTH_NAME,R_MONTH_WEEK,R_MSEC,R_SEC,R_STAMP,R_TZ,R_TZOFFSET,R_UNIXTIME,R_USEC,R_WEEK,R_WEEKDAY,R_WEEK_DAY,R_WEEK_DAY_ABBREV,R_WEEK_DAY_NAME,R_YEAR,R_YEAR_DAY,SDATA,SEC,SEQNUM,SOURCEIP,STAMP,SYSUPTIME,S_AMPM,S_DATE,S_DAY,S_FULLDATE,S_HOUR,S_HOUR12,S_ISODATE,S_MIN,S_MONTH,S_MONTH_ABBREV,S_MONTH_NAME,S_MONTH_WEEK,S_MSEC,S_SEC,S_STAMP,S_TZ,S_TZOFFSET,S_UNIXTIME,S_USEC,S_WEEK,S_WEEKDAY,S_WEEK_DAY,S_WEEK_DAY_ABBREV,S_WEEK_DAY_NAME,S_YEAR,S_YEAR_DAY,TAG,TAGS,TZ,TZOFFSET,UNIXTIME,USEC,WEEK,WEEKDAY,WEEK_DAY,WEEK_DAY_ABBREV,WEEK_DAY_NAME,YEAR,YEAR_DAY", transformers); g_ptr_array_free(transformers, TRUE); app_shutdown(); if (success) return 0; return 1; } syslog-ng-syslog-ng-3.13.2/lib/value-pairs/tests/test_value_pairs_walk.c000066400000000000000000000106271321171025300263360ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include #include #include #include #include "logmsg/logmsg.h" MsgFormatOptions parse_options; LogTemplateOptions template_options; int root_data = 1; int root_test_data = 2; static gboolean test_vp_obj_start(const gchar *name, const gchar *prefix, gpointer *prefix_data, const gchar *prev, gpointer *prev_data, gpointer user_data) { static int times_called = 0; switch(times_called) { case 0: assert_true(prefix == 0, "First vp_obj_start but prefix is not NULL!"); break; case 1: assert_string(prefix, "root", "Second vp_obj_start but prefix is not 'root'!"); *prefix_data = &root_data; break; case 2: assert_string(prefix, "root.test", "Third vp_obj_start but prefix is not 'root.test'!"); assert_string(prev, "root", "Wrong previous prefix"); assert_gint(*((gint *)(*prev_data)), root_data, "Wrong previous data"); *prefix_data = &root_test_data; break; default: assert_false(TRUE, "vp_obj_start called more times than number of path elements!"); } times_called++; return FALSE; } static gboolean test_vp_obj_stop(const gchar *name, const gchar *prefix, gpointer *prefix_data, const gchar *prev, gpointer *prev_data, gpointer user_data) { static int times_called = 0; switch(times_called) { case 0: assert_string(prefix, "root.test", "First vp_obj_stop but prefix is not 'root.test'!"); assert_string(prev, "root", "Wrong previous prefix"); assert_gint(*((gint *)(*prev_data)), root_data, "Wrong previous data"); break; case 1: assert_string(prefix, "root", "Second vp_obj_stop but prefix is not 'root'!"); break; case 2: assert_true(prefix == 0, "Third vp_obj_stop but prefix is not NULL!"); break; default: assert_false(TRUE, "vp_obj_stop called more times than number of path elements!"); } times_called++; return FALSE; } static gboolean test_vp_value(const gchar *name, const gchar *prefix, TypeHint type, const gchar *value, gsize value_len, gpointer *prefix_data, gpointer user_data) { assert_string(prefix, "root.test", "Wrong prefix"); assert_nstring(value, value_len, "value", -1, "Wrong value"); assert_gint(*((gint *)(*prefix_data)), root_test_data, "Wrong prefix data"); return FALSE; } void test_value_pairs_walk_prefix_data(GlobalConfig *cfg) { ValuePairs *vp; LogMessage *msg; const char *value = "value"; log_template_options_init(&template_options, cfg); msg_format_options_init(&parse_options, cfg); vp = value_pairs_new(); value_pairs_add_glob_pattern(vp, "root.*", TRUE); msg = log_msg_new("test", 4, NULL, &parse_options); log_msg_set_value_by_name(msg, "root.test.alma", value, strlen(value)); log_msg_set_value_by_name(msg, "root.test.korte", value, strlen(value)); value_pairs_walk(vp, test_vp_obj_start, test_vp_value, test_vp_obj_stop, msg, 0, LTZ_LOCAL, &template_options, NULL); value_pairs_unref(vp); log_msg_unref(msg); }; int main(void) { app_startup(); configuration = cfg_new_snippet(); cfg_load_module(configuration, "syslogformat"); msg_format_options_defaults(&parse_options); msg_format_options_init(&parse_options, configuration); test_value_pairs_walk_prefix_data(configuration); app_shutdown(); }; syslog-ng-syslog-ng-3.13.2/lib/value-pairs/transforms.c000066400000000000000000000126501321171025300230010ustar00rootroot00000000000000/* * Copyright (c) 2011-2013 Balabit * Copyright (c) 2011-2013 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "transforms.h" #include "template/templates.h" #include "cfg-parser.h" #include "str-utils.h" #include "scratch-buffers.h" #include typedef void (*VPTransFunc)(ValuePairsTransform *t, GString *name); typedef void (*VPTransDestroyFunc)(ValuePairsTransform *t); struct _ValuePairsTransformSet { GPatternSpec *pattern; GList *transforms; }; struct _ValuePairsTransform { VPTransFunc transform; VPTransDestroyFunc destroy; }; typedef struct { ValuePairsTransform super; gint amount; } VPTransShift; typedef struct { ValuePairsTransform super; gchar *prefix; } VPTransAddPrefix; typedef struct { ValuePairsTransform super; gchar *old_prefix; gchar *new_prefix; gint new_prefix_len; gint old_prefix_len; } VPTransReplacePrefix; static void vp_trans_init(ValuePairsTransform *t, VPTransFunc trans, VPTransDestroyFunc dest) { if (!t) return; t->transform = trans; t->destroy = dest; } void value_pairs_transform_free(ValuePairsTransform *t) { if (t->destroy) t->destroy(t); g_free(t); } static inline void value_pairs_transform_apply(ValuePairsTransform *t, GString *key) { t->transform(t, key); } /* add_prefix() */ static void vp_trans_add_prefix(ValuePairsTransform *t, GString *key) { VPTransAddPrefix *self = (VPTransAddPrefix *)t; g_string_prepend(key, self->prefix); } static void vp_trans_add_prefix_destroy(ValuePairsTransform *t) { VPTransAddPrefix *self = (VPTransAddPrefix *)t; g_free(self->prefix); } ValuePairsTransform * value_pairs_new_transform_add_prefix (const gchar *prefix) { VPTransAddPrefix *vpt; vpt = g_new(VPTransAddPrefix, 1); vp_trans_init((ValuePairsTransform *)vpt, vp_trans_add_prefix, vp_trans_add_prefix_destroy); vpt->prefix = g_strdup(prefix); return (ValuePairsTransform *)vpt; } /* shift() */ static void vp_trans_shift(ValuePairsTransform *t, GString *key) { VPTransShift *self = (VPTransShift *)t; g_string_erase(key, 0, self->amount); } ValuePairsTransform * value_pairs_new_transform_shift (gint amount) { VPTransShift *vpt; vpt = g_new(VPTransShift, 1); vp_trans_init((ValuePairsTransform *)vpt, vp_trans_shift, NULL); vpt->amount = amount; return (ValuePairsTransform *)vpt; } /* replace-prefix() */ static void vp_trans_replace_prefix(ValuePairsTransform *t, GString *key) { VPTransReplacePrefix *self = (VPTransReplacePrefix *)t; if (strncmp(self->old_prefix, key->str, self->old_prefix_len) != 0) return; g_string_erase(key, 0, self->old_prefix_len); g_string_prepend_len(key, self->new_prefix, self->new_prefix_len); } static void vp_trans_replace_prefix_destroy(ValuePairsTransform *t) { VPTransReplacePrefix *self = (VPTransReplacePrefix *)t; g_free(self->old_prefix); g_free(self->new_prefix); } ValuePairsTransform * value_pairs_new_transform_replace_prefix(const gchar *prefix, const gchar *new_prefix) { VPTransReplacePrefix *vpt; vpt = g_new(VPTransReplacePrefix, 1); vp_trans_init((ValuePairsTransform *)vpt, vp_trans_replace_prefix, vp_trans_replace_prefix_destroy); vpt->old_prefix = g_strdup(prefix); vpt->old_prefix_len = strlen(prefix); vpt->new_prefix = g_strdup(new_prefix); vpt->new_prefix_len = strlen(vpt->new_prefix); return (ValuePairsTransform *)vpt; } /* * ValuePairsTransformSet */ ValuePairsTransformSet * value_pairs_transform_set_new(const gchar *glob) { ValuePairsTransformSet *vpts; vpts = g_new(ValuePairsTransformSet, 1); vpts->transforms = NULL; vpts->pattern = g_pattern_spec_new(glob); return vpts; } void value_pairs_transform_set_add_func(ValuePairsTransformSet *vpts, ValuePairsTransform *vpt) { vpts->transforms = g_list_append(vpts->transforms, vpt); } void value_pairs_transform_set_free(ValuePairsTransformSet *vpts) { GList *l; l = vpts->transforms; while (l) { value_pairs_transform_free((ValuePairsTransform *)l->data); l = g_list_delete_link(l, l); } g_pattern_spec_free(vpts->pattern); g_free(vpts); } void value_pairs_transform_set_apply(ValuePairsTransformSet *vpts, GString *key) { if (g_pattern_match_string(vpts->pattern, key->str)) { GList *l; l = vpts->transforms; while (l) { value_pairs_transform_apply((ValuePairsTransform *)l->data, key); l = l->next; } } } syslog-ng-syslog-ng-3.13.2/lib/value-pairs/transforms.h000066400000000000000000000035201321171025300230020ustar00rootroot00000000000000/* * Copyright (c) 2011-2013 Balabit * Copyright (c) 2011-2013 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef VPTRANSFORM_INCLUDED #define VPTRANSFORM_INCLUDED 1 #include "syslog-ng.h" typedef struct _ValuePairsTransform ValuePairsTransform; typedef struct _ValuePairsTransformSet ValuePairsTransformSet; ValuePairsTransform *value_pairs_new_transform_add_prefix (const gchar *prefix); ValuePairsTransform *value_pairs_new_transform_shift (gint amount); ValuePairsTransform *value_pairs_new_transform_replace_prefix(const gchar *prefix, const gchar *new_prefix); void value_pairs_transform_free(ValuePairsTransform *t); ValuePairsTransformSet *value_pairs_transform_set_new(const gchar *glob); void value_pairs_transform_set_add_func(ValuePairsTransformSet *vpts, ValuePairsTransform *vpt); void value_pairs_transform_set_free(ValuePairsTransformSet *vpts); void value_pairs_transform_set_apply(ValuePairsTransformSet *vpts, GString *key); #endif syslog-ng-syslog-ng-3.13.2/lib/value-pairs/value-pairs.c000066400000000000000000000620221321171025300230310ustar00rootroot00000000000000/* * Copyright (c) 2011-2015 Balabit * Copyright (c) 2011-2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "value-pairs/value-pairs.h" #include "logmsg/logmsg.h" #include "template/templates.h" #include "template/macros.h" #include "type-hinting.h" #include "cfg-parser.h" #include "string-list.h" #include "scratch-buffers.h" #include "cfg.h" #include typedef struct { GPatternSpec *pattern; gboolean include; } VPPatternSpec; typedef struct { gchar *name; LogTemplate *template; } VPPairConf; typedef struct { /* we don't own any of the fields here, it is assumed that allocations are * managed by the caller */ GString *name; GString *value; TypeHint type_hint; } VPResultValue; typedef struct { GTree *result_tree; /* array of VPResultValue instances */ GArray *values; } VPResults; struct _ValuePairs { GAtomicCounter ref_cnt; GPtrArray *builtins; GPtrArray *patterns; GPtrArray *vpairs; GPtrArray *transforms; /* guint32 as CfgFlagHandler only supports 32 bit integers */ guint32 scopes; }; typedef enum { VPS_NV_PAIRS = 0x01, VPS_DOT_NV_PAIRS = 0x02, VPS_RFC3164 = 0x04, VPS_RFC5424 = 0x08, VPS_ALL_MACROS = 0x10, VPS_SELECTED_MACROS = 0x20, VPS_SDATA = 0x40, VPS_EVERYTHING = 0x7f, } ValuePairScope; enum { VPT_MACRO, VPT_NVPAIR, }; typedef struct { gchar *name; gchar *alt_name; gint type; gint id; } ValuePairSpec; static ValuePairSpec rfc3164[] = { /* there's one macro named DATE that'll be expanded specially */ { "FACILITY" }, { "PRIORITY" }, { "HOST" }, { "PROGRAM" }, { "PID" }, { "MESSAGE" }, { "DATE" }, { 0 }, }; static ValuePairSpec rfc5424[] = { { "MSGID", }, { 0 }, }; static ValuePairSpec selected_macros[] = { { "TAGS" }, { "SOURCEIP" }, { "SEQNUM" }, { 0 }, }; static ValuePairSpec *all_macros; static CfgFlagHandler value_pair_scope[] = { { "nv-pairs", CFH_SET, offsetof(ValuePairs, scopes), VPS_NV_PAIRS }, { "dot-nv-pairs", CFH_SET, offsetof(ValuePairs, scopes), VPS_DOT_NV_PAIRS}, { "all-nv-pairs", CFH_SET, offsetof(ValuePairs, scopes), VPS_NV_PAIRS | VPS_DOT_NV_PAIRS }, { "rfc3164", CFH_SET, offsetof(ValuePairs, scopes), VPS_RFC3164 }, { "core", CFH_SET, offsetof(ValuePairs, scopes), VPS_RFC3164 }, { "base", CFH_SET, offsetof(ValuePairs, scopes), VPS_RFC3164 }, { "rfc5424", CFH_SET, offsetof(ValuePairs, scopes), VPS_RFC5424 }, { "syslog-proto", CFH_SET, offsetof(ValuePairs, scopes), VPS_RFC5424 }, { "all-macros", CFH_SET, offsetof(ValuePairs, scopes), VPS_ALL_MACROS }, { "selected-macros", CFH_SET, offsetof(ValuePairs, scopes), VPS_SELECTED_MACROS }, { "sdata", CFH_SET, offsetof(ValuePairs, scopes), VPS_SDATA }, { "everything", CFH_SET, offsetof(ValuePairs, scopes), VPS_EVERYTHING }, { NULL, 0, 0, 0}, }; static gboolean vp_pattern_spec_eval(VPPatternSpec *self, const gchar *input) { return g_pattern_match_string(self->pattern, input); } static void vp_pattern_spec_free(VPPatternSpec *self) { g_pattern_spec_free(self->pattern); g_free(self); } static VPPatternSpec * vp_pattern_spec_new(const gchar *pattern, gboolean include) { VPPatternSpec *self = g_new0(VPPatternSpec, 1); self->pattern = g_pattern_spec_new(pattern); self->include = include; return self; } static VPPairConf * vp_pair_conf_new(const gchar *key, LogTemplate *value) { VPPairConf *p = g_new(VPPairConf, 1); p->name = g_strdup(key); p->template = log_template_ref(value); return p; } static void vp_pair_conf_free(VPPairConf *vpc) { log_template_unref(vpc->template); g_free(vpc->name); g_free(vpc); } static void vp_result_value_init(VPResultValue *rv, GString *name, TypeHint type_hint, GString *value) { rv->type_hint = type_hint; rv->name = name; rv->value = value; } static void vp_results_init(VPResults *results, GCompareFunc compare_func) { results->values = g_array_sized_new(FALSE, FALSE, sizeof(VPResultValue), 16); results->result_tree = g_tree_new_full((GCompareDataFunc) compare_func, NULL, NULL, NULL); } static void vp_results_deinit(VPResults *results) { g_tree_destroy(results->result_tree); g_array_free(results->values, TRUE); } static void vp_results_insert(VPResults *results, GString *name, TypeHint type_hint, GString *value) { VPResultValue *rv; gint ndx = results->values->len; g_array_set_size(results->values, ndx + 1); rv = &g_array_index(results->values, VPResultValue, ndx); vp_result_value_init(rv, name, type_hint, value); /* GTree takes over ownership of name */ g_tree_insert(results->result_tree, name->str, GINT_TO_POINTER(ndx)); } static GString * vp_transform_apply (ValuePairs *vp, gchar *key) { gint i; GString *result = scratch_buffers_alloc(); g_string_assign(result, key); if (vp->transforms->len == 0) return result; for (i = 0; i < vp->transforms->len; i++) { ValuePairsTransformSet *t = (ValuePairsTransformSet *) g_ptr_array_index(vp->transforms, i); value_pairs_transform_set_apply(t, result); } return result; } /* runs over the name-value pairs requested by the user (e.g. with value_pairs_add_pair) */ static void vp_pairs_foreach(gpointer data, gpointer user_data) { ValuePairs *vp = ((gpointer *)user_data)[0]; LogMessage *msg = ((gpointer *)user_data)[2]; gint32 seq_num = GPOINTER_TO_INT (((gpointer *)user_data)[3]); VPResults *results = ((gpointer *)user_data)[5]; const LogTemplateOptions *template_options = ((gpointer *)user_data)[6]; GString *sb = scratch_buffers_alloc(); VPPairConf *vpc = (VPPairConf *)data; gint time_zone_mode = GPOINTER_TO_INT (((gpointer *)user_data)[7]); log_template_append_format((LogTemplate *)vpc->template, msg, template_options, time_zone_mode, seq_num, NULL, sb); vp_results_insert(results, vp_transform_apply(vp, vpc->name), vpc->template->type_hint, sb); } /* runs over the LogMessage nv-pairs, and inserts them unless excluded */ static gboolean vp_msg_nvpairs_foreach(NVHandle handle, gchar *name, const gchar *value, gssize value_len, gpointer user_data) { ValuePairs *vp = ((gpointer *)user_data)[0]; VPResults *results = ((gpointer *)user_data)[5]; guint j; gboolean inc; GString *sb; inc = (name[0] == '.' && (vp->scopes & VPS_DOT_NV_PAIRS)) || (name[0] != '.' && (vp->scopes & VPS_NV_PAIRS)) || (log_msg_is_handle_sdata(handle) && (vp->scopes & (VPS_SDATA + VPS_RFC5424))); for (j = 0; j < vp->patterns->len; j++) { VPPatternSpec *vps = (VPPatternSpec *) g_ptr_array_index(vp->patterns, j); if (vp_pattern_spec_eval(vps, name)) inc = vps->include; } if (!inc) return FALSE; sb = scratch_buffers_alloc(); g_string_append_len(sb, value, value_len); vp_results_insert(results, vp_transform_apply(vp, name), TYPE_HINT_STRING, sb); return FALSE; } static gboolean vp_find_in_set(ValuePairs *vp, gchar *name, gboolean exclude) { guint j; gboolean included = exclude; for (j = 0; j < vp->patterns->len; j++) { VPPatternSpec *vps = (VPPatternSpec *) g_ptr_array_index(vp->patterns, j); if (vp_pattern_spec_eval(vps, name)) included = vps->include; } return included; } static void vp_merge_other_set(ValuePairs *vp, ValuePairSpec *set, gboolean exclude) { gint i; for (i = 0; set[i].name; i++) { if (!vp_find_in_set(vp, set[i].name, exclude)) continue; g_ptr_array_add(vp->builtins, &set[i]); } } /* runs over the all macros and merges the selected ones by the pattern into the value-pair set */ static void vp_merge_macros(ValuePairs *vp) { vp_merge_other_set(vp, all_macros, FALSE); } /* runs over a set of ValuePairSpec structs and merges them into the value-pair set */ static void vp_merge_set(ValuePairs *vp, ValuePairSpec *set) { vp_merge_other_set(vp, set, TRUE); } static void vp_update_builtin_list_of_values(ValuePairs *vp) { g_ptr_array_set_size(vp->builtins, 0); if (vp->patterns->len > 0) vp_merge_macros(vp); if (vp->scopes & (VPS_RFC3164 + VPS_RFC5424 + VPS_SELECTED_MACROS)) vp_merge_set(vp, rfc3164); if (vp->scopes & VPS_RFC5424) vp_merge_set(vp, rfc5424); if (vp->scopes & VPS_SELECTED_MACROS) vp_merge_set(vp, selected_macros); if (vp->scopes & VPS_ALL_MACROS) vp_merge_set(vp, all_macros); } static void vp_merge_builtins(ValuePairs *vp, VPResults *results, LogMessage *msg, gint32 seq_num, gint time_zone_mode, const LogTemplateOptions *template_options) { gint i; GString *sb; for (i = 0; i < vp->builtins->len; i++) { ValuePairSpec *spec = (ValuePairSpec *) g_ptr_array_index(vp->builtins, i); sb = scratch_buffers_alloc(); switch (spec->type) { case VPT_MACRO: log_macro_expand(sb, spec->id, FALSE, template_options, time_zone_mode, seq_num, NULL, msg); break; case VPT_NVPAIR: { const gchar *nv; gssize len; nv = log_msg_get_value(msg, (NVHandle) spec->id, &len); g_string_append_len(sb, nv, len); break; } default: g_assert_not_reached(); } if (sb->len == 0) { continue; } vp_results_insert(results, vp_transform_apply(vp, spec->name), TYPE_HINT_STRING, sb); } } static gboolean vp_foreach_helper(const gchar *name, gpointer ndx_as_pointer, gpointer data) { VPResults *results = ((gpointer *)data)[0]; gint ndx = GPOINTER_TO_INT(ndx_as_pointer); VPResultValue *rv = &g_array_index(results->values, VPResultValue, ndx); VPForeachFunc func = ((gpointer *)data)[1]; gpointer user_data = ((gpointer *)data)[2]; gboolean *r = ((gpointer *)data)[3]; *r &= !func(name, rv->type_hint, rv->value->str, rv->value->len, user_data); return !*r; } gboolean value_pairs_foreach_sorted (ValuePairs *vp, VPForeachFunc func, GCompareFunc compare_func, LogMessage *msg, gint32 seq_num, gint time_zone_mode, const LogTemplateOptions *template_options, gpointer user_data) { gpointer args[] = { vp, func, msg, GINT_TO_POINTER (seq_num), user_data, NULL, /* remove constness, we are not using that pointer non-const anyway */ (LogTemplateOptions *) template_options, GINT_TO_POINTER(time_zone_mode) }; gboolean result = TRUE; VPResults results; gpointer helper_args[] = { &results, func, user_data, &result }; ScratchBuffersMarker mark; scratch_buffers_mark(&mark); vp_results_init(&results, compare_func); args[5] = &results; /* * Build up the base set */ if (vp->scopes & (VPS_NV_PAIRS + VPS_DOT_NV_PAIRS + VPS_SDATA + VPS_RFC5424) || vp->patterns->len > 0) nv_table_foreach(msg->payload, logmsg_registry, (NVTableForeachFunc) vp_msg_nvpairs_foreach, args); vp_merge_builtins(vp, &results, msg, seq_num, time_zone_mode, template_options); /* Merge the explicit key-value pairs too */ g_ptr_array_foreach(vp->vpairs, (GFunc)vp_pairs_foreach, args); /* Aaand we run it through the callback! */ g_tree_foreach(results.result_tree, (GTraverseFunc)vp_foreach_helper, helper_args); vp_results_deinit(&results); scratch_buffers_reclaim_marked(mark); return result; } gboolean value_pairs_foreach(ValuePairs *vp, VPForeachFunc func, LogMessage *msg, gint32 seq_num, gint time_zone_mode, const LogTemplateOptions *template_options, gpointer user_data) { return value_pairs_foreach_sorted(vp, func, (GCompareFunc) strcmp, msg, seq_num, time_zone_mode, template_options, user_data); } /******************************************************************************* * vp_stack (represented by vp_stack_t) * * A not very generic stack implementation used by vp_walker. *******************************************************************************/ #define VP_STACK_INITIAL_SIZE 16 typedef struct { GPtrArray *elems; } vp_stack_t; static void vp_stack_init(vp_stack_t *stack) { stack->elems = g_ptr_array_sized_new(VP_STACK_INITIAL_SIZE); } static void vp_stack_destroy(vp_stack_t *stack) { g_ptr_array_free(stack->elems, TRUE); } static void vp_stack_push(vp_stack_t *stack, gpointer data) { g_ptr_array_add(stack->elems, data); } static gpointer vp_stack_peek(vp_stack_t *stack) { if (stack->elems->len == 0) return NULL; return g_ptr_array_index(stack->elems, stack->elems->len - 1); } static gpointer vp_stack_pop(vp_stack_t *stack) { gpointer data = NULL; data = vp_stack_peek(stack); if (data) g_ptr_array_remove_index(stack->elems, stack->elems->len - 1); return data; } static guint vp_stack_height(vp_stack_t *stack) { return stack->elems->len; } /******************************************************************************* * vp_walker (represented by vp_walk_state_t), * * The stuff that translates name-value pairs to a tree with SAX like * callbacks. (start/value/end) *******************************************************************************/ typedef struct { gchar *key; gchar *prefix; gint prefix_len; gpointer data; } vp_walk_stack_data_t; typedef struct { VPWalkCallbackFunc obj_start; VPWalkCallbackFunc obj_end; VPWalkValueCallbackFunc process_value; gpointer user_data; vp_stack_t stack; } vp_walk_state_t; static vp_walk_stack_data_t * vp_walker_stack_push (vp_stack_t *stack, gchar *key, gchar *prefix) { vp_walk_stack_data_t *nt = g_new(vp_walk_stack_data_t, 1); nt->key = key; nt->prefix = prefix; nt->prefix_len = strlen(nt->prefix); nt->data = NULL; vp_stack_push(stack, nt); return nt; } static vp_walk_stack_data_t * vp_walker_stack_peek(vp_stack_t *stack) { return (vp_walk_stack_data_t *) vp_stack_peek(stack); } static vp_walk_stack_data_t * vp_walker_stack_pop(vp_stack_t *stack) { return (vp_walk_stack_data_t *) vp_stack_pop(stack); } static void vp_walker_free_stack_data(vp_walk_stack_data_t *t) { g_free(t->key); g_free(t->prefix); g_free(t); } static void vp_walker_stack_unwind_containers_until(vp_walk_state_t *state, const gchar *name) { vp_walk_stack_data_t *t; while ((t = vp_walker_stack_pop(&state->stack)) != NULL) { vp_walk_stack_data_t *p; if (name && strncmp(name, t->prefix, t->prefix_len) == 0) { /* This one matched, put it back, PUT IT BACK! */ vp_stack_push(&state->stack, t); break; } p = vp_walker_stack_peek(&state->stack); if (p) state->obj_end(t->key, t->prefix, &t->data, p->prefix, &p->data, state->user_data); else state->obj_end(t->key, t->prefix, &t->data, NULL, NULL, state->user_data); vp_walker_free_stack_data(t); } } static void vp_walker_stack_unwind_all_containers(vp_walk_state_t *state) { vp_walker_stack_unwind_containers_until(state, NULL); } static const gchar * vp_walker_skip_sdata_enterprise_id(const gchar *name) { /* parse .SDATA.foo@1234.56.678 format, starting with the '@' character. Assume that any numbers + dots form part of the "foo@1234.56.678" key, even if they contain dots */ do { /* skip @ or . */ ++name; name += strspn(name, "0123456789"); } while (*name == '.' && isdigit(*(name + 1))); return name; } static GPtrArray * vp_walker_split_name_to_tokens(vp_walk_state_t *state, const gchar *name) { const gchar *token_start = name; const gchar *token_end = name; GPtrArray *array = g_ptr_array_sized_new(VP_STACK_INITIAL_SIZE); while (*token_end) { switch (*token_end) { case '@': token_end = vp_walker_skip_sdata_enterprise_id(token_end); break; case '.': if (token_start != token_end) { g_ptr_array_add(array, g_strndup(token_start, token_end - token_start)); ++token_end; token_start = token_end; break; } /* fall through, zero length token is not considered a separate token */ default: ++token_end; token_end += strcspn(token_end, "@."); break; } } if (token_start != token_end) g_ptr_array_add(array, g_strndup(token_start, token_end - token_start)); if (array->len == 0) { g_ptr_array_free(array, TRUE); return NULL; } return array; } static gchar * vp_walker_name_combine_prefix(GPtrArray *tokens, gint until) { GString *s = scratch_buffers_alloc(); gchar *str; gint i; for (i = 0; i < until; i++) { g_string_append(s, g_ptr_array_index(tokens, i)); g_string_append_c(s, '.'); } g_string_append(s, g_ptr_array_index(tokens, until)); str = g_strdup(s->str); return str; } static gchar * vp_walker_start_containers_for_name(vp_walk_state_t *state, const gchar *name) { GPtrArray *tokens; gchar *key = NULL; guint i, start; tokens = vp_walker_split_name_to_tokens(state, name); start = vp_stack_height(&state->stack); for (i = start; i < tokens->len - 1; i++) { vp_walk_stack_data_t *p, *nt; p = vp_walker_stack_peek(&state->stack); nt = vp_walker_stack_push(&state->stack, g_strdup(g_ptr_array_index(tokens, i)), vp_walker_name_combine_prefix(tokens, i)); if (p) state->obj_start(nt->key, nt->prefix, &nt->data, p->prefix, &p->data, state->user_data); else state->obj_start(nt->key, nt->prefix, &nt->data, NULL, NULL, state->user_data); } /* The last token is the key (well, second to last, last being NULL), so treat that normally. */ key = g_ptr_array_index(tokens, tokens->len - 1); g_ptr_array_index(tokens, tokens->len - 1) = NULL; g_ptr_array_foreach(tokens, (GFunc)g_free, NULL); g_ptr_array_free(tokens, TRUE); return key; } static gboolean value_pairs_walker(const gchar *name, TypeHint type, const gchar *value, gsize value_len, gpointer user_data) { vp_walk_state_t *state = (vp_walk_state_t *)user_data; vp_walk_stack_data_t *data; gchar *key; gboolean result; vp_walker_stack_unwind_containers_until(state, name); key = vp_walker_start_containers_for_name(state, name); data = vp_walker_stack_peek(&state->stack); if (data != NULL) result = state->process_value(key, data->prefix, type, value, value_len, &data->data, state->user_data); else result = state->process_value(key, NULL, type, value, value_len, NULL, state->user_data); g_free(key); return result; } static gint vp_walk_cmp(const gchar *s1, const gchar *s2) { return strcmp(s2, s1); } /******************************************************************************* * Public API *******************************************************************************/ gboolean value_pairs_walk(ValuePairs *vp, VPWalkCallbackFunc obj_start_func, VPWalkValueCallbackFunc process_value_func, VPWalkCallbackFunc obj_end_func, LogMessage *msg, gint32 seq_num, gint time_zone_mode, const LogTemplateOptions *template_options, gpointer user_data) { vp_walk_state_t state; gboolean result; state.user_data = user_data; state.obj_start = obj_start_func; state.obj_end = obj_end_func; state.process_value = process_value_func; vp_stack_init(&state.stack); state.obj_start(NULL, NULL, NULL, NULL, NULL, user_data); result = value_pairs_foreach_sorted(vp, value_pairs_walker, (GCompareFunc)vp_walk_cmp, msg, seq_num, time_zone_mode, template_options, &state); vp_walker_stack_unwind_all_containers(&state); state.obj_end(NULL, NULL, NULL, NULL, NULL, user_data); vp_stack_destroy(&state.stack); return result; } gboolean value_pairs_add_scope(ValuePairs *vp, const gchar *scope) { gboolean result; result = cfg_process_flag(value_pair_scope, vp, scope); vp_update_builtin_list_of_values(vp); return result; } void value_pairs_add_glob_pattern(ValuePairs *vp, const gchar *pattern, gboolean include) { g_ptr_array_add(vp->patterns, vp_pattern_spec_new(pattern, include)); vp_update_builtin_list_of_values(vp); } void value_pairs_add_glob_patterns(ValuePairs *vp, GList *patterns, gboolean include) { GList *l = patterns; while (l) { value_pairs_add_glob_pattern(vp, (gchar *)l->data, include); l = g_list_next (l); } string_list_free(patterns); vp_update_builtin_list_of_values(vp); } void value_pairs_add_pair(ValuePairs *vp, const gchar *key, LogTemplate *value) { g_ptr_array_add(vp->vpairs, vp_pair_conf_new(key, value)); vp_update_builtin_list_of_values(vp); } void value_pairs_add_transforms(ValuePairs *vp, ValuePairsTransformSet *vpts) { g_ptr_array_add(vp->transforms, vpts); vp_update_builtin_list_of_values(vp); } ValuePairs * value_pairs_new(void) { ValuePairs *vp; vp = g_new0(ValuePairs, 1); g_atomic_counter_set(&vp->ref_cnt, 1); vp->builtins = g_ptr_array_new(); vp->vpairs = g_ptr_array_new(); vp->patterns = g_ptr_array_new(); vp->transforms = g_ptr_array_new(); return vp; } ValuePairs * value_pairs_new_default(GlobalConfig *cfg) { ValuePairs *vp = value_pairs_new(); value_pairs_add_scope(vp, "selected-macros"); value_pairs_add_scope(vp, "nv-pairs"); value_pairs_add_scope(vp, "sdata"); return vp; } static void value_pairs_free (ValuePairs *vp) { guint i; for (i = 0; i < vp->vpairs->len; i++) vp_pair_conf_free(g_ptr_array_index(vp->vpairs, i)); g_ptr_array_free(vp->vpairs, TRUE); for (i = 0; i < vp->patterns->len; i++) { VPPatternSpec *vps = (VPPatternSpec *) g_ptr_array_index(vp->patterns, i); vp_pattern_spec_free(vps); } g_ptr_array_free(vp->patterns, TRUE); for (i = 0; i < vp->transforms->len; i++) { ValuePairsTransformSet *vpts = (ValuePairsTransformSet *) g_ptr_array_index(vp->transforms, i); value_pairs_transform_set_free(vpts); } g_ptr_array_free(vp->transforms, TRUE); g_ptr_array_free(vp->builtins, TRUE); g_free(vp); } ValuePairs * value_pairs_ref(ValuePairs *self) { g_assert(!self || g_atomic_counter_get(&self->ref_cnt) > 0); if (self) { g_atomic_counter_inc(&self->ref_cnt); } return self; } void value_pairs_unref(ValuePairs *self) { if (self) { g_assert(g_atomic_counter_get(&self->ref_cnt) > 0); if (g_atomic_counter_dec_and_test(&self->ref_cnt)) value_pairs_free(self); } } static void value_pairs_init_set(ValuePairSpec *set) { gint i; for (i = 0; set[i].name; i++) { guint id; gchar *name; name = set[i].alt_name ? set[i].alt_name : set[i].name; if ((id = log_macro_lookup(name, strlen(name)))) { set[i].type = VPT_MACRO; set[i].id = id; } else { set[i].type = VPT_NVPAIR; set[i].id = log_msg_get_value_handle(name); } } } void value_pairs_global_init(void) { gint i = 0; GArray *a; value_pairs_init_set(rfc3164); value_pairs_init_set(rfc5424); value_pairs_init_set(selected_macros); a = g_array_new(TRUE, TRUE, sizeof(ValuePairSpec)); for (i = 0; macros[i].name; i++) { ValuePairSpec pair; pair.name = macros[i].name; pair.type = VPT_MACRO; pair.id = macros[i].id; g_array_append_val(a, pair); } all_macros = (ValuePairSpec *) g_array_free(a, FALSE); } void value_pairs_global_deinit(void) { g_free(all_macros); } syslog-ng-syslog-ng-3.13.2/lib/value-pairs/value-pairs.h000066400000000000000000000070651321171025300230440ustar00rootroot00000000000000/* * Copyright (c) 2011-2014 Balabit * Copyright (c) 2011-2014 Gergely Nagy * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef VALUE_PAIRS_H_INCLUDED #define VALUE_PAIRS_H_INCLUDED 1 #include "syslog-ng.h" #include "logmsg/nvtable.h" #include "value-pairs/transforms.h" #include "type-hinting.h" #include "template/templates.h" typedef struct _ValuePairs ValuePairs; typedef gboolean (*VPForeachFunc) (const gchar *name, TypeHint type, const gchar *value, gsize value_len, gpointer user_data); typedef gboolean (*VPWalkValueCallbackFunc) (const gchar *name, const gchar *prefix, TypeHint type, const gchar *value, gsize value_len, gpointer *prefix_data, gpointer user_data); typedef gboolean (*VPWalkCallbackFunc)(const gchar *name, const gchar *prefix, gpointer *prefix_data, const gchar *prev, gpointer *prev_data, gpointer user_data); gboolean value_pairs_add_scope(ValuePairs *vp, const gchar *scope); void value_pairs_add_glob_pattern(ValuePairs *vp, const gchar *pattern, gboolean include); void value_pairs_add_glob_patterns(ValuePairs *vp, GList *patterns, gboolean include); void value_pairs_add_pair(ValuePairs *vp, const gchar *key, LogTemplate *value); void value_pairs_add_transforms(ValuePairs *vp, ValuePairsTransformSet *vpts); gboolean value_pairs_foreach_sorted(ValuePairs *vp, VPForeachFunc func, GCompareFunc compare_func, LogMessage *msg, gint32 seq_num, gint tz, const LogTemplateOptions *template_options, gpointer user_data); gboolean value_pairs_foreach(ValuePairs *vp, VPForeachFunc func, LogMessage *msg, gint32 seq_num, gint tz, const LogTemplateOptions *template_options, gpointer user_data); gboolean value_pairs_walk(ValuePairs *vp, VPWalkCallbackFunc obj_start_func, VPWalkValueCallbackFunc process_value_func, VPWalkCallbackFunc obj_end_func, LogMessage *msg, gint32 seq_num, gint tz, const LogTemplateOptions *template_options, gpointer user_data); ValuePairs *value_pairs_new(void); ValuePairs *value_pairs_new_default(GlobalConfig *cfg); ValuePairs *value_pairs_ref(ValuePairs *self); void value_pairs_unref(ValuePairs *self); void value_pairs_global_init(void); void value_pairs_global_deinit(void); #endif syslog-ng-syslog-ng-3.13.2/lib/versioning.h000066400000000000000000000126101321171025300205370ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef __VERSIONING_H__ #define __VERSIONING_H__ /* The aim of this header file is to make it easy to track version * identification in code when porting code from the PE tree to the OSE tree * or vice versa. Error and warning messages should always use these macros * instead of inlining a concrete version number. Runtime checks should * always use the get_version_value() function to convert OSE version codes * to PE ones. * **************************************************************************** * The code _should_ always use OSE version numbering, otherwise it'd break * * and confuse the user when code gets ported between trees. * **************************************************************************** * * Versions in error messages * ========================== * * Whenever using an error message that needs to state a version number, it * should use one of the VERSION_X_Y macros, X_Y identifying the OSE version * number where the incompatible change was applied. * * Example: * * msg_warning("WARNING: foo got changed to bar in " VERSION_3_4"); * * Incompatible changes in non-OSE products * ======================================== * * If you introduce an incompatible change in a private tree (but don't do * that), you should explicitly define a macro that identifies your version, * e.g. if you have a product named foo, which is based on syslog-ng 3.3 * and you decide to change the interpretation of a config syntax in your * 1.0 release, you should create a macro: * * VERSION_FOO_1_0 "foo 1.0" * * This would be changed once the code gets integrated into syslog-ng, to * the "integrated-to" release. That way, users that always used OSE gets * the version number properly. * * Rebasing to a tree that already has your incompatible change * ============================================================ * * Assuming your change makes it to the OSE tree, the FOO specific version * references will be changed to OSE version macros, which could be a * problem for you when rebase your product, since your rebased product will * claim that the incompatible change happened _after_ it really happened. * The best solution is not to introduce incompatible changes or do that in * the OSE tree first. If you have to something like this, make sure that * you take care about these at rebase time. * * Version number barrier * ====================== * * For now there's an explicit barrier in version numbering between PE and * OSE, which is "4.0"; everything below "4.0" is an OSE version number, * everything ahead is a PE one. This will change once there's sufficient * gap between the two (e.g. PE 4.0 is long forgotten), in that case * OSE can also use version 4 and later. * * If there's another similar products built on syslog-ng (e.g. someone * other than BB creates such a product, the same scheme can be used by them * too). */ /* version references for major syslog-ng OSE versions. All error messages * should reference the syslog-ng version number through these macros, in order * to make it relatively simple to explain PE/OSE version numbers to users. */ #define PRODUCT_NAME "syslog-ng-ose" #define PRODUCT_CONTACT "https://lists.balabit.hu/mailman/listinfo/syslog-ng" #define VERSION_3_0 "syslog-ng 3.0" #define VERSION_3_1 "syslog-ng 3.1" #define VERSION_3_2 "syslog-ng 3.2" #define VERSION_3_3 "syslog-ng 3.3" #define VERSION_3_4 "syslog-ng 3.4" #define VERSION_3_5 "syslog-ng 3.5" #define VERSION_3_6 "syslog-ng 3.6" #define VERSION_3_7 "syslog-ng 3.7" #define VERSION_3_8 "syslog-ng 3.8" #define VERSION_3_9 "syslog-ng 3.9" #define VERSION_3_10 "syslog-ng 3.10" #define VERSION_3_11 "syslog-ng 3.11" #define VERSION_3_12 "syslog-ng 3.12" #define VERSION_3_13 "syslog-ng 3.13" #define VERSION_VALUE_3_0 0x0300 #define VERSION_VALUE_3_1 0x0301 #define VERSION_VALUE_3_2 0x0302 #define VERSION_VALUE_3_3 0x0303 #define VERSION_VALUE_3_4 0x0304 #define VERSION_VALUE_3_5 0x0305 #define VERSION_VALUE_3_6 0x0306 #define VERSION_VALUE_3_7 0x0307 #define VERSION_VALUE_3_8 0x0308 #define VERSION_VALUE_3_9 0x0309 #define VERSION_VALUE_3_10 0x030a #define VERSION_VALUE_3_11 0x030b #define VERSION_VALUE_3_12 0x030c #define VERSION_VALUE_3_13 0x030d /* config version code, in the same format as GlobalConfig->version */ #define VERSION_VALUE 0x030d #define VERSION_CURRENT VERSION_3_13 #define VERSION_CURRENT_VER_ONLY "3.13" #define version_convert_from_user(v) (v) #include "pe-versioning.h" #endif syslog-ng-syslog-ng-3.13.2/libtest/000077500000000000000000000000001321171025300171035ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/libtest/Makefile.am000066400000000000000000000020271321171025300211400ustar00rootroot00000000000000libtestdir = \ $(pkglibdir)/libtest libtestincludedir = \ $(pkgincludedir)/libtest libtest_LIBRARIES = \ libtest/libsyslog-ng-test.a libtest_libsyslog_ng_test_a_SOURCES = \ libtest/libtest.c \ libtest/testutils.c \ libtest/testutils.h \ libtest/stopwatch.c \ libtest/stopwatch.h \ libtest/msg_parse_lib.c \ libtest/msg_parse_lib.h \ libtest/template_lib.c \ libtest/template_lib.h \ libtest/proto_lib.c \ libtest/proto_lib.h \ libtest/persist_lib.h \ libtest/persist_lib.c \ libtest/mock-transport.c \ libtest/mock-transport.h \ libtest/config_parse_lib.c \ libtest/config_parse_lib.h \ libtest/queue_utils_lib.c \ libtest/queue_utils_lib.h \ libtest/license_module_mock.c \ libtest/license_module_mock.h libtestinclude_HEADERS = \ libtest/testutils.h \ libtest/msg_parse_lib.h \ libtest/template_lib.h \ libtest/proto_lib.h \ libtest/persist_lib.h \ libtest/mock-transport.h \ libtest/license_module_mock.h pkgconfig_DATA += \ libtest/syslog-ng-test.pc syslog-ng-syslog-ng-3.13.2/libtest/config_parse_lib.c000066400000000000000000000075711321171025300225460ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Viktor Juhász * Copyright (c) 2014 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "config_parse_lib.h" #include "cfg.h" #include "cfg-parser.h" #include "plugin.h" static gchar ** split_plugin_name_and_config(const gchar *config_to_parse) { gchar **delimited = NULL; if (!config_to_parse || strlen(config_to_parse) == 0) return NULL; delimited = g_strsplit(config_to_parse, "(", 2); if (!delimited) return NULL; if (g_strv_length(delimited) == 2) { gchar *tmp = delimited[1]; delimited[1] = g_strdup_printf("(%s", tmp); g_free(tmp); return delimited; } g_strfreev(delimited); return NULL; } static gpointer parse_plugin_config(const gchar *config_to_parse, gint context, gpointer arg) { gpointer result = NULL; CfgLexer *old_lexer = configuration->lexer; CfgLexer *lexer = NULL; YYLTYPE *yylloc = NULL; Plugin *plugin = NULL; gchar **delimited; delimited = split_plugin_name_and_config(config_to_parse); if (!delimited) { fprintf(stderr, "Error parsing expression\n"); return NULL; } lexer = cfg_lexer_new_buffer(configuration, delimited[1], strlen(delimited[1])); if (!lexer) { fprintf(stderr, "Error parsing expression\n"); goto finish; } yylloc = g_new0(YYLTYPE, 1); yylloc->first_column = 1; yylloc->first_line = 1; yylloc->last_column = 1; yylloc->last_line = 1; yylloc->level = &lexer->include_stack[0]; plugin = cfg_find_plugin(configuration, context, delimited[0]); if (!plugin) { fprintf(stderr, "Error parsing expression\n"); goto finish; } configuration->lexer = lexer; cfg_set_global_paths(configuration); cfg_lexer_push_context(lexer, main_parser.context, main_parser.keywords, main_parser.name); result = cfg_parse_plugin(configuration, plugin, yylloc, arg); cfg_lexer_pop_context(lexer); if (!result) { fprintf(stderr, "Error parsing expression\n"); goto finish; } finish: configuration->lexer = old_lexer; if (lexer) cfg_lexer_free(lexer); g_free(yylloc); g_strfreev(delimited); return result; } static gboolean parse_general_config(const gchar *config_to_parse, gint context, gpointer arg) { gpointer result = NULL; CfgLexer *lexer = cfg_lexer_new_buffer(configuration, config_to_parse, strlen(config_to_parse)); if (!cfg_run_parser(configuration, lexer, &main_parser, &result, arg)) { fprintf(stderr, "Error parsing expression\n"); return FALSE; } return TRUE; } gboolean parse_config(const gchar *config_to_parse, gint context, gpointer arg, gpointer *result) { if (!config_to_parse || strlen(config_to_parse) == 0) return FALSE; if (result) { *result = parse_plugin_config(config_to_parse, context, arg); if (*result) return TRUE; } if (main_parser.context != context) return FALSE; return parse_general_config(config_to_parse, context, arg); } syslog-ng-syslog-ng-3.13.2/libtest/config_parse_lib.h000066400000000000000000000024061321171025300225430ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Viktor Juhász * Copyright (c) 2014 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CONFIG_PARSE_LIB_H_INCLUDED #define CONFIG_PARSE_LIB_H_INCLUDED 1 #include "testutils.h" gboolean parse_config(const gchar *config_to_parse, gint context, gpointer arg, gpointer *result); #endif syslog-ng-syslog-ng-3.13.2/libtest/libtest.c000066400000000000000000000021141321171025300207130ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ void msg_event(int prio, const char *desc, void *tag1, ...) { ; } void main_loop_wakeup(void) { ; } syslog-ng-syslog-ng-3.13.2/libtest/license_module_mock.c000066400000000000000000000020571321171025300232530ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "license_module_mock.h" gboolean license_module_init(GlobalConfig *cfg, CfgArgs *args) { return TRUE; } syslog-ng-syslog-ng-3.13.2/libtest/license_module_mock.h000066400000000000000000000021201321171025300232470ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LICENSE_MODULE_MOCK #define LICENSE_MODULE_MOCK 1 #include "cfg.h" gboolean license_module_init(GlobalConfig *cfg, CfgArgs *args); #endif syslog-ng-syslog-ng-3.13.2/libtest/mock-transport.c000066400000000000000000000117131321171025300222350ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "mock-transport.h" #include "gsockaddr.h" #include #include typedef struct { LogTransport super; /* data is stored in a series of data chunks, that are going to be returned as individual reads */ struct iovec iov[32]; gint iov_cnt; /* index currently read i/o chunk */ gint current_iov_ndx; /* position within the current I/O chunk */ gint current_iov_pos; gboolean input_is_a_stream; gboolean inject_eagain; gboolean eof_is_eagain; } LogTransportMock; gssize log_transport_mock_read_method(LogTransport *s, gpointer buf, gsize count, LogTransportAuxData *aux) { LogTransportMock *self = (LogTransportMock *) s; struct iovec *current_iov; if (self->current_iov_ndx >= self->iov_cnt) { count = 0; goto exit; } current_iov = &self->iov[self->current_iov_ndx]; if (self->inject_eagain) { self->inject_eagain = FALSE; errno = EAGAIN; return -1; } else { self->inject_eagain = TRUE; } if (self->input_is_a_stream) count = 1; if (count + self->current_iov_pos > current_iov->iov_len) count = current_iov->iov_len - self->current_iov_pos; if (GPOINTER_TO_UINT(current_iov->iov_base) < 4096) { /* error injection */ errno = GPOINTER_TO_UINT(current_iov->iov_base); return -1; } memcpy(buf, current_iov->iov_base + self->current_iov_pos, count); self->current_iov_pos += count; if (self->current_iov_pos >= current_iov->iov_len) { self->current_iov_pos = 0; self->current_iov_ndx++; } if (aux) aux->peer_addr = g_sockaddr_inet_new("1.2.3.4", 5555); exit: if (count == 0 && self->eof_is_eagain) { errno = EAGAIN; return -1; } return count; } static void log_transport_mock_init(LogTransportMock *self, gchar *read_buffer1, gssize read_buffer_length1, va_list va) { gchar *buffer; gssize length; self->super.fd = 0; self->super.cond = 0; self->super.read = log_transport_mock_read_method; self->super.free_fn = log_transport_free_method; buffer = read_buffer1; length = read_buffer_length1; while (buffer) { /* NOTE: our iov buffer is of a fixed size, increase if your test needs more chunks of data */ g_assert(self->iov_cnt < sizeof(self->iov) / sizeof(self->iov[0])); if (length < 0) length = strlen(buffer); self->iov[self->iov_cnt].iov_base = buffer; self->iov[self->iov_cnt].iov_len = length; self->iov_cnt++; buffer = va_arg(va, gchar *); length = va_arg(va, gint); } self->current_iov_ndx = 0; self->current_iov_pos = 0; } LogTransport * log_transport_mock_stream_new(gchar *read_buffer1, gssize read_buffer_length1, ...) { LogTransportMock *self = g_new0(LogTransportMock, 1); va_list va; va_start(va, read_buffer_length1); log_transport_mock_init(self, read_buffer1, read_buffer_length1, va); va_end(va); self->input_is_a_stream = TRUE; return &self->super; } LogTransport * log_transport_mock_endless_stream_new(gchar *read_buffer1, gssize read_buffer_length1, ...) { LogTransportMock *self = g_new0(LogTransportMock, 1); va_list va; va_start(va, read_buffer_length1); log_transport_mock_init(self, read_buffer1, read_buffer_length1, va); va_end(va); self->input_is_a_stream = TRUE; self->eof_is_eagain = TRUE; return &self->super; } LogTransport * log_transport_mock_records_new(gchar *read_buffer1, gssize read_buffer_length1, ...) { LogTransportMock *self = g_new0(LogTransportMock, 1); va_list va; va_start(va, read_buffer_length1); log_transport_mock_init(self, read_buffer1, read_buffer_length1, va); va_end(va); return &self->super; } LogTransport * log_transport_mock_endless_records_new(gchar *read_buffer1, gssize read_buffer_length1, ...) { LogTransportMock *self = g_new0(LogTransportMock, 1); va_list va; va_start(va, read_buffer_length1); log_transport_mock_init(self, read_buffer1, read_buffer_length1, va); va_end(va); self->eof_is_eagain = TRUE; return &self->super; } syslog-ng-syslog-ng-3.13.2/libtest/mock-transport.h000066400000000000000000000034451321171025300222450ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MOCK_TRANSPORT_H_INCLUDED #define MOCK_TRANSPORT_H_INCLUDED 1 #include "transport/logtransport.h" /* macro to be used when injecting an error in the I/O stream */ #define LTM_INJECT_ERROR(err) (GUINT_TO_POINTER(err)), 0 /* macro to be used at the end of the I/O stream */ #define LTM_EOF NULL, 0 #define LTM_PADDING "padd", -1, "padd", -1, "padd", -1, "padd", -1, "padd", -1 LogTransport * log_transport_mock_stream_new(gchar *read_buffer1, gssize read_buffer_length1, ...); LogTransport * log_transport_mock_endless_stream_new(gchar *read_buffer1, gssize read_buffer_length1, ...); LogTransport * log_transport_mock_records_new(gchar *read_buffer1, gssize read_buffer_length1, ...); LogTransport * log_transport_mock_endless_records_new(gchar *read_buffer1, gssize read_buffer_length1, ...); #endif syslog-ng-syslog-ng-3.13.2/libtest/msg_parse_lib.c000066400000000000000000000117771321171025300220720ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "msg_parse_lib.h" #include "plugin.h" void init_and_load_syslogformat_module(void) { configuration = cfg_new_snippet(); cfg_load_module(configuration, "syslogformat"); msg_format_options_defaults(&parse_options); msg_format_options_init(&parse_options, configuration); } void deinit_syslogformat_module(void) { if (configuration) cfg_free(configuration); configuration = NULL; } void assert_log_message_has_tag(LogMessage *log_message, const gchar *tag_name) { assert_true(log_msg_is_tag_by_name(log_message, tag_name), "Expected message to have '%s' tag", tag_name); } void assert_log_message_doesnt_have_tag(LogMessage *log_message, const gchar *tag_name) { assert_false(log_msg_is_tag_by_name(log_message, tag_name), "Expected message not to have '%s' tag", tag_name); } void assert_log_message_value(LogMessage *self, NVHandle handle, const gchar *expected_value) { gssize key_name_length; gssize value_length; const gchar *key_name = log_msg_get_value_name(handle, &key_name_length); const gchar *actual_value = log_msg_get_value(self, handle, &value_length); if (expected_value) assert_string(actual_value, expected_value, "Value is not expected for key %s", key_name); else assert_string(actual_value, "", "No value is expected for key %s but its value is %s", key_name, actual_value); } void assert_log_message_value_by_name(LogMessage *self, const gchar *name, const gchar *expected_value) { assert_log_message_value(self, log_msg_get_value_handle(name), expected_value); } void assert_log_messages_saddr(LogMessage *log_message_a, LogMessage *log_message_b) { gchar address_a[256], address_b[256]; g_sockaddr_format(log_message_a->saddr, address_a, sizeof(address_a), GSA_FULL); g_sockaddr_format(log_message_b->saddr, address_b, sizeof(address_b), GSA_FULL); assert_string(address_a, address_b, "Socket address is not expected"); } void assert_structured_data_of_messages(LogMessage *log_message_a, LogMessage *log_message_b) { GString *structured_data_string_a = g_string_sized_new(0); GString *structured_data_string_b = g_string_sized_new(0); log_msg_format_sdata(log_message_a, structured_data_string_a, 0); log_msg_format_sdata(log_message_b, structured_data_string_b, 0); assert_string(structured_data_string_a->str, structured_data_string_b->str, "Structure data string are not the same"); g_string_free(structured_data_string_a, TRUE); g_string_free(structured_data_string_b, TRUE); } void assert_log_message_values_equal(LogMessage *log_message_a, LogMessage *log_message_b, NVHandle handle) { gssize key_name_length; const gchar *key_name = log_msg_get_value_name(handle, &key_name_length); const gchar *value_a = log_msg_get_value(log_message_a, handle, NULL); const gchar *value_b = log_msg_get_value(log_message_b, handle, NULL); assert_string(value_a, value_b, "Value is not expected for key %s", key_name); } void assert_log_messages_equal(LogMessage *log_message_a, LogMessage *log_message_b) { assert_gint(log_message_a->timestamps[LM_TS_STAMP].tv_sec, log_message_b->timestamps[LM_TS_STAMP].tv_sec, "Timestamps are not the same"); assert_guint32(log_message_a->timestamps[LM_TS_STAMP].tv_usec, log_message_b->timestamps[LM_TS_STAMP].tv_usec, "Timestamps usec are not the same"); assert_guint32(log_message_a->timestamps[LM_TS_STAMP].zone_offset, log_message_b->timestamps[LM_TS_STAMP].zone_offset, "Timestamp offset are not the same"); assert_guint16(log_message_a->pri, log_message_b->pri, "Priorities are not the same"); assert_log_message_values_equal(log_message_a, log_message_b, LM_V_HOST); assert_log_message_values_equal(log_message_a, log_message_b, LM_V_PROGRAM); assert_log_message_values_equal(log_message_a, log_message_b, LM_V_MESSAGE); assert_log_message_values_equal(log_message_a, log_message_b, LM_V_PID); assert_log_message_values_equal(log_message_a, log_message_b, LM_V_MSGID); assert_structured_data_of_messages(log_message_a, log_message_b); assert_log_messages_saddr(log_message_a, log_message_b); } syslog-ng-syslog-ng-3.13.2/libtest/msg_parse_lib.h000066400000000000000000000047701321171025300220720ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MSG_PARSE_LIB_H_INCLUDED #define MSG_PARSE_LIB_H_INCLUDED #include "testutils.h" #include "cfg.h" #include "logmsg/logmsg.h" MsgFormatOptions parse_options; #define MSG_TESTCASE(x, ...) do { log_message_testcase_begin(#x, #__VA_ARGS__); x(__VA_ARGS__); log_message_testcase_end(); } while(0) #define log_message_testcase_begin(func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ } \ while (0) #define log_message_testcase_end() \ do \ { \ testcase_end(); \ } \ while (0) void init_and_load_syslogformat_module(void); void deinit_syslogformat_module(void); void assert_log_messages_equal(LogMessage *log_message_a, LogMessage *log_message_b); void assert_log_message_value(LogMessage *self, NVHandle handle, const gchar *expected_value); void assert_log_message_value_by_name(LogMessage *self, const gchar *name, const gchar *expected_value); void assert_log_message_has_tag(LogMessage *log_message, const gchar *tag_name); void assert_log_message_doesnt_have_tag(LogMessage *log_message, const gchar *tag_name); void assert_log_messages_saddr(LogMessage *log_message_a, LogMessage *log_message_b); void assert_structured_data_of_messages(LogMessage *log_message_a, LogMessage *log_message_b); void assert_log_message_values_equal(LogMessage *log_message_a, LogMessage *log_message_b, NVHandle handle); #endif syslog-ng-syslog-ng-3.13.2/libtest/persist_lib.c000066400000000000000000000044301321171025300215670ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "persist_lib.h" #include #include PersistState * create_persist_state_for_test(const gchar *name) { PersistState *state = persist_state_new(name); if (!persist_state_start(state)) { fprintf(stderr, "Error starting persist_state object\n"); exit(1); } return state; }; PersistState * clean_and_create_persist_state_for_test(const gchar *name) { unlink(name); return create_persist_state_for_test(name); }; PersistState * restart_persist_state(PersistState *state) { PersistState *new_state; gchar *name = g_strdup(persist_state_get_filename(state)); persist_state_commit(state); persist_state_free(state); new_state = create_persist_state_for_test(name); g_free(name); return new_state; }; void cancel_and_destroy_persist_state(PersistState *state) { gchar *filename = g_strdup(persist_state_get_filename(state)); persist_state_cancel(state); persist_state_free(state); unlink(filename); g_free(filename); }; void commit_and_free_persist_state(PersistState *state) { persist_state_commit(state); persist_state_free(state); }; void commit_and_destroy_persist_state(PersistState *state) { gchar *filename = g_strdup(persist_state_get_filename(state)); commit_and_free_persist_state(state); unlink(filename); g_free(filename); }; syslog-ng-syslog-ng-3.13.2/libtest/persist_lib.h000066400000000000000000000027341321171025300216010ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Viktor Tusa * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LIBTEST_PERSIST_LIB_H_INCLUDED #define LIBTEST_PERSIST_LIB_H_INCLUDED #include "testutils.h" #include "persist-state.h" PersistState *create_persist_state_for_test(const gchar *name); PersistState *clean_and_create_persist_state_for_test(const gchar *name); void cancel_and_destroy_persist_state(PersistState *state); void commit_and_destroy_persist_state(PersistState *state); void commit_and_free_persist_state(PersistState *state); PersistState *restart_persist_state(PersistState *state); #endif syslog-ng-syslog-ng-3.13.2/libtest/proto_lib.c000066400000000000000000000117441321171025300212470ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "proto_lib.h" #include "msg_parse_lib.h" LogProtoServerOptions proto_server_options; void assert_proto_server_status(LogProtoServer *proto, LogProtoStatus status, LogProtoStatus expected_status) { assert_gint(status, expected_status, "LogProtoServer expected status mismatch"); } LogProtoStatus proto_server_fetch(LogProtoServer *proto, const guchar **msg, gsize *msg_len) { Bookmark bookmark; LogTransportAuxData aux; GSockAddr *saddr; gboolean may_read = TRUE; LogProtoStatus status; start_grabbing_messages(); do { log_transport_aux_data_init(&aux); status = log_proto_server_fetch(proto, msg, msg_len, &may_read, &aux, &bookmark); } while (status == LPS_SUCCESS && *msg == NULL && may_read); saddr = aux.peer_addr; if (status == LPS_SUCCESS) { g_sockaddr_unref(saddr); } else { assert_true(saddr == NULL, "returned saddr must be NULL on failure"); } stop_grabbing_messages(); return status; } LogProtoServer * construct_server_proto_plugin(const gchar *name, LogTransport *transport) { LogProtoServerFactory *proto_factory; log_proto_server_options_init(&proto_server_options, configuration); proto_factory = log_proto_server_get_factory(&configuration->plugin_context, name); assert_true(proto_factory != NULL, "error looking up proto factory"); return log_proto_server_factory_construct(proto_factory, transport, &proto_server_options); } void assert_proto_server_fetch(LogProtoServer *proto, const gchar *expected_msg, gssize expected_msg_len) { const guchar *msg = NULL; gsize msg_len = 0; LogProtoStatus status; status = proto_server_fetch(proto, &msg, &msg_len); assert_proto_server_status(proto, status, LPS_SUCCESS); assert_nstring((const gchar *) msg, msg_len, expected_msg, expected_msg_len, "LogProtoServer expected message mismatch"); } void assert_proto_server_fetch_single_read(LogProtoServer *proto, const gchar *expected_msg, gssize expected_msg_len) { const guchar *msg = NULL; gsize msg_len = 0; LogProtoStatus status; LogTransportAuxData aux; Bookmark bookmark; gboolean may_read = TRUE; start_grabbing_messages(); log_transport_aux_data_init(&aux); status = log_proto_server_fetch(proto, &msg, &msg_len, &may_read, &aux, &bookmark); assert_proto_server_status(proto, status, LPS_SUCCESS); if (expected_msg) { assert_nstring((const gchar *) msg, msg_len, expected_msg, expected_msg_len, "LogProtoServer expected message mismatch"); } else { assert_true(msg == NULL, "when single-read finds an incomplete message, msg must be NULL"); assert_true(aux.peer_addr == NULL, "returned saddr must be NULL on success"); } stop_grabbing_messages(); } void assert_proto_server_fetch_failure(LogProtoServer *proto, LogProtoStatus expected_status, const gchar *error_message) { const guchar *msg = NULL; gsize msg_len = 0; LogProtoStatus status; status = proto_server_fetch(proto, &msg, &msg_len); assert_proto_server_status(proto, status, expected_status); if (error_message) assert_grabbed_messages_contain(error_message, "expected error message didn't show up"); } void assert_proto_server_fetch_ignored_eof(LogProtoServer *proto) { const guchar *msg = NULL; gsize msg_len = 0; LogProtoStatus status; LogTransportAuxData aux; Bookmark bookmark; gboolean may_read = TRUE; start_grabbing_messages(); log_transport_aux_data_init(&aux); status = log_proto_server_fetch(proto, &msg, &msg_len, &may_read, &aux, &bookmark); assert_proto_server_status(proto, status, LPS_SUCCESS); assert_true(msg == NULL, "when an EOF is ignored msg must be NULL"); assert_true(aux.peer_addr == NULL, "returned saddr must be NULL on success"); stop_grabbing_messages(); } void init_proto_tests(void) { init_and_load_syslogformat_module(); log_proto_server_options_defaults(&proto_server_options); log_proto_server_options_init(&proto_server_options, configuration); } void deinit_proto_tests(void) { deinit_syslogformat_module(); } syslog-ng-syslog-ng-3.13.2/libtest/proto_lib.h000066400000000000000000000052301321171025300212450ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PROTO_LIB_H_INCLUDED #define PROTO_LIB_H_INCLUDED #include "testutils.h" #include "logproto/logproto-server.h" extern LogProtoServerOptions proto_server_options; #define PROTO_TESTCASE(x, ...) do { log_proto_testcase_begin(#x, #__VA_ARGS__); x(__VA_ARGS__); log_proto_testcase_end(); } while(0) #define log_proto_testcase_begin(func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ log_proto_server_options_defaults(&proto_server_options); \ } \ while (0) #define log_proto_testcase_end() \ do \ { \ log_proto_server_options_destroy(&proto_server_options); \ testcase_end(); \ } \ while (0) void assert_proto_server_status(LogProtoServer *proto, LogProtoStatus status, LogProtoStatus expected_status); void assert_proto_server_fetch(LogProtoServer *proto, const gchar *expected_msg, gssize expected_msg_len); void assert_proto_server_fetch_single_read(LogProtoServer *proto, const gchar *expected_msg, gssize expected_msg_len); void assert_proto_server_fetch_failure(LogProtoServer *proto, LogProtoStatus expected_status, const gchar *error_message); void assert_proto_server_fetch_ignored_eof(LogProtoServer *proto); LogProtoServer *construct_server_proto_plugin(const gchar *name, LogTransport *transport); void init_proto_tests(void); void deinit_proto_tests(void); static inline LogProtoServerOptions * get_inited_proto_server_options(void) { log_proto_server_options_init(&proto_server_options, configuration); return &proto_server_options; } #endif syslog-ng-syslog-ng-3.13.2/libtest/queue_utils_lib.c000066400000000000000000000050771321171025300224520ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2016 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "queue_utils_lib.h" #include #include #include #include int acked_messages = 0; int fed_messages = 0; void test_ack(LogMessage *msg, AckType ack_type) { acked_messages++; } void feed_some_messages(LogQueue *q, int n, MsgFormatOptions *po) { LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; LogMessage *msg; gint i; path_options.ack_needed = q->use_backlog; path_options.flow_control_requested = TRUE; for (i = 0; i < n; i++) { gchar *msg_str = g_strdup_printf("<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]: árvíztűrőtükörfúrógép ID :%08d",i); GSockAddr *test_addr = g_sockaddr_inet_new("10.10.10.10", 1010); msg = log_msg_new(msg_str, strlen(msg_str), test_addr, po); g_sockaddr_unref(test_addr); g_free(msg_str); log_msg_add_ack(msg, &path_options); msg->ack_func = test_ack; log_queue_push_tail(q, msg, &path_options); fed_messages++; } } void send_some_messages(LogQueue *q, gint n) { gint i; LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; for (i = 0; i < n; i++) { LogMessage *msg = log_queue_pop_head(q, &path_options); if (q->use_backlog) { log_msg_ack(msg, &path_options, AT_PROCESSED); } log_msg_unref(msg); } } void app_rewind_some_messages(LogQueue *q, guint n) { log_queue_rewind_backlog(q,n); } void app_ack_some_messages(LogQueue *q, guint n) { log_queue_ack_backlog(q, n); } void rewind_messages(LogQueue *q) { log_queue_rewind_backlog_all(q); } syslog-ng-syslog-ng-3.13.2/libtest/queue_utils_lib.h000066400000000000000000000027211321171025300224500ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2016 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef QUEUE_UTILS_LIB_H #define QUEUE_UTILS_LIB_H 1 #include "logqueue.h" #include "logpipe.h" extern int acked_messages; extern int fed_messages; void test_ack(LogMessage *msg, AckType ack_type); void feed_some_messages(LogQueue *q, int n, MsgFormatOptions *po); void send_some_messages(LogQueue *q, gint n); void app_rewind_some_messages(LogQueue *q, guint n); void app_ack_some_messages(LogQueue *q, guint n); void rewind_messages(LogQueue *q); #endif syslog-ng-syslog-ng-3.13.2/libtest/stopwatch.c000066400000000000000000000032661321171025300212720ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * Copyright (c) 2016 Peter Gyorko * Copyright (c) 2016 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stopwatch.h" #include #include struct timeval start_time_val; void start_stopwatch(void) { gettimeofday(&start_time_val, NULL); } void stop_stopwatch_and_display_result(gint iterations, gchar *message_template, ...) { va_list args; guint64 diff; struct timeval end_time_val; gettimeofday(&end_time_val, NULL); va_start(args, message_template); vprintf(message_template, args); va_end(args); diff = (end_time_val.tv_sec - start_time_val.tv_sec) * 1000000 + end_time_val.tv_usec - start_time_val.tv_usec; printf("; %.2f iterations/sec", iterations * 1e6 / diff); printf(", runtime=%lu.%06lus\n", diff / 1000000, diff % 1000000); } syslog-ng-syslog-ng-3.13.2/libtest/stopwatch.h000066400000000000000000000023211321171025300212660ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Peter Gyorko * Copyright (c) 2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STOPWATCH_H_INCLUDED #define STOPWATCH_H_INCLUDED 1 #include void start_stopwatch(void); void stop_stopwatch_and_display_result(gint iterations, gchar *message_template, ...); #endif syslog-ng-syslog-ng-3.13.2/libtest/syslog-ng-test.pc.in000066400000000000000000000005711321171025300227360ustar00rootroot00000000000000# Package Information for pkg-config prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ pkglibdir=@libdir@/syslog-ng includedir=@includedir@ Name: syslog-ng-test Description: Test helper package for syslog-ng modules Version: @PACKAGE_VERSION@ Requires.private: glib-2.0 syslog-ng Libs: -L${pkglibdir}/libtest -lsyslog-ng-test Cflags: -I${includedir}/syslog-ng/libtest syslog-ng-syslog-ng-3.13.2/libtest/template_lib.c000066400000000000000000000215621321171025300217160ustar00rootroot00000000000000/* * Copyright (c) 2012-2015 Balabit * Copyright (c) 2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "template_lib.h" #include "msg_parse_lib.h" #include "stopwatch.h" #include void init_template_tests(void) { init_and_load_syslogformat_module(); } void deinit_template_tests(void) { deinit_syslogformat_module(); if (!testutils_deinit()) exit(1); } LogMessage * message_from_list(va_list ap) { char *key, *value; LogMessage *msg = create_empty_message(); if (!msg) return NULL; key = va_arg(ap, char *); while (key) { value = va_arg(ap, char *); if (!value) return msg; log_msg_set_value_by_name(msg, key, value, -1); key = va_arg(ap, char *); } return msg; } LogMessage * create_empty_message(void) { LogMessage *msg; char *msg_str = "<155>2006-02-11T10:34:56+01:00 bzorp syslog-ng[23323]:árvíztűrőtükörfúrógép"; GSockAddr *saddr; saddr = g_sockaddr_inet_new("10.11.12.13", 1010); msg = log_msg_new(msg_str, strlen(msg_str), saddr, &parse_options); g_sockaddr_unref(saddr); log_msg_set_match(msg, 0, "whole-match", -1); log_msg_set_match(msg, 1, "first-match", -1); log_msg_set_tag_by_name(msg, "alma"); log_msg_set_tag_by_name(msg, "korte"); log_msg_clear_tag_by_name(msg, "narancs"); log_msg_set_tag_by_name(msg, "citrom"); log_msg_set_tag_by_name(msg, "tag,containing,comma"); msg->rcptid = 555; msg->host_id = 0xcafebabe; /* fix some externally or automatically defined values */ log_msg_set_value(msg, LM_V_HOST_FROM, "kismacska", -1); msg->timestamps[LM_TS_RECVD].tv_sec = 1139684315; msg->timestamps[LM_TS_RECVD].tv_usec = 639000; msg->timestamps[LM_TS_RECVD].zone_offset = get_local_timezone_ofs(1139684315); return msg; } LogMessage * create_sample_message(void) { LogMessage *msg = create_empty_message(); log_msg_set_value_by_name(msg, "APP.VALUE", "value", -1); log_msg_set_value_by_name(msg, "APP.VALUE2", "value", -1); log_msg_set_value_by_name(msg, "APP.VALUE3", "value", -1); log_msg_set_value_by_name(msg, "APP.VALUE4", "value", -1); log_msg_set_value_by_name(msg, "APP.VALUE5", "value", -1); log_msg_set_value_by_name(msg, "APP.VALUE6", "value", -1); log_msg_set_value_by_name(msg, "APP.VALUE7", "value", -1); log_msg_set_value_by_name(msg, "APP.STRIP1", " value", -1); log_msg_set_value_by_name(msg, "APP.STRIP2", "value ", -1); log_msg_set_value_by_name(msg, "APP.STRIP3", " value ", -1); log_msg_set_value_by_name(msg, "APP.STRIP4", "value", -1); log_msg_set_value_by_name(msg, "APP.STRIP5", "", -1); log_msg_set_value_by_name(msg, "APP.QVALUE", "\"value\"", -1); log_msg_set_value_by_name(msg, ".unix.uid", "1000", -1); log_msg_set_value_by_name(msg, ".unix.gid", "1000", -1); log_msg_set_value_by_name(msg, ".unix.cmd", "command", -1); log_msg_set_value_by_name(msg, ".json.foo", "bar", -1); log_msg_set_value_by_name(msg, ".json.sub.value1", "subvalue1", -1); log_msg_set_value_by_name(msg, ".json.sub.value2", "subvalue2", -1); log_msg_set_value_by_name(msg, "escaping", "binary stuff follows \"\xad árvíztűrőtükörfúrógép", -1); log_msg_set_value_by_name(msg, "escaping2", "\xc3", -1); log_msg_set_value_by_name(msg, "null", "binary\0stuff", 12); log_msg_set_value_by_name(msg, "comma_value", "value,with,a,comma", -1); return msg; } LogTemplate * compile_template(const gchar *template, gboolean escaping) { LogTemplate *templ = log_template_new(configuration, NULL); gboolean success; GError *error = NULL; log_template_set_escape(templ, escaping); success = log_template_compile(templ, template, &error); expect_true(success, "template expected to compile cleanly," " but it didn't, template=%s, error=%s", template, error ? error->message : "(none)"); g_clear_error(&error); return templ; } void assert_template_format_with_escaping_and_context_msgs(const gchar *template, gboolean escaping, const gchar *expected, gssize expected_len, LogMessage **msgs, gint num_messages) { LogTemplate *templ = compile_template(template, escaping); if (!templ) return; GString *res = g_string_sized_new(128); const gchar *context_id = "test-context-id"; log_template_format_with_context(templ, msgs, num_messages, NULL, LTZ_LOCAL, 999, context_id, res); expect_nstring(res->str, res->len, expected, expected_len >= 0 ? expected_len : strlen(expected), "context template test failed, template=%s", template); log_template_unref(templ); g_string_free(res, TRUE); } void assert_template_format_with_context_msgs(const gchar *template, const gchar *expected, LogMessage **msgs, gint num_messages) { assert_template_format_with_escaping_and_context_msgs(template, FALSE, expected, -1, msgs, num_messages); } void assert_template_format_with_escaping_msg(const gchar *template, gboolean escaping, const gchar *expected, LogMessage *msg) { assert_template_format_with_escaping_and_context_msgs(template, escaping, expected, -1, &msg, 1); } void assert_template_format_with_escaping(const gchar *template, gboolean escaping, const gchar *expected) { LogMessage *msg = create_sample_message(); assert_template_format_with_escaping_msg(template, escaping, expected, msg); log_msg_unref(msg); } void assert_template_format_msg(const gchar *template, const gchar *expected, LogMessage *msg) { assert_template_format_with_escaping_msg(template, FALSE, expected, msg); } void assert_template_format(const gchar *template, const gchar *expected) { assert_template_format_with_escaping(template, FALSE, expected); } void assert_template_format_with_context(const gchar *template, const gchar *expected) { LogMessage *msg; LogMessage *context[2]; msg = create_sample_message(); context[0] = context[1] = msg; assert_template_format_with_context_msgs(template, expected, context, 2); log_msg_unref(msg); } void assert_template_format_with_len(const gchar *template, const gchar *expected, gssize expected_len) { LogMessage *msg = create_sample_message(); assert_template_format_with_escaping_and_context_msgs(template, FALSE, expected, expected_len, &msg, 1); log_msg_unref(msg); } void assert_template_failure(const gchar *template, const gchar *expected_error) { LogTemplate *templ = log_template_new(configuration, NULL); GError *error = NULL; expect_false(log_template_compile(templ, template, &error), "compilation failure expected to template," " but success was returned, template=%s, expected_error=%s\n", template, expected_error); expect_true(strstr(error ? error->message : "", expected_error) != NULL, "FAIL: compilation error doesn't match, error=%s, expected_error=%s\n", error->message, expected_error); g_clear_error(&error); log_template_unref(templ); } #define BENCHMARK_COUNT 100000 void perftest_template(gchar *template) { LogTemplate *templ; LogMessage *msg; GString *res = g_string_sized_new(1024); gint i; GError *error = NULL; templ = log_template_new(configuration, NULL); if (!log_template_compile(templ, template, &error)) { expect_true(FALSE, "template expected to compile cleanly," " but it didn't, template=%s, error=%s", template, error ? error->message : "(none)"); return; } msg = create_sample_message(); start_stopwatch(); for (i = 0; i < BENCHMARK_COUNT; i++) { log_template_format(templ, msg, NULL, LTZ_LOCAL, 0, NULL, res); } stop_stopwatch_and_display_result(BENCHMARK_COUNT, " %-90.*s", (int) strlen(template) - 1, template); log_template_unref(templ); g_string_free(res, TRUE); log_msg_unref(msg); } syslog-ng-syslog-ng-3.13.2/libtest/template_lib.h000066400000000000000000000051511321171025300217170ustar00rootroot00000000000000/* * Copyright (c) 2012-2015 Balabit * Copyright (c) 2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LIBTEST_TEMPLATE_LIB_H_INCLUDED #define LIBTEST_TEMPLATE_LIB_H_INCLUDED 1 #include "testutils.h" #include "template/templates.h" #include void assert_template_format(const gchar *template, const gchar *expected); void assert_template_format_msg(const gchar *template, const gchar *expected, LogMessage *msg); void assert_template_format_with_escaping(const gchar *template, gboolean escaping, const gchar *expected); void assert_template_format_with_escaping_msg(const gchar *template, gboolean escaping, const gchar *expected, LogMessage *msg); void assert_template_format_with_context(const gchar *template, const gchar *expected); void assert_template_format_with_context_msgs(const gchar *template, const gchar *expected, LogMessage **msgs, gint num_messages); void assert_template_format_with_len(const gchar *template, const gchar *expected, gssize expected_len); void assert_template_format_with_escaping_and_context_msgs(const gchar *template, gboolean escaping, const gchar *expected, gssize expected_len, LogMessage **msgs, gint num_messages); void assert_template_failure(const gchar *template, const gchar *expected_failure); void perftest_template(gchar *template); LogMessage *create_empty_message(void); LogMessage *create_sample_message(void); LogMessage *message_from_list(va_list ap); LogTemplate *compile_template(const gchar *template, gboolean escaping); void init_template_tests(void); void deinit_template_tests(void); #endif syslog-ng-syslog-ng-3.13.2/libtest/testutils.c000066400000000000000000000332621321171025300213150ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Peter Gyorko * Copyright (c) 2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include "messages.h" #include #include #include #include static gboolean testutils_global_success = TRUE; GString *current_testcase_description = NULL; gchar *current_testcase_function = NULL; gchar *current_testcase_file = NULL; GList *internal_messages = NULL; static void print_failure(const gchar *custom_template, va_list custom_args, gchar *assertion_failure_template, ...) { testutils_global_success = FALSE; va_list assertion_failure_args; fprintf(stderr, "\n ###########################################################################\n #\n"); fprintf(stderr, " # FAIL: ASSERTION FAILED"); if (custom_template != NULL) { fprintf(stderr, ": "); vfprintf(stderr, custom_template, custom_args); } fprintf(stderr, "; "); va_start(assertion_failure_args, assertion_failure_template); vfprintf(stderr, assertion_failure_template, assertion_failure_args); va_end(assertion_failure_args); fprintf(stderr, "\n"); if (current_testcase_description != NULL) { fprintf(stderr, " #\n"); fprintf(stderr, " # Test case: %s/%s()\n", current_testcase_file, current_testcase_function); fprintf(stderr, " #\n"); fprintf(stderr, " # %s\n", current_testcase_description->str); } fprintf(stderr, " #\n ###########################################################################\n\n"); } static void grab_message(LogMessage *msg) { internal_messages = g_list_append(internal_messages, msg); } void reset_grabbed_messages(void) { g_list_foreach(internal_messages, (GFunc) log_msg_unref, NULL); g_list_free(internal_messages); internal_messages = NULL; } void start_grabbing_messages(void) { reset_grabbed_messages(); msg_set_post_func(grab_message); } void display_grabbed_messages(void) { GList *l; if (internal_messages) { fprintf(stderr, " # Grabbed internal messages follow:\n"); for (l = internal_messages; l; l = l->next) { LogMessage *msg = (LogMessage *) l->data; const gchar *msg_text = log_msg_get_value(msg, LM_V_MESSAGE, NULL); fprintf(stderr, " #\t%s\n", msg_text); } } else { fprintf(stderr, " # No internal messeges grabbed!\n"); } } void stop_grabbing_messages(void) { msg_set_post_func(NULL); } gboolean assert_grabbed_messages_contain_non_fatal(const gchar *pattern, const gchar *error_message, ...) { GList *l; va_list args; for (l = internal_messages; l; l = l->next) { LogMessage *msg = (LogMessage *) l->data; const gchar *msg_text = log_msg_get_value(msg, LM_V_MESSAGE, NULL); if (strstr(msg_text, pattern)) { return TRUE; } } va_start(args, error_message); print_failure(error_message, args, "no grabbed message contains the pattern=%s", pattern); va_end(args); display_grabbed_messages(); return FALSE; } gchar ** fill_string_array(gint number_of_elements, ...) { va_list args; gint i; gchar **result; result = g_new(gchar *, number_of_elements); va_start(args, number_of_elements); for (i = 0; i < number_of_elements; ++i) { result[i] = va_arg(args, char *); } va_end(args); return result; } gboolean assert_guint16_non_fatal(guint16 actual, guint16 expected, const gchar *error_message, ...) { va_list args; if (actual == expected) return TRUE; va_start(args, error_message); print_failure(error_message, args, "actual=%d, expected=%d", actual, expected); va_end(args); return FALSE; } gboolean assert_gint64_non_fatal(gint64 actual, gint64 expected, const gchar *error_message, ...) { va_list args; if (actual == expected) return TRUE; va_start(args, error_message); print_failure(error_message, args, "actual=%lld, expected=%lld", actual, expected); va_end(args); return FALSE; } gboolean assert_guint64_non_fatal(guint64 actual, guint64 expected, const gchar *error_message, ...) { va_list args; if (actual == expected) return TRUE; va_start(args, error_message); print_failure(error_message, args, "actual=%llu, expected=%llu", actual, expected); va_end(args); return FALSE; } gboolean assert_gdouble_non_fatal(gdouble actual, gdouble expected, const gchar *error_message, ...) { va_list args; if (actual == expected) return TRUE; va_start(args, error_message); print_failure(error_message, args, "actual=%f, expected=%f", actual, expected); va_end(args); return FALSE; } static gboolean assert_nstring_non_fatal_va(const gchar *actual, gint actual_len, const gchar *expected, gint expected_len, const gchar *error_message, va_list args) { if (expected == NULL && actual == NULL) return TRUE; if (actual && actual_len < 0) actual_len = strlen(actual); if (expected && expected_len < 0) expected_len = strlen(expected); if (actual_len == expected_len && actual != NULL && expected != NULL && memcmp(actual, expected, actual_len) == 0) return TRUE; print_failure(error_message, args, " actual_length=%d expected_length=%d,\n" " # actual= " PRETTY_NSTRING_FORMAT ",\n" " # expected= " PRETTY_NSTRING_FORMAT, actual_len, expected_len, PRETTY_NSTRING(actual, actual_len), PRETTY_NSTRING(expected, expected_len)); return FALSE; } gboolean assert_nstring_non_fatal(const gchar *actual, gint actual_len, const gchar *expected, gint expected_len, const gchar *error_message, ...) { va_list args; gboolean result; va_start(args, error_message); result = assert_nstring_non_fatal_va(actual, actual_len, expected, expected_len, error_message, args); va_end(args); return result; } static gboolean compare_arrays_trivially(void *actual, guint32 actual_length, void *expected, guint32 expected_length, const gchar *error_message_template, va_list error_message_args) { if (expected_length != actual_length) { print_failure(error_message_template, error_message_args, "actual_length=%u, expected_length=%u", actual_length, expected_length); return FALSE; } if (expected_length > 0 && actual == NULL) { print_failure(error_message_template, error_message_args, "actual=NULL, expected_length=%u", expected_length); return FALSE; } return TRUE; } gboolean assert_guint32_array_non_fatal(guint32 *actual, guint32 actual_length, guint32 *expected, guint32 expected_length, const gchar *error_message, ...) { va_list args; gboolean assertion_ok = TRUE; guint32 i; va_start(args, error_message); assertion_ok = compare_arrays_trivially((void *)actual, actual_length, (void *)expected, expected_length, error_message, args); if (assertion_ok) { for (i = 0; i < expected_length; ++i) { if (expected[i] != actual[i]) { print_failure(error_message, args, "actual=%u, expected=%u, index=%u", actual[i], expected[i], i); assertion_ok = FALSE; break; } } } va_end(args); return assertion_ok; } /* NOTE: this does the same as g_strcmp0(), but we use an older glib, which lacks this function */ static gboolean are_strings_equal(gchar *a, gchar *b) { if (a == NULL && b == NULL) return TRUE; if (a == NULL || b == NULL) return FALSE; return strcmp(a, b) == 0; } gboolean assert_string_array_non_fatal(gchar **actual, guint32 actual_length, gchar **expected, guint32 expected_length, const gchar *error_message, ...) { va_list args; gboolean assertion_ok = TRUE; guint32 i; va_start(args, error_message); assertion_ok = compare_arrays_trivially((void *)actual, actual_length, (void *)expected, expected_length, error_message, args); if (assertion_ok) { for (i = 0; i < expected_length; ++i) { if (!are_strings_equal(actual[i], expected[i])) { print_failure(error_message, args, "actual=" PRETTY_STRING_FORMAT ", expected=" PRETTY_STRING_FORMAT ", index=%u", PRETTY_STRING(actual[i]), PRETTY_STRING(expected[i]), i); assertion_ok = FALSE; break; } } } va_end(args); return assertion_ok; } gboolean expect_not_reached(const gchar *error_message, ...) { va_list args; va_start(args, error_message); print_failure(error_message, args, "execution was not expected to reach this point"); va_end(args); return FALSE; } gboolean assert_gboolean_non_fatal(gboolean actual, gboolean expected, const gchar *error_message, ...) { va_list args; if (actual == expected) return TRUE; va_start(args, error_message); print_failure(error_message, args, "actual=%s, expected=%s", gboolean_to_string(actual), gboolean_to_string(expected)); va_end(args); return FALSE; } gboolean assert_null_non_fatal_va(const void *pointer, const gchar *error_message, va_list args) { if (pointer == NULL) return TRUE; print_failure(error_message, args, "Pointer expected to be NULL; pointer=%llx", (guint64)pointer); return FALSE; } gboolean assert_null_non_fatal(const void *pointer, const gchar *error_message, ...) { va_list args; va_start(args, error_message); gboolean success = assert_null_non_fatal_va(pointer, error_message, args); va_end(args); return success; } gboolean assert_not_null_non_fatal_va(void *pointer, const gchar *error_message, va_list args) { if (pointer != NULL) return TRUE; print_failure(error_message, args, "Unexpected NULL pointer"); return FALSE; } gboolean assert_not_null_non_fatal(void *pointer, const gchar *error_message, ...) { va_list args; va_start(args, error_message); gboolean success = assert_not_null_non_fatal_va(pointer, error_message, args); va_end(args); return success; } gboolean assert_no_error_non_fatal(GError *error, const gchar *error_message, ...) { va_list args; if (error == NULL) return TRUE; va_start(args, error_message); print_failure(error_message, args, "GError expected to be NULL; message='%s'", error->message); va_end(args); return FALSE; } static int cmp_guint32(const void *a, const void *b) { return (*(guint32 *)a - *(guint32 *)b); } gboolean assert_guint32_set_non_fatal(guint32 *actual, guint32 actual_length, guint32 *expected, guint32 expected_length, const gchar *error_message, ...) { va_list args; gboolean ret; if (actual_length != expected_length) { va_start(args, error_message); print_failure(error_message, args, "actual_length='%d', expected_length='%d'", actual_length, expected_length); va_end(args); return FALSE; } qsort(actual, actual_length, sizeof(guint32), cmp_guint32); qsort(expected, expected_length, sizeof(guint32), cmp_guint32); va_start(args, error_message); ret = assert_guint32_array(actual, actual_length, expected, expected_length, error_message, args); va_end(args); return ret; } gboolean assert_gpointer_non_fatal(gpointer actual, gpointer expected, const gchar *error_message, ...) { va_list args; if (actual == expected) return TRUE; va_start(args, error_message); print_failure(error_message, args, "actual=%x, expected=%x", actual, expected); va_end(args); return FALSE; } gboolean assert_msg_field_equals_non_fatal(LogMessage *msg, gchar *field_name, gchar *expected_value, gssize expected_value_len, const gchar *error_message, ...) { gssize actual_value_len; const gchar *actual_value; va_list args; gboolean result; if (expected_value_len < 0) expected_value_len = strlen(expected_value); NVHandle handle = log_msg_get_value_handle(field_name); actual_value = log_msg_get_value(msg, handle, &actual_value_len); va_start(args, error_message); result = assert_nstring_non_fatal_va(actual_value, actual_value_len, expected_value, expected_value_len, error_message, args); va_end(args); return result; } gboolean assert_msg_field_unset_non_fatal(LogMessage *msg, gchar *field_name, const gchar *error_message, ...) { gssize actual_value_len; const gchar *actual_value; va_list args; NVHandle handle = log_msg_get_value_handle(field_name); actual_value = log_msg_get_value_if_set(msg, handle, &actual_value_len); va_start(args, error_message); gboolean success = assert_null_non_fatal_va(actual_value, error_message, args); va_end(args); return success; } gboolean testutils_deinit(void) { return testutils_global_success; } syslog-ng-syslog-ng-3.13.2/libtest/testutils.h000066400000000000000000000223421321171025300213170ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Peter Gyorko * Copyright (c) 2012 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LIBTEST_H_INCLUDED #define LIBTEST_H_INCLUDED #include #include #include #include #include #include "logmsg/logmsg.h" #define PRETTY_STRING_FORMAT "%s%s%s" #define PRETTY_STRING(str) ((str) ? "'" : "<"), ((str) ? (str) : "NULL"), ((str) ? "'" : ">") #define PRETTY_NSTRING_FORMAT "%s%.*s%s" #define PRETTY_NSTRING(str, len) ((str) ? "'" : "<"), len, ((str) ? (str) : "NULL"), ((str) ? "'" : ">") #define array_count_guint32(array) ((array != NULL) ? ((guint32)(sizeof(array) / sizeof(guint32))) : 0) #define gboolean_to_string(value) (value ? "TRUE" : "FALSE") #define ASSERTION_ERROR(message) "%s:%d/%s\n # %s", \ basename(__FILE__), __LINE__, __FUNCTION__, ((message) ? (message) : "") void reset_grabbed_messages(void); void start_grabbing_messages(void); void stop_grabbing_messages(void); void display_grabbed_messages(void); gboolean assert_grabbed_messages_contain_non_fatal(const gchar *pattern, const gchar *error_message, ...); #define assert_grabbed_messages_contain(pattern, error_message, ...) (assert_grabbed_messages_contain_non_fatal(pattern, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) gchar **fill_string_array(gint number_of_elements, ...); gboolean assert_guint16_non_fatal(guint16 actual, guint16 expected, const gchar *error_message, ...); gboolean assert_gint64_non_fatal(gint64 actual, gint64 expected, const gchar *error_message, ...); gboolean assert_guint64_non_fatal(guint64 actual, guint64 expected, const gchar *error_message, ...); gboolean assert_gdouble_non_fatal(gdouble actual, gdouble expected, const gchar *error_message, ...); gboolean assert_nstring_non_fatal(const gchar *actual, gint actual_len, const gchar *expected, gint expected_len, const gchar *error_message, ...); gboolean assert_guint32_array_non_fatal(guint32 *actual, guint32 actual_length, guint32 *expected, guint32 expected_length, const gchar *error_message, ...); gboolean assert_string_array_non_fatal(gchar **actual, guint32 actual_length, gchar **expected, guint32 expected_length, const gchar *error_message, ...); gboolean assert_gboolean_non_fatal(gboolean actual, gboolean expected, const gchar *error_message, ...); gboolean assert_null_non_fatal(const void *pointer, const gchar *error_message, ...); gboolean assert_not_null_non_fatal(void *pointer, const gchar *error_message, ...); gboolean assert_no_error_non_fatal(GError *error, const gchar *error_message, ...); gboolean assert_guint32_set_non_fatal(guint32 *actual, guint32 actual_length, guint32 *expected, guint32 expected_length, const gchar *error_message, ...); gboolean assert_gpointer_non_fatal(gpointer actual, gpointer expected, const gchar *error_message, ...); gboolean assert_msg_field_equals_non_fatal(LogMessage *msg, gchar *field_name, gchar *expected_value, gssize expected_value_len, const gchar *error_message, ...); gboolean assert_msg_field_unset_non_fatal(LogMessage *msg, gchar *field_name, const gchar *error_message, ...); gboolean expect_not_reached(const gchar *error_message, ...); #define assert_guint16(actual, expected, error_message, ...) (assert_guint16_non_fatal(actual, expected, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_gint64(actual, expected, error_message, ...) (assert_gint64_non_fatal(actual, expected, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_guint64(actual, expected, error_message, ...) (assert_guint64_non_fatal(actual, expected, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_gint(actual, expected, error_message, ...) (assert_gint64((gint64)actual, (gint64)expected, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_guint(actual, expected, error_message, ...) (assert_guint64((guint64)actual, (guint64)expected, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_gint32(actual, expected, error_message, ...) (assert_gint64((gint64)actual, (gint64)expected, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_guint32(actual, expected, error_message, ...) (assert_guint64((guint64)actual, (guint64)expected, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_gdouble(actual, expected, error_message, ...) (assert_gdouble_non_fatal(actual, expected, error_message, ##__VA_ARGS__) ? 1 : (exit (1),0)) #define assert_string(actual, expected, error_message, ...) (assert_nstring_non_fatal(actual, -1, expected, -1, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_nstring(actual, actual_len, expected, expected_len, error_message, ...) (assert_nstring_non_fatal(actual, actual_len, expected, expected_len, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define expect_nstring(actual, actual_len, expected, expected_len, error_message, ...) \ assert_nstring_non_fatal(actual, actual_len, expected, expected_len, error_message, ##__VA_ARGS__) #define assert_guint32_array(actual, actual_length, expected, expected_length, error_message, ...) ( \ assert_guint32_array_non_fatal(actual, actual_length, expected, expected_length, error_message, ##__VA_ARGS__)\ ? 1 : (exit(1),0)) #define assert_string_array(actual, actual_length, expected, expected_length, error_message, ...) ( \ assert_string_array_non_fatal(actual, actual_length, expected, expected_length, error_message, ##__VA_ARGS__)\ ? 1 : (exit(1),0)) #define assert_gboolean(actual, expected, error_message, ...) (assert_gboolean_non_fatal(actual, expected, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_true(value, error_message, ...) (assert_gboolean(value, TRUE, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_false(value, error_message, ...) (assert_gboolean(value, FALSE, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define expect_gboolean(actual, expected, error_message, ...) \ assert_gboolean_non_fatal(actual, expected, error_message, ##__VA_ARGS__) #define expect_true(value, error_message, ...) expect_gboolean(value, TRUE, error_message, ##__VA_ARGS__) #define expect_false(value, error_message, ...) expect_gboolean(value, FALSE, error_message, ##__VA_ARGS__) #define assert_null(pointer, error_message, ...) (assert_null_non_fatal((void *)pointer, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_not_null(pointer, error_message, ...) (assert_not_null_non_fatal((void *)pointer, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_no_error(error, error_message, ...) (assert_no_error_non_fatal(error, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_guint32_set(actual, actual_length, expected, expected_length, error_message, ...) (assert_guint32_set_non_fatal(actual, actual_length, expected, expected_length, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_gpointer(actual, expected, error_message, ...) (assert_gpointer_non_fatal(actual, expected, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_msg_field_equals(msg, field_name, expected_value, expected_value_len, error_message, ...) (assert_msg_field_equals_non_fatal(msg, field_name, expected_value, expected_value_len, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) #define assert_msg_field_unset(msg, field_name, error_message, ...) (assert_msg_field_unset_non_fatal(msg, field_name, error_message, ##__VA_ARGS__) ? 1 : (exit(1),0)) extern GString *current_testcase_description; extern gchar *current_testcase_function; extern gchar *current_testcase_file; gboolean testutils_deinit(void); #define testcase_begin(description_template, ...) \ do { \ if (current_testcase_description != NULL) \ { \ fprintf(stderr, "\nERROR: testcase_begin() called without testcase_end(); file='%s', function='%s'\n", \ current_testcase_file, current_testcase_function); \ exit(1); \ } \ current_testcase_description = g_string_sized_new(0); \ g_string_printf(current_testcase_description, description_template, ##__VA_ARGS__); \ current_testcase_function = (gchar *)(__FUNCTION__); \ current_testcase_file = basename(__FILE__); \ } while (0) #define testcase_end() \ do { \ g_string_free(current_testcase_description, TRUE); \ current_testcase_description = NULL; \ current_testcase_function = NULL; \ current_testcase_file = NULL; \ } while (0) #endif syslog-ng-syslog-ng-3.13.2/m4/000077500000000000000000000000001321171025300157555ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/m4/_ax_valgrind_check.m4000066400000000000000000000142271321171025300220170ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_valgrind_check.html # =========================================================================== # # SYNOPSIS # # AX_VALGRIND_CHECK() # # DESCRIPTION # # Checks whether Valgrind is present and, if so, allows running `make # check` under a variety of Valgrind tools to check for memory and # threading errors. # # Defines VALGRIND_CHECK_RULES which should be substituted in your # Makefile; and $enable_valgrind which can be used in subsequent configure # output. VALGRIND_ENABLED is defined and substituted, and corresponds to # the value of the --enable-valgrind option, which defaults to being # enabled if Valgrind is installed and disabled otherwise. # # If unit tests are written using a shell script and automake's # LOG_COMPILER system, the $(VALGRIND) variable can be used within the # shell scripts to enable Valgrind, as described here: # # https://www.gnu.org/software/gnulib/manual/html_node/Running-self_002dtests-under-valgrind.html # # Usage example: # # configure.ac: # # AX_VALGRIND_CHECK # # Makefile.am: # # @VALGRIND_CHECK_RULES@ # VALGRIND_SUPPRESSIONS_FILES = my-project.supp # EXTRA_DIST = my-project.supp # # This results in a "check-valgrind" rule being added to any Makefile.am # which includes "@VALGRIND_CHECK_RULES@" (assuming the module has been # configured with --enable-valgrind). Running `make check-valgrind` in # that directory will run the module's test suite (`make check`) once for # each of the available Valgrind tools (out of memcheck, helgrind, drd and # sgcheck), and will output results to test-suite-$toolname.log for each. # The target will succeed if there are zero errors and fail otherwise. # # The macro supports running with and without libtool. # # LICENSE # # Copyright (c) 2014, 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 4 AC_DEFUN([AX_VALGRIND_CHECK],[ dnl Check for --enable-valgrind AC_MSG_CHECKING([whether to enable Valgrind on the unit tests]) AC_ARG_ENABLE([valgrind], [AS_HELP_STRING([--enable-valgrind], [Whether to enable Valgrind on the unit tests])], [enable_valgrind=$enableval],[enable_valgrind=]) # Check for Valgrind. AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind]) AS_IF([test "$enable_valgrind" = "yes" -a "$VALGRIND" = ""],[ AC_MSG_ERROR([Could not find valgrind; either install it or reconfigure with --disable-valgrind]) ]) AS_IF([test "$enable_valgrind" != "no"],[enable_valgrind=yes]) AM_CONDITIONAL([VALGRIND_ENABLED],[test "$enable_valgrind" = "yes"]) AC_SUBST([VALGRIND_ENABLED],[$enable_valgrind]) AC_MSG_RESULT([$enable_valgrind]) # Check for Valgrind tools we care about. m4_define([valgrind_tool_list],[[memcheck], [helgrind], [drd], [exp-sgcheck]]) AS_IF([test "$VALGRIND" != ""],[ m4_foreach([vgtool],[valgrind_tool_list],[ m4_define([vgtooln],AS_TR_SH(vgtool)) m4_define([ax_cv_var],[ax_cv_valgrind_tool_]vgtooln) AC_CACHE_CHECK([for Valgrind tool ]vgtool,ax_cv_var,[ ax_cv_var= AS_IF([`$VALGRIND --tool=vgtool --help >/dev/null 2>&1`],[ ax_cv_var="vgtool" ]) ]) AC_SUBST([VALGRIND_HAVE_TOOL_]vgtooln,[$ax_cv_var]) ]) ]) VALGRIND_CHECK_RULES=' # Valgrind check # # Optional: # - VALGRIND_SUPPRESSIONS_FILES: Space-separated list of Valgrind suppressions # files to load. (Default: empty) # - VALGRIND_FLAGS: General flags to pass to all Valgrind tools. # (Default: --num-callers=30) # - VALGRIND_$toolname_FLAGS: Flags to pass to Valgrind $toolname (one of: # memcheck, helgrind, drd, sgcheck). (Default: various) # Optional variables VALGRIND_SUPPRESSIONS ?= $(addprefix --suppressions=,$(VALGRIND_SUPPRESSIONS_FILES)) VALGRIND_FLAGS ?= --num-callers=30 VALGRIND_memcheck_FLAGS ?= --leak-check=full --show-reachable=no VALGRIND_helgrind_FLAGS ?= --history-level=approx VALGRIND_drd_FLAGS ?= VALGRIND_sgcheck_FLAGS ?= # Internal use valgrind_tools = memcheck helgrind drd sgcheck valgrind_log_files = $(addprefix test-suite-,$(addsuffix .log,$(valgrind_tools))) valgrind_memcheck_flags = --tool=memcheck $(VALGRIND_memcheck_FLAGS) valgrind_helgrind_flags = --tool=helgrind $(VALGRIND_helgrind_FLAGS) valgrind_drd_flags = --tool=drd $(VALGRIND_drd_FLAGS) valgrind_sgcheck_flags = --tool=exp-sgcheck $(VALGRIND_sgcheck_FLAGS) valgrind_quiet = $(valgrind_quiet_$(V)) valgrind_quiet_ = $(valgrind_quiet_$(AM_DEFAULT_VERBOSITY)) valgrind_quiet_0 = --quiet # Support running with and without libtool. ifneq ($(LIBTOOL),) valgrind_lt = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=execute else valgrind_lt = endif # Use recursive makes in order to ignore errors during check check-valgrind: ifeq ($(VALGRIND_ENABLED),yes) -$(foreach tool,$(valgrind_tools), \ $(if $(VALGRIND_HAVE_TOOL_$(tool))$(VALGRIND_HAVE_TOOL_exp_$(tool)), \ $(MAKE) $(AM_MAKEFLAGS) -k check-valgrind-tool VALGRIND_TOOL=$(tool); \ ) \ ) else @echo "Need to reconfigure with --enable-valgrind" endif # Valgrind running VALGRIND_TESTS_ENVIRONMENT = \ $(TESTS_ENVIRONMENT) \ env VALGRIND=$(VALGRIND) \ G_SLICE=always-malloc,debug-blocks \ G_DEBUG=fatal-warnings,fatal-criticals,gc-friendly VALGRIND_LOG_COMPILER = \ $(valgrind_lt) \ $(VALGRIND) $(VALGRIND_SUPPRESSIONS) --error-exitcode=1 $(VALGRIND_FLAGS) check-valgrind-tool: ifeq ($(VALGRIND_ENABLED),yes) $(MAKE) check-TESTS \ TESTS_ENVIRONMENT="$(VALGRIND_TESTS_ENVIRONMENT)" \ LOG_COMPILER="$(VALGRIND_LOG_COMPILER)" \ LOG_FLAGS="$(valgrind_$(VALGRIND_TOOL)_flags)" \ TEST_SUITE_LOG=test-suite-$(VALGRIND_TOOL).log else @echo "Need to reconfigure with --enable-valgrind" endif DISTCHECK_CONFIGURE_FLAGS ?= DISTCHECK_CONFIGURE_FLAGS += --disable-valgrind MOSTLYCLEANFILES ?= MOSTLYCLEANFILES += $(valgrind_log_files) .PHONY: check-valgrind check-valgrind-tool ' AC_SUBST([VALGRIND_CHECK_RULES]) m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([VALGRIND_CHECK_RULES])]) ]) syslog-ng-syslog-ng-3.13.2/m4/ax_cflags_gcc_option.m4000066400000000000000000000156221321171025300223600ustar00rootroot00000000000000dnl @synopsis AX_CFLAGS_GCC_OPTION (optionflag [,[shellvar][,[A][,[NA]]]) dnl dnl AX_CFLAGS_GCC_OPTION(-fvomit-frame) would show a message as like dnl "checking CFLAGS for gcc -fvomit-frame ... yes" and adds the dnl optionflag to CFLAGS if it is understood. You can override the dnl shellvar-default of CFLAGS of course. The order of arguments stems dnl from the explicit macros like AX_CFLAGS_WARN_ALL. dnl dnl The cousin AX_CXXFLAGS_GCC_OPTION would check for an option to add dnl to CXXFLAGS - and it uses the autoconf setup for C++ instead of C dnl (since it is possible to use different compilers for C and C++). dnl dnl The macro is a lot simpler than any special AX_CFLAGS_* macro (or dnl ac_cxx_rtti.m4 macro) but allows to check for arbitrary options. dnl However, if you use this macro in a few places, it would be great dnl if you would make up a new function-macro and submit it to the dnl ac-archive. dnl dnl - $1 option-to-check-for : required ("-option" as non-value) dnl - $2 shell-variable-to-add-to : CFLAGS (or CXXFLAGS in the other case) dnl - $3 action-if-found : add value to shellvariable dnl - $4 action-if-not-found : nothing dnl dnl note: in earlier versions, $1-$2 were swapped. We try to detect the dnl situation and accept a $2=~/-/ as being the old dnl option-to-check-for. dnl dnl also: there are other variants that emerged from the original macro dnl variant which did just test an option to be possibly added. dnl However, some compilers accept an option silently, or possibly for dnl just another option that was not intended. Therefore, we have to do dnl a generic test for a compiler family. For gcc we check "-pedantic" dnl being accepted which is also understood by compilers who just want dnl to be compatible with gcc even when not being made from gcc dnl sources. dnl dnl see also: dnl dnl AX_CFLAGS_SUN_OPTION AX_CFLAGS_HPUX_OPTION dnl AX_CFLAGS_AIX_OPTION AX_CFLAGS_IRIX_OPTION dnl dnl @category C dnl @author Guido U. Draheim dnl @version 2006-12-12 dnl @license GPLWithACException AC_DEFUN([AX_CFLAGS_GCC_OPTION_OLD], [dnl AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_gcc_option_$2])dnl AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for gcc m4_ifval($2,$2,-option)], VAR,[VAR="no, unknown" AC_LANG_SAVE AC_LANG_C ac_save_[]FLAGS="$[]FLAGS" for ac_arg dnl in "-pedantic -Werror % m4_ifval($2,$2,-option)" dnl GCC "-pedantic % m4_ifval($2,$2,-option) %% no, obsolete" dnl new GCC # do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` AC_TRY_COMPILE([],[return 0;], [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) done FLAGS="$ac_save_[]FLAGS" AC_LANG_RESTORE ]) case ".$VAR" in .ok|.ok,*) m4_ifvaln($3,$3) ;; .|.no|.no,*) m4_ifvaln($4,$4) ;; *) m4_ifvaln($3,$3,[ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR]) else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"]) m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR" fi ]) ;; esac AS_VAR_POPDEF([VAR])dnl AS_VAR_POPDEF([FLAGS])dnl ]) dnl the only difference - the LANG selection... and the default FLAGS AC_DEFUN([AX_CXXFLAGS_GCC_OPTION_OLD], [dnl AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_gcc_option_$2])dnl AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for gcc m4_ifval($2,$2,-option)], VAR,[VAR="no, unknown" AC_LANG_SAVE AC_LANG_CPLUSPLUS ac_save_[]FLAGS="$[]FLAGS" for ac_arg dnl in "-pedantic -Werror % m4_ifval($2,$2,-option)" dnl GCC "-pedantic % m4_ifval($2,$2,-option) %% no, obsolete" dnl new GCC # do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` AC_TRY_COMPILE([],[return 0;], [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) done FLAGS="$ac_save_[]FLAGS" AC_LANG_RESTORE ]) case ".$VAR" in .ok|.ok,*) m4_ifvaln($3,$3) ;; .|.no|.no,*) m4_ifvaln($4,$4) ;; *) m4_ifvaln($3,$3,[ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR]) else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"]) m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR" fi ]) ;; esac AS_VAR_POPDEF([VAR])dnl AS_VAR_POPDEF([FLAGS])dnl ]) dnl ------------------------------------------------------------------------- AC_DEFUN([AX_CFLAGS_GCC_OPTION_NEW], [dnl AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_gcc_option_$1])dnl AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for gcc m4_ifval($1,$1,-option)], VAR,[VAR="no, unknown" AC_LANG_SAVE AC_LANG_C ac_save_[]FLAGS="$[]FLAGS" for ac_arg dnl in "-pedantic -Werror % m4_ifval($1,$1,-option)" dnl GCC "-pedantic % m4_ifval($1,$1,-option) %% no, obsolete" dnl new GCC # do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` AC_TRY_COMPILE([],[return 0;], [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) done FLAGS="$ac_save_[]FLAGS" AC_LANG_RESTORE ]) case ".$VAR" in .ok|.ok,*) m4_ifvaln($3,$3) ;; .|.no|.no,*) m4_ifvaln($4,$4) ;; *) m4_ifvaln($3,$3,[ if echo " $[]m4_ifval($2,$2,FLAGS) " | grep " $VAR " 2>&1 >/dev/null then AC_RUN_LOG([: m4_ifval($2,$2,FLAGS) does contain $VAR]) else AC_RUN_LOG([: m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"]) m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR" fi ]) ;; esac AS_VAR_POPDEF([VAR])dnl AS_VAR_POPDEF([FLAGS])dnl ]) dnl the only difference - the LANG selection... and the default FLAGS AC_DEFUN([AX_CXXFLAGS_GCC_OPTION_NEW], [dnl AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_gcc_option_$1])dnl AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for gcc m4_ifval($1,$1,-option)], VAR,[VAR="no, unknown" AC_LANG_SAVE AC_LANG_CPLUSPLUS ac_save_[]FLAGS="$[]FLAGS" for ac_arg dnl in "-pedantic -Werror % m4_ifval($1,$1,-option)" dnl GCC "-pedantic % m4_ifval($1,$1,-option) %% no, obsolete" dnl new GCC # do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` AC_TRY_COMPILE([],[return 0;], [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) done FLAGS="$ac_save_[]FLAGS" AC_LANG_RESTORE ]) case ".$VAR" in .ok|.ok,*) m4_ifvaln($3,$3) ;; .|.no|.no,*) m4_ifvaln($4,$4) ;; *) m4_ifvaln($3,$3,[ if echo " $[]m4_ifval($2,$2,FLAGS) " | grep " $VAR " 2>&1 >/dev/null then AC_RUN_LOG([: m4_ifval($2,$2,FLAGS) does contain $VAR]) else AC_RUN_LOG([: m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"]) m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR" fi ]) ;; esac AS_VAR_POPDEF([VAR])dnl AS_VAR_POPDEF([FLAGS])dnl ]) AC_DEFUN([AX_CFLAGS_GCC_OPTION],[ifelse(m4_bregexp([$2],[-]),-1, [AX_CFLAGS_GCC_OPTION_NEW($@)],[AX_CFLAGS_GCC_OPTION_OLD($@)])]) AC_DEFUN([AX_CXXFLAGS_GCC_OPTION],[ifelse(m4_bregexp([$2],[-]),-1, [AX_CXXFLAGS_GCC_OPTION_NEW($@)],[AX_CXXFLAGS_GCC_OPTION_OLD($@)])]) syslog-ng-syslog-ng-3.13.2/m4/check_java_support.m4000066400000000000000000000073511321171025300220770ustar00rootroot00000000000000AU_ALIAS([AC_CHECK_JAVA_VERSION], [AX_CHECK_JAVA_VERSION]) AU_ALIAS([AC_CHECK_GRADLE_VERSION], [AX_CHECK_GRADLE_VERSION]) AC_DEFUN([AX_READLINK], [ READLINK_TARGET=[$1] cd $(dirname "$READLINK_TARGET") while test -L "$READLINK_TARGET"; do READLINK_TARGET=$(readlink "$READLINK_TARGET") cd $(dirname "$READLINK_TARGET") done echo $(pwd -P)/$(basename "$READLINK_TARGET") ]) AC_DEFUN([AX_CHECK_GRADLE_VERSION], [AC_MSG_CHECKING([for GRADLE_VERSION]) EXPECTED_GRADLE_VERSION=[$1] GRADLE_BIN=`which gradle` if test "x$GRADLE_BIN" != "x"; then GRADLE_BIN=`AX_READLINK([$GRADLE_BIN])` GRADLE_VERSION=`gradle -version 2>&1 | grep Gradle | head -1 |sed "s/.*\ \(.*\)/\1/"` SHORT_VERSION=${GRADLE_VERSION%.*} MAJOR_VERSION=${SHORT_VERSION%.*} MINOR_VERSION=${SHORT_VERSION##*.} EXPECTED_MAJOR_VERSION=${EXPECTED_GRADLE_VERSION%.*} EXPECTED_MINOR_VERSION=${EXPECTED_GRADLE_VERSION##*.} if test "$MAJOR_VERSION" -lt "$EXPECTED_MAJOR_VERSION"; then AC_MSG_ERROR([Too old gradle version required: $EXPECTED_GRADLE_VERSION found: $GRADLE_VERSION]) elif test "$MAJOR_VERSION" -eq "$EXPECTED_MAJOR_VERSION"; then if test "$MINOR_VERSION" -lt "$EXPECTED_MINOR_VERSION"; then AC_MSG_ERROR([Too old gradle version required: $EXPECTED_GRADLE_VERSION= found: $GRADLE_VERSION]) fi fi AC_SUBST(GRADLE, "$GRADLE_BIN") $2 AC_MSG_RESULT([$SHORT_VERSION]) else $3 AC_MSG_RESULT([no]) fi ]) AC_DEFUN([AX_CHECK_JAVA_VERSION], [AC_MSG_CHECKING([for JAVA_VERSION]) case $host_os in freebsd*) DONT_RESOLVE_JAVA_BIN_LINKS="YES" ;; *) ;; esac JAVA_VERSION=[$1] JAVAC_BIN=`which javac` JAVAH_BIN=`which javah` JAR_BIN=`which jar` JAVA_HOME_CHECKER="/usr/libexec/java_home" if test "x$JAVAC_BIN" != "x"; then if test "x$DONT_RESOLVE_JAVA_BIN_LINKS" == "x"; then JAVAC_BIN=`AX_READLINK([$JAVAC_BIN])` JAVAH_BIN=`AX_READLINK([$JAVAH_BIN])` JAR_BIN=`AX_READLINK([$JAR_BIN])` fi JAVAC_VERSION=`$JAVAC_BIN -version 2>&1 | sed "s/.*\ \(.*\)/\1/"` SHORT_VERSION=${JAVAC_VERSION%.*} MAJOR_VERSION=${SHORT_VERSION%.*} MINOR_VERSION=${SHORT_VERSION##*.} VERSION_OK="1" EXPECTED_MAJOR_VERSION=${JAVA_VERSION%.*} EXPECTED_MINOR_VERSION=${JAVA_VERSION##*.} if test "$MAJOR_VERSION" -lt "$EXPECTED_MAJOR_VERSION"; then AC_MSG_NOTICE([Too old java version required: $JAVA_VERSION found: $SHORT_VERSION]) VERSION_OK="0" elif test "$MAJOR_VERSION" -eq "$EXPECTED_MAJOR_VERSION"; then if test "$MINOR_VERSION" -lt "$EXPECTED_MINOR_VERSION"; then AC_MSG_NOTICE([Too old java version required: $JAVA_VERSION found: $SHORT_VERSION]) VERSION_OK="0" fi fi if test "$VERSION_OK" = "1"; then if test -e "$JAVA_HOME_CHECKER"; then JNI_HOME=`$JAVA_HOME_CHECKER` else JNI_HOME=`echo $JAVAC_BIN | sed "s/\(.*\)[[/]]bin[[/]]java.*/\1\//"` fi JNI_LIBDIR=`find $JNI_HOME \( -name "libjvm.so" -or -name "libjvm.dylib" \) \ | sed "s-/libjvm\.so-/-" \ | sed "s-/libjvm\.dylib-/-" | head -n 1` JNI_LIBS="-L$JNI_LIBDIR -ljvm" JNI_INCLUDE_DIR=`find $JNI_HOME -name "jni.h" | sed "s/\(.*\)jni.h/\1/" | head -n 1` JNI_CFLAGS="-I$JNI_INCLUDE_DIR" JNI_MD_INCLUDE_DIR=`find $JNI_HOME -name "jni_md.h" | sed "s/\(.*\)jni_md.h/\1/" | head -n 1` JNI_CFLAGS="$JNI_CFLAGS -I$JNI_MD_INCLUDE_DIR" AC_SUBST(JNI_CFLAGS, "$JNI_CFLAGS") AC_SUBST(JNI_LIBS, "$JNI_LIBS") AC_SUBST(JAVAC, "$JAVAC_BIN") AC_SUBST(JAVAH, "$JAVAH_BIN") AC_SUBST(JAR, "$JAR_BIN") $2 AC_MSG_RESULT([$SHORT_VERSION]) else $3 AC_MSG_RESULT([no]) fi else $3 AC_MSG_RESULT([no]) fi ]) syslog-ng-syslog-ng-3.13.2/modules/000077500000000000000000000000001321171025300171055ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/CMakeLists.txt000066400000000000000000000017151321171025300216510ustar00rootroot00000000000000add_subdirectory(afuser) add_subdirectory(redis) add_subdirectory(affile) add_subdirectory(afprog) add_subdirectory(afsmtp) add_subdirectory(afsocket) add_subdirectory(native) add_subdirectory(csvparser) add_subdirectory(date) add_subdirectory(dbparser) add_subdirectory(kvformat) add_subdirectory(linux-kmsg-format) add_subdirectory(pacctformat) add_subdirectory(pseudofile) add_subdirectory(syslogformat) add_subdirectory(geoip) add_subdirectory(systemd-journal) add_subdirectory(cef) add_subdirectory(json) add_subdirectory(afsql) add_subdirectory(afstomp) add_subdirectory(afstreams) add_subdirectory(basicfuncs) add_subdirectory(confgen) add_subdirectory(cryptofuncs) add_subdirectory(graphite) add_subdirectory(system-source) add_subdirectory(riemann) add_subdirectory(add-contextual-data) add_subdirectory(diskq) add_subdirectory(python) add_subdirectory(java) add_subdirectory(java-modules) add_subdirectory(http) add_subdirectory(tagsparser) add_subdirectory(xml) syslog-ng-syslog-ng-3.13.2/modules/Makefile.am000066400000000000000000000057131321171025300211470ustar00rootroot00000000000000include modules/syslogformat/Makefile.am include modules/afsocket/Makefile.am include modules/afsql/Makefile.am include modules/afstreams/Makefile.am include modules/affile/Makefile.am include modules/afprog/Makefile.am include modules/afuser/Makefile.am include modules/afamqp/Makefile.am include modules/afmongodb/Makefile.am include modules/afsmtp/Makefile.am include modules/http/Makefile.am include modules/csvparser/Makefile.am include modules/confgen/Makefile.am include modules/system-source/Makefile.am include modules/linux-kmsg-format/Makefile.am include modules/pacctformat/Makefile.am include modules/basicfuncs/Makefile.am include modules/cryptofuncs/Makefile.am include modules/dbparser/Makefile.am include modules/json/Makefile.am include modules/geoip/Makefile.am include modules/geoip2/Makefile.am include modules/afstomp/Makefile.am include modules/redis/Makefile.am include modules/pseudofile/Makefile.am include modules/graphite/Makefile.am include modules/riemann/Makefile.am include modules/systemd-journal/Makefile.am include modules/python/Makefile.am include modules/java/Makefile.am include modules/java-modules/Makefile.am include modules/kvformat/Makefile.am include modules/date/Makefile.am include modules/native/Makefile.am include modules/cef/Makefile.am include modules/diskq/Makefile.am include modules/add-contextual-data/Makefile.am include modules/getent/Makefile.am include modules/map-value-pairs/Makefile.am include modules/stardate/Makefile.am include modules/snmptrapd-parser/Makefile.am include modules/tagsparser/Makefile.am include modules/xml/Makefile.am include modules/appmodel/Makefile.am SYSLOG_NG_CORE_JAR=$(top_builddir)/modules/java/syslog-ng-core/libs/syslog-ng-core.jar SYSLOG_NG_MODULES = \ mod-afsocket mod-afstreams mod-affile mod-afprog \ mod-usertty mod-amqp mod-mongodb mod-smtp mod-http mod-json \ mod-syslogformat mod-linux-kmsg mod-pacctformat \ mod-confgen mod-system-source mod-csvparser mod-dbparser \ mod-basicfuncs mod-cryptofuncs mod-geoip mod-afstomp \ mod-redis mod-pseudofile mod-graphite mod-riemann \ mod-python mod-java mod-java-modules mod-kvformat mod-date \ mod-native mod-cef mod-add-contextual-data mod-diskq mod-getent \ mod-map-value-pairs mod-snmptrapd-parser mod-tags-parser mod-xml \ mod-appmodel modules modules/: ${SYSLOG_NG_MODULES} modules_test_subdirs = \ modules_afsocket modules_afstreams modules_affile \ modules_afprog modules_usertty modules_afamqp \ modules_afmongodb modules_afsmtp modules_http modules_json \ modules_syslogformat modules_linux_kmsg \ modules_pacctformat modules_confgen modules_system_source \ modules_csvparser modules_dbparser modules_basicfuncs \ modules_cryptofuncs modules_geoip modules_afstomp \ modules_graphite modules_riemann modules_python \ modules_systemd_journal modules_kvformat modules_date \ modules_cef modules_diskq modules-add-contextual-data modules_getent \ modules_map-value-pairs modules_tagsparser modules_xml modules_appmodel .PHONY: modules modules/ syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/000077500000000000000000000000001321171025300227305ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/CMakeLists.txt000066400000000000000000000023341321171025300254720ustar00rootroot00000000000000set(add_contextual_data_SOURCES add-contextual-data.c add-contextual-data.h add-contextual-data-parser.c add-contextual-data-parser.h add-contextual-data-plugin.c context-info-db.h context-info-db.c contextual-data-record-scanner.h contextual-data-record-scanner.c csv-contextual-data-record-scanner.h csv-contextual-data-record-scanner.c add-contextual-data-selector.h add-contextual-data-template-selector.h add-contextual-data-template-selector.c ${CMAKE_CURRENT_BINARY_DIR}/add-contextual-data-grammar.h ${CMAKE_CURRENT_BINARY_DIR}/add-contextual-data-grammar.c ) generate_y_from_ym(modules/add-contextual-data/add-contextual-data-grammar) bison_target(add_contextual_dataGrammar ${CMAKE_CURRENT_BINARY_DIR}/add-contextual-data-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/add-contextual-data-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) include_directories (${CMAKE_CURRENT_BINARY_DIR}) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) add_library(add_contextual_data MODULE ${add_contextual_data_SOURCES}) target_link_libraries(add_contextual_data PRIVATE syslog-ng) install(TARGETS add_contextual_data LIBRARY DESTINATION lib/syslog-ng/ COMPONENT add_contextual_data) syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/Makefile.am000066400000000000000000000052071321171025300247700ustar00rootroot00000000000000module_LTLIBRARIES += \ modules/add-contextual-data/libadd-contextual-data.la modules_add_contextual_data_libadd_contextual_data_la_SOURCES = \ modules/add-contextual-data/add-contextual-data.c \ modules/add-contextual-data/add-contextual-data.h \ modules/add-contextual-data/csv-contextual-data-record-scanner.c \ modules/add-contextual-data/csv-contextual-data-record-scanner.h \ modules/add-contextual-data/contextual-data-record-scanner.h \ modules/add-contextual-data/contextual-data-record-scanner.c \ modules/add-contextual-data/add-contextual-data-grammar.y \ modules/add-contextual-data/add-contextual-data-parser.c \ modules/add-contextual-data/add-contextual-data-parser.h \ modules/add-contextual-data/context-info-db.h \ modules/add-contextual-data/context-info-db.c \ modules/add-contextual-data/add-contextual-data-plugin.c \ modules/add-contextual-data/add-contextual-data-selector.h \ modules/add-contextual-data/add-contextual-data-template-selector.h \ modules/add-contextual-data/add-contextual-data-template-selector.c add_contextual_data_includedir = ${pkgincludedir}/modules/add-contextual-data pkgconfig_DATA += syslog-ng-add-contextual-data.pc add_contextual_data_include_HEADERS = \ modules/add-contextual-data/add-contextual-data.h \ modules/add-contextual-data/csv-contextual-data-record-scanner.h \ modules/add-contextual-data/contextual-data-record-scanner.h \ modules/add-contextual-data/add-contextual-data-parser.h \ modules/add-contextual-data/context-info-db.h \ modules/add-contextual-data/add-contextual-data-selector.h \ modules/add-contextual-data/add-contextual-data-template-selector.h modules_add_contextual_data_libadd_contextual_data_la_CFLAGS = \ $(AM_CFLAGS) \ -I$(top_srcdir)/modules/add-contextual-data \ -I$(top_builddir)/modules/add-contextual-data modules_add_contextual_data_libadd_contextual_data_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_add_contextual_data_libadd_contextual_data_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_add_contextual_data_libadd_contextual_data_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) BUILT_SOURCES += \ modules/add-contextual-data/add-contextual-data-grammar.y \ modules/add-contextual-data/add-contextual-data-grammar.c \ modules/add-contextual-data/add-contextual-data-grammar.h EXTRA_DIST += \ modules/add-contextual-data/add-contextual-data-grammar.ym modules/add-contextual-data modules/add-contextual-data/ mod-add-contextual-data: \ modules/add-contextual-data/libadd_contextual_data.la .PHONY: modules/add-contextual-data/ mod-add-contextual-data include modules/add-contextual-data/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/add-contextual-data-grammar.ym000066400000000000000000000070521321171025300305520ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code top { #include "add-contextual-data-parser.h" } %code { #include "add-contextual-data.h" #include "cfg-parser.h" #include "cfg-grammar.h" #include "add-contextual-data-selector.h" #include "syslog-names.h" #include "messages.h" #include "plugin.h" } %name-prefix "add_contextual_data_" /* this parameter is needed in order to instruct bison to use a complete * argument list for yylex/yyerror */ %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogParser **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_ADD_CONTEXTUAL_DATA %token KW_ADD_CONTEXTUAL_DATA_DATABASE %token KW_ADD_CONTEXTUAL_DATA_SELECTOR %token KW_ADD_CONTEXTUAL_DATA_DEFAULT_SELECTOR %token KW_ADD_CONTEXTUAL_DATA_PREFIX %type parser_expr_add_contextual_data %% start : LL_CONTEXT_PARSER parser_expr_add_contextual_data { YYACCEPT; } ; parser_expr_add_contextual_data : KW_ADD_CONTEXTUAL_DATA '(' { last_parser = *instance = add_contextual_data_parser_new(configuration); } parser_add_contextual_data_opts ')' { $$ = last_parser; } ; parser_add_contextual_data_opts : parser_add_contextual_data_opt parser_add_contextual_data_opts | ; parser_add_contextual_data_opt : KW_ADD_CONTEXTUAL_DATA_DATABASE '(' string ')' { add_contextual_data_set_filename(last_parser, $3); free($3); } | KW_ADD_CONTEXTUAL_DATA_SELECTOR '(' parser_add_contextual_data_selector ')' | KW_ADD_CONTEXTUAL_DATA_DEFAULT_SELECTOR '(' string ')' { add_contextual_data_set_database_default_selector(last_parser, $3); free($3); } | KW_ADD_CONTEXTUAL_DATA_PREFIX '(' string ')' { add_contextual_data_set_prefix(last_parser, $3); free($3); }; parser_add_contextual_data_selector : LL_IDENTIFIER { Plugin *p; gint context = LL_CONTEXT_SELECTOR; gpointer value; p = cfg_find_plugin(configuration, context, $1); CHECK_ERROR(p, @1, "%s plugin %s not found", cfg_lexer_lookup_context_name_by_type(context), $1); value = cfg_parse_plugin(configuration, p, &@1, NULL); free($1); if (!value) { YYERROR; } add_contextual_data_set_selector(last_parser, (AddContextualDataSelector *) value); } | LL_STRING { add_contextual_data_set_database_selector_template(last_parser, $1); free($1); }; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/add-contextual-data-parser.c000066400000000000000000000037131321171025300302150ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "add-contextual-data.h" #include "cfg-parser.h" #include "add-contextual-data-grammar.h" #include "logpipe.h" #include "parser/parser-expr.h" #include "syslog-ng-config.h" #include extern int add_contextual_data_debug; int add_contextual_data_parse(CfgLexer *lexer, LogParser **instance, gpointer arg); static CfgLexerKeyword add_contextual_data_keywords[] = { {"add_contextual_data", KW_ADD_CONTEXTUAL_DATA}, {"database", KW_ADD_CONTEXTUAL_DATA_DATABASE}, {"selector", KW_ADD_CONTEXTUAL_DATA_SELECTOR}, {"default_selector", KW_ADD_CONTEXTUAL_DATA_DEFAULT_SELECTOR}, {"prefix", KW_ADD_CONTEXTUAL_DATA_PREFIX}, {NULL} }; CfgParser add_contextual_data_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &add_contextual_data_debug, #endif .name = "add-contextual-data", .keywords = add_contextual_data_keywords, .parse = (gint(*)(CfgLexer *, gpointer *, gpointer)) add_contextual_data_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(add_contextual_data_, LogParser **) syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/add-contextual-data-parser.h000066400000000000000000000022321321171025300302150ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef ADD_CONTEXTUAL_DATA_PARSER_H_INCLUDED #define ADD_CONTEXTUAL_DATA_PARSER_H_INCLUDED #include "cfg-parser.h" #include "parser/parser-expr.h" extern CfgParser add_contextual_data_parser; CFG_PARSER_DECLARE_LEXER_BINDING(add_contextual_data_, LogParser **) #endif syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/add-contextual-data-plugin.c000066400000000000000000000034561321171025300302230ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "add-contextual-data.h" #include "plugin.h" #include "plugin-types.h" extern CfgParser add_contextual_data_parser; static Plugin add_contextual_data_plugins[] = { { .type = LL_CONTEXT_PARSER, .name = "add_contextual_data", .parser = &add_contextual_data_parser, }, }; gboolean add_contextual_data_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, add_contextual_data_plugins, G_N_ELEMENTS(add_contextual_data_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "add_contextual_data", .version = SYSLOG_NG_VERSION, .description = "The add_contextual_data module provides parsing support for CSV and other separated value formats for syslog-ng.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = add_contextual_data_plugins, .plugins_len = G_N_ELEMENTS(add_contextual_data_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/add-contextual-data-selector.h000066400000000000000000000046261321171025300305520ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef ADD_CONTEXTUAL_DATA_SELECTOR_H_INCLUDED #define ADD_CONTEXTUAL_DATA_SELECTOR_H_INCLUDED #include "logmsg/logmsg.h" #include "context-info-db.h" typedef struct _AddContextualDataSelector AddContextualDataSelector; struct _AddContextualDataSelector{ gboolean ordering_required; gchar *(*resolve)(AddContextualDataSelector *self, LogMessage *msg); void (*free)(AddContextualDataSelector *self); AddContextualDataSelector*(*clone)(AddContextualDataSelector *self, GlobalConfig *cfg); gboolean (*init)(AddContextualDataSelector *self, GList *ordered_selectors); }; static inline gchar* add_contextual_data_selector_resolve(AddContextualDataSelector *self, LogMessage *msg) { if (self && self->resolve) { return self->resolve(self, msg); } return NULL; } static inline void add_contextual_data_selector_free(AddContextualDataSelector *self) { if (self && self->free) { self->free(self); } } static inline gboolean add_contextual_data_selector_init(AddContextualDataSelector *self, GList *ordered_selectors) { if (self && self->init) { return self->init(self, ordered_selectors); } return FALSE; } static inline AddContextualDataSelector * add_contextual_data_selector_clone(AddContextualDataSelector *self, GlobalConfig *cfg) { if (self && self->clone) { return self->clone(self, cfg); } return NULL; } static inline gboolean add_contextual_data_selector_is_ordering_required(AddContextualDataSelector *self) { return self->ordering_required; } #endif syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/add-contextual-data-template-selector.c000066400000000000000000000073241321171025300323540ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "add-contextual-data-template-selector.h" #include "template/templates.h" #include "syslog-ng.h" #include "messages.h" typedef struct _AddContextualDataTemplateSelector { AddContextualDataSelector super; gchar *selector_template_string; LogTemplate *selector_template; } AddContextualDataTemplateSelector; static gboolean _compile_selector_template(AddContextualDataTemplateSelector *self) { GError *error = NULL; if (!self->selector_template_string) { msg_error("No selector set."); return FALSE; } if (!log_template_compile(self->selector_template, self->selector_template_string, &error)) { msg_error("Failed to compile template", evt_tag_str("template", self->selector_template_string), evt_tag_str("error", error->message)); return FALSE; } return TRUE; } static void _replace_template(LogTemplate **old_template, LogTemplate *new_template) { log_template_unref(*old_template); *old_template = log_template_ref(new_template); } static gboolean _init(AddContextualDataSelector *s, GList *ordered_selectors) { AddContextualDataTemplateSelector *self = (AddContextualDataTemplateSelector *)s; return _compile_selector_template(self); } static gchar * _resolve(AddContextualDataSelector *s, LogMessage *msg) { GString *selector_str = g_string_new(NULL); AddContextualDataTemplateSelector *self = (AddContextualDataTemplateSelector *)s; log_template_format(self->selector_template, msg, NULL, LTZ_LOCAL, 0, NULL, selector_str); return g_string_free(selector_str, FALSE); } static void _free(AddContextualDataSelector *s) { AddContextualDataTemplateSelector *self = (AddContextualDataTemplateSelector *)s; log_template_unref(self->selector_template); g_free(self->selector_template_string); } static AddContextualDataSelector * _clone(AddContextualDataSelector *s, GlobalConfig *cfg) { AddContextualDataTemplateSelector *self = (AddContextualDataTemplateSelector *)s; AddContextualDataTemplateSelector *cloned = (AddContextualDataTemplateSelector *) add_contextual_data_template_selector_new(cfg, self->selector_template_string); _replace_template(&cloned->selector_template, self->selector_template); return &cloned->super; } AddContextualDataSelector * add_contextual_data_template_selector_new(GlobalConfig *cfg, const gchar *selector_template_string) { AddContextualDataTemplateSelector *new_instance = g_new0(AddContextualDataTemplateSelector, 1); new_instance->selector_template_string = g_strdup(selector_template_string); new_instance->selector_template = log_template_new(cfg, NULL); new_instance->super.resolve = _resolve; new_instance->super.free = _free; new_instance->super.init = _init; new_instance->super.clone = _clone; return &new_instance->super; } syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/add-contextual-data-template-selector.h000066400000000000000000000022601321171025300323530ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef ADD_CONTEXTUAL_DATA_TEMPLATE_SELECTOR_H_INCLUDED #define ADD_CONTEXTUAL_DATA_TEMPLATE_SELECTOR_H_INCLUDED #include "add-contextual-data-selector.h" AddContextualDataSelector* add_contextual_data_template_selector_new(GlobalConfig *cfg, const gchar *selector_template_string); #endif syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/add-contextual-data.c000066400000000000000000000201421321171025300267160ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "add-contextual-data.h" #include "logmsg/logmsg.h" #include "logpipe.h" #include "parser/parser-expr.h" #include "reloc.h" #include "cfg.h" #include "contextual-data-record-scanner.h" #include "add-contextual-data-selector.h" #include "add-contextual-data-template-selector.h" #include "template/templates.h" #include "context-info-db.h" #include "pathutils.h" #include #include typedef struct AddContextualData { LogParser super; ContextInfoDB *context_info_db; AddContextualDataSelector *selector; gchar *default_selector; gchar *filename; gchar *prefix; } AddContextualData; void add_contextual_data_set_filename(LogParser *p, const gchar *filename) { AddContextualData *self = (AddContextualData *) p; g_free(self->filename); self->filename = g_strdup(filename); } void add_contextual_data_set_database_selector_template(LogParser *p, const gchar *selector) { AddContextualData *self = (AddContextualData *) p; add_contextual_data_selector_free(self->selector); self->selector = add_contextual_data_template_selector_new(log_pipe_get_config(&p->super), selector); } void add_contextual_data_set_prefix(LogParser *p, const gchar *prefix) { AddContextualData *self = (AddContextualData *) p; g_free(self->prefix); self->prefix = g_strdup(prefix); } void add_contextual_data_set_database_default_selector(LogParser *p, const gchar *default_selector) { AddContextualData *self = (AddContextualData *) p; g_free(self->default_selector); self->default_selector = g_strdup(default_selector); } void add_contextual_data_set_selector(LogParser *p, AddContextualDataSelector *selector) { AddContextualData *self = (AddContextualData *) p; self->selector = selector; } static gboolean _is_default_selector_set(const AddContextualData *self) { return (self->default_selector != NULL); } static void _add_context_data_to_message(gpointer pmsg, const ContextualDataRecord *record) { LogMessage *msg = (LogMessage *) pmsg; log_msg_set_value_by_name(msg, record->name->str, record->value->str, record->value->len); } static gboolean _process(LogParser *s, LogMessage **pmsg, const LogPathOptions *path_options, const gchar *input, gsize input_len) { AddContextualData *self = (AddContextualData *) s; LogMessage *msg = log_msg_make_writable(pmsg, path_options); gchar *resolved_selector = add_contextual_data_selector_resolve(self->selector, msg); const gchar *selector = resolved_selector; if (!context_info_db_contains(self->context_info_db, selector) && _is_default_selector_set(self)) selector = self->default_selector; if (selector) context_info_db_foreach_record(self->context_info_db, selector, _add_context_data_to_message, (gpointer) msg); g_free(resolved_selector); return TRUE; } static void _replace_context_info_db(ContextInfoDB **old_db, ContextInfoDB *new_db) { context_info_db_unref(*old_db); *old_db = context_info_db_ref(new_db); } static LogPipe * _clone(LogPipe *s) { AddContextualData *self = (AddContextualData *) s; AddContextualData *cloned = (AddContextualData *) add_contextual_data_parser_new(s->cfg); log_parser_set_template(&cloned->super, log_template_ref(self->super.template)); _replace_context_info_db(&cloned->context_info_db, self->context_info_db); add_contextual_data_set_prefix(&cloned->super, self->prefix); add_contextual_data_set_filename(&cloned->super, self->filename); add_contextual_data_set_database_default_selector(&cloned->super, self->default_selector); cloned->selector = add_contextual_data_selector_clone(self->selector, s->cfg); return &cloned->super.super; } static void _free(LogPipe *s) { AddContextualData *self = (AddContextualData *) s; context_info_db_unref(self->context_info_db); g_free(self->filename); g_free(self->prefix); g_free(self->default_selector); add_contextual_data_selector_free(self->selector); log_parser_free_method(s); } static gboolean _is_relative_path(const gchar *filename) { return (filename[0] != '/'); } static gchar * _complete_relative_path_with_config_path(const gchar *filename) { return g_build_filename(get_installation_path_for(SYSLOG_NG_PATH_SYSCONFDIR), filename, NULL); } static FILE * _open_data_file(const gchar *filename) { FILE *f = NULL; if (_is_relative_path(filename)) { gchar *absolute_path = _complete_relative_path_with_config_path(filename); f = fopen(absolute_path, "r"); g_free(absolute_path); } else { f = fopen(filename, "r"); } return f; } static ContextualDataRecordScanner * _get_scanner(AddContextualData *self) { const gchar *type = get_filename_extension(self->filename); ContextualDataRecordScanner *scanner = create_contextual_data_record_scanner_by_type(type); if (!scanner) { msg_error("Unknown file extension", evt_tag_str("filename", self->filename)); return NULL; } contextual_data_record_scanner_set_name_prefix(scanner, self->prefix); return scanner; } static gboolean _load_context_info_db(AddContextualData *self) { ContextualDataRecordScanner *scanner = _get_scanner(self); if (!scanner) return FALSE; FILE *f = _open_data_file(self->filename); if (!f) { msg_error("Error loading add_contextual_data database", evt_tag_str("filename", self->filename)); contextual_data_record_scanner_free(scanner); return FALSE; } gboolean tag_db_loaded = context_info_db_import(self->context_info_db, f, scanner); contextual_data_record_scanner_free(scanner); fclose(f); if (!tag_db_loaded) { msg_error("Error while parsing add_contextual_data database"); return FALSE; } return TRUE; } static gboolean _init_context_info_db(AddContextualData *self) { if (self->selector && add_contextual_data_selector_is_ordering_required(self->selector)) context_info_db_enable_ordering(self->context_info_db); if (self->filename == NULL) { msg_error("No database file set."); return FALSE; } if (!context_info_db_is_loaded(self->context_info_db) && !_load_context_info_db(self)) { msg_error("Failed to load the database file."); return FALSE; } return TRUE; } static gboolean _init_selector(AddContextualData *self) { return add_contextual_data_selector_init(self->selector, context_info_db_ordered_selectors(self->context_info_db)); } static gboolean _init(LogPipe *s) { AddContextualData *self = (AddContextualData *)s; if (!_init_context_info_db(self)) return FALSE; if (!_init_selector(self)) return FALSE; if (!log_parser_init_method(s)) return FALSE; return TRUE; } LogParser * add_contextual_data_parser_new(GlobalConfig *cfg) { AddContextualData *self = g_new0(AddContextualData, 1); log_parser_init_instance(&self->super, cfg); self->super.process = _process; self->selector = NULL; self->context_info_db = context_info_db_new(); self->super.super.clone = _clone; self->super.super.free_fn = _free; self->super.super.init = _init; self->default_selector = NULL; self->prefix = NULL; return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/add-contextual-data.h000066400000000000000000000041531321171025300267270ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef ADD_CONTEXTUAL_DATA_H_INCLUDED #define ADD_CONTEXTUAL_DATA_H_INCLUDED #include "parser/parser-expr.h" #include "syslog-ng.h" #include "template/common-template-typedefs.h" #include "add-contextual-data-selector.h" LogParser *add_contextual_data_parser_new(GlobalConfig *cfg); LogTemplateOptions *add_contextual_data_get_template_options(LogParser *d); void add_contextual_data_set_database_key_template(LogParser *p, const gchar *key); void add_contextual_data_set_filename(LogParser *p, const gchar *filename); void add_contextual_data_set_database_selector_template(LogParser *p, const gchar * selector); void add_contextual_data_set_database_default_selector(LogParser *p, const gchar * default_selector); void add_contextual_data_set_prefix(LogParser *p, const gchar *perfix); void add_contextual_data_set_filters_path(LogParser *p, const gchar *filename); void add_contextual_data_set_selector(LogParser *p, AddContextualDataSelector *selector); #endif syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/context-info-db.c000066400000000000000000000177751321171025300261150ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "context-info-db.h" #include "atomic.h" #include "messages.h" #include #include #include struct _ContextInfoDB { GAtomicCounter ref_cnt; GArray *data; GHashTable *index; gboolean is_data_indexed; gboolean is_ordering_enabled; GList *ordered_selectors; }; typedef struct _element_range { gsize offset; gsize length; } element_range; static gint _contextual_data_record_cmp(gconstpointer k1, gconstpointer k2) { ContextualDataRecord *r1 = (ContextualDataRecord *) k1; ContextualDataRecord *r2 = (ContextualDataRecord *) k2; return strcmp(r1->selector->str, r2->selector->str); } void context_info_db_enable_ordering(ContextInfoDB *self) { self->is_ordering_enabled = TRUE; } GList * context_info_db_ordered_selectors(ContextInfoDB *self) { return self->ordered_selectors; } void context_info_db_index(ContextInfoDB *self) { if (self->data->len > 0) { g_array_sort(self->data, _contextual_data_record_cmp); gsize range_start = 0; ContextualDataRecord range_start_record = g_array_index(self->data, ContextualDataRecord, 0); for (gsize i = 1; i < self->data->len; ++i) { ContextualDataRecord current_record = g_array_index(self->data, ContextualDataRecord, i); if (_contextual_data_record_cmp (&range_start_record, ¤t_record)) { element_range *current_range = g_new(element_range, 1); current_range->offset = range_start; current_range->length = i - range_start; g_hash_table_insert(self->index, range_start_record.selector->str, current_range); range_start_record = current_record; range_start = i; } } { element_range *last_range = g_new(element_range, 1); last_range->offset = range_start; last_range->length = self->data->len - range_start; g_hash_table_insert(self->index, range_start_record.selector->str, last_range); } self->is_data_indexed = TRUE; } } static void _ensure_indexed_db(ContextInfoDB *self) { if (!self->is_data_indexed) context_info_db_index(self); } static void _record_free(gpointer p) { ContextualDataRecord *rec = (ContextualDataRecord *) p; contextual_data_record_clean(rec); } static void _new(ContextInfoDB *self) { self->data = g_array_new(FALSE, FALSE, sizeof(ContextualDataRecord)); self->index = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); self->is_data_indexed = FALSE; self->ordered_selectors = NULL; g_atomic_counter_set(&self->ref_cnt, 1); } static void _free_array(GArray *array) { for (gsize i = 0; i < array->len; ++i) { ContextualDataRecord current_record = g_array_index(array, ContextualDataRecord, i); _record_free(¤t_record); } g_array_free(array, TRUE); } static void _free(ContextInfoDB *self) { if (self->index) { g_hash_table_unref(self->index); } if (self->data) { _free_array(self->data); } if (self->ordered_selectors) { g_list_free(self->ordered_selectors); } } ContextInfoDB * context_info_db_new(void) { ContextInfoDB *self = g_new0(ContextInfoDB, 1); _new(self); return self; } ContextInfoDB * context_info_db_ref(ContextInfoDB *self) { g_assert(!self || g_atomic_counter_get(&self->ref_cnt) > 0); g_atomic_counter_inc(&self->ref_cnt); return self; } void context_info_db_unref(ContextInfoDB *self) { g_assert(!self || g_atomic_counter_get(&self->ref_cnt)); if (g_atomic_counter_dec_and_test(&self->ref_cnt)) { context_info_db_free(self); } } static element_range * _get_range_of_records(ContextInfoDB *self, const gchar *selector) { _ensure_indexed_db(self); return (element_range *) g_hash_table_lookup(self->index, selector); } void context_info_db_purge(ContextInfoDB *self) { g_hash_table_remove_all(self->index); if (self->data->len > 0) self->data = g_array_remove_range(self->data, 0, self->data->len); } void context_info_db_free(ContextInfoDB *self) { if (self) { _free(self); g_free(self); } } static gint _g_strcmp(const gconstpointer a, gconstpointer b) { return g_strcmp0((const gchar *) a, (const gchar *) b); } void context_info_db_insert(ContextInfoDB *self, const ContextualDataRecord *record) { g_array_append_val(self->data, *record); self->is_data_indexed = FALSE; if (self->is_ordering_enabled && !g_list_find_custom(self->ordered_selectors, record->selector->str, _g_strcmp)) self->ordered_selectors = g_list_append(self->ordered_selectors, record->selector->str); } gboolean context_info_db_contains(ContextInfoDB *self, const gchar *selector) { if (!selector) return FALSE; _ensure_indexed_db(self); return (_get_range_of_records(self, selector) != NULL); } gsize context_info_db_number_of_records(ContextInfoDB *self, const gchar *selector) { _ensure_indexed_db(self); gsize n = 0; element_range *range = _get_range_of_records(self, selector); if (range) n = range->length; return n; } void context_info_db_foreach_record(ContextInfoDB *self, const gchar *selector, ADD_CONTEXT_INFO_CB callback, gpointer arg) { _ensure_indexed_db(self); element_range *record_range = _get_range_of_records(self, selector); if (!record_range) return; for (gsize i = record_range->offset; i < record_range->offset + record_range->length; ++i) { ContextualDataRecord record = g_array_index(self->data, ContextualDataRecord, i); callback(arg, &record); } } gboolean context_info_db_is_indexed(const ContextInfoDB *self) { return self->is_data_indexed; } gboolean context_info_db_is_loaded(const ContextInfoDB *self) { return (self->data != NULL && self->data->len > 0); } GList * context_info_db_get_selectors(ContextInfoDB *self) { _ensure_indexed_db(self); return g_hash_table_get_keys(self->index); } static void _truncate_eol(gchar *line, gsize line_len) { if (line_len >= 2 && line[line_len - 2] == '\r' && line[line_len - 1] == '\n') line[line_len - 2] = '\0'; else if (line_len >= 1 && line[line_len - 1] == '\n') line[line_len - 1] = '\0'; } static gboolean _get_line_without_eol(gchar **line_buf, gsize *line_buf_len, FILE *fp) { gssize n; if ((n = getline(line_buf, line_buf_len, fp)) == -1) return FALSE; _truncate_eol(*line_buf, n); return TRUE; } gboolean context_info_db_import(ContextInfoDB *self, FILE *fp, ContextualDataRecordScanner *scanner) { size_t line_buf_len; gchar *line_buf = NULL; const ContextualDataRecord *next_record; while (_get_line_without_eol(&line_buf, &line_buf_len, fp)) { next_record = contextual_data_record_scanner_get_next(scanner, line_buf); if (!next_record) { context_info_db_purge(self); g_free(line_buf); return FALSE; } context_info_db_insert(self, next_record); } g_free(line_buf); context_info_db_index(self); return TRUE; } syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/context-info-db.h000066400000000000000000000050121321171025300260770ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CONTEXTINFODB_H_INCLUDED #define CONTEXTINFODB_H_INCLUDED #include "syslog-ng.h" #include "contextual-data-record-scanner.h" #include typedef struct _ContextInfoDB ContextInfoDB; typedef void (*ADD_CONTEXT_INFO_CB) (gpointer arg, const ContextualDataRecord *record); void context_info_db_enable_ordering(ContextInfoDB *self); GList * context_info_db_ordered_selectors(ContextInfoDB *self); ContextInfoDB *context_info_db_new(void); void context_info_db_free(ContextInfoDB *self); ContextInfoDB *context_info_db_ref(ContextInfoDB *self); void context_info_db_unref(ContextInfoDB *self); void context_info_db_purge(ContextInfoDB *self); void context_info_db_index(ContextInfoDB *self); gboolean context_info_db_is_loaded(const ContextInfoDB *self); gboolean context_info_db_is_indexed(const ContextInfoDB *self); void context_info_db_insert(ContextInfoDB *self, const ContextualDataRecord *record); gboolean context_info_db_contains(ContextInfoDB *self, const gchar *selector); gsize context_info_db_number_of_records(ContextInfoDB *self, const gchar *selector); void context_info_db_foreach_record(ContextInfoDB *self, const gchar *selector, ADD_CONTEXT_INFO_CB callback, gpointer arg); GList *context_info_db_get_selectors(ContextInfoDB *self); gboolean context_info_db_import(ContextInfoDB *self, FILE *fp, ContextualDataRecordScanner *scanner); #endif syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/contextual-data-record-scanner.c000066400000000000000000000050661321171025300311030ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "contextual-data-record-scanner.h" #include "csv-contextual-data-record-scanner.h" #include "messages.h" #include void contextual_data_record_scanner_free(ContextualDataRecordScanner *self) { if (self && self->free_fn) self->free_fn(self); } void contextual_data_record_scanner_set_name_prefix(ContextualDataRecordScanner * self, const gchar *prefix) { self->name_prefix = prefix; } void contextual_data_record_init(ContextualDataRecord *record) { record->selector = NULL; record->name = NULL; record->value = NULL; } void contextual_data_record_clean(ContextualDataRecord *record) { if (record->selector) g_string_free(record->selector, TRUE); if (record->name) g_string_free(record->name, TRUE); if (record->value) g_string_free(record->value, TRUE); contextual_data_record_init(record); } ContextualDataRecordScanner * create_contextual_data_record_scanner_by_type(const gchar *type) { ContextualDataRecordScanner *scanner = NULL; if (type == NULL) return NULL; if (!strcmp(type, "csv")) { scanner = csv_contextual_data_record_scanner_new(); } if (!scanner) msg_warning("Unknown ContextualDataRecordScanner", evt_tag_str("type", type)); return scanner; } ContextualDataRecord * contextual_data_record_scanner_get_next(ContextualDataRecordScanner *self, const gchar *input) { if (!self->get_next) return NULL; contextual_data_record_init(&self->last_record); if (!self->get_next(self, input, &self->last_record)) { contextual_data_record_clean(&self->last_record); return NULL; } return &self->last_record; } syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/contextual-data-record-scanner.h000066400000000000000000000041741321171025300311070ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CONTEXTUAL_DATA_RECORD_SCANNER_H_INCLUDED #define CONTEXTUAL_DATA_RECORD_SCANNER_H_INCLUDED #include "syslog-ng.h" typedef struct _ContextualDataRecordScanner ContextualDataRecordScanner; typedef struct _ContextualDataRecord { GString *selector; GString *name; GString *value; } ContextualDataRecord; struct _ContextualDataRecordScanner { ContextualDataRecord last_record; gpointer scanner; const gchar *name_prefix; const gboolean (*get_next) (ContextualDataRecordScanner *self, const gchar *input, ContextualDataRecord *record); void (*free_fn) (ContextualDataRecordScanner *self); }; void contextual_data_record_scanner_free(ContextualDataRecordScanner *self); void contextual_data_record_scanner_set_name_prefix(ContextualDataRecordScanner * self, const gchar *prefix); void contextual_data_record_init(ContextualDataRecord *record); void contextual_data_record_clean(ContextualDataRecord *record); ContextualDataRecordScanner *create_contextual_data_record_scanner_by_type(const gchar *type); ContextualDataRecord * contextual_data_record_scanner_get_next(ContextualDataRecordScanner *self, const gchar *input); #endif syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/csv-contextual-data-record-scanner.c000066400000000000000000000074251321171025300316750ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "csv-contextual-data-record-scanner.h" #include "scanner/csv-scanner/csv-scanner.h" #include "string-list.h" #include static gchar * _csv_scanner_dup_current_value_with_prefix(CSVScanner *line_scanner, const gchar *prefix) { return g_strdup_printf("%s%s", prefix ? prefix : "", csv_scanner_get_current_value(line_scanner)); } static gboolean _fetch_next_with_prefix(CSVContextualDataRecordScanner *record_scanner, GString **target, const gchar *prefix) { if (!csv_scanner_scan_next(&record_scanner->scanner)) { return FALSE; } gchar *next = _csv_scanner_dup_current_value_with_prefix(&record_scanner->scanner, prefix); *target = g_string_new(next); g_free(next); return TRUE; } static gboolean _fetch_next_without_prefix(CSVContextualDataRecordScanner * record_scanner, GString **target) { return _fetch_next_with_prefix(record_scanner, target, NULL); } static gboolean _is_whole_record_parsed(CSVContextualDataRecordScanner *csv_record_scanner) { csv_scanner_scan_next(&csv_record_scanner->scanner); return csv_scanner_is_scan_finished(&csv_record_scanner->scanner); } const gboolean get_next_record(ContextualDataRecordScanner *s, const gchar *input, ContextualDataRecord *record) { CSVContextualDataRecordScanner *csv_record_scanner = (CSVContextualDataRecordScanner *) s; csv_scanner_init(&csv_record_scanner->scanner, &csv_record_scanner->options, input); if (!_fetch_next_without_prefix(csv_record_scanner, &record->selector)) return FALSE; if (!_fetch_next_with_prefix(csv_record_scanner, &record->name, s->name_prefix)) return FALSE; if (!_fetch_next_without_prefix(csv_record_scanner, &record->value)) return FALSE; return _is_whole_record_parsed(csv_record_scanner); } static void csv_contextual_data_record_scanner_free(ContextualDataRecordScanner *s) { CSVContextualDataRecordScanner *self = (CSVContextualDataRecordScanner *) s; csv_scanner_options_clean(&self->options); csv_scanner_deinit(&self->scanner); g_free(self); } ContextualDataRecordScanner * csv_contextual_data_record_scanner_new(void) { CSVContextualDataRecordScanner *self = g_new0(CSVContextualDataRecordScanner, 1); csv_scanner_options_set_delimiters(&self->options, ","); csv_scanner_options_set_quote_pairs(&self->options, "\"\"''"); const gchar *column_array[] = { "selector", "name", "value", NULL }; csv_scanner_options_set_columns(&self->options, string_array_to_list(column_array)); csv_scanner_options_set_flags(&self->options, CSV_SCANNER_STRIP_WHITESPACE | CSV_SCANNER_DROP_INVALID); csv_scanner_options_set_dialect(&self->options, CSV_SCANNER_ESCAPE_DOUBLE_CHAR); self->super.get_next = get_next_record; self->super.free_fn = csv_contextual_data_record_scanner_free; return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/csv-contextual-data-record-scanner.h000066400000000000000000000025001321171025300316670ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CSV_CONTEXTUAL_DATA_RECORD_H_INCLUDED #define CSV_CONTEXTUAL_DATA_RECORD_H_INCLUDED #include "contextual-data-record-scanner.h" #include "scanner/csv-scanner/csv-scanner.h" typedef struct _CSVContextualDataRecordScanner { ContextualDataRecordScanner super; CSVScanner scanner; CSVScannerOptions options; } CSVContextualDataRecordScanner; ContextualDataRecordScanner *csv_contextual_data_record_scanner_new(void); #endif syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/tests/000077500000000000000000000000001321171025300240725ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/tests/Makefile.am000066400000000000000000000022041321171025300261240ustar00rootroot00000000000000if ENABLE_CRITERION modules_add_contextual_data_tests_TESTS = \ modules/add-contextual-data/tests/test_context_info_db \ modules/add-contextual-data/tests/test_selector check_PROGRAMS += \ ${modules_add_contextual_data_tests_TESTS} modules_add_contextual_data_tests_test_context_info_db_CFLAGS = \ $(TEST_CFLAGS) -I$(top_srcdir)/modules/add-contextual-data modules_add_contextual_data_tests_test_context_info_db_LDADD = \ $(TEST_LDADD) modules_add_contextual_data_tests_test_context_info_db_LDFLAGS = \ $(PREOPEN_SYSLOGFORMAT) \ -dlpreopen $(top_builddir)/modules/add-contextual-data/libadd-contextual-data.la modules_add_contextual_data_tests_test_selector_CFLAGS = \ $(TEST_CFLAGS) -I$(top_srcdir)/modules/add-contextual-data modules_add_contextual_data_tests_test_selector_LDADD = \ $(TEST_LDADD) modules_add_contextual_data_tests_test_selector_LDFLAGS = \ $(PREOPEN_SYSLOGFORMAT) \ -dlpreopen $(top_builddir)/modules/add-contextual-data/libadd-contextual-data.la endif syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/tests/test_context_info_db.c000066400000000000000000000341371321171025300304510ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "context-info-db.h" #include "scratch-buffers.h" #include #include #include #include #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) TestSuite(add_contextual_data, .init=scratch_buffers_allocator_init, .fini=scratch_buffers_allocator_deinit); static void _count_records(gpointer arg, const ContextualDataRecord *record) { int *ctr = (int *) arg; ++(*ctr); } static void _test_empty_db(ContextInfoDB *context_info_db) { cr_assert_not(context_info_db_is_loaded(context_info_db) == TRUE, "Empty ContextInfoDB should be in unloaded state."); cr_assert_not(context_info_db_is_indexed(context_info_db) == TRUE, "Empty ContextInfoDB should be in un-indexed state."); cr_assert_not(context_info_db_contains(context_info_db, "selector") == TRUE, "Method context_info_db_contains should work with empty ContextInfoDB."); cr_assert_eq(context_info_db_number_of_records(context_info_db, "selector"), 0, "Method context_info_db_number should work with empty ContextInfoDB."); int ctr = 0; context_info_db_foreach_record(context_info_db, "selector", _count_records, (gpointer) & ctr); cr_assert_eq(ctr, 0, "Method context_info_db_foreach_record should work for with empty ContextInfoDB."); } Test(add_contextual_data, test_empty_db) { ContextInfoDB *context_info_db = context_info_db_new(); _test_empty_db(context_info_db); context_info_db_unref(context_info_db); } Test(add_contextual_data, test_purge_empty_db) { ContextInfoDB *context_info_db = context_info_db_new(); context_info_db_purge(context_info_db); _test_empty_db(context_info_db); context_info_db_unref(context_info_db); } Test(add_contextual_data, test_index_empty_db) { ContextInfoDB *context_info_db = context_info_db_new(); context_info_db_index(context_info_db); _test_empty_db(context_info_db); context_info_db_unref(context_info_db); } static void _fill_context_info_db(ContextInfoDB *context_info_db, const gchar *selector_base, const gchar *name_base, const gchar *value_base, int number_of_selectors, int number_of_nv_pairs_per_selector) { int i, j; for (i = 0; i < number_of_selectors; i++) { for (j = 0; j < number_of_nv_pairs_per_selector; j++) { ContextualDataRecord record = { .selector = g_string_new(NULL), .name = g_string_new(NULL), .value = g_string_new(NULL) }; g_string_printf(record.selector, "%s-%d", selector_base, i), g_string_printf(record.name, "%s-%d.%d", name_base, i, j), g_string_printf(record.value, "%s-%d.%d", value_base, i, j); context_info_db_insert(context_info_db, &record); } } } static gint _g_strcmp(const gconstpointer a, gconstpointer b) { return g_strcmp0((const gchar *) a, (const gchar *) b); } Test(add_contextual_data, test_insert) { ContextInfoDB *context_info_db = context_info_db_new(); context_info_db_enable_ordering(context_info_db); _fill_context_info_db(context_info_db, "selector", "name", "value", 2, 5); int ctr = 0; cr_assert_eq(context_info_db_number_of_records(context_info_db, "selector-0"), 5, "selector-0 should have 5 nv-pairs"); context_info_db_foreach_record(context_info_db, "selector-0", _count_records, (gpointer) & ctr); cr_assert_eq(ctr, 5, "foreach should find 5 nv-pairs for selector-0"); cr_assert_eq(g_list_length(context_info_db_ordered_selectors(context_info_db)), 2, "2 different selectors were saved to the ordered list"); context_info_db_unref(context_info_db); } Test(add_contextual_data, test_get_selectors) { ContextInfoDB *context_info_db = context_info_db_new(); _fill_context_info_db(context_info_db, "selector", "name", "value", 2, 5); GList *selectors = context_info_db_get_selectors(context_info_db); GList *selector0 = g_list_find_custom(selectors, "selector-0", _g_strcmp); GList *selector1 = g_list_find_custom(selectors, "selector-1", _g_strcmp); cr_assert_str_eq((const gchar *)selector0->data, "selector-0"); cr_assert_str_eq((const gchar *)selector1->data, "selector-1"); context_info_db_unref(context_info_db); g_list_free(selectors); } typedef struct _TestNVPair { const gchar *name; const gchar *value; } TestNVPair; typedef struct _TestNVPairStore { TestNVPair *pairs; int ctr; } TestNVPairStore; static void _foreach_get_nvpairs(gpointer arg, const ContextualDataRecord *record) { TestNVPairStore *store = (TestNVPairStore *) arg; TestNVPair pair = {.name = record->name->str,.value = record->value->str }; store->pairs[store->ctr++] = pair; } static void _assert_context_info_db_contains_name_value_pairs_by_selector(ContextInfoDB * context_info_db, const gchar * selector, TestNVPair * expected_nvpairs, guint number_of_expected_nvpairs) { TestNVPair result[number_of_expected_nvpairs]; TestNVPairStore result_store = {.pairs = result,.ctr = 0 }; context_info_db_foreach_record(context_info_db, selector, _foreach_get_nvpairs, (gpointer) & result_store); cr_assert_eq(result_store.ctr, number_of_expected_nvpairs); guint i; for (i = 0; i < number_of_expected_nvpairs; i++) { cr_assert_str_eq(result[i].name, expected_nvpairs[i].name); cr_assert_str_eq(result[i].value, expected_nvpairs[i].value); } } static void _assert_import_csv_with_single_selector(gchar *csv_content, gchar *selector_to_check, TestNVPair *expected_nvpairs, gsize expected_nvpairs_size) { FILE *fp = fmemopen(csv_content, strlen(csv_content) + 1, "r"); ContextInfoDB *db = context_info_db_new(); ContextualDataRecordScanner *scanner = create_contextual_data_record_scanner_by_type("csv"); cr_assert(context_info_db_import(db, fp, scanner), "Failed to import valid CSV file."); fclose(fp); _assert_context_info_db_contains_name_value_pairs_by_selector(db, selector_to_check, expected_nvpairs, expected_nvpairs_size); context_info_db_free(db); contextual_data_record_scanner_free(scanner); } Test(add_contextual_data, test_inserted_nv_pairs) { ContextInfoDB *context_info_db = context_info_db_new(); _fill_context_info_db(context_info_db, "selector", "name", "value", 1, 3); TestNVPair expected_nvpairs[] = { {.name = "name-0.0",.value = "value-0.0"}, {.name = "name-0.1",.value = "value-0.1"}, {.name = "name-0.2",.value = "value-0.2"} }; _assert_context_info_db_contains_name_value_pairs_by_selector (context_info_db, "selector-0", expected_nvpairs, ARRAY_SIZE(expected_nvpairs)); context_info_db_unref(context_info_db); } Test(add_contextual_data, test_import_with_valid_csv) { gchar csv_content[] = "selector1,name1,value1\n" "selector1,name1.1,value1.1\n" "selector2,name2,value2\n" "selector3,name3,value3"; FILE *fp = fmemopen(csv_content, sizeof(csv_content), "r"); ContextInfoDB *db = context_info_db_new(); ContextualDataRecordScanner *scanner = create_contextual_data_record_scanner_by_type("csv"); cr_assert(context_info_db_import(db, fp, scanner), "Failed to import valid CSV file."); cr_assert(context_info_db_is_loaded(db), "The context_info_db_is_loaded reports False after a successful import operation. "); cr_assert(context_info_db_is_indexed(db), "The context_info_db_is_indexed reports False after successful import&load operations."); fclose(fp); TestNVPair expected_nvpairs_selector1[] = { {.name = "name1",.value = "value1"}, {.name = "name1.1",.value = "value1.1"}, }; TestNVPair expected_nvpairs_selector2[] = { {.name = "name2",.value = "value2"}, }; TestNVPair expected_nvpairs_selector3[] = { {.name = "name3",.value = "value3"}, }; _assert_context_info_db_contains_name_value_pairs_by_selector(db, "selector1", expected_nvpairs_selector1, ARRAY_SIZE(expected_nvpairs_selector1)); _assert_context_info_db_contains_name_value_pairs_by_selector(db, "selector2", expected_nvpairs_selector2, ARRAY_SIZE(expected_nvpairs_selector2)); _assert_context_info_db_contains_name_value_pairs_by_selector(db, "selector3", expected_nvpairs_selector3, ARRAY_SIZE(expected_nvpairs_selector3)); context_info_db_free(db); contextual_data_record_scanner_free(scanner); } Test(add_contextual_data, test_import_from_csv_with_crlf_line_ending, .description = "RFC 4180: Each record should be located on a separate line, delimited by a line break (CRLF).") { gchar csv_content[] = "selector1,name1,value1\r\n" "selector1,name1.1,value1.1"; TestNVPair expected_nvpairs[] = { {.name = "name1",.value = "value1"}, {.name = "name1.1",.value = "value1.1"}, }; _assert_import_csv_with_single_selector(csv_content, "selector1", expected_nvpairs, ARRAY_SIZE(expected_nvpairs)); } Test(add_contextual_data, test_import_from_csv_with_escaped_double_quote, .description = "RFC 4180: If double-quotes are used to enclose fields, then a double-quote appearing inside a " "field must be escaped by preceding it with another double quote.") { gchar csv_content[] = "selector1,name1,\"c\"\"cc\""; TestNVPair expected_nvpairs[] = { {.name = "name1",.value = "c\"cc"}, }; _assert_import_csv_with_single_selector(csv_content, "selector1", expected_nvpairs, ARRAY_SIZE(expected_nvpairs)); } Test(add_contextual_data, test_import_with_invalid_csv_content) { gchar csv_content[] = "xxx"; FILE *fp = fmemopen(csv_content, strlen(csv_content) + 1, "r"); ContextInfoDB *db = context_info_db_new(); ContextualDataRecordScanner *scanner = create_contextual_data_record_scanner_by_type("csv"); cr_assert_not(context_info_db_import(db, fp, scanner), "Sucessfully import an invalid CSV file."); cr_assert_not(context_info_db_is_loaded(db), "The context_info_db_is_loaded reports True after a failing import operation. "); cr_assert_not(context_info_db_is_indexed(db), "The context_info_db_is_indexed reports True after failing import&load operations."); fclose(fp); context_info_db_free(db); contextual_data_record_scanner_free(scanner); } Test(add_contextual_data, test_import_with_csv_contains_invalid_line) { gchar csv_content[] = "selector1,name1,value1\n" ",,value1.1\n"; FILE *fp = fmemopen(csv_content, strlen(csv_content) + 1, "r"); ContextInfoDB *db = context_info_db_new(); ContextualDataRecordScanner *scanner = create_contextual_data_record_scanner_by_type("csv"); cr_assert_not(context_info_db_import(db, fp, scanner), "Sucessfully import an invalid CSV file."); cr_assert_not(context_info_db_is_loaded(db), "The context_info_db_is_loaded reports True after a failing import operation. "); cr_assert_not(context_info_db_is_indexed(db), "The context_info_db_is_indexed reports True after failing import&load operations."); fclose(fp); context_info_db_free(db); contextual_data_record_scanner_free(scanner); } struct TestNVPairPrefix { TestNVPair expected; const gchar *prefix; }; ParameterizedTestParameters(add_contextual_data, test_import_with_prefix) { static struct TestNVPairPrefix params[] = { { .expected = {.name = "name1",.value = "value1"}, .prefix = NULL }, { .expected = {.name = "name1",.value = "value1"}, .prefix = "" }, { .expected = {.name = "aaaname1",.value = "value1"}, .prefix = "aaa" }, { .expected = {.name = "aaa.name1",.value = "value1"}, .prefix = "aaa." }, { .expected = {.name = ".aaa.name1",.value = "value1"}, .prefix = ".aaa." }, { .expected = {.name = ".name1",.value = "value1"}, .prefix = "." }, { .expected = {.name = "....name1",.value = "value1"}, .prefix = "...." } }; size_t nb_params = sizeof (params) / sizeof (struct TestNVPairPrefix); return cr_make_param_array(struct TestNVPairPrefix, params, nb_params); } ParameterizedTest(struct TestNVPairPrefix *param, add_contextual_data, test_import_with_prefix) { gchar csv_content[] = "selector1,name1,value1"; FILE *fp = fmemopen(csv_content, sizeof(csv_content), "r"); ContextInfoDB *db = context_info_db_new(); ContextualDataRecordScanner *scanner = create_contextual_data_record_scanner_by_type("csv"); contextual_data_record_scanner_set_name_prefix(scanner, param->prefix); cr_assert(context_info_db_import(db, fp, scanner), "Failed to import valid CSV file."); cr_assert(context_info_db_is_loaded(db), "The context_info_db_is_loaded reports False after a successful import operation. "); cr_assert(context_info_db_is_indexed(db), "The context_info_db_is_indexed reports False after successful import&load operations."); fclose(fp); _assert_context_info_db_contains_name_value_pairs_by_selector(db, "selector1", ¶m->expected, 1); } syslog-ng-syslog-ng-3.13.2/modules/add-contextual-data/tests/test_selector.c000066400000000000000000000060311321171025300271150ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "add-contextual-data-template-selector.h" #include "logmsg/logmsg.h" #include "template/macros.h" #include "cfg.h" #include "apphook.h" #include #include TestSuite(add_contextual_data_template_selector, .init = app_startup, .fini = app_shutdown); static LogMessage * _create_log_msg(const gchar *message, const gchar *host) { LogMessage *msg = NULL; msg = log_msg_new_empty(); log_msg_set_value(msg, LM_V_MESSAGE, message, -1); log_msg_set_value(msg, LM_V_HOST, host, -1); return msg; } Test(add_contextual_data_template_selector, test_given_empty_selector_when_resolve_then_result_is_null) { AddContextualDataSelector *selector = NULL; LogMessage *msg = _create_log_msg("testmsg", "localhost"); cr_assert_null(add_contextual_data_selector_resolve(selector, msg), "When selector is NULL the resolve should return NULL."); log_msg_unref(msg); } static AddContextualDataSelector * _create_template_selector(const gchar *template_string) { GlobalConfig *cfg = cfg_new_snippet(); AddContextualDataSelector *selector = add_contextual_data_template_selector_new(cfg, template_string); add_contextual_data_selector_init(selector, NULL); return selector; } Test(add_contextual_data_template_selector, test_given_template_selector_when_resolve_then_result_is_the_formatted_template_value) { AddContextualDataSelector *selector = _create_template_selector("$HOST"); LogMessage *msg = _create_log_msg("testmsg", "localhost"); gchar *resolved_selector = add_contextual_data_selector_resolve(selector, msg); cr_assert_str_eq(resolved_selector, "localhost", ""); log_msg_unref(msg); add_contextual_data_selector_free(selector); } Test(add_contextual_data_template_selector, test_template_selector_cannot_be_resolved) { AddContextualDataSelector *selector = _create_template_selector("$PROGRAM"); LogMessage *msg = _create_log_msg("testmsg", "localhost"); gchar *resolved_selector = add_contextual_data_selector_resolve(selector, msg); cr_assert_str_eq(resolved_selector, "", "No template should be resolved."); log_msg_unref(msg); add_contextual_data_selector_free(selector); } syslog-ng-syslog-ng-3.13.2/modules/afamqp/000077500000000000000000000000001321171025300203525ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afamqp/Makefile.am000066400000000000000000000025301321171025300224060ustar00rootroot00000000000000DIST_SUBDIRS += @LIBRABBITMQ_SUBDIRS@ if LIBRABBITMQ_INTERNAL CLEAN_SUBDIRS += @LIBRABBITMQ_SUBDIRS@ lr_EXTRA_DEPS = modules/afamqp/rabbitmq-c/librabbitmq/librabbitmq.la $(lr_EXTRA_DEPS): ${MAKE} -C modules/afamqp/rabbitmq-c endif if ENABLE_AMQP module_LTLIBRARIES += modules/afamqp/libafamqp.la modules_afamqp_libafamqp_la_CFLAGS = \ $(AM_CFLAGS) \ $(LIBRABBITMQ_CFLAGS) \ -I$(top_srcdir)/modules/afamqp \ -I$(top_builddir)/modules/afamqp modules_afamqp_libafamqp_la_SOURCES = \ modules/afamqp/afamqp-grammar.y \ modules/afamqp/afamqp.c \ modules/afamqp/afamqp.h \ modules/afamqp/afamqp-parser.c \ modules/afamqp/afamqp-parser.h modules_afamqp_libafamqp_la_LIBADD = \ $(MODULE_DEPS_LIBS) $(LIBRABBITMQ_LIBS) modules_afamqp_libafamqp_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_afamqp_libafamqp_la_DEPENDENCIES= \ $(MODULE_DEPS_LIBS) \ $(lr_EXTRA_DEPS) modules/afamqp modules/afamqp/ mod-afamqp mod-amqp: \ modules/afamqp/libafamqp.la else modules/afamqp modules/afamqp/ mod-afamqp mod-amqp: endif if LIBRABBITMQ_INTERNAL EXTRA_DIST += \ modules/afamqp/rabbitmq-c/configure.gnu endif BUILT_SOURCES += \ modules/afamqp/afamqp-grammar.y \ modules/afamqp/afamqp-grammar.c \ modules/afamqp/afamqp-grammar.h EXTRA_DIST += \ modules/afamqp/afamqp-grammar.ym .PHONY: modules/afamqp/ mod-afamqp mod-amqp syslog-ng-syslog-ng-3.13.2/modules/afamqp/afamqp-grammar.ym000066400000000000000000000072141321171025300236160ustar00rootroot00000000000000/* * Copyright (c) 2012 Nagy, Attila * Copyright (c) 2012-2014 Balabit * Copyright (c) 2012-2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code requires { #include "afamqp-parser.h" } %code { #include "cfg-parser.h" #include "cfg-grammar.h" #include "afamqp-grammar.h" #include "plugin.h" #include "value-pairs/value-pairs.h" } %name-prefix "afamqp_" %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogDriver **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_AMQP %token KW_EXCHANGE %token KW_EXCHANGE_DECLARE %token KW_EXCHANGE_TYPE %token KW_PERSISTENT %token KW_VHOST %token KW_ROUTING_KEY %token KW_BODY %token KW_PASSWORD %token KW_USERNAME %token KW_CA_FILE %token KW_KEY_FILE %token KW_CERT_FILE %token KW_PEER_VERIFY %token KW_TLS %% start : LL_CONTEXT_DESTINATION KW_AMQP { last_driver = *instance = afamqp_dd_new(configuration); } '(' afamqp_options ')' { YYACCEPT; } ; afamqp_options : afamqp_option afamqp_options | ; afamqp_option : KW_HOST '(' string ')' { afamqp_dd_set_host(last_driver, $3); free($3); } | KW_PORT '(' positive_integer ')' { afamqp_dd_set_port(last_driver, $3); } | KW_VHOST '(' string ')' { afamqp_dd_set_vhost(last_driver, $3); free($3); } | KW_EXCHANGE '(' string ')' { afamqp_dd_set_exchange(last_driver, $3); free($3); } | KW_EXCHANGE_DECLARE '(' yesno ')' { afamqp_dd_set_exchange_declare(last_driver, $3); } | KW_EXCHANGE_TYPE '(' string ')' { afamqp_dd_set_exchange_type(last_driver, $3); free($3); } | KW_ROUTING_KEY '(' string ')' { afamqp_dd_set_routing_key(last_driver, $3); free($3); } | KW_BODY '(' string ')' { afamqp_dd_set_body(last_driver, $3); free($3); } | KW_PERSISTENT '(' yesno ')' { afamqp_dd_set_persistent(last_driver, $3); } | KW_USERNAME '(' string ')' { afamqp_dd_set_user(last_driver, $3); free($3); } | KW_PASSWORD '(' string ')' { afamqp_dd_set_password(last_driver, $3); free($3); } | value_pair_option { afamqp_dd_set_value_pairs(last_driver, $1); } | dest_driver_option | threaded_dest_driver_option | afamqp_tls_option | KW_TLS '(' afamqp_tls_options ')' | { last_template_options = afamqp_dd_get_template_options(last_driver); } template_option ; afamqp_tls_options : afamqp_tls_option afamqp_tls_options | ; afamqp_tls_option : KW_CA_FILE '(' string ')' { afamqp_dd_set_ca_file(last_driver, $3); free($3); } | KW_KEY_FILE '(' string ')' { afamqp_dd_set_key_file(last_driver, $3); free($3); } | KW_CERT_FILE '(' string ')' { afamqp_dd_set_cert_file(last_driver, $3); free($3); } | KW_PEER_VERIFY '(' yesno ')' { afamqp_dd_set_peer_verify(last_driver, $3); } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/afamqp/afamqp-parser.c000066400000000000000000000042741321171025300232640ustar00rootroot00000000000000/* * Copyright (c) 2012 Nagy, Attila * Copyright (c) 2012, 2014 Balabit * Copyright (c) 2012, 2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afamqp.h" #include "cfg-parser.h" #include "afamqp-grammar.h" extern int afamqp_debug; int afamqp_parse(CfgLexer *lexer, LogDriver **instance, gpointer arg); static CfgLexerKeyword afamqp_keywords[] = { { "amqp", KW_AMQP }, { "vhost", KW_VHOST }, { "host", KW_HOST }, { "port", KW_PORT }, { "exchange", KW_EXCHANGE }, { "exchange_declare", KW_EXCHANGE_DECLARE }, { "exchange_type", KW_EXCHANGE_TYPE }, { "routing_key", KW_ROUTING_KEY }, { "persistent", KW_PERSISTENT }, { "username", KW_USERNAME }, { "password", KW_PASSWORD }, { "log_fifo_size", KW_LOG_FIFO_SIZE }, { "body", KW_BODY }, { "ca_file", KW_CA_FILE }, { "key_file", KW_KEY_FILE }, { "cert_file", KW_CERT_FILE }, { "peer_verify", KW_PEER_VERIFY }, { "tls", KW_TLS }, { NULL } }; CfgParser afamqp_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &afamqp_debug, #endif .name = "afamqp", .keywords = afamqp_keywords, .parse = (int (*)(CfgLexer *lexer, gpointer *instance, gpointer)) afamqp_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(afamqp_, LogDriver **) syslog-ng-syslog-ng-3.13.2/modules/afamqp/afamqp-parser.h000066400000000000000000000023041321171025300232610ustar00rootroot00000000000000/* * Copyright (c) 2012 Nagy, Attila * Copyright (c) 2012 Balabit * Copyright (c) 2012 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFAMQP_PARSER_H_INCLUDED #define AFAMQP_PARSER_H_INCLUDED #include "cfg-parser.h" #include "afamqp.h" extern CfgParser afamqp_parser; CFG_PARSER_DECLARE_LEXER_BINDING(afamqp_, LogDriver **) #endif syslog-ng-syslog-ng-3.13.2/modules/afamqp/afamqp.c000066400000000000000000000464331321171025300217750ustar00rootroot00000000000000/* * Copyright (c) 2012 Nagy, Attila * Copyright (c) 2012-2014 Balabit * Copyright (c) 2012-2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afamqp.h" #include "afamqp-parser.h" #include "plugin.h" #include "messages.h" #include "stats/stats-registry.h" #include "logmsg/nvtable.h" #include "logqueue.h" #include "scratch-buffers.h" #include "plugin-types.h" #include "logthrdestdrv.h" #include #include #include #include typedef struct { LogThrDestDriver super; /* Shared between main/writer; only read by the writer, never written */ gchar *exchange; gchar *exchange_type; LogTemplate *routing_key_template; LogTemplate *body_template; gboolean declare; gint persistent; gchar *vhost; gchar *host; gint port; gchar *user; gchar *password; LogTemplateOptions template_options; ValuePairs *vp; /* Writer-only stuff */ amqp_connection_state_t conn; amqp_socket_t *sockfd; amqp_table_entry_t *entries; gint32 max_entries; /* SSL props */ gchar *ca_file; gchar *key_file; gchar *cert_file; gboolean peer_verify; } AMQPDestDriver; /* * Configuration */ void afamqp_dd_set_user(LogDriver *d, const gchar *user) { AMQPDestDriver *self = (AMQPDestDriver *) d; g_free(self->user); self->user = g_strdup(user); } void afamqp_dd_set_password(LogDriver *d, const gchar *password) { AMQPDestDriver *self = (AMQPDestDriver *) d; g_free(self->password); self->password = g_strdup(password); } void afamqp_dd_set_vhost(LogDriver *d, const gchar *vhost) { AMQPDestDriver *self = (AMQPDestDriver *) d; g_free(self->vhost); self->vhost = g_strdup(vhost); } void afamqp_dd_set_host(LogDriver *d, const gchar *host) { AMQPDestDriver *self = (AMQPDestDriver *) d; g_free(self->host); self->host = g_strdup(host); } void afamqp_dd_set_port(LogDriver *d, gint port) { AMQPDestDriver *self = (AMQPDestDriver *) d; self->port = (int) port; } void afamqp_dd_set_exchange(LogDriver *d, const gchar *exchange) { AMQPDestDriver *self = (AMQPDestDriver *) d; g_free(self->exchange); self->exchange = g_strdup(exchange); } void afamqp_dd_set_exchange_declare(LogDriver *d, gboolean declare) { AMQPDestDriver *self = (AMQPDestDriver *) d; self->declare = declare; } void afamqp_dd_set_exchange_type(LogDriver *d, const gchar *exchange_type) { AMQPDestDriver *self = (AMQPDestDriver *) d; g_free(self->exchange_type); self->exchange_type = g_strdup(exchange_type); } void afamqp_dd_set_routing_key(LogDriver *d, const gchar *routing_key) { AMQPDestDriver *self = (AMQPDestDriver *) d; log_template_compile(self->routing_key_template, routing_key, NULL); } void afamqp_dd_set_body(LogDriver *d, const gchar *body) { AMQPDestDriver *self = (AMQPDestDriver *) d; if (!self->body_template) self->body_template = log_template_new(configuration, NULL); log_template_compile(self->body_template, body, NULL); } void afamqp_dd_set_persistent(LogDriver *s, gboolean persistent) { AMQPDestDriver *self = (AMQPDestDriver *) s; if (persistent) self->persistent = 2; else self->persistent = 1; } void afamqp_dd_set_value_pairs(LogDriver *d, ValuePairs *vp) { AMQPDestDriver *self = (AMQPDestDriver *) d; value_pairs_unref(self->vp); self->vp = vp; } LogTemplateOptions * afamqp_dd_get_template_options(LogDriver *s) { AMQPDestDriver *self = (AMQPDestDriver *) s; return &self->template_options; } void afamqp_dd_set_ca_file(LogDriver *d, const gchar *cacrt) { AMQPDestDriver *self = (AMQPDestDriver *) d; g_free(self->ca_file); self->ca_file = g_strdup(cacrt); } void afamqp_dd_set_key_file(LogDriver *d, const gchar *key) { AMQPDestDriver *self = (AMQPDestDriver *) d; g_free(self->key_file); self->key_file = g_strdup(key); } void afamqp_dd_set_cert_file(LogDriver *d, const gchar *usercrt) { AMQPDestDriver *self = (AMQPDestDriver *) d; g_free(self->cert_file); self->cert_file = g_strdup(usercrt); } void afamqp_dd_set_peer_verify(LogDriver *d, gboolean verify) { AMQPDestDriver *self = (AMQPDestDriver *) d; self->peer_verify = verify; } /* * Utilities */ static gchar * afamqp_dd_format_stats_instance(LogThrDestDriver *s) { AMQPDestDriver *self = (AMQPDestDriver *) s; static gchar persist_name[1024]; if (s->super.super.super.persist_name) g_snprintf(persist_name, sizeof(persist_name), "amqp,%s", s->super.super.super.persist_name); else g_snprintf(persist_name, sizeof(persist_name), "amqp,%s,%s,%u,%s,%s", self->vhost, self->host, self->port, self->exchange, self->exchange_type); return persist_name; } static const gchar * afamqp_dd_format_persist_name(const LogPipe *s) { const AMQPDestDriver *self = (const AMQPDestDriver *)s; static gchar persist_name[1024]; if (s->persist_name) g_snprintf(persist_name, sizeof(persist_name), "afamqp.%s", s->persist_name); else g_snprintf(persist_name, sizeof(persist_name), "afamqp(%s,%s,%u,%s,%s)", self->vhost, self->host, self->port, self->exchange, self->exchange_type); return persist_name; } static inline void _amqp_connection_deinit(AMQPDestDriver *self) { amqp_destroy_connection(self->conn); self->conn = NULL; } static void _amqp_connection_disconnect(AMQPDestDriver *self) { amqp_channel_close(self->conn, 1, AMQP_REPLY_SUCCESS); amqp_connection_close(self->conn, AMQP_REPLY_SUCCESS); _amqp_connection_deinit(self); } static void afamqp_dd_disconnect(LogThrDestDriver *s) { AMQPDestDriver *self = (AMQPDestDriver *)s; if (self->conn != NULL) { _amqp_connection_disconnect(self); } } static gboolean afamqp_is_ok(AMQPDestDriver *self, gchar *context, amqp_rpc_reply_t ret) { switch (ret.reply_type) { case AMQP_RESPONSE_NORMAL: break; case AMQP_RESPONSE_NONE: msg_error(context, evt_tag_str("driver", self->super.super.super.id), evt_tag_str("error", "missing RPC reply type"), evt_tag_int("time_reopen", self->super.time_reopen)); return FALSE; case AMQP_RESPONSE_LIBRARY_EXCEPTION: { msg_error(context, evt_tag_str("driver", self->super.super.super.id), evt_tag_str("error", amqp_error_string2(ret.library_error)), evt_tag_int("time_reopen", self->super.time_reopen)); return FALSE; } case AMQP_RESPONSE_SERVER_EXCEPTION: switch (ret.reply.id) { case AMQP_CONNECTION_CLOSE_METHOD: { amqp_connection_close_t *m = (amqp_connection_close_t *) ret.reply.decoded; msg_error(context, evt_tag_str("driver", self->super.super.super.id), evt_tag_str("error", "server connection error"), evt_tag_int("code", m->reply_code), evt_tag_str("text", m->reply_text.bytes), evt_tag_int("time_reopen", self->super.time_reopen)); return FALSE; } case AMQP_CHANNEL_CLOSE_METHOD: { amqp_channel_close_t *m = (amqp_channel_close_t *) ret.reply.decoded; msg_error(context, evt_tag_str("driver", self->super.super.super.id), evt_tag_str("error", "server channel error"), evt_tag_int("code", m->reply_code), evt_tag_str("text", m->reply_text.bytes), evt_tag_int("time_reopen", self->super.time_reopen)); return FALSE; } default: msg_error(context, evt_tag_str("driver", self->super.super.super.id), evt_tag_str("error", "unknown server error"), evt_tag_printf("method_id", "0x%08X", ret.reply.id), evt_tag_int("time_reopen", self->super.time_reopen)); return FALSE; } return FALSE; } return TRUE; } static gboolean afamqp_dd_socket_init(AMQPDestDriver *self) { self->conn = amqp_new_connection(); if (self->conn == NULL) { msg_error("Error allocating AMQP connection."); return FALSE; } if (self->ca_file) { int ca_file_ret; self->sockfd = amqp_ssl_socket_new(self->conn); ca_file_ret = amqp_ssl_socket_set_cacert(self->sockfd, self->ca_file); if(ca_file_ret != AMQP_STATUS_OK) { msg_error("Error connecting to AMQP server while setting ca_file", evt_tag_str("driver", self->super.super.super.id), evt_tag_str("error", amqp_error_string2(ca_file_ret)), evt_tag_int("time_reopen", self->super.time_reopen)); return FALSE; } if (self->key_file && self->cert_file) { int setkey_ret = amqp_ssl_socket_set_key(self->sockfd, self->cert_file, self->key_file); if(setkey_ret != AMQP_STATUS_OK) { msg_error("Error connecting to AMQP server while setting key_file and cert_file", evt_tag_str("driver", self->super.super.super.id), evt_tag_str("error", amqp_error_string2(setkey_ret)), evt_tag_int("time_reopen", self->super.time_reopen)); return FALSE; } } amqp_ssl_socket_set_verify_peer(self->sockfd, self->peer_verify); amqp_ssl_socket_set_verify_hostname(self->sockfd, self->peer_verify); } else self->sockfd = amqp_tcp_socket_new(self->conn); return TRUE; } static gboolean afamqp_dd_connect(AMQPDestDriver *self, gboolean reconnect) { int sockfd_ret; amqp_rpc_reply_t ret; if (reconnect && self->conn) { ret = amqp_get_rpc_reply(self->conn); if (ret.reply_type == AMQP_RESPONSE_NORMAL) { return TRUE; } else { _amqp_connection_disconnect(self); } } if(!afamqp_dd_socket_init(self)) goto exception_amqp_dd_connect_failed_init; struct timeval delay; delay.tv_sec = 1; delay.tv_usec = 0; sockfd_ret = amqp_socket_open_noblock(self->sockfd, self->host, self->port, &delay); if (sockfd_ret != AMQP_STATUS_OK) { msg_error("Error connecting to AMQP server", evt_tag_str("driver", self->super.super.super.id), evt_tag_str("error", amqp_error_string2(sockfd_ret)), evt_tag_int("time_reopen", self->super.time_reopen)); goto exception_amqp_dd_connect_failed_init; } ret = amqp_login(self->conn, self->vhost, 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, self->user, self->password); if (!afamqp_is_ok(self, "Error during AMQP login", ret)) { goto exception_amqp_dd_connect_failed_init; } amqp_channel_open(self->conn, 1); ret = amqp_get_rpc_reply(self->conn); if (!afamqp_is_ok(self, "Error during AMQP channel open", ret)) { goto exception_amqp_dd_connect_failed_channel; } if (self->declare) { amqp_exchange_declare(self->conn, 1, amqp_cstring_bytes(self->exchange), amqp_cstring_bytes(self->exchange_type), 0, 0, 0, 0, amqp_empty_table); ret = amqp_get_rpc_reply(self->conn); if (!afamqp_is_ok(self, "Error during AMQP exchange declaration", ret)) { goto exception_amqp_dd_connect_failed_exchange; } } msg_debug ("Connecting to AMQP succeeded", evt_tag_str("driver", self->super.super.super.id)); return TRUE; /* Exceptions */ exception_amqp_dd_connect_failed_exchange: amqp_channel_close(self->conn, 1, AMQP_REPLY_SUCCESS); exception_amqp_dd_connect_failed_channel: amqp_connection_close(self->conn, AMQP_REPLY_SUCCESS); exception_amqp_dd_connect_failed_init: _amqp_connection_deinit(self); return FALSE; } /* * Worker thread */ /* TODO escape '\0' when passing down the value */ static gboolean afamqp_vp_foreach(const gchar *name, TypeHint type, const gchar *value, gsize value_len, gpointer user_data) { amqp_table_entry_t **entries = (amqp_table_entry_t **) ((gpointer *)user_data)[0]; gint *pos = (gint *) ((gpointer *)user_data)[1]; gint32 *max_size = (gint32 *) ((gpointer *)user_data)[2]; if (*pos == *max_size) { *max_size *= 2; *entries = g_renew(amqp_table_entry_t, *entries, *max_size); } (*entries)[*pos].key = amqp_cstring_bytes(strdup(name)); (*entries)[*pos].value.kind = AMQP_FIELD_KIND_UTF8; (*entries)[*pos].value.value.bytes = amqp_cstring_bytes(strdup(value)); (*pos)++; return FALSE; } static gboolean afamqp_worker_publish(AMQPDestDriver *self, LogMessage *msg) { gint pos = 0, ret; amqp_table_t table; amqp_basic_properties_t props; gboolean success = TRUE; GString *routing_key = scratch_buffers_alloc(); GString *body = scratch_buffers_alloc(); amqp_bytes_t body_bytes = amqp_cstring_bytes(""); gpointer user_data[] = { &self->entries, &pos, &self->max_entries }; value_pairs_foreach(self->vp, afamqp_vp_foreach, msg, self->super.seq_num, LTZ_SEND, &self->template_options, user_data); table.num_entries = pos; table.entries = self->entries; props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG | AMQP_BASIC_HEADERS_FLAG; props.content_type = amqp_cstring_bytes("text/plain"); props.delivery_mode = self->persistent; props.headers = table; log_template_format(self->routing_key_template, msg, NULL, LTZ_LOCAL, self->super.seq_num, NULL, routing_key); if (self->body_template) { log_template_format(self->body_template, msg, NULL, LTZ_LOCAL, self->super.seq_num, NULL, body); body_bytes = amqp_cstring_bytes(body->str); } ret = amqp_basic_publish(self->conn, 1, amqp_cstring_bytes(self->exchange), amqp_cstring_bytes(routing_key->str), 0, 0, &props, body_bytes); if (ret < 0) { msg_error("Network error while inserting into AMQP server", evt_tag_str("driver", self->super.super.super.id), evt_tag_str("error", amqp_error_string2(-ret)), evt_tag_int("time_reopen", self->super.time_reopen)); success = FALSE; } while (--pos >= 0) { amqp_bytes_free(self->entries[pos].key); amqp_bytes_free(self->entries[pos].value.value.bytes); } return success; } static worker_insert_result_t afamqp_worker_insert(LogThrDestDriver *s, LogMessage *msg) { AMQPDestDriver *self = (AMQPDestDriver *)s; if (!afamqp_dd_connect(self, TRUE)) return WORKER_INSERT_RESULT_NOT_CONNECTED; if (!afamqp_worker_publish (self, msg)) return WORKER_INSERT_RESULT_ERROR; return WORKER_INSERT_RESULT_SUCCESS; } static void afamqp_worker_thread_init(LogThrDestDriver *d) { AMQPDestDriver *self = (AMQPDestDriver *)d; afamqp_dd_connect(self, FALSE); } /* * Main thread */ static gboolean afamqp_dd_init(LogPipe *s) { AMQPDestDriver *self = (AMQPDestDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_dest_driver_init_method(s)) return FALSE; if (!self->user || !self->password) { msg_error("Error initializing AMQP destination: username and password MUST be set!", evt_tag_str("driver", self->super.super.super.id)); return FALSE; } log_template_options_init(&self->template_options, cfg); msg_verbose("Initializing AMQP destination", evt_tag_str("vhost", self->vhost), evt_tag_str("host", self->host), evt_tag_int("port", self->port), evt_tag_str("exchange", self->exchange), evt_tag_str("exchange_type", self->exchange_type)); return log_threaded_dest_driver_start(s); } static void afamqp_dd_free(LogPipe *d) { AMQPDestDriver *self = (AMQPDestDriver *) d; log_template_options_destroy(&self->template_options); g_free(self->exchange); g_free(self->exchange_type); log_template_unref(self->routing_key_template); log_template_unref(self->body_template); g_free(self->user); g_free(self->password); g_free(self->host); g_free(self->vhost); g_free(self->entries); value_pairs_unref(self->vp); g_free(self->ca_file); g_free(self->key_file); g_free(self->cert_file); log_threaded_dest_driver_free(d); } static gboolean afamqp_dd_worker_connect(LogThrDestDriver *s) { AMQPDestDriver *self = (AMQPDestDriver *)s; return afamqp_dd_connect(self, FALSE); } /* * Plugin glue. */ LogDriver * afamqp_dd_new(GlobalConfig *cfg) { AMQPDestDriver *self = g_new0(AMQPDestDriver, 1); log_threaded_dest_driver_init_instance(&self->super, cfg); self->super.super.super.super.init = afamqp_dd_init; self->super.super.super.super.free_fn = afamqp_dd_free; self->super.super.super.super.generate_persist_name = afamqp_dd_format_persist_name; self->super.worker.thread_init = afamqp_worker_thread_init; self->super.worker.connect = afamqp_dd_worker_connect; self->super.worker.disconnect = afamqp_dd_disconnect; self->super.worker.insert = afamqp_worker_insert; self->super.format.stats_instance = afamqp_dd_format_stats_instance; self->super.stats_source = SCS_AMQP; self->routing_key_template = log_template_new(cfg, NULL); afamqp_dd_set_vhost((LogDriver *) self, "/"); afamqp_dd_set_host((LogDriver *) self, "127.0.0.1"); afamqp_dd_set_port((LogDriver *) self, 5672); afamqp_dd_set_exchange((LogDriver *) self, "syslog"); afamqp_dd_set_exchange_type((LogDriver *) self, "fanout"); afamqp_dd_set_routing_key((LogDriver *) self, ""); afamqp_dd_set_persistent((LogDriver *) self, TRUE); afamqp_dd_set_exchange_declare((LogDriver *) self, FALSE); self->max_entries = 256; self->entries = g_new(amqp_table_entry_t, self->max_entries); log_template_options_defaults(&self->template_options); afamqp_dd_set_value_pairs(&self->super.super.super, value_pairs_new_default(cfg)); afamqp_dd_set_peer_verify((LogDriver *) self, TRUE); return (LogDriver *) self; } extern CfgParser afamqp_dd_parser; static Plugin afamqp_plugin = { .type = LL_CONTEXT_DESTINATION, .name = "amqp", .parser = &afamqp_parser }; gboolean afamqp_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, &afamqp_plugin, 1); return TRUE; } const ModuleInfo module_info = { .canonical_name = "afamqp", .version = SYSLOG_NG_VERSION, .description = "The afamqp module provides AMQP destination support for syslog-ng.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = &afamqp_plugin, .plugins_len = 1, }; syslog-ng-syslog-ng-3.13.2/modules/afamqp/afamqp.h000066400000000000000000000043211321171025300217700ustar00rootroot00000000000000/* * Copyright (c) 2012 Nagy, Attila * Copyright (c) 2012 Balabit * Copyright (c) 2012 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFAMQP_H_INCLUDED #define AFAMQP_H_INCLUDED #include "driver.h" #include "value-pairs/value-pairs.h" LogDriver *afamqp_dd_new(GlobalConfig *cfg); void afamqp_dd_set_host(LogDriver *d, const gchar *host); void afamqp_dd_set_port(LogDriver *d, gint port); void afamqp_dd_set_exchange(LogDriver *d, const gchar *database); void afamqp_dd_set_exchange_declare(LogDriver *d, gboolean declare); void afamqp_dd_set_exchange_type(LogDriver *d, const gchar *exchange_type); void afamqp_dd_set_vhost(LogDriver *d, const gchar *vhost); void afamqp_dd_set_routing_key(LogDriver *d, const gchar *routing_key); void afamqp_dd_set_body(LogDriver *d, const gchar *body); void afamqp_dd_set_persistent(LogDriver *d, gboolean persistent); void afamqp_dd_set_user(LogDriver *d, const gchar *user); void afamqp_dd_set_password(LogDriver *d, const gchar *password); void afamqp_dd_set_value_pairs(LogDriver *d, ValuePairs *vp); void afamqp_dd_set_ca_file(LogDriver *d, const gchar *cacrt); void afamqp_dd_set_key_file(LogDriver *d, const gchar *key); void afamqp_dd_set_cert_file(LogDriver *d, const gchar *usercrt); void afamqp_dd_set_peer_verify(LogDriver *d, gboolean verify); LogTemplateOptions *afamqp_dd_get_template_options(LogDriver *s); #endif syslog-ng-syslog-ng-3.13.2/modules/afamqp/rabbitmq-c/000077500000000000000000000000001321171025300223735ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/affile/000077500000000000000000000000001321171025300203335ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/affile/CMakeLists.txt000066400000000000000000000030551321171025300230760ustar00rootroot00000000000000set(AFFILE_HEADERS "logproto-file-writer.h" "logproto-file-reader.h" "poll-file-changes.h" "transport-prockmsg.h" "file-reader.h" "file-opener.h" "file-specializations.h" "stdin.h" "named-pipe.h" "affile-source.h" "affile-dest.h" "affile-parser.h" "wildcard-source.h" "directory-monitor.h" "directory-monitor-inotify.h" "directory-monitor-poll.h" "directory-monitor-factory.h" "collection-comporator.h" "${CMAKE_CURRENT_BINARY_DIR}/affile-grammar.h" ) set(AFFILE_SOURCES "logproto-file-writer.c" "logproto-file-reader.c" "poll-file-changes.c" "transport-prockmsg.c" "file-reader.c" "file-opener.c" "regular-files.c" "named-pipe.c" "linux-kmsg.c" "stdin.c" "affile-source.c" "affile-dest.c" "affile-parser.c" "affile-plugin.c" "wildcard-source.c" "directory-monitor.c" "directory-monitor-inotify.c" "directory-monitor-poll.c" "directory-monitor-factory.c" "collection-comporator.c" "${CMAKE_CURRENT_BINARY_DIR}/affile-grammar.c" ) generate_y_from_ym(modules/affile/affile-grammar) bison_target(AffileGrammar ${CMAKE_CURRENT_BINARY_DIR}/affile-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/affile-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) include_directories (${CMAKE_CURRENT_BINARY_DIR}) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) add_library(affile MODULE ${AFFILE_SOURCES}) target_link_libraries(affile PRIVATE syslog-ng) install(TARGETS affile LIBRARY DESTINATION lib/syslog-ng/ COMPONENT affile) syslog-ng-syslog-ng-3.13.2/modules/affile/Makefile.am000066400000000000000000000050231321171025300223670ustar00rootroot00000000000000module_LTLIBRARIES += modules/affile/libaffile.la modules_affile_libaffile_la_SOURCES = \ modules/affile/logproto-file-writer.c \ modules/affile/logproto-file-writer.h \ modules/affile/logproto-file-reader.c \ modules/affile/logproto-file-reader.h \ modules/affile/poll-file-changes.c \ modules/affile/poll-file-changes.h \ modules/affile/transport-prockmsg.c \ modules/affile/transport-prockmsg.h \ modules/affile/file-reader.c \ modules/affile/file-reader.h \ modules/affile/wildcard-source.h \ modules/affile/wildcard-source.c \ modules/affile/directory-monitor.h \ modules/affile/directory-monitor.c \ modules/affile/directory-monitor-factory.h \ modules/affile/directory-monitor-factory.c \ modules/affile/collection-comporator.h \ modules/affile/collection-comporator.c \ modules/affile/directory-monitor-poll.h \ modules/affile/directory-monitor-poll.c \ modules/affile/file-opener.c \ modules/affile/file-opener.h \ modules/affile/file-specializations.h \ modules/affile/regular-files.c \ modules/affile/named-pipe.c \ modules/affile/named-pipe.h \ modules/affile/linux-kmsg.c \ modules/affile/stdin.c \ modules/affile/stdin.h \ modules/affile/affile-source.c \ modules/affile/affile-source.h \ modules/affile/affile-dest.c \ modules/affile/affile-dest.h \ modules/affile/affile-grammar.y \ modules/affile/affile-parser.c \ modules/affile/affile-parser.h \ modules/affile/affile-plugin.c \ modules/affile/affile-dest-internal-queue-filter.h if HAVE_INOTIFY modules_affile_libaffile_la_SOURCES += \ modules/affile/directory-monitor-inotify.h \ modules/affile/directory-monitor-inotify.c else EXTRA_DIST += \ modules/affile/directory-monitor-inotify.h \ modules/affile/directory-monitor-inotify.c endif BUILT_SOURCES += \ modules/affile/affile-grammar.y \ modules/affile/affile-grammar.c \ modules/affile/affile-grammar.h EXTRA_DIST += \ modules/affile/affile-grammar.ym modules_affile_libaffile_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/affile \ -I$(top_builddir)/modules/affile modules_affile_libaffile_la_LIBADD = $(MODULE_DEPS_LIBS) $(IVYKIS_LIBS) modules_affile_libaffile_la_LDFLAGS = $(MODULE_LDFLAGS) modules_affile_libaffile_la_DEPENDENCIES= $(MODULE_DEPS_LIBS) modules/affile modules/affile/ mod-affile mod-file: modules/affile/libaffile.la .PHONY: modules/affile/ mod-affile mod-file include modules/affile/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/modules/affile/affile-dest-internal-queue-filter.h000066400000000000000000000021661321171025300271130ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFFILE_DEST_INTERNAL_QUEUE_FILTER_H_INCLUDED #define AFFILE_DEST_INTERNAL_QUEUE_FILTER_H_INCLUDED #include "syslog-ng.h" static inline gboolean affile_dw_queue_enabled_for_msg(LogMessage *msg) { return TRUE; } #endif syslog-ng-syslog-ng-3.13.2/modules/affile/affile-dest.c000066400000000000000000000572511321171025300226740ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "file-opener.h" #include "affile-dest.h" #include "driver.h" #include "messages.h" #include "serialize.h" #include "gprocess.h" #include "stats/stats-registry.h" #include "mainloop-call.h" #include "transport/transport-file.h" #include "logproto-file-writer.h" #include "transport/transport-file.h" #include "transport/transport-pipe.h" #include "logwriter.h" #include "affile-dest-internal-queue-filter.h" #include "file-specializations.h" #include "apphook.h" #include #include #include #include #include #include #include #include #include /* * Threading notes: * * Apart from standard initialization/deinitialization (normally performed * by the main thread when syslog-ng starts up) the following processes are * performed in various threads. * * - queue runs in the thread of the source thread that generated the message * - if the message is to be written to a not-yet-opened file, a new gets * opened and stored in the writer_hash hashtable (initiated from queue, * but performed in the main thread, but more on that later) * - currently opened destination files are checked regularly and closed * if they are idle for a given amount of time (time_reap) (this is done * in the main thread) * * Some of these operations have to be performed in the main thread, others * are done in the queue call. * * References * ========== * * The AFFileDestDriver instance is registered into the current * configuration, thus its presence is always given, it cannot go away while * syslog-ng is running. * * AFFileDestWriter instances are created dynamically when a new file is * opened. A reference is stored in the writer_hash hashtable. This is then: * - looked up in _queue() (in the source thread) * - cleaned up in reap callback (in the main thread) * * writer_hash is locked (currently a simple mutex) using * AFFileDestDriver->lock. The "queue" method cannot hold the lock while * forwarding it to the next pipe, thus a reference is taken under the * protection of the lock, keeping a the next pipe alive, even if that would * go away in a parallel reaper process. */ static GList *affile_dest_drivers = NULL; struct _AFFileDestWriter { LogPipe super; GStaticMutex lock; AFFileDestDriver *owner; gchar *filename; LogWriter *writer; time_t last_msg_stamp; time_t last_open_stamp; time_t time_reopen; struct iv_timer reap_timer; gboolean reopen_pending, queue_pending; }; static gchar * affile_dw_format_persist_name(AFFileDestWriter *self) { static gchar persist_name[1024]; g_snprintf(persist_name, sizeof(persist_name), "affile_dw_queue(%s)", self->filename); return persist_name; } static void affile_dd_reap_writer(AFFileDestDriver *self, AFFileDestWriter *dw); static void affile_dw_arm_reaper(AFFileDestWriter *self) { /* not yet reaped, set up the next callback */ iv_validate_now(); self->reap_timer.expires = iv_now; timespec_add_msec(&self->reap_timer.expires, self->owner->time_reap * 1000 / 2); iv_timer_register(&self->reap_timer); } static void affile_dw_reap(gpointer s) { AFFileDestWriter *self = (AFFileDestWriter *) s; main_loop_assert_main_thread(); g_static_mutex_lock(&self->lock); if (!log_writer_has_pending_writes(self->writer) && !self->queue_pending && (cached_g_current_time_sec() - self->last_msg_stamp) >= self->owner->time_reap) { g_static_mutex_unlock(&self->lock); msg_verbose("Destination timed out, reaping", evt_tag_str("template", self->owner->filename_template->template), evt_tag_str("filename", self->filename)); affile_dd_reap_writer(self->owner, self); } else { g_static_mutex_unlock(&self->lock); affile_dw_arm_reaper(self); } } static gboolean affile_dw_reopen(AFFileDestWriter *self) { int fd; struct stat st; GlobalConfig *cfg; LogProtoClient *proto = NULL; cfg = log_pipe_get_config(&self->super); if (cfg) self->time_reopen = cfg->time_reopen; msg_verbose("Initializing destination file writer", evt_tag_str("template", self->owner->filename_template->template), evt_tag_str("filename", self->filename)); self->last_open_stamp = self->last_msg_stamp; if (self->owner->overwrite_if_older > 0 && stat(self->filename, &st) == 0 && st.st_mtime < time(NULL) - self->owner->overwrite_if_older) { msg_info("Destination file is older than overwrite_if_older(), overwriting", evt_tag_str("filename", self->filename), evt_tag_int("overwrite_if_older", self->owner->overwrite_if_older)); unlink(self->filename); } if (file_opener_open_fd(self->owner->file_opener, self->filename, AFFILE_DIR_WRITE, &fd)) { LogTransport *transport = file_opener_construct_transport(self->owner->file_opener, fd); proto = file_opener_construct_dst_proto(self->owner->file_opener, transport, &self->owner->writer_options.proto_options.super); if (!iv_timer_registered(&self->reap_timer)) main_loop_call((void *(*)(void *)) affile_dw_arm_reaper, self, TRUE); } else { msg_error("Error opening file for writing", evt_tag_str("filename", self->filename), evt_tag_errno(EVT_TAG_OSERROR, errno)); } log_writer_reopen(self->writer, proto); return TRUE; } static gboolean affile_dw_init(LogPipe *s) { AFFileDestWriter *self = (AFFileDestWriter *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!self->writer) { self->writer = log_writer_new(self->owner->writer_flags, cfg); } log_writer_set_options(self->writer, s, &self->owner->writer_options, self->owner->super.super.id, self->filename); log_writer_set_queue(self->writer, log_dest_driver_acquire_queue(&self->owner->super, affile_dw_format_persist_name(self))); if (!log_pipe_init((LogPipe *) self->writer)) { msg_error("Error initializing log writer"); log_pipe_unref((LogPipe *) self->writer); self->writer = NULL; return FALSE; } log_pipe_append(&self->super, (LogPipe *) self->writer); return affile_dw_reopen(self); } static gboolean affile_dw_deinit(LogPipe *s) { AFFileDestWriter *self = (AFFileDestWriter *) s; main_loop_assert_main_thread(); if (self->writer) { log_pipe_deinit((LogPipe *) self->writer); } log_writer_set_queue(self->writer, NULL); if (iv_timer_registered(&self->reap_timer)) iv_timer_unregister(&self->reap_timer); return TRUE; } /* * NOTE: the caller (e.g. AFFileDestDriver) holds a reference to @self, thus * @self may _never_ be freed, even if the reaper timer is elapsed in the * main thread. */ static void affile_dw_queue(LogPipe *s, LogMessage *lm, const LogPathOptions *path_options, gpointer user_data) { if (!affile_dw_queue_enabled_for_msg(lm)) { log_msg_drop(lm, path_options, AT_PROCESSED); return; } AFFileDestWriter *self = (AFFileDestWriter *) s; g_static_mutex_lock(&self->lock); self->last_msg_stamp = cached_g_current_time_sec(); if (self->last_open_stamp == 0) self->last_open_stamp = self->last_msg_stamp; if (!log_writer_opened(self->writer) && !self->reopen_pending && (self->last_open_stamp < self->last_msg_stamp - self->time_reopen)) { self->reopen_pending = TRUE; /* if the file couldn't be opened, try it again every time_reopen seconds */ g_static_mutex_unlock(&self->lock); affile_dw_reopen(self); g_static_mutex_lock(&self->lock); self->reopen_pending = FALSE; } g_static_mutex_unlock(&self->lock); log_pipe_forward_msg(&self->super, lm, path_options); } static void affile_dw_set_owner(AFFileDestWriter *self, AFFileDestDriver *owner) { GlobalConfig *cfg = log_pipe_get_config(&owner->super.super.super); if (self->owner) log_pipe_unref(&self->owner->super.super.super); log_pipe_ref(&owner->super.super.super); self->owner = owner; self->super.expr_node = owner->super.super.super.expr_node; log_pipe_set_config(&self->super, cfg); if (self->writer) { log_pipe_set_config((LogPipe *) self->writer, cfg); log_writer_set_options(self->writer, &self->super, &owner->writer_options, self->owner->super.super.id, self->filename); } } static void affile_dw_free(LogPipe *s) { AFFileDestWriter *self = (AFFileDestWriter *) s; log_pipe_unref((LogPipe *) self->writer); g_static_mutex_free(&self->lock); self->writer = NULL; g_free(self->filename); log_pipe_unref(&self->owner->super.super.super); log_pipe_free_method(s); } static void affile_dw_notify(LogPipe *s, gint notify_code, gpointer user_data) { switch(notify_code) { case NC_REOPEN_REQUIRED: affile_dw_reopen((AFFileDestWriter *)s); break; default: break; } } static AFFileDestWriter * affile_dw_new(const gchar *filename, GlobalConfig *cfg) { AFFileDestWriter *self = g_new0(AFFileDestWriter, 1); log_pipe_init_instance(&self->super, cfg); self->super.init = affile_dw_init; self->super.deinit = affile_dw_deinit; self->super.free_fn = affile_dw_free; self->super.queue = affile_dw_queue; self->super.notify = affile_dw_notify; self->time_reopen = 60; IV_TIMER_INIT(&self->reap_timer); self->reap_timer.cookie = self; self->reap_timer.handler = affile_dw_reap; /* we have to take care about freeing filename later. This avoids a move of the filename. */ self->filename = g_strdup(filename); g_static_mutex_init(&self->lock); return self; } static void affile_dw_reopen_writer(gpointer key, gpointer value, gpointer user_data) { AFFileDestWriter *writer = (AFFileDestWriter *) value; affile_dw_reopen(writer); } static void affile_dd_reopen_all_writers(gpointer data, gpointer user_data) { AFFileDestDriver *driver = (AFFileDestDriver *) data; if (driver->single_writer) affile_dw_reopen(driver->single_writer); else if (driver->writer_hash) g_hash_table_foreach(driver->writer_hash, affile_dw_reopen_writer, NULL); } static void affile_dd_register_reopen_hook(gint hook_type, gpointer user_data) { g_list_foreach(affile_dest_drivers, affile_dd_reopen_all_writers, NULL); } void affile_dd_set_create_dirs(LogDriver *s, gboolean create_dirs) { AFFileDestDriver *self = (AFFileDestDriver *) s; self->file_opener_options.create_dirs = create_dirs; } void affile_dd_set_overwrite_if_older(LogDriver *s, gint overwrite_if_older) { AFFileDestDriver *self = (AFFileDestDriver *) s; self->overwrite_if_older = overwrite_if_older; } void affile_dd_set_fsync(LogDriver *s, gboolean use_fsync) { AFFileDestDriver *self = (AFFileDestDriver *) s; self->use_fsync = use_fsync; } static inline const gchar * affile_dd_format_persist_name(const LogPipe *s) { const AFFileDestDriver *self = (const AFFileDestDriver *)s; static gchar persist_name[1024]; if (s->persist_name) g_snprintf(persist_name, sizeof(persist_name), "affile_dd.%s.writers", s->persist_name); else g_snprintf(persist_name, sizeof(persist_name), "affile_dd_writers(%s)", self->filename_template->template); return persist_name; } static void affile_dd_reap_writer(AFFileDestDriver *self, AFFileDestWriter *dw) { LogWriter *writer = (LogWriter *)dw->writer; main_loop_assert_main_thread(); if (self->filename_is_a_template) { g_static_mutex_lock(&self->lock); /* remove from hash table */ g_hash_table_remove(self->writer_hash, dw->filename); g_static_mutex_unlock(&self->lock); } else { g_static_mutex_lock(&self->lock); g_assert(dw == self->single_writer); self->single_writer = NULL; g_static_mutex_unlock(&self->lock); } LogQueue *queue = log_writer_get_queue(writer); log_pipe_deinit(&dw->super); log_dest_driver_release_queue(&self->super, queue); log_pipe_unref(&dw->super); } /** * affile_dd_reuse_writer: * * This function is called as a g_hash_table_foreach() callback to set the * owner of each writer, previously connected to an AFileDestDriver instance * in an earlier configuration. This way AFFileDestWriter instances are * remembered accross reloads. * **/ static void affile_dd_reuse_writer(gpointer key, gpointer value, gpointer user_data) { AFFileDestDriver *self = (AFFileDestDriver *) user_data; AFFileDestWriter *writer = (AFFileDestWriter *) value; affile_dw_set_owner(writer, self); if (!log_pipe_init(&writer->super)) { affile_dw_set_owner(writer, NULL); log_pipe_unref(&writer->super); g_hash_table_remove(self->writer_hash, key); } } static gboolean affile_dd_init(LogPipe *s) { AFFileDestDriver *self = (AFFileDestDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_dest_driver_init_method(s)) return FALSE; if (self->file_opener_options.create_dirs == -1) self->file_opener_options.create_dirs = cfg->create_dirs; if (self->time_reap == -1) self->time_reap = cfg->time_reap; file_opener_options_init(&self->file_opener_options, cfg); file_opener_set_options(self->file_opener, &self->file_opener_options); log_writer_options_init(&self->writer_options, cfg, 0); if (self->filename_is_a_template) { self->writer_hash = cfg_persist_config_fetch(cfg, affile_dd_format_persist_name(s)); if (self->writer_hash) g_hash_table_foreach(self->writer_hash, affile_dd_reuse_writer, self); } else { self->single_writer = cfg_persist_config_fetch(cfg, affile_dd_format_persist_name(s)); if (self->single_writer) { affile_dw_set_owner(self->single_writer, self); if (!log_pipe_init(&self->single_writer->super)) { log_pipe_unref(&self->single_writer->super); return FALSE; } } } return TRUE; } /** * This is registered as a destroy-notify callback for an AFFileDestWriter * instance. It destructs and frees the writer instance. **/ static void affile_dd_destroy_writer(gpointer value) { AFFileDestWriter *writer = (AFFileDestWriter *) value; main_loop_assert_main_thread(); log_pipe_deinit(&writer->super); log_pipe_unref(&writer->super); } /* * This function is called as a g_hash_table_foreach_remove() callback to * free the specific AFFileDestWriter instance in the hashtable. */ static gboolean affile_dd_destroy_writer_hr(gpointer key, gpointer value, gpointer user_data) { affile_dd_destroy_writer(value); return TRUE; } /** * affile_dd_destroy_writer_hash: * @value: GHashTable instance passed as a generic pointer * * Destroy notify callback for the GHashTable storing AFFileDestWriter instances. **/ static void affile_dd_destroy_writer_hash(gpointer value) { GHashTable *writer_hash = (GHashTable *) value; g_hash_table_foreach_remove(writer_hash, affile_dd_destroy_writer_hr, NULL); g_hash_table_destroy(writer_hash); } static void affile_dd_deinit_writer(gpointer key, gpointer value, gpointer user_data) { log_pipe_deinit((LogPipe *) value); } static gboolean affile_dd_deinit(LogPipe *s) { AFFileDestDriver *self = (AFFileDestDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); /* NOTE: we free all AFFileDestWriter instances here as otherwise we'd * have circular references between AFFileDestDriver and file writers */ if (self->single_writer) { g_assert(self->writer_hash == NULL); log_pipe_deinit(&self->single_writer->super); cfg_persist_config_add(cfg, affile_dd_format_persist_name(s), self->single_writer, affile_dd_destroy_writer, FALSE); self->single_writer = NULL; } else if (self->writer_hash) { g_assert(self->single_writer == NULL); g_hash_table_foreach(self->writer_hash, affile_dd_deinit_writer, NULL); cfg_persist_config_add(cfg, affile_dd_format_persist_name(s), self->writer_hash, affile_dd_destroy_writer_hash, FALSE); self->writer_hash = NULL; } if (!log_dest_driver_deinit_method(s)) return FALSE; return TRUE; } /* * This function is ran in the main thread whenever a writer is not yet * instantiated. Returns a reference to the newly constructed LogPipe * instance where the caller needs to forward its message. */ static LogPipe * affile_dd_open_writer(gpointer args[]) { AFFileDestDriver *self = args[0]; AFFileDestWriter *next; main_loop_assert_main_thread(); if (!self->filename_is_a_template) { if (!self->single_writer) { next = affile_dw_new(self->filename_template->template, log_pipe_get_config(&self->super.super.super)); affile_dw_set_owner(next, self); if (next && log_pipe_init(&next->super)) { log_pipe_ref(&next->super); g_static_mutex_lock(&self->lock); self->single_writer = next; g_static_mutex_unlock(&self->lock); } else { log_pipe_unref(&next->super); next = NULL; } } else { next = self->single_writer; log_pipe_ref(&next->super); } } else { GString *filename = args[1]; /* hash table construction is serialized, as we only do that in the main thread. */ if (!self->writer_hash) self->writer_hash = g_hash_table_new(g_str_hash, g_str_equal); /* we don't need to lock the hashtable as it is only written in * the main thread, which we're running right now. lookups in * other threads must be locked. writers must be locked even in * this thread to exclude lookups in other threads. */ next = g_hash_table_lookup(self->writer_hash, filename->str); if (!next) { next = affile_dw_new(filename->str, log_pipe_get_config(&self->super.super.super)); affile_dw_set_owner(next, self); if (!log_pipe_init(&next->super)) { log_pipe_unref(&next->super); next = NULL; } else { log_pipe_ref(&next->super); g_static_mutex_lock(&self->lock); g_hash_table_insert(self->writer_hash, next->filename, next); g_static_mutex_unlock(&self->lock); } } else { log_pipe_ref(&next->super); } } if (next) { next->queue_pending = TRUE; /* we're returning a reference */ return &next->super; } return NULL; } static void affile_dd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { AFFileDestDriver *self = (AFFileDestDriver *) s; AFFileDestWriter *next; gpointer args[2] = { self, NULL }; if (!self->filename_is_a_template) { /* no need to lock the check below, the worst case that happens is * that we go to the mainloop to return the same information, but this * is not fast path anyway */ g_static_mutex_lock(&self->lock); if (!self->single_writer) { g_static_mutex_unlock(&self->lock); next = main_loop_call((void *(*)(void *)) affile_dd_open_writer, args, TRUE); } else { /* we need to lock single_writer in order to get a reference and * make sure it is not a stale pointer by the time we ref it */ next = self->single_writer; next->queue_pending = TRUE; log_pipe_ref(&next->super); g_static_mutex_unlock(&self->lock); } } else { GString *filename; filename = g_string_sized_new(32); log_template_format(self->filename_template, msg, &self->writer_options.template_options, LTZ_LOCAL, 0, NULL, filename); g_static_mutex_lock(&self->lock); if (self->writer_hash) next = g_hash_table_lookup(self->writer_hash, filename->str); else next = NULL; if (next) { log_pipe_ref(&next->super); next->queue_pending = TRUE; g_static_mutex_unlock(&self->lock); } else { g_static_mutex_unlock(&self->lock); args[1] = filename; next = main_loop_call((void *(*)(void *)) affile_dd_open_writer, args, TRUE); } g_string_free(filename, TRUE); } if (next) { log_msg_add_ack(msg, path_options); log_pipe_queue(&next->super, log_msg_ref(msg), path_options); next->queue_pending = FALSE; log_pipe_unref(&next->super); } log_dest_driver_queue_method(s, msg, path_options, user_data); } static void affile_dd_free(LogPipe *s) { AFFileDestDriver *self = (AFFileDestDriver *) s; g_static_mutex_free(&self->lock); affile_dest_drivers = g_list_remove(affile_dest_drivers, self); /* NOTE: this must be NULL as deinit has freed it, otherwise we'd have circular references */ g_assert(self->single_writer == NULL && self->writer_hash == NULL); log_template_unref(self->filename_template); log_writer_options_destroy(&self->writer_options); file_opener_options_deinit(&self->file_opener_options); file_opener_free(self->file_opener); log_dest_driver_free(s); } AFFileDestDriver * affile_dd_new_instance(gchar *filename, GlobalConfig *cfg) { AFFileDestDriver *self = g_new0(AFFileDestDriver, 1); log_dest_driver_init_instance(&self->super, cfg); self->super.super.super.init = affile_dd_init; self->super.super.super.deinit = affile_dd_deinit; self->super.super.super.queue = affile_dd_queue; self->super.super.super.free_fn = affile_dd_free; self->super.super.super.generate_persist_name = affile_dd_format_persist_name; self->filename_template = log_template_new(cfg, NULL); log_template_compile(self->filename_template, filename, NULL); log_writer_options_defaults(&self->writer_options); self->writer_options.mark_mode = MM_NONE; self->writer_options.stats_level = STATS_LEVEL1; self->writer_flags = LW_FORMAT_FILE; if (strchr(filename, '$') != NULL) { self->filename_is_a_template = TRUE; } file_opener_options_defaults(&self->file_opener_options); self->time_reap = -1; g_static_mutex_init(&self->lock); affile_dest_drivers = g_list_append(affile_dest_drivers, self); return self; } LogDriver * affile_dd_new(gchar *filename, GlobalConfig *cfg) { AFFileDestDriver *self = affile_dd_new_instance(filename, cfg); self->writer_flags |= LW_SOFT_FLOW_CONTROL; self->writer_options.stats_source = SCS_FILE; self->file_opener = file_opener_for_regular_dest_files_new(&self->writer_options, &self->use_fsync); return &self->super.super; } void affile_dd_global_init(void) { register_application_hook(AH_REOPEN, affile_dd_register_reopen_hook, NULL); } syslog-ng-syslog-ng-3.13.2/modules/affile/affile-dest.h000066400000000000000000000041231321171025300226670ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFFILE_DEST_H_INCLUDED #define AFFILE_DEST_H_INCLUDED #include "driver.h" #include "logwriter.h" #include "file-opener.h" typedef struct _AFFileDestWriter AFFileDestWriter; typedef struct _AFFileDestDriver { LogDestDriver super; GStaticMutex lock; LogTemplate *filename_template; AFFileDestWriter *single_writer; gboolean filename_is_a_template; gboolean template_escape; gboolean use_fsync; FileOpenerOptions file_opener_options; FileOpener *file_opener; TimeZoneInfo *local_time_zone_info; LogWriterOptions writer_options; guint32 writer_flags; GHashTable *writer_hash; gint overwrite_if_older; gboolean use_time_recvd; gint time_reap; } AFFileDestDriver; AFFileDestDriver *affile_dd_new_instance(gchar *filename, GlobalConfig *cfg); LogDriver *affile_dd_new(gchar *filename, GlobalConfig *cfg); void affile_dd_set_create_dirs(LogDriver *s, gboolean create_dirs); void affile_dd_set_fsync(LogDriver *s, gboolean enable); void affile_dd_set_overwrite_if_older(LogDriver *s, gint overwrite_if_older); void affile_dd_set_local_time_zone(LogDriver *s, const gchar *local_time_zone); void affile_dd_global_init(void); #endif syslog-ng-syslog-ng-3.13.2/modules/affile/affile-grammar.ym000066400000000000000000000212341321171025300235560ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code top { #include "affile-parser.h" } %code { #include "file-opener.h" #include "affile-source.h" #include "wildcard-source.h" #include "affile-dest.h" #include "cfg-parser.h" #include "affile-grammar.h" #include "syslog-names.h" #include "messages.h" #include "plugin.h" #include "cfg-grammar.h" #include "stdin.h" #include "named-pipe.h" #include FileReaderOptions *last_file_reader_options; LogProtoFileReaderOptions *last_log_proto_options; } %name-prefix "affile_" /* this parameter is needed in order to instruct bison to use a complete * argument list for yylex/yyerror */ %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogDriver **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_PIPE %token KW_FSYNC %token KW_FOLLOW_FREQ %token KW_OVERWRITE_IF_OLDER %token KW_MULTI_LINE_MODE %token KW_MULTI_LINE_PREFIX %token KW_MULTI_LINE_GARBAGE %token KW_WILDCARD_FILE %token KW_BASE_DIR %token KW_FILENAME_PATTERN %token KW_RECURSIVE %token KW_MAX_FILES %token KW_MONITOR_METHOD %token KW_STDIN %type source_affile %type source_affile_params %type source_afpipe_params %type source_wildcard_params %type source_stdin_params %type dest_affile %type dest_affile_params %type dest_afpipe_params %% start : LL_CONTEXT_SOURCE source_affile { YYACCEPT; } | LL_CONTEXT_DESTINATION dest_affile { YYACCEPT; } ; source_affile : KW_FILE '(' source_affile_params ')' { $$ = $3; } | KW_PIPE '(' source_afpipe_params ')' { $$ = $3; } | KW_STDIN '(' source_stdin_params ')' { $$ = $3; } | KW_WILDCARD_FILE { last_driver = *instance = wildcard_sd_new(configuration); last_file_reader_options = &((WildcardSourceDriver *) last_driver)->file_reader_options; last_reader_options = &last_file_reader_options->reader_options; last_file_perm_options = &((WildcardSourceDriver *) last_driver)->file_opener_options.file_perm_options; last_log_proto_options = file_reader_options_get_log_proto_options(last_file_reader_options); } '(' source_wildcard_params ')' { $$ = last_driver; } ; source_wildcard_params : source_wildcard_options ; source_wildcard_options : source_wildcard_option source_wildcard_options | ; source_stdin_params : { last_driver = *instance = stdin_sd_new(configuration); last_file_reader_options = &((AFFileSourceDriver *) last_driver)->file_reader_options; last_reader_options = &last_file_reader_options->reader_options; last_file_perm_options = &((AFFileSourceDriver *) last_driver)->file_opener_options.file_perm_options; last_log_proto_options = file_reader_options_get_log_proto_options(last_file_reader_options); } source_affile_options { $$ = last_driver; } ; source_affile_params : string { last_driver = *instance = affile_sd_new($1, configuration); last_file_reader_options = &((AFFileSourceDriver *) last_driver)->file_reader_options; last_reader_options = &last_file_reader_options->reader_options; last_file_perm_options = &((AFFileSourceDriver *) last_driver)->file_opener_options.file_perm_options; last_log_proto_options = file_reader_options_get_log_proto_options(last_file_reader_options); } source_affile_options { $$ = last_driver; free($1); } ; source_affile_options : source_affile_option source_affile_options | ; source_affile_option : KW_FOLLOW_FREQ '(' LL_FLOAT ')' { file_reader_options_set_follow_freq(last_file_reader_options, (long) ($3 * 1000)); } | KW_FOLLOW_FREQ '(' nonnegative_integer ')' { file_reader_options_set_follow_freq(last_file_reader_options, ($3 * 1000)); } | KW_PAD_SIZE '(' nonnegative_integer ')' { last_log_proto_options->pad_size = $3; } | multi_line_option | file_perm_option | source_reader_option ; source_wildcard_option : KW_BASE_DIR '(' string ')' { wildcard_sd_set_base_dir(last_driver, $3); free($3); } | KW_FILENAME_PATTERN '(' string ')' { wildcard_sd_set_filename_pattern(last_driver, $3); free($3); } | KW_RECURSIVE '(' yesno ')' { wildcard_sd_set_recursive(last_driver, $3); } | KW_MAX_FILES '(' LL_NUMBER ')' { wildcard_sd_set_max_files(last_driver, $3); } | KW_MONITOR_METHOD '(' string ')' { CHECK_ERROR(wildcard_sd_set_monitor_method(last_driver, $3), @3, "Invalid monitor-method"); free($3); } | source_affile_option ; source_afpipe_params : string { last_driver = *instance = pipe_sd_new($1, configuration); last_file_reader_options = &((AFFileSourceDriver *) last_driver)->file_reader_options; last_reader_options = &last_file_reader_options->reader_options; last_file_perm_options = &((AFFileSourceDriver *) last_driver)->file_opener_options.file_perm_options; last_log_proto_options = file_reader_options_get_log_proto_options(last_file_reader_options); } source_afpipe_options { $$ = last_driver; free($1); } ; source_afpipe_options : source_afpipe_option source_afpipe_options | ; source_afpipe_option : KW_OPTIONAL '(' yesno ')' { last_driver->optional = $3; } | KW_PAD_SIZE '(' nonnegative_integer ')' { last_log_proto_options->pad_size = $3; } | multi_line_option | file_perm_option | source_reader_option ; /* NOTE: don't copy this to other drivers blindly, but make it general and * move it to cfg-grammar.y instead */ multi_line_option : KW_MULTI_LINE_MODE '(' string ')' { CHECK_ERROR(log_proto_multi_line_server_options_set_mode(&last_log_proto_options->super, $3), @3, "Invalid multi-line mode"); free($3); } | KW_MULTI_LINE_PREFIX '(' string ')' { GError *error = NULL; CHECK_ERROR_GERROR(log_proto_multi_line_server_options_set_prefix(&last_log_proto_options->super, $3, &error), @3, error, "error compiling multi-line regexp"); free($3); } | KW_MULTI_LINE_GARBAGE '(' string ')' { GError *error = NULL; CHECK_ERROR_GERROR(log_proto_multi_line_server_options_set_garbage(&last_log_proto_options->super, $3, &error), @3, error, "error compiling multi-line regexp"); free($3); } ; dest_affile : KW_FILE '(' dest_affile_params ')' { $$ = $3; } | KW_PIPE '(' dest_afpipe_params ')' { $$ = $3; } ; dest_affile_params : string { last_driver = *instance = affile_dd_new($1, configuration); last_writer_options = &((AFFileDestDriver *) last_driver)->writer_options; last_file_perm_options = &((AFFileDestDriver *) last_driver)->file_opener_options.file_perm_options; } dest_affile_options { $$ = last_driver; free($1); } ; dest_affile_options : dest_affile_option dest_affile_options | ; dest_affile_option : dest_writer_option | dest_driver_option | file_perm_option | KW_OPTIONAL '(' yesno ')' { last_driver->optional = $3; } | KW_CREATE_DIRS '(' yesno ')' { affile_dd_set_create_dirs(last_driver, $3); } | KW_OVERWRITE_IF_OLDER '(' nonnegative_integer ')' { affile_dd_set_overwrite_if_older(last_driver, $3); } | KW_FSYNC '(' yesno ')' { affile_dd_set_fsync(last_driver, $3); } ; dest_afpipe_params : string { last_driver = *instance = pipe_dd_new($1, configuration); last_writer_options = &((AFFileDestDriver *) last_driver)->writer_options; last_file_perm_options = &((AFFileDestDriver *) last_driver)->file_opener_options.file_perm_options; } dest_afpipe_options { $$ = last_driver; free($1); } ; dest_afpipe_options : dest_afpipe_option dest_afpipe_options | ; dest_afpipe_option : dest_writer_option | dest_driver_option | file_perm_option ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/affile/affile-parser.c000066400000000000000000000044601321171025300232230ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "driver.h" #include "cfg-parser.h" #include "affile-grammar.h" extern int affile_debug; int affile_parse(CfgLexer *lexer, LogDriver **instance, gpointer arg); static CfgLexerKeyword affile_keywords[] = { { "file", KW_FILE }, { "fifo", KW_PIPE }, { "pipe", KW_PIPE }, { "stdin", KW_STDIN }, { "wildcard_file", KW_WILDCARD_FILE }, { "base_dir", KW_BASE_DIR }, { "filename_pattern", KW_FILENAME_PATTERN }, { "recursive", KW_RECURSIVE }, { "max_files", KW_MAX_FILES }, { "monitor_method", KW_MONITOR_METHOD }, { "fsync", KW_FSYNC }, { "remove_if_older", KW_OVERWRITE_IF_OLDER, KWS_OBSOLETE, "overwrite_if_older" }, { "overwrite_if_older", KW_OVERWRITE_IF_OLDER }, { "follow_freq", KW_FOLLOW_FREQ }, { "multi_line_mode", KW_MULTI_LINE_MODE }, { "multi_line_prefix", KW_MULTI_LINE_PREFIX }, { "multi_line_garbage", KW_MULTI_LINE_GARBAGE }, { "multi_line_suffix", KW_MULTI_LINE_GARBAGE }, { NULL } }; CfgParser affile_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &affile_debug, #endif .name = "affile", .keywords = affile_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer)) affile_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(affile_, LogDriver **) syslog-ng-syslog-ng-3.13.2/modules/affile/affile-parser.h000066400000000000000000000022151321171025300232240ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFFILE_PARSER_H_INCLUDED #define AFFILE_PARSER_H_INCLUDED #include "cfg-parser.h" #include "driver.h" extern CfgParser affile_parser; CFG_PARSER_DECLARE_LEXER_BINDING(affile_, LogDriver **) #endif syslog-ng-syslog-ng-3.13.2/modules/affile/affile-plugin.c000066400000000000000000000042141321171025300232220ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "plugin.h" #include "plugin-types.h" #include "affile-dest.h" extern CfgParser affile_parser; static Plugin affile_plugins[] = { { .type = LL_CONTEXT_SOURCE, .name = "file", .parser = &affile_parser, }, { .type = LL_CONTEXT_SOURCE, .name = "pipe", .parser = &affile_parser, }, { .type = LL_CONTEXT_SOURCE, .name = "wildcard_file", .parser = &affile_parser, }, { .type = LL_CONTEXT_SOURCE, .name = "stdin", .parser = &affile_parser, }, { .type = LL_CONTEXT_DESTINATION, .name = "file", .parser = &affile_parser, }, { .type = LL_CONTEXT_DESTINATION, .name = "pipe", .parser = &affile_parser, }, }; gboolean affile_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, affile_plugins, G_N_ELEMENTS(affile_plugins)); affile_dd_global_init(); return TRUE; } const ModuleInfo module_info = { .canonical_name = "affile", .version = SYSLOG_NG_VERSION, .description = "The affile module provides file source & destination support for syslog-ng.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = affile_plugins, .plugins_len = G_N_ELEMENTS(affile_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/affile/affile-source.c000066400000000000000000000137511321171025300232320ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "affile-source.h" #include "driver.h" #include "messages.h" #include "gprocess.h" #include "file-specializations.h" #include #include #include #include #include #include #include #include #include static gboolean _is_linux_proc_kmsg(const gchar *filename) { #ifdef __linux__ if (strcmp(filename, "/proc/kmsg") == 0) return TRUE; #endif return FALSE; } static gboolean _is_linux_dev_kmsg(const gchar *filename) { #ifdef __linux__ if (strcmp(filename, "/dev/kmsg") == 0) return TRUE; #endif return FALSE; } static inline gboolean _is_device_node(const gchar *filename) { struct stat st; if (stat(filename, &st) < 0) return FALSE; return !S_ISREG(st.st_mode); } static inline const gchar * affile_sd_format_persist_name(const LogPipe *s) { AFFileSourceDriver *self = (AFFileSourceDriver *)s; return log_pipe_get_persist_name(&self->file_reader->super); } static void affile_sd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { log_src_driver_queue_method(s, msg, path_options, user_data); } static gboolean _are_multi_line_settings_invalid(AFFileSourceDriver *self) { LogProtoMultiLineServerOptions *multi_line_options = (LogProtoMultiLineServerOptions *) &self->file_reader_options.reader_options.proto_options; gboolean is_garbage_mode = multi_line_options->mode == MLM_PREFIX_GARBAGE; gboolean is_suffix_mode = multi_line_options->mode == MLM_PREFIX_SUFFIX; return (!is_garbage_mode && !is_suffix_mode) && (multi_line_options->prefix || multi_line_options->garbage); } static gboolean affile_sd_init(LogPipe *s) { AFFileSourceDriver *self = (AFFileSourceDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_src_driver_init_method(s)) return FALSE; file_reader_options_init(&self->file_reader_options, cfg, self->super.super.group); file_opener_options_init(&self->file_opener_options, cfg); file_opener_set_options(self->file_opener, &self->file_opener_options); self->file_reader = file_reader_new(self->filename->str, &self->file_reader_options, self->file_opener, &self->super, cfg); if (_are_multi_line_settings_invalid(self)) { msg_error("multi-line-prefix() and/or multi-line-garbage() specified but multi-line-mode() is not regexp based " "(prefix-garbage or prefix-suffix), please set multi-line-mode() properly"); return FALSE; } log_pipe_append(&self->file_reader->super, &self->super.super.super); return log_pipe_init(&self->file_reader->super); } static gboolean affile_sd_deinit(LogPipe *s) { AFFileSourceDriver *self = (AFFileSourceDriver *) s; log_pipe_deinit(&self->file_reader->super); if (!log_src_driver_deinit_method(s)) return FALSE; return TRUE; } static void affile_sd_free(LogPipe *s) { AFFileSourceDriver *self = (AFFileSourceDriver *) s; file_opener_free(self->file_opener); log_pipe_unref(&self->file_reader->super); g_string_free(self->filename, TRUE); file_reader_options_deinit(&self->file_reader_options); file_opener_options_deinit(&self->file_opener_options); log_src_driver_free(s); } AFFileSourceDriver * affile_sd_new_instance(gchar *filename, GlobalConfig *cfg) { AFFileSourceDriver *self = g_new0(AFFileSourceDriver, 1); log_src_driver_init_instance(&self->super, cfg); self->super.super.super.init = affile_sd_init; self->super.super.super.queue = affile_sd_queue; self->super.super.super.deinit = affile_sd_deinit; self->super.super.super.free_fn = affile_sd_free; self->super.super.super.generate_persist_name = affile_sd_format_persist_name; self->filename = g_string_new(filename); file_reader_options_defaults(&self->file_reader_options); self->file_reader_options.reader_options.super.stats_level = STATS_LEVEL1; file_opener_options_defaults(&self->file_opener_options); return self; } LogDriver * affile_sd_new(gchar *filename, GlobalConfig *cfg) { AFFileSourceDriver *self = affile_sd_new_instance(filename, cfg); self->file_reader_options.reader_options.super.stats_source = SCS_FILE; if (_is_device_node(filename) || _is_linux_proc_kmsg(filename)) self->file_reader_options.follow_freq = 0; else self->file_reader_options.follow_freq = 1000; if (self->file_reader_options.follow_freq > 0) self->file_opener = file_opener_for_regular_source_files_new(); else if (_is_linux_proc_kmsg(self->filename->str)) { self->file_opener_options.needs_privileges = TRUE; self->file_opener = file_opener_for_prockmsg_new(); } else if (_is_linux_dev_kmsg(self->filename->str)) self->file_opener = file_opener_for_devkmsg_new(); else self->file_opener = file_opener_for_regular_source_files_new(); self->file_reader_options.restore_state = self->file_reader_options.follow_freq > 0; file_opener_options_defaults_dont_change_permissions(&self->file_opener_options); return &self->super.super; } syslog-ng-syslog-ng-3.13.2/modules/affile/affile-source.h000066400000000000000000000032611321171025300232320ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFFILE_SOURCE_H_INCLUDED #define AFFILE_SOURCE_H_INCLUDED #include "driver.h" #include "logreader.h" #include "file-opener.h" #include "file-reader.h" typedef struct _AFFileSourceDriver { LogSrcDriver super; GString *filename; FileReader *file_reader; FileOpener *file_opener; FileReaderOptions file_reader_options; FileOpenerOptions file_opener_options; } AFFileSourceDriver; AFFileSourceDriver *affile_sd_new_instance(gchar *filename, GlobalConfig *cfg); LogDriver *affile_sd_new(gchar *filename, GlobalConfig *cfg); void affile_sd_set_recursion(LogDriver *s, const gint recursion); void affile_sd_set_pri_level(LogDriver *s, const gint16 severity); void affile_sd_set_pri_facility(LogDriver *s, const gint16 facility); #endif syslog-ng-syslog-ng-3.13.2/modules/affile/collection-comporator.c000066400000000000000000000110661321171025300250210ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "collection-comporator.h" #define IN_OLD 0x01 #define IN_NEW 0x02 #define IN_BOTH 0x03 typedef struct _CollectionComporatorEntry { gchar *value; guint8 flag; } CollectionComporatorEntry; struct _CollectionComporator { GList *original_list; GHashTable *original_map; gboolean running; GList *deleted_entries; gpointer callback_data; void (*handle_new_entry)(const gchar *name, gpointer callback_data); void (*handle_deleted_entry)(const gchar *name, gpointer callback_data); }; static void _free_poll_entry(gpointer s) { CollectionComporatorEntry *entry = (CollectionComporatorEntry *)s; g_free(entry->value); g_free(entry); } void collection_comporator_free(CollectionComporator *self) { g_hash_table_unref(self->original_map); g_list_free_full(self->original_list, _free_poll_entry); g_free(self); } CollectionComporator * collection_comporator_new(void) { CollectionComporator *self = g_new0(CollectionComporator, 1); self->original_map = g_hash_table_new(g_str_hash, g_str_equal); return self; } void collection_comporator_start(CollectionComporator *self) { if (!self->running) { self->running = TRUE; self->deleted_entries = NULL; } } void collection_comporator_add_value(CollectionComporator *self, const gchar *value) { CollectionComporatorEntry *entry = g_hash_table_lookup(self->original_map, value); if (entry) { entry->flag = IN_BOTH; } else { entry = g_new0(CollectionComporatorEntry, 1); entry->value = g_strdup(value); entry->flag = IN_NEW; self->original_list = g_list_append(self->original_list, entry); g_hash_table_insert(self->original_map, entry->value, entry); self->handle_new_entry(entry->value, self->callback_data); } } void collection_comporator_add_initial_value(CollectionComporator *self, const gchar *value) { CollectionComporatorEntry *entry = g_new0(CollectionComporatorEntry, 1); entry->value = g_strdup(value); entry->flag = IN_OLD; self->original_list = g_list_append(self->original_list, entry); g_hash_table_insert(self->original_map, entry->value, entry); } void _move_link(GList *item, GList **old_list, GList **new_list) { *old_list = g_list_remove_link(*old_list, item); *new_list = g_list_concat(*new_list, item); } void _deleted_entries_callback(gpointer data, gpointer user_data) { CollectionComporatorEntry *entry = (CollectionComporatorEntry *)data; CollectionComporator *self = (CollectionComporator *)user_data; self->handle_deleted_entry(entry->value, self->callback_data); } void collection_comporator_collect_deleted_entries(CollectionComporator *self) { GList *iter = self->original_list; CollectionComporatorEntry *entry; while (iter) { entry = (CollectionComporatorEntry *)iter->data; if (entry->flag == IN_OLD) { GList *next = iter->next; g_hash_table_remove(self->original_map, entry->value); _move_link(iter, &self->original_list, &self->deleted_entries); iter = next; } else { entry->flag = IN_OLD; iter = iter->next; } } } void collection_comporator_stop(CollectionComporator *self) { collection_comporator_collect_deleted_entries(self); g_list_foreach(self->deleted_entries, _deleted_entries_callback, self); g_list_free_full(self->deleted_entries, _free_poll_entry); self->running = FALSE; } void collection_comporator_set_callbacks(CollectionComporator *self, cc_callback handle_new, cc_callback handle_delete, gpointer user_data) { self->callback_data = user_data; self->handle_deleted_entry = handle_delete; self->handle_new_entry = handle_new; } syslog-ng-syslog-ng-3.13.2/modules/affile/collection-comporator.h000066400000000000000000000033541321171025300250270ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MODULES_AFFILE_COLLECTION_COMPORATOR_H_ #define MODULES_AFFILE_COLLECTION_COMPORATOR_H_ #include "syslog-ng.h" typedef struct _CollectionComporator CollectionComporator; typedef void (*cc_callback)(const gchar *value, gpointer user_data); CollectionComporator *collection_comporator_new(void); void collection_comporator_free(CollectionComporator *self); void collection_comporator_start(CollectionComporator *self); void collection_comporator_stop(CollectionComporator *self); void collection_comporator_add_value(CollectionComporator *self, const gchar *value); void collection_comporator_add_initial_value(CollectionComporator *self, const gchar *value); void collection_comporator_set_callbacks(CollectionComporator *self, cc_callback handle_new, cc_callback handle_delete, gpointer user_data); #endif /* MODULES_AFFILE_COLLECTION_COMPORATOR_H_ */ syslog-ng-syslog-ng-3.13.2/modules/affile/directory-monitor-factory.c000066400000000000000000000044461321171025300256450ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "directory-monitor-factory.h" #include "directory-monitor-poll.h" #if SYSLOG_NG_HAVE_INOTIFY #include "directory-monitor-inotify.h" #endif #include MonitorMethod directory_monitor_factory_get_monitor_method(const gchar *method) { if (strcmp(method, "auto") == 0) { return MM_AUTO; } else if (strcmp(method, "poll") == 0) { return MM_POLL; } #if SYSLOG_NG_HAVE_INOTIFY else if (strcmp(method, "inotify") == 0) { return MM_INOTIFY; } #endif return MM_UNKNOWN; } DirectoryMonitorConstructor directory_monitor_factory_get_constructor(DirectoryMonitorOptions *options) { DirectoryMonitorConstructor constructor = NULL; #if SYSLOG_NG_HAVE_INOTIFY if (options->method == MM_AUTO || options->method == MM_INOTIFY) { constructor = directory_monitor_inotify_new; } else if (options->method == MM_POLL) { constructor = directory_monitor_poll_new; } #else if (options->method == MM_AUTO || options->method == MM_POLL) { constructor = directory_monitor_poll_new; } #endif return constructor; } DirectoryMonitor * create_directory_monitor(DirectoryMonitorOptions *options) { DirectoryMonitor *monitor = NULL; DirectoryMonitorConstructor constructor = directory_monitor_factory_get_constructor(options); if (constructor) { monitor = constructor(options->dir, options->follow_freq); } return monitor; } syslog-ng-syslog-ng-3.13.2/modules/affile/directory-monitor-factory.h000066400000000000000000000032241321171025300256430ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MODULES_AFFILE_DIRECTORY_MONITOR_FACTORY_H_ #define MODULES_AFFILE_DIRECTORY_MONITOR_FACTORY_H_ #include "directory-monitor.h" typedef DirectoryMonitor *(*DirectoryMonitorConstructor)(const gchar *dir, guint recheck_time); typedef enum { MM_AUTO, MM_POLL, MM_INOTIFY, MM_UNKNOWN } MonitorMethod; typedef struct _DirectoryMonitorOptions { const gchar *dir; guint follow_freq; MonitorMethod method; } DirectoryMonitorOptions; DirectoryMonitorConstructor directory_monitor_factory_get_constructor(DirectoryMonitorOptions *options); MonitorMethod directory_monitor_factory_get_monitor_method(const gchar *method_name); DirectoryMonitor *create_directory_monitor(DirectoryMonitorOptions *options); #endif /* MODULES_AFFILE_DIRECTORY_MONITOR_FACTORY_H_ */ syslog-ng-syslog-ng-3.13.2/modules/affile/directory-monitor-inotify.c000066400000000000000000000064751321171025300256630ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "directory-monitor-inotify.h" #include "messages.h" #include #include #include typedef struct _DirectoryMonitorInotify { DirectoryMonitor super; struct iv_inotify inotify; struct iv_inotify_watch watcher; } DirectoryMonitorInotify; static DirectoryMonitorEventType _get_event_type(struct inotify_event *event, gchar *filename) { if ((event->mask & IN_CREATE) || (event->mask & IN_MOVED_TO)) { if (event->mask & IN_ISDIR) { return DIRECTORY_CREATED; } return FILE_CREATED; } else if ((event->mask & IN_DELETE) || (event->mask & IN_MOVED_FROM)) { return DELETED; } return UNKNOWN; } static void _handle_event(gpointer s, struct inotify_event *event) { DirectoryMonitorInotify *self = (DirectoryMonitorInotify *)s; DirectoryMonitorEvent dir_event; dir_event.name = g_strdup_printf("%.*s", event->len, &event->name[0]); dir_event.full_path = build_filename(self->super.real_path, dir_event.name); dir_event.event_type = _get_event_type(event, dir_event.full_path); if (self->super.callback && dir_event.event_type != UNKNOWN) { self->super.callback(&dir_event, self->super.callback_data); } g_free(dir_event.full_path); g_free((gchar *)dir_event.name); } static void _start_watches(DirectoryMonitor *s) { DirectoryMonitorInotify *self = (DirectoryMonitorInotify *)s; IV_INOTIFY_WATCH_INIT(&self->watcher); self->watcher.inotify = &self->inotify; self->watcher.pathname = self->super.dir; self->watcher.mask = IN_CREATE | IN_DELETE | IN_MOVE; self->watcher.cookie = self; self->watcher.handler = _handle_event; iv_inotify_watch_register(&self->watcher); } static void _stop_watches(DirectoryMonitor *s) { DirectoryMonitorInotify *self = (DirectoryMonitorInotify *)s; iv_inotify_watch_unregister(&self->watcher); } static void _free(DirectoryMonitor *s) { DirectoryMonitorInotify *self = (DirectoryMonitorInotify *)s; iv_inotify_unregister(&self->inotify); } DirectoryMonitor * directory_monitor_inotify_new(const gchar *dir, guint recheck_time) { DirectoryMonitorInotify *self = g_new0(DirectoryMonitorInotify, 1); directory_monitor_init_instance(&self->super, dir, recheck_time); self->super.start_watches = _start_watches; self->super.stop_watches = _stop_watches; self->super.free_fn = _free; IV_INOTIFY_INIT(&self->inotify); iv_inotify_register(&self->inotify); return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/affile/directory-monitor-inotify.h000066400000000000000000000022731321171025300256600ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MODULES_AFFILE_DIRECTORY_MONITOR_INOTIFY_H_ #define MODULES_AFFILE_DIRECTORY_MONITOR_INOTIFY_H_ #include "directory-monitor.h" #include DirectoryMonitor *directory_monitor_inotify_new(const gchar *dir, guint recheck_time); #endif /* MODULES_AFFILE_DIRECTORY_MONITOR_INOTIFY_H_ */ syslog-ng-syslog-ng-3.13.2/modules/affile/directory-monitor-poll.c000066400000000000000000000110001321171025300251240ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "directory-monitor-poll.h" #include "collection-comporator.h" #include "timeutils.h" #include typedef struct _DirectoryMonitorPoll { DirectoryMonitor super; CollectionComporator *comporator; struct iv_timer rescan_timer; } DirectoryMonitorPoll; static void _handle_new_entry(const gchar *filename, gpointer user_data) { DirectoryMonitorPoll *self = (DirectoryMonitorPoll *)user_data; DirectoryMonitorEvent event; event.name = filename; event.full_path = build_filename(self->super.real_path, event.name); event.event_type = g_file_test(event.full_path, G_FILE_TEST_IS_DIR) ? DIRECTORY_CREATED : FILE_CREATED; if (self->super.callback) { self->super.callback(&event, self->super.callback_data); } g_free(event.full_path); } static void _handle_deleted_entry(const gchar *filename, gpointer user_data) { DirectoryMonitorPoll *self = (DirectoryMonitorPoll *)user_data; DirectoryMonitorEvent event; event.name = filename; event.event_type = DELETED; event.full_path = build_filename(self->super.real_path, event.name); if (self->super.callback) { self->super.callback(&event, self->super.callback_data); } g_free(event.full_path); } static void _rescan_directory(DirectoryMonitorPoll *self) { GError *error = NULL; GDir *directory = g_dir_open(self->super.real_path, 0, &error); collection_comporator_start(self->comporator); const gchar *filename = g_dir_read_name(directory); while (filename) { collection_comporator_add_value(self->comporator, filename); filename = g_dir_read_name(directory); } g_dir_close(directory); collection_comporator_stop(self->comporator); } void _rearm_rescan_timer(DirectoryMonitorPoll *self) { iv_validate_now(); self->rescan_timer.expires = iv_now; timespec_add_msec(&self->rescan_timer.expires, self->super.recheck_time); iv_timer_register(&self->rescan_timer); } static void _start_watches(DirectoryMonitor *s) { DirectoryMonitorPoll *self = (DirectoryMonitorPoll *)s; GDir *directory = NULL; GError *error = NULL; directory = g_dir_open(self->super.real_path, 0, &error); const gchar *filename = g_dir_read_name(directory); while (filename) { collection_comporator_add_initial_value(self->comporator, filename); filename = g_dir_read_name(directory); } g_dir_close(directory); _rearm_rescan_timer(self); } static void _stop_watches(DirectoryMonitor *s) { DirectoryMonitorPoll *self = (DirectoryMonitorPoll *)s; if (iv_timer_registered(&self->rescan_timer)) { iv_timer_unregister(&self->rescan_timer); } } static void _free_fn(DirectoryMonitor *s) { DirectoryMonitorPoll *self = (DirectoryMonitorPoll *)s; collection_comporator_free(self->comporator); } static void _triggered_timer(gpointer data) { DirectoryMonitorPoll *self = (DirectoryMonitorPoll *)data; _rescan_directory(self); _rearm_rescan_timer(self); } DirectoryMonitor * directory_monitor_poll_new(const gchar *dir, guint recheck_time) { DirectoryMonitorPoll *self = g_new0(DirectoryMonitorPoll, 1); directory_monitor_init_instance(&self->super, dir, recheck_time); IV_TIMER_INIT(&self->rescan_timer); self->rescan_timer.cookie = self; self->rescan_timer.handler = _triggered_timer; self->super.start_watches = _start_watches; self->super.stop_watches = _stop_watches; self->super.free_fn = _free_fn; self->comporator = collection_comporator_new(); collection_comporator_set_callbacks(self->comporator, _handle_new_entry, _handle_deleted_entry, self); return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/affile/directory-monitor-poll.h000066400000000000000000000022271321171025300251440ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MODULES_AFFILE_DIRECTORY_MONITOR_POLL_H_ #define MODULES_AFFILE_DIRECTORY_MONITOR_POLL_H_ #include "directory-monitor.h" DirectoryMonitor *directory_monitor_poll_new(const gchar *dir, guint recheck_time); #endif /* MODULES_AFFILE_DIRECTORY_MONITOR_POLL_H_ */ syslog-ng-syslog-ng-3.13.2/modules/affile/directory-monitor.c000066400000000000000000000144731321171025300242010ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "directory-monitor.h" #include "timeutils.h" #include #include #include #include #include #include #include gchar * build_filename(const gchar *basedir, const gchar *path) { gchar *result; if (!path) return NULL; if (basedir) { result = g_build_path(G_DIR_SEPARATOR_S, basedir, path, NULL); } else { result = g_strdup(path); } return result; } #define PATH_MAX_GUESS 1024 static inline long get_path_max(void) { static long path_max = 0; if (path_max == 0) { #ifdef PATH_MAX path_max = PATH_MAX; #else { /* This code based on example from the Advanced Programming in the UNIX environment * on how to determine the max path length */ static long posix_version = 0; static long xsi_version = 0; if (posix_version == 0) posix_version = sysconf(_SC_VERSION); if (xsi_version == 0) xsi_version = sysconf(_SC_XOPEN_VERSION); if ((path_max = pathconf("/", _PC_PATH_MAX)) < 0) path_max = PATH_MAX_GUESS; else path_max++; /* add one since it's relative to root */ /* * Before POSIX.1-2001, we aren't guaranteed that PATH_MAX includes * the terminating null byte. Same goes for XPG3. */ if ((posix_version < 200112L) && (xsi_version < 4)) pathmax++; #endif } return path_max; } /* Resolve . and .. Resolve symlinks Resolve tricki symlinks like a -> ../a/../a/./b */ gchar * resolve_to_absolute_path(const gchar *path, const gchar *basedir) { long path_max = get_path_max(); gchar *res; gchar *w_name; w_name = build_filename(basedir, path); res = (char *)g_malloc(path_max); if (!realpath(w_name, res)) { g_free(res); if (errno == ENOENT) { res = g_strdup(path); } else { msg_error("Can't resolve to absolute path", evt_tag_str("path", path), evt_tag_errno("error", errno), NULL); res = NULL; } } g_free(w_name); return res; } static gchar * _get_real_path(DirectoryMonitor *self) { gchar *dir_real_path = NULL; if (!g_path_is_absolute(self->dir)) { gchar *wd = g_get_current_dir(); dir_real_path = resolve_to_absolute_path(self->dir, wd); g_free(wd); } else { dir_real_path = resolve_to_absolute_path(self->dir, NULL); } return dir_real_path; } void directory_monitor_stop(DirectoryMonitor *self) { if (iv_timer_registered(&self->check_timer)) { iv_timer_unregister(&self->check_timer); } if (self->stop_watches && self->watches_running) { self->stop_watches(self); } self->watches_running = FALSE; } static void _collect_all_files(DirectoryMonitor *self, GDir *directory) { const gchar *filename = g_dir_read_name(directory); while (filename) { DirectoryMonitorEvent event = { .name = filename }; gchar *filename_real_path = resolve_to_absolute_path(filename, self->real_path); event.full_path = build_filename(self->real_path, filename); event.event_type = g_file_test(filename_real_path, G_FILE_TEST_IS_DIR) ? DIRECTORY_CREATED : FILE_CREATED; self->callback(&event, self->callback_data); g_free(filename_real_path); g_free(event.full_path); filename = g_dir_read_name(directory); } } static void _arm_recheck_timer(DirectoryMonitor *self) { iv_validate_now(); self->check_timer.cookie = self; self->check_timer.handler = (GDestroyNotify) directory_monitor_start; self->check_timer.expires = iv_now; timespec_add_msec(&self->check_timer.expires, self->recheck_time); iv_timer_register(&self->check_timer); } static void _set_real_path(DirectoryMonitor *self) { if (self->real_path) g_free(self->real_path); self->real_path = _get_real_path(self); } void directory_monitor_start(DirectoryMonitor *self) { GDir *directory = NULL; GError *error = NULL; if (self->watches_running) { return; } _set_real_path(self); directory = g_dir_open(self->real_path, 0, &error); if (!directory) { msg_error("Can not open directory", evt_tag_str("base_dir", self->real_path), evt_tag_str("error", error->message)); _arm_recheck_timer(self); g_error_free(error); return; } _collect_all_files(self, directory); g_dir_close(directory); if (self->start_watches) { self->start_watches(self); } self->watches_running = TRUE; return; } void directory_monitor_set_callback(DirectoryMonitor *self, DirectoryMonitorEventCallback callback, gpointer user_data) { self->callback = callback; self->callback_data = user_data; } void directory_monitor_init_instance(DirectoryMonitor *self, const gchar *dir, guint recheck_time) { self->dir = g_strdup(dir); self->recheck_time = recheck_time; IV_TIMER_INIT(&self->check_timer); } DirectoryMonitor * directory_monitor_new(const gchar *dir, guint recheck_time) { DirectoryMonitor *self = g_new0(DirectoryMonitor, 1); directory_monitor_init_instance(self, dir, recheck_time); return self; } void directory_monitor_free(DirectoryMonitor *self) { if (self) { msg_debug("Free directory monitor", evt_tag_str("dir", self->dir)); if (self->free_fn) { self->free_fn(self); } g_free(self->real_path); g_free(self->dir); g_free(self); } } syslog-ng-syslog-ng-3.13.2/modules/affile/directory-monitor.h000066400000000000000000000045551321171025300242060ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MODULES_AFFILE_DIRECTORY_MONITOR_H_ #define MODULES_AFFILE_DIRECTORY_MONITOR_H_ #include #include typedef enum { FILE_CREATED, DIRECTORY_CREATED, DELETED, UNKNOWN } DirectoryMonitorEventType; typedef struct _DirectoryMonitorEvent { const gchar *name; gchar *full_path; DirectoryMonitorEventType event_type; } DirectoryMonitorEvent; typedef void (*DirectoryMonitorEventCallback)(const DirectoryMonitorEvent *event, gpointer user_data); typedef struct _DirectoryMonitor DirectoryMonitor; struct _DirectoryMonitor { gchar *dir; gchar *real_path; DirectoryMonitorEventCallback callback; gpointer callback_data; guint recheck_time; struct iv_timer check_timer; gboolean watches_running; void (*start_watches)(DirectoryMonitor *self); void (*stop_watches)(DirectoryMonitor *self); void (*free_fn)(DirectoryMonitor *self); }; DirectoryMonitor* directory_monitor_new(const gchar *dir, guint recheck_time); void directory_monitor_init_instance(DirectoryMonitor *self, const gchar *dir, guint recheck_time); void directory_monitor_free(DirectoryMonitor *self); void directory_monitor_set_callback(DirectoryMonitor *self, DirectoryMonitorEventCallback callback, gpointer user_data); void directory_monitor_start(DirectoryMonitor *self); void directory_monitor_stop(DirectoryMonitor *self); gchar *build_filename(const gchar *basedir, const gchar *path); #endif /* MODULES_AFFILE_DIRECTORY_MONITOR_H_ */ syslog-ng-syslog-ng-3.13.2/modules/affile/file-opener.c000066400000000000000000000126611321171025300227120ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "file-opener.h" #include "messages.h" #include "gprocess.h" #include "fdhelpers.h" #include "pathutils.h" #include "cfg.h" #include "transport/transport-file.h" #include #include #include #include #include #include #include #include static inline gboolean file_opener_prepare_open(FileOpener *self, const gchar *name) { if (self->prepare_open) return self->prepare_open(self, name); return TRUE; } static inline gint file_opener_open(FileOpener *self, const gchar *name, gint flags) { return self->open(self, name, flags); } static gint file_opener_get_open_flags_method(FileOpener *self, FileDirection dir) { switch (dir) { case AFFILE_DIR_READ: return O_RDONLY | O_NOCTTY | O_NONBLOCK | O_LARGEFILE; case AFFILE_DIR_WRITE: return O_WRONLY | O_CREAT | O_NOCTTY | O_NONBLOCK | O_LARGEFILE | O_APPEND; default: g_assert_not_reached(); } } static inline gint file_opener_get_open_flags(FileOpener *self, FileDirection dir) { return self->get_open_flags(self, dir); } static const gchar *spurious_paths[] = {"../", "/..", NULL}; static inline gboolean _string_contains_fragment(const gchar *str, const gchar *fragments[]) { int i; for (i = 0; fragments[i]; i++) { if (strstr(str, fragments[i])) return TRUE; } return FALSE; } static inline gboolean _is_path_spurious(const gchar *name) { return _string_contains_fragment(name, spurious_paths); } static inline gboolean _obtain_capabilities(FileOpener *self, gchar *name, cap_t *act_caps) { if (self->options->needs_privileges) { g_process_cap_modify(CAP_DAC_READ_SEARCH, TRUE); g_process_cap_modify(CAP_SYSLOG, TRUE); } else { g_process_cap_modify(CAP_DAC_OVERRIDE, TRUE); } if (self->options->create_dirs && !file_perm_options_create_containing_directory(&self->options->file_perm_options, name)) { return FALSE; } return TRUE; } static inline void _set_fd_permission(FileOpener *self, int fd) { if (fd != -1) { g_fd_set_cloexec(fd, TRUE); g_process_cap_modify(CAP_CHOWN, TRUE); g_process_cap_modify(CAP_FOWNER, TRUE); file_perm_options_apply_fd(&self->options->file_perm_options, fd); } } static int _open(FileOpener *self, const gchar *name, gint open_flags) { FilePermOptions *perm_opts = &self->options->file_perm_options; int fd; int mode = (perm_opts && (perm_opts->file_perm >= 0)) ? perm_opts->file_perm : 0600; fd = open(name, open_flags, mode); return fd; } gboolean file_opener_open_fd(FileOpener *self, gchar *name, FileDirection dir, gint *fd) { cap_t saved_caps; if (_is_path_spurious(name)) { msg_error("Spurious path, logfile not created", evt_tag_str("path", name)); return FALSE; } saved_caps = g_process_cap_save(); if (!_obtain_capabilities(self, name, &saved_caps)) { g_process_cap_restore(saved_caps); return FALSE; } if (!file_opener_prepare_open(self, name)) return FALSE; *fd = file_opener_open(self, name, file_opener_get_open_flags(self, dir)); if (!is_file_device(name)) _set_fd_permission(self, *fd); g_process_cap_restore(saved_caps); msg_trace("affile_open_file", evt_tag_str("path", name), evt_tag_int("fd", *fd)); return (*fd != -1); } void file_opener_set_options(FileOpener *self, FileOpenerOptions *options) { self->options = options; } void file_opener_init_instance(FileOpener *self) { self->get_open_flags = file_opener_get_open_flags_method; self->open = _open; } FileOpener * file_opener_new(void) { FileOpener *self = g_new0(FileOpener, 1); file_opener_init_instance(self); return self; } void file_opener_free(FileOpener *self) { g_free(self); } void file_opener_options_defaults(FileOpenerOptions *options) { file_perm_options_defaults(&options->file_perm_options); options->create_dirs = -1; options->needs_privileges = FALSE; } void file_opener_options_defaults_dont_change_permissions(FileOpenerOptions *options) { file_opener_options_defaults(options); file_perm_options_inherit_dont_change(&options->file_perm_options); } void file_opener_options_init(FileOpenerOptions *options, GlobalConfig *cfg) { file_perm_options_inherit_from(&options->file_perm_options, &cfg->file_perm_options); } void file_opener_options_deinit(FileOpenerOptions *options) { /* empty, this function only serves to meet the conventions of *Options */ } syslog-ng-syslog-ng-3.13.2/modules/affile/file-opener.h000066400000000000000000000063421321171025300227160ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFFILE_FILE_OPENER_H_INCLUDED #define AFFILE_FILE_OPENER_H_INCLUDED /* portable largefile support for affile */ #include "compat/lfs.h" #include "file-perms.h" #include "transport/logtransport.h" #include "logproto/logproto-server.h" #include "logproto/logproto-client.h" #include "logproto-file-reader.h" #include typedef enum { AFFILE_DIR_READ = 0x01, AFFILE_DIR_WRITE = 0x02, } FileDirection; typedef struct _FileOpenerOptions { FilePermOptions file_perm_options; gboolean needs_privileges:1; gint create_dirs; } FileOpenerOptions; typedef struct _FileOpener FileOpener; struct _FileOpener { FileOpenerOptions *options; gboolean (*prepare_open)(FileOpener *self, const gchar *name); gint (*open)(FileOpener *self, const gchar *name, gint flags); gint (*get_open_flags)(FileOpener *self, FileDirection dir); LogTransport *(*construct_transport)(FileOpener *self, gint fd); LogProtoServer *(*construct_src_proto)(FileOpener *self, LogTransport *transport, LogProtoFileReaderOptions *proto_options); LogProtoClient *(*construct_dst_proto)(FileOpener *self, LogTransport *transport, LogProtoClientOptions *proto_options); }; static inline LogTransport * file_opener_construct_transport(FileOpener *self, gint fd) { return self->construct_transport(self, fd); } static inline LogProtoServer * file_opener_construct_src_proto(FileOpener *self, LogTransport *transport, LogProtoFileReaderOptions *proto_options) { return self->construct_src_proto(self, transport, proto_options); } static inline LogProtoClient * file_opener_construct_dst_proto(FileOpener *self, LogTransport *transport, LogProtoClientOptions *proto_options) { return self->construct_dst_proto(self, transport, proto_options); } gboolean file_opener_open_fd(FileOpener *self, gchar *name, FileDirection dir, gint *fd); void file_opener_set_options(FileOpener *self, FileOpenerOptions *options); void file_opener_init_instance(FileOpener *self); FileOpener *file_opener_new(void); void file_opener_free(FileOpener *self); void file_opener_options_defaults(FileOpenerOptions *options); void file_opener_options_defaults_dont_change_permissions(FileOpenerOptions *options); void file_opener_options_init(FileOpenerOptions *options, GlobalConfig *cfg); void file_opener_options_deinit(FileOpenerOptions *options); #endif syslog-ng-syslog-ng-3.13.2/modules/affile/file-reader.c000066400000000000000000000246101321171025300226610ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "file-reader.h" #include "driver.h" #include "messages.h" #include "serialize.h" #include "gprocess.h" #include "stats/stats-registry.h" #include "transport/transport-file.h" #include "transport/transport-pipe.h" #include "transport-prockmsg.h" #include "poll-fd-events.h" #include "poll-file-changes.h" #include #include #include #include #include #include #include #include #include static inline const gchar * _format_persist_name(const LogPipe *s) { const FileReader *self = (const FileReader *)s; static gchar persist_name[1024]; if (self->owner->super.super.persist_name) g_snprintf(persist_name, sizeof(persist_name), "affile_sd.%s.curpos", self->owner->super.super.persist_name); else g_snprintf(persist_name, sizeof(persist_name), "affile_sd_curpos(%s)", self->filename->str); return persist_name; } static void _recover_state(LogPipe *s, GlobalConfig *cfg, LogProtoServer *proto) { FileReader *self = (FileReader *) s; if (!self->options->restore_state) return; if (!log_proto_server_restart_with_state(proto, cfg->state, _format_persist_name(s))) { msg_error("Error converting persistent state from on-disk format, losing file position information", evt_tag_str("filename", self->filename->str)); return; } } static gboolean _is_fd_pollable(gint fd) { struct iv_fd check_fd; gboolean pollable; IV_FD_INIT(&check_fd); check_fd.fd = fd; check_fd.cookie = NULL; pollable = (iv_fd_register_try(&check_fd) == 0); if (pollable) iv_fd_unregister(&check_fd); return pollable; } static PollEvents * _construct_poll_events(FileReader *self, gint fd) { if (self->options->follow_freq > 0) return poll_file_changes_new(fd, self->filename->str, self->options->follow_freq, &self->super); else if (fd >= 0 && _is_fd_pollable(fd)) return poll_fd_events_new(fd); else { msg_error("Unable to determine how to monitor this file, follow_freq() unset and it is not possible to poll it " "with the current ivykis polling method. Set follow-freq() for regular files or change " "IV_EXCLUDE_POLL_METHOD environment variable to override the automatically selected polling method", evt_tag_str("filename", self->filename->str), evt_tag_int("fd", fd)); return NULL; } } static LogTransport * _construct_transport(FileReader *self, gint fd) { return file_opener_construct_transport(self->opener, fd); } static LogProtoServer * _construct_proto(FileReader *self, gint fd) { LogReaderOptions *reader_options = &self->options->reader_options; LogProtoFileReaderOptions *proto_options = file_reader_options_get_log_proto_options(self->options); LogTransport *transport; MsgFormatHandler *format_handler; transport = _construct_transport(self, fd); format_handler = reader_options->parse_options.format_handler; if ((format_handler && format_handler->construct_proto)) { proto_options->super.super.position_tracking_enabled = TRUE; return format_handler->construct_proto(&reader_options->parse_options, transport, &proto_options->super.super); } return file_opener_construct_src_proto(self->opener, transport, proto_options); } static void _deinit_sd_logreader(FileReader *self) { log_pipe_deinit((LogPipe *) self->reader); log_pipe_unref((LogPipe *) self->reader); self->reader = NULL; } static void _setup_logreader(LogPipe *s, PollEvents *poll_events, LogProtoServer *proto, gboolean check_immediately) { FileReader *self = (FileReader *) s; self->reader = log_reader_new(log_pipe_get_config(s)); log_reader_reopen(self->reader, proto, poll_events); log_reader_set_options(self->reader, s, &self->options->reader_options, self->owner->super.id, self->filename->str); if (check_immediately) log_reader_set_immediate_check(self->reader); /* NOTE: if the file could not be opened, we ignore the last * remembered file position, if the file is created in the future * we're going to read from the start. */ log_pipe_append((LogPipe *) self->reader, s); } static gboolean _is_immediate_check_needed(gboolean file_opened, gboolean open_deferred) { if (file_opened) return TRUE; else if (open_deferred) return FALSE; return FALSE; } static gboolean _reader_open_file(LogPipe *s, gboolean recover_state) { FileReader *self = (FileReader *) s; GlobalConfig *cfg = log_pipe_get_config(s); gint fd; gboolean file_opened, open_deferred = FALSE; file_opened = file_opener_open_fd(self->opener, self->filename->str, AFFILE_DIR_READ, &fd); if (!file_opened && self->options->follow_freq > 0) { msg_info("Follow-mode file source not found, deferring open", evt_tag_str("filename", self->filename->str)); open_deferred = TRUE; fd = -1; } if (file_opened || open_deferred) { LogProtoServer *proto; PollEvents *poll_events; gboolean check_immediately; poll_events = _construct_poll_events(self, fd); if (!poll_events) { close(fd); return FALSE; } proto = _construct_proto(self, fd); check_immediately = _is_immediate_check_needed(file_opened, open_deferred); _setup_logreader(s, poll_events, proto, check_immediately); if (!log_pipe_init((LogPipe *) self->reader)) { msg_error("Error initializing log_reader, closing fd", evt_tag_int("fd", fd)); log_pipe_unref((LogPipe *) self->reader); self->reader = NULL; close(fd); return FALSE; } if (recover_state) _recover_state(s, cfg, proto); } else { msg_error("Error opening file for reading", evt_tag_str("filename", self->filename->str), evt_tag_errno(EVT_TAG_OSERROR, errno)); return self->owner->super.optional; } return TRUE; } static void _reopen_on_notify(LogPipe *s, gboolean recover_state) { FileReader *self = (FileReader *) s; _deinit_sd_logreader(self); _reader_open_file(s, recover_state); } /* NOTE: runs in the main thread */ static void _notify(LogPipe *s, gint notify_code, gpointer user_data) { FileReader *self = (FileReader *) s; switch (notify_code) { case NC_CLOSE: if (self->options->exit_on_eof) cfg_shutdown(log_pipe_get_config(s)); break; case NC_FILE_MOVED: msg_verbose("Follow-mode file source moved, tracking of the new file is started", evt_tag_str("filename", self->filename->str)); _reopen_on_notify(s, TRUE); break; case NC_READ_ERROR: msg_verbose("Error while following source file, reopening in the hope it would work", evt_tag_str("filename", self->filename->str)); _reopen_on_notify(s, FALSE); break; default: break; } } static void _queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { FileReader *self = (FileReader *)s; static NVHandle filename_handle = 0; if (!filename_handle) filename_handle = log_msg_get_value_handle("FILE_NAME"); log_msg_set_value(msg, filename_handle, self->filename->str, self->filename->len); log_pipe_forward_msg(s, msg, path_options); } static gboolean _init(LogPipe *s) { return _reader_open_file(s, TRUE); } static gboolean _deinit(LogPipe *s) { FileReader *self = (FileReader *)s; if (self->reader) _deinit_sd_logreader(self); return TRUE; } static void _free(LogPipe *s) { FileReader *self = (FileReader *) s; g_assert(!self->reader); g_string_free(self->filename, TRUE); } void file_reader_remove_persist_state(FileReader *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super); const gchar *old_persist_name = _format_persist_name(&self->super); gchar *new_persist_name = g_strdup_printf("%s_REMOVED", old_persist_name); persist_state_rename_entry(cfg->state, old_persist_name, new_persist_name); g_free(new_persist_name); } FileReader * file_reader_new(const gchar *filename, FileReaderOptions *options, FileOpener *opener, LogSrcDriver *owner, GlobalConfig *cfg) { FileReader *self = g_new0(FileReader, 1); log_pipe_init_instance(&self->super, cfg); self->super.init = _init; self->super.queue = _queue; self->super.deinit = _deinit; self->super.notify = _notify; self->super.free_fn = _free; self->super.generate_persist_name = _format_persist_name; self->filename = g_string_new(filename); self->options = options; self->opener = opener; self->owner = owner; return self; } void file_reader_options_set_follow_freq(FileReaderOptions *options, gint follow_freq) { options->follow_freq = follow_freq; } void file_reader_options_defaults(FileReaderOptions *options) { log_reader_options_defaults(&options->reader_options); log_proto_file_reader_options_defaults(file_reader_options_get_log_proto_options(options)); options->reader_options.parse_options.flags |= LP_LOCAL; options->restore_state = FALSE; } void file_reader_options_init(FileReaderOptions *options, GlobalConfig *cfg, const gchar *group) { log_reader_options_init(&options->reader_options, cfg, group); log_proto_file_reader_options_init(file_reader_options_get_log_proto_options(options)); } void file_reader_options_deinit(FileReaderOptions *options) { log_reader_options_destroy(&options->reader_options); log_proto_file_reader_options_destroy(file_reader_options_get_log_proto_options(options)); } syslog-ng-syslog-ng-3.13.2/modules/affile/file-reader.h000066400000000000000000000041631321171025300226670ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MODULES_AFFILE_FILE_READER_H_ #define MODULES_AFFILE_FILE_READER_H_ #include "driver.h" #include "logreader.h" #include "file-opener.h" typedef struct _FileReaderOptions { gint follow_freq; gboolean restore_state; LogReaderOptions reader_options; gboolean exit_on_eof; } FileReaderOptions; typedef struct _FileReader { LogPipe super; LogSrcDriver *owner; GString *filename; FileReaderOptions *options; FileOpener *opener; LogReader *reader; gboolean is_pipe; } FileReader; static inline LogProtoFileReaderOptions * file_reader_options_get_log_proto_options(FileReaderOptions *options) { return (LogProtoFileReaderOptions *) &options->reader_options.proto_options; } FileReader *file_reader_new(const gchar *filename, FileReaderOptions *options, FileOpener *opener, LogSrcDriver *owner, GlobalConfig *cfg); void file_reader_remove_persist_state(FileReader *self); void file_reader_options_set_follow_freq(FileReaderOptions *options, gint follow_freq); void file_reader_options_defaults(FileReaderOptions *options); void file_reader_options_init(FileReaderOptions *options, GlobalConfig *cfg, const gchar *group); void file_reader_options_deinit(FileReaderOptions *options); #endif /* MODULES_AFFILE_FILE_READER_H_ */ syslog-ng-syslog-ng-3.13.2/modules/affile/file-specializations.h000066400000000000000000000025261321171025300246270ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFFILE_FILE_SPECIALIZATIONS_H_INCLUDED #define AFFILE_FILE_SPECIALIZATIONS_H_INCLUDED #include "file-opener.h" #include "logwriter.h" FileOpener *file_opener_for_regular_source_files_new(void); FileOpener *file_opener_for_regular_dest_files_new(const LogWriterOptions *writer_options, gboolean *use_fsync); FileOpener *file_opener_for_devkmsg_new(void); FileOpener *file_opener_for_prockmsg_new(void); #endif syslog-ng-syslog-ng-3.13.2/modules/affile/linux-kmsg.c000066400000000000000000000061361321171025300226030ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "file-specializations.h" #include "transport/transport-file.h" #include "transport-prockmsg.h" #include "messages.h" #include "logproto/logproto-dgram-server.h" #include "logproto/logproto-text-server.h" #include #include /************************************************************** * /dev/kmsg support **************************************************************/ LogTransport * log_transport_devkmsg_new(gint fd) { if (lseek(fd, 0, SEEK_END) < 0) { msg_error("Error seeking /dev/kmsg to the end", evt_tag_str("error", g_strerror(errno))); } return log_transport_file_new(fd); } static LogTransport * _construct_devkmsg_transport(FileOpener *self, gint fd) { return log_transport_devkmsg_new(fd); } static LogProtoServer * _construct_devkmsg_proto(FileOpener *self, LogTransport *transport, LogProtoFileReaderOptions *options) { return log_proto_dgram_server_new(transport, &options->super.super); } FileOpener * file_opener_for_devkmsg_new(void) { FileOpener *self = file_opener_new(); self->construct_transport = _construct_devkmsg_transport; self->construct_src_proto = _construct_devkmsg_proto; return self; } /************************************************************** * /proc/kmsg support **************************************************************/ static LogProtoServer * log_proto_linux_proc_kmsg_reader_new(LogTransport *transport, const LogProtoServerOptions *options) { LogProtoServer *proto; proto = log_proto_text_server_new(transport, options); ((LogProtoTextServer *) proto)->super.no_multi_read = TRUE; return proto; } static LogTransport * _construct_prockmsg_transport(FileOpener *self, gint fd) { return log_transport_prockmsg_new(fd, 10); } static LogProtoServer * _construct_prockmsg_proto(FileOpener *self, LogTransport *transport, LogProtoFileReaderOptions *options) { return log_proto_linux_proc_kmsg_reader_new(transport, &options->super.super); } FileOpener * file_opener_for_prockmsg_new(void) { FileOpener *self = file_opener_new(); self->construct_transport = _construct_prockmsg_transport; self->construct_src_proto = _construct_prockmsg_proto; return self; } syslog-ng-syslog-ng-3.13.2/modules/affile/logproto-file-reader.c000066400000000000000000000035041321171025300245230ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto-file-reader.h" #include "logproto/logproto-record-server.h" #include "logproto/logproto-multiline-server.h" LogProtoServer * log_proto_file_reader_new(LogTransport *transport, const LogProtoFileReaderOptions *options) { if (options->pad_size > 0) return log_proto_padded_record_server_new(transport, &options->super.super, options->pad_size); else return log_proto_multiline_server_new(transport, &options->super); } void log_proto_file_reader_options_defaults(LogProtoFileReaderOptions *options) { log_proto_multi_line_server_options_defaults(&options->super); options->pad_size = 0; } void log_proto_file_reader_options_init(LogProtoFileReaderOptions *options) { log_proto_multi_line_server_options_init(&options->super); } void log_proto_file_reader_options_destroy(LogProtoFileReaderOptions *options) { log_proto_multi_line_server_options_destroy(&options->super); } syslog-ng-syslog-ng-3.13.2/modules/affile/logproto-file-reader.h000066400000000000000000000030371321171025300245310ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOG_PROTO_FILE_READER_H_INCLUDED #define LOG_PROTO_FILE_READER_H_INCLUDED #include "logproto/logproto-multiline-server.h" typedef struct _LogProtoFileReaderOptions { LogProtoMultiLineServerOptions super; gint pad_size; } LogProtoFileReaderOptions; LogProtoServer *log_proto_file_reader_new(LogTransport *transport, const LogProtoFileReaderOptions *options); void log_proto_file_reader_options_defaults(LogProtoFileReaderOptions *options); void log_proto_file_reader_options_init(LogProtoFileReaderOptions *options); void log_proto_file_reader_options_destroy(LogProtoFileReaderOptions *options); #endif syslog-ng-syslog-ng-3.13.2/modules/affile/logproto-file-writer.c000066400000000000000000000161561321171025300246040ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "logproto-file-writer.h" #include "messages.h" #include #include #include #include typedef struct _LogProtoFileWriter { LogProtoClient super; guchar *partial; gsize partial_len, partial_pos; gint buf_size; gint buf_count; gint fd; gint sum_len; gboolean fsync; struct iovec buffer[0]; } LogProtoFileWriter; /* * log_proto_file_writer_flush: * * this function flushes the file output buffer * it is called either form log_proto_file_writer_post (normal mode: the buffer is full) * or from log_proto_flush (foced flush: flush time, exit, etc) * */ static LogProtoStatus log_proto_file_writer_flush(LogProtoClient *s) { LogProtoFileWriter *self = (LogProtoFileWriter *)s; gint rc, i, i0, sum, ofs, pos; if (self->partial) { /* there is still some data from the previous file writing process */ gint len = self->partial_len - self->partial_pos; rc = write(self->fd, self->partial + self->partial_pos, len); if (rc > 0 && self->fsync) fsync(self->fd); if (rc < 0) { goto write_error; } else if (rc != len) { self->partial_pos += rc; return LPS_SUCCESS; } else { g_free(self->partial); self->partial = NULL; } } /* we might be called from log_writer_deinit() without having a buffer at all */ if (self->buf_count == 0) return LPS_SUCCESS; rc = writev(self->fd, self->buffer, self->buf_count); if (rc > 0 && self->fsync) fsync(self->fd); if (rc < 0) { goto write_error; } else if (rc != self->sum_len) { /* partial success: not everything has been written out */ /* look for the first chunk that has been cut */ sum = self->buffer[0].iov_len; /* sum is the cumulated length of the already processed items */ i = 0; while (rc > sum) sum += self->buffer[++i].iov_len; self->partial_len = sum - rc; /* this is the length of the first non-written chunk */ i0 = i; ++i; /* add the lengths of the following messages */ while (i < self->buf_count) self->partial_len += self->buffer[i++].iov_len; /* allocate and copy the remaning data */ self->partial = (guchar *)g_malloc(self->partial_len); ofs = sum - rc; /* the length of the remaning (not processed) chunk in the first message */ pos = self->buffer[i0].iov_len - ofs; memcpy(self->partial, self->buffer[i0].iov_base + pos, ofs); i = i0 + 1; while (i < self->buf_count) { memcpy(self->partial + ofs, self->buffer[i].iov_base, self->buffer[i].iov_len); ofs += self->buffer[i].iov_len; ++i; } self->partial_pos = 0; } /* free the previous message strings (the remaning part has been copied to the partial buffer) */ for (i = 0; i < self->buf_count; ++i) g_free(self->buffer[i].iov_base); self->buf_count = 0; self->sum_len = 0; return LPS_SUCCESS; write_error: if (errno != EINTR && errno != EAGAIN) { msg_error("I/O error occurred while writing", evt_tag_int("fd", self->super.transport->fd), evt_tag_errno(EVT_TAG_OSERROR, errno)); return LPS_ERROR; } return LPS_SUCCESS; } /* * log_proto_file_writer_post: * @msg: formatted log message to send (this might be consumed by this function) * @msg_len: length of @msg * @consumed: pointer to a gboolean that gets set if the message was consumed by this function * @error: error information, if any * * This function posts a message to the log transport, performing buffering * of partially sent data if needed. The return value indicates whether we * successfully sent this message, or if it should be resent by the caller. **/ static LogProtoStatus log_proto_file_writer_post(LogProtoClient *s, guchar *msg, gsize msg_len, gboolean *consumed) { LogProtoFileWriter *self = (LogProtoFileWriter *)s; LogProtoStatus result; *consumed = FALSE; if (self->buf_count >= self->buf_size || self->partial) { result = log_proto_file_writer_flush(s); if (result != LPS_SUCCESS || self->buf_count >= self->buf_size || self->partial) { /* don't consume a new message if flush failed OR if we couldn't * progress in flush() to empty the outgoing buffer (either * buffers or partial) */ return result; } } /* register the new message */ self->buffer[self->buf_count].iov_base = (void *) msg; self->buffer[self->buf_count].iov_len = msg_len; ++self->buf_count; self->sum_len += msg_len; *consumed = TRUE; log_proto_client_msg_ack(&self->super, 1); if (self->buf_count == self->buf_size) { /* we have reached the max buffer size -> we need to write the messages */ return log_proto_file_writer_flush(s); } return LPS_SUCCESS; } static gboolean log_proto_file_writer_prepare(LogProtoClient *s, gint *fd, GIOCondition *cond) { LogProtoFileWriter *self = (LogProtoFileWriter *) s; *fd = self->super.transport->fd; *cond = self->super.transport->cond; /* if there's no pending I/O in the transport layer, then we want to do a write */ if (*cond == 0) *cond = G_IO_OUT; return self->buf_count > 0 || self->partial; } LogProtoClient * log_proto_file_writer_new(LogTransport *transport, const LogProtoClientOptions *options, gint flush_lines, gint fsync_) { if (flush_lines == 0) /* the flush-lines option has not been specified, use a default value */ flush_lines = 1; #ifdef IOV_MAX if (flush_lines > IOV_MAX) /* limit the flush_lines according to the current platform */ flush_lines = IOV_MAX; #endif /* allocate the structure with the proper number of items at the end */ LogProtoFileWriter *self = (LogProtoFileWriter *)g_malloc0(sizeof(LogProtoFileWriter) + sizeof( struct iovec)*flush_lines); log_proto_client_init(&self->super, transport, options); self->fd = transport->fd; self->buf_size = flush_lines; self->fsync = fsync_; self->super.prepare = log_proto_file_writer_prepare; self->super.post = log_proto_file_writer_post; self->super.flush = log_proto_file_writer_flush; return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/affile/logproto-file-writer.h000066400000000000000000000023121321171025300245760ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef LOG_PROTO_FILE_WRITER_H_INCLUDED #define LOG_PROTO_FILE_WRITER_H_INCLUDED #include "logproto/logproto-client.h" LogProtoClient *log_proto_file_writer_new(LogTransport *transport, const LogProtoClientOptions *options, gint flush_lines, gboolean fsync); #endif syslog-ng-syslog-ng-3.13.2/modules/affile/named-pipe.c000066400000000000000000000103771321171025300225260ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "named-pipe.h" #include "affile-source.h" #include "affile-dest.h" #include "transport/transport-file.h" #include "transport/transport-pipe.h" #include "file-opener.h" #include "logproto/logproto-text-client.h" #include "messages.h" #include #include #include #include #include static gboolean _prepare_open(FileOpener *self, const gchar *name) { struct stat st; if (stat(name, &st) < 0 && (errno == ENOENT || errno == ENOTDIR)) { if (mkfifo(name, self->options->file_perm_options.file_perm) < 0) { msg_error("Error creating named pipe, mkfifo() returned an error", evt_tag_str("file", name), evt_tag_str("error", g_strerror(errno))); return FALSE; } return TRUE; } if (!S_ISFIFO(st.st_mode)) { msg_error("You are using the pipe() driver, underlying file is not a FIFO, it should be used by file()", evt_tag_str("filename", name)); errno = EINVAL; return FALSE; } return TRUE; } static gint _get_open_flags(FileOpener *self, FileDirection dir) { switch (dir) { case AFFILE_DIR_READ: case AFFILE_DIR_WRITE: return (O_RDWR | O_NOCTTY | O_NONBLOCK | O_LARGEFILE); default: g_assert_not_reached(); } } static LogTransport * _construct_transport(FileOpener *self, gint fd) { LogTransport *transport = log_transport_pipe_new(fd); transport->read = log_transport_file_read_and_ignore_eof_method; return transport; } static LogProtoServer * _construct_src_proto(FileOpener *s, LogTransport *transport, LogProtoFileReaderOptions *proto_options) { return log_proto_file_reader_new(transport, proto_options); } static LogProtoClient * _construct_dst_proto(FileOpener *self, LogTransport *transport, LogProtoClientOptions *proto_options) { return log_proto_text_client_new(transport, proto_options); } FileOpener * file_opener_for_named_pipes_new(void) { FileOpener *self = file_opener_new(); self->prepare_open = _prepare_open; self->get_open_flags = _get_open_flags; self->construct_transport = _construct_transport; self->construct_src_proto = _construct_src_proto; self->construct_dst_proto = _construct_dst_proto; return self; } LogDriver * pipe_sd_new(gchar *filename, GlobalConfig *cfg) { AFFileSourceDriver *self = affile_sd_new_instance(filename, cfg); self->file_reader_options.reader_options.super.stats_source = SCS_PIPE; if (cfg_is_config_version_older(cfg, 0x0302)) { msg_warning_once("WARNING: the expected message format is being changed for pipe() to improve " "syslogd compatibity with " VERSION_3_2 ". If you are using custom " "applications which bypass the syslog() API, you might " "need the 'expect-hostname' flag to get the old behaviour back"); } else { self->file_reader_options.reader_options.parse_options.flags &= ~LP_EXPECT_HOSTNAME; } self->file_opener = file_opener_for_named_pipes_new(); return &self->super.super; } LogDriver * pipe_dd_new(gchar *filename, GlobalConfig *cfg) { AFFileDestDriver *self = affile_dd_new_instance(filename, cfg); self->writer_options.stats_source = SCS_PIPE; self->file_opener = file_opener_for_named_pipes_new(); return &self->super.super; } syslog-ng-syslog-ng-3.13.2/modules/affile/named-pipe.h000066400000000000000000000023571321171025300225320ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFFILE_NAMED_PIPE_H_INCLUDED #define AFFILE_NAMED_PIPE_H_INCLUDED #include "driver.h" #include "cfg.h" #include "file-opener.h" FileOpener *file_opener_for_named_pipes_new(void); LogDriver *pipe_sd_new(gchar *filename, GlobalConfig *cfg); LogDriver *pipe_dd_new(gchar *filename, GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/modules/affile/poll-file-changes.c000066400000000000000000000135271321171025300240000ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "poll-file-changes.h" #include "logpipe.h" #include #include #include #include #include #include #include #include #include #include #include #include typedef struct _PollFileChanges { PollEvents super; gint fd; gchar *follow_filename; gint follow_freq; struct iv_timer follow_timer; LogPipe *control; } PollFileChanges; /* follow timer callback. Check if the file has new content, or deleted or * moved. Ran every follow_freq seconds. */ static void poll_file_changes_check_file(gpointer s) { PollFileChanges *self = (PollFileChanges *) s; struct stat st, followed_st; off_t pos = -1; gint fd = self->fd; msg_trace("Checking if the followed file has new lines", evt_tag_str("follow_filename", self->follow_filename)); if (fd >= 0) { pos = lseek(fd, 0, SEEK_CUR); if (pos == (off_t) -1) { msg_error("Error invoking seek on followed file", evt_tag_errno("error", errno)); goto reschedule; } if (fstat(fd, &st) < 0) { if (errno == ESTALE) { msg_trace("log_reader_fd_check file moved ESTALE", evt_tag_str("follow_filename", self->follow_filename)); log_pipe_notify(self->control, NC_FILE_MOVED, self); return; } else { msg_error("Error invoking fstat() on followed file", evt_tag_errno("error", errno)); goto reschedule; } } msg_trace("log_reader_fd_check", evt_tag_int("pos", pos), evt_tag_int("size", st.st_size)); if (pos < st.st_size || !S_ISREG(st.st_mode)) { /* we have data to read */ poll_events_invoke_callback(s); return; } else if (pos == st.st_size) { /* we are at EOF */ log_pipe_notify(self->control, NC_FILE_EOF, self); } else if (pos > st.st_size) { /* the last known position is larger than the current size of the file. it got truncated. Restart from the beginning. */ log_pipe_notify(self->control, NC_FILE_MOVED, self); /* we may be freed by the time the notification above returns */ return; } } if (self->follow_filename) { if (stat(self->follow_filename, &followed_st) != -1) { if (fd < 0 || (st.st_ino != followed_st.st_ino && followed_st.st_size > 0)) { msg_trace("log_reader_fd_check file moved eof", evt_tag_int("pos", pos), evt_tag_int("size", followed_st.st_size), evt_tag_str("follow_filename", self->follow_filename)); /* file was moved and we are at EOF, follow the new file */ log_pipe_notify(self->control, NC_FILE_MOVED, self); /* we may be freed by the time the notification above returns */ return; } } else { msg_verbose("Follow mode file still does not exist", evt_tag_str("filename", self->follow_filename)); } } reschedule: poll_events_update_watches(s, G_IO_IN); } static void poll_file_changes_stop_watches(PollEvents *s) { PollFileChanges *self = (PollFileChanges *) s; if (iv_timer_registered(&self->follow_timer)) iv_timer_unregister(&self->follow_timer); } static void poll_file_changes_rearm_timer(PollFileChanges *self) { iv_validate_now(); self->follow_timer.expires = iv_now; timespec_add_msec(&self->follow_timer.expires, self->follow_freq); iv_timer_register(&self->follow_timer); } static void poll_file_changes_update_watches(PollEvents *s, GIOCondition cond) { PollFileChanges *self = (PollFileChanges *) s; /* we can only provide input events */ g_assert((cond & ~G_IO_IN) == 0); poll_file_changes_stop_watches(s); if (cond & G_IO_IN) poll_file_changes_rearm_timer(self); } static void poll_file_changes_free(PollEvents *s) { PollFileChanges *self = (PollFileChanges *) s; log_pipe_unref(self->control); g_free(self->follow_filename); } PollEvents * poll_file_changes_new(gint fd, const gchar *follow_filename, gint follow_freq, LogPipe *control) { PollFileChanges *self = g_new0(PollFileChanges, 1); self->super.stop_watches = poll_file_changes_stop_watches; self->super.update_watches = poll_file_changes_update_watches; self->super.free_fn = poll_file_changes_free; self->fd = fd; self->follow_filename = g_strdup(follow_filename); self->follow_freq = follow_freq; self->control = log_pipe_ref(control); IV_TIMER_INIT(&self->follow_timer); self->follow_timer.cookie = self; self->follow_timer.handler = poll_file_changes_check_file; return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/affile/poll-file-changes.h000066400000000000000000000022271321171025300240000ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef POLL_FILE_CHANGES_H_INCLUDED #define POLL_FILE_CHANGES_H_INCLUDED #include "poll-events.h" PollEvents *poll_file_changes_new(gint fd, const gchar *follow_filename, gint follow_freq, LogPipe *control); #endif syslog-ng-syslog-ng-3.13.2/modules/affile/regular-files.c000066400000000000000000000065341321171025300232500ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "file-specializations.h" #include "transport/transport-file.h" #include "logproto-file-writer.h" #include "messages.h" #include #include #include #include static gboolean _prepare_open(FileOpener *self, const gchar *name) { struct stat st; if (stat(name, &st) >= 0) { if (S_ISFIFO(st.st_mode)) { msg_error("You are using the file() driver, underlying file is a FIFO, it should be used by pipe()", evt_tag_str("filename", name)); errno = EINVAL; return FALSE; } } return TRUE; } static LogTransport * _construct_src_transport(FileOpener *self, gint fd) { LogTransport *transport = log_transport_file_new(fd); transport->read = log_transport_file_read_and_ignore_eof_method; return transport; } static LogProtoServer * _construct_src_proto(FileOpener *s, LogTransport *transport, LogProtoFileReaderOptions *proto_options) { proto_options->super.super.position_tracking_enabled = TRUE; return log_proto_file_reader_new(transport, proto_options); } FileOpener * file_opener_for_regular_source_files_new(void) { FileOpener *self = file_opener_new(); self->prepare_open = _prepare_open; self->construct_transport = _construct_src_transport; self->construct_src_proto = _construct_src_proto; return self; } typedef struct _FileOpenerRegularDestFiles { FileOpener super; const LogWriterOptions *writer_options; gboolean *use_fsync; } FileOpenerRegularDestFiles; static LogProtoClient * _construct_dst_proto(FileOpener *s, LogTransport *transport, LogProtoClientOptions *proto_options) { FileOpenerRegularDestFiles *self = (FileOpenerRegularDestFiles *) s; return log_proto_file_writer_new(transport, proto_options, self->writer_options->flush_lines, *self->use_fsync); } static LogTransport * _construct_transport(FileOpener *s, gint fd) { return log_transport_file_new(fd); } FileOpener * file_opener_for_regular_dest_files_new(const LogWriterOptions *writer_options, gboolean *use_fsync) { FileOpenerRegularDestFiles *self = g_new0(FileOpenerRegularDestFiles, 1); file_opener_init_instance(&self->super); self->super.construct_transport = _construct_transport; self->super.construct_dst_proto = _construct_dst_proto; self->writer_options = writer_options; self->use_fsync = use_fsync; return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/affile/stdin.c000066400000000000000000000037301321171025300216230ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "file-specializations.h" #include "transport/transport-file.h" #include "affile-source.h" #include static LogTransport * _construct_transport(FileOpener *self, gint fd) { return log_transport_file_new(fd); } static LogProtoServer * _construct_src_proto(FileOpener *s, LogTransport *transport, LogProtoFileReaderOptions *proto_options) { return log_proto_file_reader_new(transport, proto_options); } static gint _open(FileOpener *self, const gchar *name, gint flags) { return dup(0); } FileOpener * file_opener_for_stdin_new(void) { FileOpener *self = file_opener_new(); self->construct_transport = _construct_transport; self->construct_src_proto = _construct_src_proto; self->open = _open; return self; } LogDriver * stdin_sd_new(GlobalConfig *cfg) { AFFileSourceDriver *self = affile_sd_new_instance("-", cfg); self->file_reader_options.exit_on_eof = TRUE; self->file_reader_options.reader_options.super.stats_source = SCS_STDIN; self->file_opener = file_opener_for_stdin_new(); return &self->super.super; } syslog-ng-syslog-ng-3.13.2/modules/affile/stdin.h000066400000000000000000000021151321171025300216240ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFFILE_STDIN_H_INCLUDED #define AFFILE_STDIN_H_INCLUDED #include "driver.h" #include "cfg.h" LogDriver *stdin_sd_new(GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/modules/affile/tests/000077500000000000000000000000001321171025300214755ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/affile/tests/Makefile.am000066400000000000000000000022211321171025300235260ustar00rootroot00000000000000if ENABLE_CRITERION check_PROGRAMS += \ ${modules_affile_tests_TESTS} modules_affile_tests_TESTS = \ modules/affile/tests/test_wildcard_source \ modules/affile/tests/test_directory_monitor \ modules/affile/tests/test_collection_comporator \ modules/affile/tests/test_file_opener modules_affile_tests_test_wildcard_source_CFLAGS = $(TEST_CFLAGS) -I$(top_srcdir)/modules/affile modules_affile_tests_test_wildcard_source_LDADD = $(TEST_LDADD) \ -dlpreopen $(top_builddir)/modules/affile/libaffile.la modules_affile_tests_test_directory_monitor_CFLAGS = $(TEST_CFLAGS) -I$(top_srcdir)/modules/affile modules_affile_tests_test_directory_monitor_LDADD = $(TEST_LDADD) \ -dlpreopen $(top_builddir)/modules/affile/libaffile.la modules_affile_tests_test_collection_comporator_CFLAGS = $(TEST_CFLAGS) -I$(top_srcdir)/modules/affile modules_affile_tests_test_collection_comporator_LDADD = $(TEST_LDADD) \ -dlpreopen $(top_builddir)/modules/affile/libaffile.la modules_affile_tests_test_file_opener_CFLAGS = $(TEST_CFLAGS) modules_affile_tests_test_file_opener_LDADD = $(TEST_LDADD) \ -dlpreopen $(top_builddir)/modules/affile/libaffile.la endif syslog-ng-syslog-ng-3.13.2/modules/affile/tests/test_collection_comporator.c000066400000000000000000000104061321171025300273010ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "collection-comporator.h" #include #include #include #include typedef struct _TestData { GHashTable *deleted_entries; GHashTable *new_entries; } TestData; static const gchar *TEST = "test"; TestData * test_data_new(void) { TestData *self = g_new0(TestData, 1); self->deleted_entries = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); self->new_entries = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); return self; } void test_data_free(TestData *self) { g_hash_table_unref(self->deleted_entries); g_hash_table_unref(self->new_entries); g_free(self); } static void _handle_new(const gchar *filename, gpointer data) { TestData *self = (TestData *)data; g_hash_table_insert(self->new_entries, g_strdup(filename), (gchar *)TEST); } static void _handle_delete(const gchar *filename, gpointer data) { TestData *self = (TestData *)data; g_hash_table_insert(self->deleted_entries, g_strdup(filename), (gchar *)TEST); } struct TestFileList { const gchar *initial_files[10]; const gchar *result_files[10]; const gchar *expected_deleted_files[10]; const gchar *expected_new_files[10]; }; struct TestFileList nothing_changed = {{"test1", "test2"}, {"test1", "test2"}, {NULL}, {NULL}}; struct TestFileList last_file_deleted = {{"test1", "test2"}, {"test2"}, {"test1"}, {NULL}}; struct TestFileList first_file_deleted = {{"test1", "test2"}, {"test1"}, {"test2"}, {NULL}}; struct TestFileList delete_all = {{"test1", "test2"}, {NULL}, {"test1", "test2"}, {NULL}}; struct TestFileList create_all = {{NULL}, {"test1", "test2"}, {NULL}, {"test1", "test2"}}; struct TestFileList mixed = {{"test1", "test2", "test3"}, {"test1", "test4"}, {"test2", "test3"}, {"test4"}}; ParameterizedTestParameters(params, multiple) { static struct TestFileList params[6]; params[0] = nothing_changed; params[1] = last_file_deleted; params[2] = first_file_deleted; params[3] = delete_all; params[4] = create_all; params[5] = mixed; return cr_make_param_array(struct TestFileList, params, sizeof (params) / sizeof (struct TestFileList)); } ParameterizedTest(struct TestFileList *tup, params, multiple) { TestData *data = test_data_new(); CollectionComporator *comporator = collection_comporator_new(); collection_comporator_set_callbacks(comporator, _handle_new, _handle_delete, data); gint i; for (i = 0; tup->initial_files[i] != NULL; i++) { collection_comporator_add_initial_value(comporator, tup->initial_files[i]); } collection_comporator_start(comporator); for (i = 0; tup->result_files[i] != NULL; i++) { collection_comporator_add_value(comporator, tup->result_files[i]); } collection_comporator_stop(comporator); for (i = 0; tup->expected_deleted_files[i] != NULL; i++) { cr_assert_str_eq(g_hash_table_lookup(data->deleted_entries, tup->expected_deleted_files[i]), TEST); } cr_assert_eq(g_hash_table_size(data->deleted_entries), i); for (i = 0; tup->expected_new_files[i] != NULL; i++) { cr_assert_str_eq(g_hash_table_lookup(data->new_entries, tup->expected_new_files[i]), TEST); } cr_assert_eq(g_hash_table_size(data->new_entries), i); collection_comporator_free(comporator); test_data_free(data); } syslog-ng-syslog-ng-3.13.2/modules/affile/tests/test_directory_monitor.c000066400000000000000000000111731321171025300264560ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "directory-monitor.h" #include "directory-monitor-factory.h" #include "directory-monitor-inotify.h" #include "directory-monitor-poll.h" #include "apphook.h" #include #include #include TestSuite(directory_monitor, .init = app_startup, .fini = app_shutdown); static void _callback(const DirectoryMonitorEvent *event, gpointer user_data) { GList **p_list = (GList **)user_data; if (event->event_type == FILE_CREATED) { *p_list = g_list_append(*p_list, g_strdup(event->name)); } } Test(directory_monitor, read_content_of_directory) { gchar *dir_pattern = g_strdup("read_content_of_directoryXXXXXX"); gchar *tmpdir = g_mkdtemp(dir_pattern); cr_assert(tmpdir); gchar *file_list[10] = {0}; gchar *file_list_full_path[10] = {0}; for (gint i = 0; i < 10; i++) { GError *error = NULL; file_list[i] = g_strdup_printf("file_%d.txt", i); file_list_full_path[i] = g_build_filename(tmpdir, file_list[i], NULL);; gboolean res = g_file_set_contents(file_list_full_path[i], file_list[i], strlen(file_list[i]), &error); cr_assert(res != FALSE, "Error: %s", error ? error->message : "OK"); } DirectoryMonitor *monitor = directory_monitor_new(tmpdir, 1); GList *found_files = NULL; directory_monitor_set_callback(monitor, _callback, &found_files); directory_monitor_start(monitor); for (gint i = 0; i < 10; i++) { cr_assert(g_list_find_custom(found_files, file_list[i], (GCompareFunc)strcmp), "Can not find: %s", file_list[i]); unlink(file_list_full_path[i]); g_free(file_list_full_path[i]); g_free(file_list[i]); } g_list_free_full(found_files, g_free); g_rmdir(tmpdir); g_free(tmpdir); directory_monitor_free(monitor); } Test(directory_monitor, non_existing_directory) { DirectoryMonitor *monitor = directory_monitor_new("this directory should not exist", 1); GList *found_files = NULL; directory_monitor_set_callback(monitor, _callback, &found_files); directory_monitor_start(monitor); cr_assert_null(found_files); directory_monitor_free(monitor); } TestSuite(directory_monitor_tools, .init = app_startup, .fini = app_shutdown); Test(directory_monitor_tools, build_filename) { gchar *built_path = build_filename(NULL, "tmp"); cr_assert_str_eq("tmp", built_path); g_free(built_path); built_path = build_filename("tmp", "test_dir"); cr_assert_str_eq("tmp/test_dir", built_path); g_free(built_path); built_path = build_filename("tmp", NULL); cr_assert_eq(NULL, built_path); } TestSuite(directory_monitor_factory, .init = app_startup, .fini = app_shutdown); Test(directory_monitor_factory, check_monitor_method) { #if SYSLOG_NG_HAVE_INOTIFY cr_assert_eq(MM_INOTIFY, directory_monitor_factory_get_monitor_method("inotify")); #endif cr_assert_eq(MM_AUTO, directory_monitor_factory_get_monitor_method("auto")); cr_assert_eq(MM_POLL, directory_monitor_factory_get_monitor_method("poll")); cr_assert_eq(MM_UNKNOWN, directory_monitor_factory_get_monitor_method("something else")); } Test(directory_monitor_factory, check_constructor) { DirectoryMonitorOptions options = {.dir = "/tmp", .follow_freq = 1, .method = MM_AUTO}; #if SYSLOG_NG_HAVE_INOTIFY cr_assert_eq(directory_monitor_factory_get_constructor(&options), directory_monitor_inotify_new); options.method = MM_INOTIFY; cr_assert_eq(directory_monitor_factory_get_constructor(&options), directory_monitor_inotify_new); #else cr_assert_eq(directory_monitor_factory_get_constructor(&options), directory_monitor_poll_new); #endif options.method = MM_POLL; cr_assert_eq(directory_monitor_factory_get_constructor(&options), directory_monitor_poll_new); options.method = MM_UNKNOWN; cr_assert_eq(directory_monitor_factory_get_constructor(&options), NULL); } syslog-ng-syslog-ng-3.13.2/modules/affile/tests/test_file_opener.c000066400000000000000000000107751321171025300252010ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Laszlo Budai * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include "affile/file-opener.h" #include "affile/named-pipe.h" #include "affile/file-specializations.h" #include "messages.h" #include #include #include #include #include #include #include #define CREATE_DIRS 0x01 #define SRC_FILE 0x02 #define DST_FILE 0x04 static mode_t get_fd_file_mode(gint fd) { struct stat st; fstat(fd, &st); return st.st_mode; } static gboolean open_fd(FileOpener *file_opener, gchar *fname, gint extra_flags, gint *fd) { FileOpenerOptions open_opts; FileDirection dir; if (extra_flags & DST_FILE) dir = AFFILE_DIR_WRITE; else if (extra_flags & SRC_FILE) dir = AFFILE_DIR_READ; else g_assert_not_reached(); file_opener_options_defaults(&open_opts); file_opener_options_init(&open_opts, configuration); open_opts.create_dirs = !!(extra_flags & CREATE_DIRS); open_opts.needs_privileges = FALSE; file_opener_set_options(file_opener, &open_opts); gboolean success = file_opener_open_fd(file_opener, fname, dir, fd); file_opener_free(file_opener); return success; } static gboolean open_regular_source_file(gchar *fname, gint extra_flags, gint *fd) { FileOpener *file_opener = file_opener_for_regular_source_files_new(); return open_fd(file_opener, fname, extra_flags, fd); } static gboolean open_named_pipe(gchar *fname, gint extra_flags, gint *fd) { FileOpener *file_opener = file_opener_for_named_pipes_new(); return open_fd(file_opener, fname, extra_flags, fd); } Test(file_opener, test_open_regular_file) { gint fd; gchar fname[] = "test.log"; cr_assert(open_regular_source_file(fname, DST_FILE, &fd), "file_opener_open_fd failed: %s", fname); cr_assert(S_ISREG(get_fd_file_mode(fd)) != 0, "%s is not regular file", fname); close(fd); cr_assert(open_regular_source_file(fname, SRC_FILE, &fd), "file_opener_open_fd failed: %s", fname); cr_assert(S_ISREG(get_fd_file_mode(fd)) != 0, "%s is not regular file", fname); close(fd); remove(fname); } Test(file_opener, test_open_named_pipe) { gint fd; gchar fname[] = "test.pipe"; cr_assert(open_named_pipe(fname, SRC_FILE, &fd), "failed to open %s", fname); cr_assert(S_ISFIFO(get_fd_file_mode(fd)) != 0, "%s is not pipe", fname); close(fd); remove(fname); } Test(file_opener, test_spurious_path) { gint fd; gchar fname[] = "./../test.fname"; cr_assert_not(open_regular_source_file(fname, DST_FILE, &fd), "file_opener_open_fd should not be able to open: %s", fname); } Test(file_opener, test_create_file_in_nonexistent_dir) { gchar test_dir[] = "nonexistent"; gchar fname[] = "nonexistent/test.txt"; gint fd; cr_assert_not(open_regular_source_file(fname, DST_FILE, &fd), "file_opener_open_fd failed: %s", fname); cr_assert(open_regular_source_file(fname, CREATE_DIRS | DST_FILE, &fd), "file_opener_open_fd failed: %s", fname); close(fd); remove(fname); rmdir(test_dir); } Test(file_opener, test_file_flags) { gint fd; gchar fname[] = "test_flags.log"; cr_assert(open_regular_source_file(fname, DST_FILE, &fd), "file_opener_open_fd failed: %s", fname); cr_assert((fcntl(fd, F_GETFL) & O_APPEND) == O_APPEND, "invalid open flags"); close(fd); cr_assert(open_regular_source_file(fname, SRC_FILE, &fd), "file_opener_open_fd failed: %s", fname); cr_assert((fcntl(fd, F_GETFL) & O_APPEND) != O_APPEND, "invalid open flags"); close(fd); remove(fname); } static void setup(void) { msg_init(FALSE); configuration = cfg_new(VERSION_VALUE); } void teardown(void) { } TestSuite(file_opener, .init = setup, .fini = teardown); syslog-ng-syslog-ng-3.13.2/modules/affile/tests/test_wildcard_source.c000066400000000000000000000155061321171025300260600ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg.h" #include "apphook.h" #include "config_parse_lib.h" #include "cfg-grammar.h" #include "plugin.h" #include "wildcard-source.h" #include static void _init(void) { app_startup(); configuration = cfg_new_snippet(); cr_assert(cfg_load_module(configuration, "affile")); } static void _deinit(void) { cfg_deinit(configuration); cfg_free(configuration); } static gboolean _parse_config(const gchar *config) { gchar *raw_config = g_strdup_printf("source s_test { wildcard-file(%s); }; log { source(s_test); };", config); gboolean result = parse_config(raw_config, LL_CONTEXT_ROOT, NULL, NULL); g_free(raw_config); return result; } static WildcardSourceDriver * _create_wildcard_filesource(const gchar *wildcard_config) { cr_assert(_parse_config(wildcard_config), "Parsing the given configuration failed"); cr_assert(cfg_init(configuration), "Config initialization failed"); LogExprNode *expr_node = cfg_tree_get_object(&configuration->tree, ENC_SOURCE, "s_test"); cr_assert(expr_node != NULL); WildcardSourceDriver *driver = (WildcardSourceDriver *)expr_node->children->children->object; cr_assert(driver != NULL); return driver; } TestSuite(wildcard_source, .init = _init, .fini = _deinit); Test(wildcard_source, initial_test) { WildcardSourceDriver *driver = _create_wildcard_filesource("base-dir(/test_non_existent_dir)" "filename-pattern(*.log)" "recursive(yes)" "max-files(100)" "monitor-method(poll)"); cr_assert_str_eq(driver->base_dir, "/test_non_existent_dir"); cr_assert_str_eq(driver->filename_pattern, "*.log"); cr_assert_eq(driver->max_files, 100); cr_assert_eq(driver->recursive, TRUE); cr_assert_eq(driver->monitor_method, MM_POLL); } Test(wildcard_source, test_option_inheritance) { WildcardSourceDriver *driver = _create_wildcard_filesource("base-dir(/test_non_existent_dir)" "filename-pattern(*.log)" "recursive(yes)" "max-files(100)" "follow-freq(10)" "follow_freq(10.0)" "pad_size(5)" "multi-line-mode(regexp)" "multi-line-prefix(\\d+)" "multi-line-garbage(garbage)"); cr_assert_eq(driver->file_reader_options.follow_freq, 10000); cr_assert_eq(file_reader_options_get_log_proto_options(&driver->file_reader_options)->pad_size, 5); cr_assert_eq(file_reader_options_get_log_proto_options(&driver->file_reader_options)->super.mode, MLM_PREFIX_GARBAGE); cr_assert(file_reader_options_get_log_proto_options(&driver->file_reader_options)->super.prefix != NULL); cr_assert(file_reader_options_get_log_proto_options(&driver->file_reader_options)->super.garbage != NULL); } Test(wildcard_source, test_option_duplication) { WildcardSourceDriver *driver = _create_wildcard_filesource("base-dir(/tmp)" "filename-pattern(*.txt)" "base-dir(/test_non_existent_dir)" "filename-pattern(*.log)"); cr_assert_str_eq(driver->base_dir, "/test_non_existent_dir"); cr_assert_str_eq(driver->filename_pattern, "*.log"); } Test(wildcard_source, test_filename_pattern_required_options) { start_grabbing_messages(); cr_assert(_parse_config("base-dir(/tmp)")); cr_assert(!cfg_init(configuration), "Config initialization should be failed"); stop_grabbing_messages(); cr_assert(assert_grabbed_messages_contain_non_fatal("filename-pattern option is required", NULL)); reset_grabbed_messages(); } Test(wildcard_source, test_base_dir_required_options) { start_grabbing_messages(); cr_assert(_parse_config("filename-pattern(/tmp)")); cr_assert(!cfg_init(configuration), "Config initialization should be failed"); stop_grabbing_messages(); cr_assert(assert_grabbed_messages_contain_non_fatal("base-dir option is required", NULL)); reset_grabbed_messages(); } Test(wildcard_source, test_invalid_monitor_method) { start_grabbing_messages(); cr_assert(!_parse_config("monitor-method(\"something else\"")); stop_grabbing_messages(); cr_assert(assert_grabbed_messages_contain_non_fatal("Invalid monitor-method", NULL)); reset_grabbed_messages(); } Test(wildcard_source, test_minimum_window_size) { WildcardSourceDriver *driver = _create_wildcard_filesource("base-dir(/test_non_existent_dir)" "filename-pattern(*.log)" "recursive(yes)" "max_files(100)" "log_iw_size(1000)"); cr_assert_eq(driver->file_reader_options.reader_options.super.init_window_size, MINIMUM_WINDOW_SIZE); } Test(wildcard_source, test_window_size) { WildcardSourceDriver *driver = _create_wildcard_filesource("base-dir(/test_non_existent_dir)" "filename-pattern(*.log)" "recursive(yes)" "max_files(10)" "log_iw_size(10000)"); cr_assert_eq(driver->file_reader_options.reader_options.super.init_window_size, 1000); } syslog-ng-syslog-ng-3.13.2/modules/affile/transport-prockmsg.c000066400000000000000000000044131321171025300243600ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "transport-prockmsg.h" #include "messages.h" #include "alarms.h" #include #include typedef struct _LogTransportDevice LogTransportDevice; struct _LogTransportDevice { LogTransport super; gint timeout; }; static gssize log_transport_prockmsg_read_method(LogTransport *s, gpointer buf, gsize buflen, LogTransportAuxData *aux) { LogTransportDevice *self = (LogTransportDevice *) s; gint rc; do { if (self->timeout) alarm_set(self->timeout); rc = read(self->super.fd, buf, buflen); if (self->timeout > 0 && rc == -1 && errno == EINTR && alarm_has_fired()) { msg_notice("Nonblocking read has blocked, returning with an error", evt_tag_int("fd", self->super.fd), evt_tag_int("timeout", self->timeout)); alarm_cancel(); break; } if (self->timeout) alarm_cancel(); } while (rc == -1 && errno == EINTR); return rc; } LogTransport * log_transport_prockmsg_new(gint fd, gint timeout) { LogTransportDevice *self = g_new0(LogTransportDevice, 1); log_transport_init_instance(&self->super, fd); self->timeout = timeout; self->super.read = log_transport_prockmsg_read_method; self->super.write = NULL; self->super.free_fn = log_transport_free_method; return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/affile/transport-prockmsg.h000066400000000000000000000021631321171025300243650ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFFILE_PROCKMSG_H_INCLUDED #define AFFILE_PROCKMSG_H_INCLUDED 1 #include "transport/logtransport.h" LogTransport *log_transport_prockmsg_new(gint fd, gint timeout); #endif syslog-ng-syslog-ng-3.13.2/modules/affile/wildcard-source.c000066400000000000000000000251631321171025300235750ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "wildcard-source.h" #include "directory-monitor-factory.h" #include "messages.h" #include "file-specializations.h" #include #define DEFAULT_SD_OPEN_FLAGS (O_RDONLY | O_NOCTTY | O_NONBLOCK | O_LARGEFILE) static void _add_directory_monitor(WildcardSourceDriver *self, const gchar *directory); static gboolean _check_required_options(WildcardSourceDriver *self) { if (!self->base_dir) { msg_error("Error: base-dir option is required", evt_tag_str("driver", self->super.super.id)); return FALSE; } if (!self->filename_pattern) { msg_error("Error: filename-pattern option is required", evt_tag_str("driver", self->super.super.id)); return FALSE; } return TRUE; } void _create_file_reader(WildcardSourceDriver *self, const gchar *full_path) { FileReader *reader = NULL; GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); if (g_hash_table_size(self->file_readers) >= self->max_files) { msg_warning("Number of allowed monitorod file is reached, rejecting read file", evt_tag_str("source", self->super.super.group), evt_tag_str("filename", full_path), evt_tag_int("max_files", self->max_files)); return; } reader = file_reader_new(full_path, &self->file_reader_options, self->file_opener, &self->super, cfg); log_pipe_append(&reader->super, &self->super.super.super); if (!log_pipe_init(&reader->super)) { msg_warning("File reader initialization failed", evt_tag_str("filename", full_path), evt_tag_str("source_driver", self->super.super.group)); log_pipe_unref(&reader->super); } else { g_hash_table_insert(self->file_readers, g_strdup(full_path), reader); } } static void _handle_file_created(WildcardSourceDriver *self, const DirectoryMonitorEvent *event) { if (g_pattern_match_string(self->compiled_pattern, event->name)) { FileReader *reader = g_hash_table_lookup(self->file_readers, event->full_path); if (!reader) { _create_file_reader(self, event->full_path); } else { if (!log_pipe_init(&reader->super)) { msg_error("Can not re-initialize reader for file", evt_tag_str("filename", event->full_path)); } } } } void _handle_directory_created(WildcardSourceDriver *self, const DirectoryMonitorEvent *event) { if (self->recursive) { msg_debug("Directory created", evt_tag_str("name", event->full_path)); DirectoryMonitor *monitor = g_hash_table_lookup(self->directory_monitors, event->full_path); if (!monitor) { _add_directory_monitor(self, event->full_path); } } } void _handle_deleted(WildcardSourceDriver *self, const DirectoryMonitorEvent *event) { FileReader *reader = g_hash_table_lookup(self->file_readers, event->full_path); if (reader) { msg_debug("Monitored file is deleted", evt_tag_str("filename", event->full_path)); log_pipe_deinit(&reader->super); file_reader_remove_persist_state(reader); } else if (g_hash_table_remove(self->directory_monitors, event->full_path)) { msg_debug("Monitored directory is deleted", evt_tag_str("directory", event->full_path)); } } static void _on_directory_monitor_changed(const DirectoryMonitorEvent *event, gpointer user_data) { WildcardSourceDriver *self = (WildcardSourceDriver *)user_data; if ((event->event_type == FILE_CREATED)) { _handle_file_created(self, event); } else if (event->event_type == DIRECTORY_CREATED) { _handle_directory_created(self, event); } else if (event->event_type == DELETED) { _handle_deleted(self, event); } } static void _ensure_minimum_window_size(WildcardSourceDriver *self) { if (self->file_reader_options.reader_options.super.init_window_size < MINIMUM_WINDOW_SIZE) { msg_warning("log_iw_size configuration value was divided by the value of max-files()." " The result was too small, clamping to minimum entries." " Ensure you have a proper log_fifo_size setting to avoid message loss.", evt_tag_int("orig_log_iw_size", self->file_reader_options.reader_options.super.init_window_size), evt_tag_int("new_log_iw_size", MINIMUM_WINDOW_SIZE), evt_tag_int("min_log_fifo_size", MINIMUM_WINDOW_SIZE * self->max_files)); self->file_reader_options.reader_options.super.init_window_size = MINIMUM_WINDOW_SIZE; } } static void _init_reader_options(WildcardSourceDriver *self, GlobalConfig *cfg) { if (!self->window_size_initialized) { self->file_reader_options.reader_options.super.init_window_size /= self->max_files; _ensure_minimum_window_size(self); self->window_size_initialized = TRUE; } file_reader_options_init(&self->file_reader_options, cfg, self->super.super.group); } static void _init_opener_options(WildcardSourceDriver *self, GlobalConfig *cfg) { file_opener_options_init(&self->file_opener_options, cfg); file_opener_set_options(self->file_opener, &self->file_opener_options); } static gboolean _init_filename_pattern(WildcardSourceDriver *self) { self->compiled_pattern = g_pattern_spec_new(self->filename_pattern); if (!self->compiled_pattern) { msg_error("Invalid filename-pattern", evt_tag_str("filename-pattern", self->filename_pattern)); return FALSE; } return TRUE; } static void _add_directory_monitor(WildcardSourceDriver *self, const gchar *directory) { DirectoryMonitorOptions options = { .dir = directory, .follow_freq = self->file_reader_options.follow_freq, .method = self->monitor_method }; DirectoryMonitor *monitor = create_directory_monitor(&options); directory_monitor_set_callback(monitor, _on_directory_monitor_changed, self); directory_monitor_start(monitor); g_hash_table_insert(self->directory_monitors, g_strdup(directory), monitor); } static gboolean _init(LogPipe *s) { WildcardSourceDriver *self = (WildcardSourceDriver *)s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_src_driver_init_method(s)) { return FALSE; } if (!_check_required_options(self)) { return FALSE; } if (!_init_filename_pattern(self)) { return FALSE; } _init_reader_options(self, cfg); _init_opener_options(self, cfg); _add_directory_monitor(self, self->base_dir); return TRUE; } static void _deinit_reader(gpointer key, gpointer value, gpointer user_data) { FileReader *reader = (FileReader *) value; log_pipe_deinit(&reader->super); } static gboolean _deinit(LogPipe *s) { WildcardSourceDriver *self = (WildcardSourceDriver *)s; g_pattern_spec_free(self->compiled_pattern); g_hash_table_foreach(self->file_readers, _deinit_reader, NULL); return TRUE; } void wildcard_sd_set_base_dir(LogDriver *s, const gchar *base_dir) { WildcardSourceDriver *self = (WildcardSourceDriver *)s; g_free(self->base_dir); self->base_dir = g_strdup(base_dir); } void wildcard_sd_set_filename_pattern(LogDriver *s, const gchar *filename_pattern) { WildcardSourceDriver *self = (WildcardSourceDriver *)s; g_free(self->filename_pattern); self->filename_pattern = g_strdup(filename_pattern); } void wildcard_sd_set_recursive(LogDriver *s, gboolean recursive) { WildcardSourceDriver *self = (WildcardSourceDriver *)s; self->recursive = recursive; } gboolean wildcard_sd_set_monitor_method(LogDriver *s, const gchar *method) { WildcardSourceDriver *self = (WildcardSourceDriver *)s; MonitorMethod new_method = directory_monitor_factory_get_monitor_method(method); if (new_method == MM_UNKNOWN) { msg_error("Invalid monitor-method", evt_tag_str("monitor-method", method)); return FALSE; } self->monitor_method = new_method; return TRUE; } void wildcard_sd_set_max_files(LogDriver *s, guint32 max_files) { WildcardSourceDriver *self = (WildcardSourceDriver *)s; self->max_files = max_files; } static void _free(LogPipe *s) { WildcardSourceDriver *self = (WildcardSourceDriver *)s; file_opener_free(self->file_opener); g_free(self->base_dir); g_free(self->filename_pattern); g_hash_table_unref(self->file_readers); g_hash_table_unref(self->directory_monitors); file_reader_options_deinit(&self->file_reader_options); file_opener_options_deinit(&self->file_opener_options); log_src_driver_free(s); } static void _stop_and_destroy_directory_monitor(gpointer s) { DirectoryMonitor *monitor = (DirectoryMonitor *)s; directory_monitor_stop(monitor); directory_monitor_free(monitor); } LogDriver * wildcard_sd_new(GlobalConfig *cfg) { WildcardSourceDriver *self = g_new0(WildcardSourceDriver, 1); log_src_driver_init_instance(&self->super, cfg); self->super.super.super.free_fn = _free; self->super.super.super.init = _init; self->super.super.super.deinit = _deinit; self->file_readers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)log_pipe_unref); self->directory_monitors = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_stop_and_destroy_directory_monitor); self->monitor_method = MM_AUTO; file_reader_options_defaults(&self->file_reader_options); file_opener_options_defaults_dont_change_permissions(&self->file_opener_options); self->file_reader_options.follow_freq = 1000; self->file_reader_options.reader_options.super.init_window_size = MINIMUM_WINDOW_SIZE * DEFAULT_MAX_FILES; self->file_reader_options.reader_options.super.stats_source = SCS_FILE; self->file_reader_options.restore_state = TRUE; self->max_files = DEFAULT_MAX_FILES; self->file_opener = file_opener_for_regular_source_files_new(); return &self->super.super; } syslog-ng-syslog-ng-3.13.2/modules/affile/wildcard-source.h000066400000000000000000000040621321171025300235750ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef MODULES_AFFILE_WILDCARD_SOURCE_H_ #define MODULES_AFFILE_WILDCARD_SOURCE_H_ #include "syslog-ng.h" #include "driver.h" #include "file-reader.h" #include "directory-monitor.h" #include "directory-monitor-factory.h" #define MINIMUM_WINDOW_SIZE 100 #define DEFAULT_MAX_FILES 100 typedef struct _WildcardSourceDriver { LogSrcDriver super; gchar *base_dir; gchar *filename_pattern; MonitorMethod monitor_method; guint32 max_files; gboolean window_size_initialized; gboolean recursive; FileReaderOptions file_reader_options; FileOpenerOptions file_opener_options; GPatternSpec *compiled_pattern; GHashTable *file_readers; GHashTable *directory_monitors; FileOpener *file_opener; } WildcardSourceDriver; LogDriver *wildcard_sd_new(GlobalConfig *cfg); void wildcard_sd_set_base_dir(LogDriver *s, const gchar *base_dir); void wildcard_sd_set_filename_pattern(LogDriver *s, const gchar *filename_pattern); void wildcard_sd_set_recursive(LogDriver *s, gboolean recursive); gboolean wildcard_sd_set_monitor_method(LogDriver *s, const gchar *method); void wildcard_sd_set_max_files(LogDriver *s, guint32 max_files); #endif /* MODULES_AFFILE_WILDCARD_SOURCE_H_ */ syslog-ng-syslog-ng-3.13.2/modules/afmongodb/000077500000000000000000000000001321171025300210415ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afmongodb/Makefile.am000066400000000000000000000037061321171025300231030ustar00rootroot00000000000000DIST_SUBDIRS += @LIBMONGO_SUBDIRS@ if LIBMONGO_INTERNAL CLEAN_SUBDIRS += @LIBMONGO_SUBDIRS@ lmc_EXTRA_DEPS = @LIBMONGO_SUBDIRS@/libmongoc-1.0.la $(lmc_EXTRA_DEPS): ${MAKE} -C modules/afmongodb/mongo-c-driver endif if ENABLE_MONGODB module_LTLIBRARIES += modules/afmongodb/libafmongodb.la modules_afmongodb_libafmongodb_la_CFLAGS = \ $(AM_CFLAGS) \ $(LIBMONGO_CFLAGS) \ -I$(top_srcdir)/modules/afmongodb \ -I$(top_builddir)/modules/afmongodb modules_afmongodb_libafmongodb_la_SOURCES = \ modules/afmongodb/afmongodb-grammar.y \ modules/afmongodb/afmongodb.c \ modules/afmongodb/afmongodb.h \ modules/afmongodb/afmongodb-private.h \ modules/afmongodb/afmongodb-parser.c \ modules/afmongodb/afmongodb-parser.h \ ${DUMMY_C} if ENABLE_LEGACY_MONGODB_OPTIONS modules_afmongodb_libafmongodb_la_SOURCES += \ modules/afmongodb/afmongodb-legacy-uri.c \ modules/afmongodb/afmongodb-legacy-uri.h \ modules/afmongodb/afmongodb-legacy-grammar.c \ modules/afmongodb/afmongodb-legacy-grammar.h \ modules/afmongodb/afmongodb-legacy-private.h \ modules/afmongodb/host-list.c \ modules/afmongodb/host-list.h endif modules_afmongodb_libafmongodb_la_LIBADD = \ $(MODULE_DEPS_LIBS) $(LIBMONGO_LIBS) modules_afmongodb_libafmongodb_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_afmongodb_libafmongodb_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) $(lmc_EXTRA_DEPS) modules/afmongodb modules/afmongodb/ mod-afmongodb mod-mongodb: \ modules/afmongodb/libafmongodb.la include modules/afmongodb/tests/Makefile.am else modules/afmongodb modules/afmongodb/ mod-afmongodb mod-mongodb: endif if LIBMONGO_INTERNAL EXTRA_DIST += \ modules/afmongodb/mongo-c-driver/configure.gnu endif BUILT_SOURCES += \ modules/afmongodb/afmongodb-grammar.y \ modules/afmongodb/afmongodb-grammar.c \ modules/afmongodb/afmongodb-grammar.h EXTRA_DIST += \ modules/afmongodb/afmongodb-grammar.ym .PHONY: modules/afmongodb/ mod-afmongodb mod-mongodb syslog-ng-syslog-ng-3.13.2/modules/afmongodb/afmongodb-grammar.ym000066400000000000000000000076461321171025300250050ustar00rootroot00000000000000/* * Copyright (c) 2010-2015 Balabit * Copyright (c) 2010-2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code requires { #include "afmongodb-parser.h" } %code { #include "cfg-grammar.h" #include "plugin.h" #include "value-pairs/value-pairs.h" } %name-prefix "afmongodb_" %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogDriver **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_MONGODB %token KW_URI %token KW_COLLECTION %token KW_SERVERS %token KW_SAFE_MODE %token KW_PATH %token KW_PASSWORD %token KW_USERNAME %token KW_DATABASE %% start : LL_CONTEXT_DESTINATION KW_MONGODB { last_driver = *instance = afmongodb_dd_new(configuration); } '(' afmongodb_options ')' { YYACCEPT; } ; afmongodb_options : afmongodb_option afmongodb_options | ; afmongodb_option : KW_URI '(' string ')' { afmongodb_dd_set_uri(last_driver, $3); free($3); } | KW_COLLECTION '(' string ')' { afmongodb_dd_set_collection(last_driver, $3); free($3); } | afmongodb_legacy_option | value_pair_option { afmongodb_dd_set_value_pairs(last_driver, $1); } | dest_driver_option | threaded_dest_driver_option | { last_template_options = afmongodb_dd_get_template_options(last_driver); } template_option ; afmongodb_legacy_option : KW_IFDEF { #if SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS } | KW_SERVERS '(' string_list ')' { CHECK_ERROR(afmongodb_dd_validate_network_combination(last_driver), @3, "Can't mix path() & servers()"); afmongodb_dd_set_servers(last_driver, $3); } | KW_HOST '(' string ')' { CHECK_ERROR(afmongodb_dd_validate_network_combination(last_driver), @3, "Can't mix path() & host()"); afmongodb_dd_set_host(last_driver, $3); free($3); } | KW_PORT '(' positive_integer ')' { CHECK_ERROR(afmongodb_dd_validate_network_combination(last_driver), @3, "Can't mix path() & port()"); afmongodb_dd_set_port(last_driver, $3); } | KW_PATH '(' string ')' { CHECK_ERROR(afmongodb_dd_validate_socket_combination(last_driver), @3, "Can't mix path() with host() or server()"); afmongodb_dd_set_path(last_driver, $3); free($3); } | KW_DATABASE '(' string ')' { afmongodb_dd_set_database(last_driver, $3); free($3); } | KW_USERNAME '(' string ')' { afmongodb_dd_set_user(last_driver, $3); free($3); } | KW_PASSWORD '(' string ')' { afmongodb_dd_set_password(last_driver, $3); free($3); } | KW_SAFE_MODE '(' yesno ')' { afmongodb_dd_set_safe_mode(last_driver, !!$3); } | KW_ENDIF { #endif /* SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS */ } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/afmongodb/afmongodb-legacy-grammar.c000066400000000000000000000100001321171025300260160ustar00rootroot00000000000000/* * Copyright (c) 2010-2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afmongodb-legacy-grammar.h" #include "afmongodb-legacy-private.h" gboolean afmongodb_dd_validate_socket_combination(LogDriver *d) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; if ((self->port != 0 || self->port != MONGO_CONN_LOCAL) && self->address != NULL) return FALSE; if (self->servers) return FALSE; return TRUE; } gboolean afmongodb_dd_validate_network_combination(LogDriver *d) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; if (self->port == MONGO_CONN_LOCAL && self->address != NULL) return FALSE; return TRUE; } void afmongodb_dd_set_user(LogDriver *d, const gchar *user) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; msg_warning_once("WARNING: Using username() option is deprecated in mongodb driver," " please use uri() instead"); g_free(self->user); self->user = g_strdup(user); self->is_legacy = TRUE; } void afmongodb_dd_set_password(LogDriver *d, const gchar *password) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; msg_warning_once("WARNING: Using password() option is deprecated in mongodb driver," " please use uri() instead"); g_free(self->password); self->password = g_strdup(password); self->is_legacy = TRUE; } void afmongodb_dd_set_host(LogDriver *d, const gchar *host) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; msg_warning_once( "WARNING: Using host() option is deprecated in mongodb driver, please use uri() instead"); g_free(self->address); self->address = g_strdup(host); self->is_legacy = TRUE; } void afmongodb_dd_set_port(LogDriver *d, gint port) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; msg_warning_once( "WARNING: Using port() option is deprecated in mongodb driver, please use uri() instead"); self->port = port; self->is_legacy = TRUE; } void afmongodb_dd_set_servers(LogDriver *d, GList *servers) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; msg_warning_once( "WARNING: Using servers() option is deprecated in mongodb driver, please use uri() instead"); string_list_free(self->servers); self->servers = servers; self->is_legacy = TRUE; } void afmongodb_dd_set_path(LogDriver *d, const gchar *path) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; msg_warning_once( "WARNING: Using path() option is deprecated in mongodb driver, please use uri() instead"); g_free(self->address); self->address = g_strdup(path); self->port = MONGO_CONN_LOCAL; self->is_legacy = TRUE; } void afmongodb_dd_set_database(LogDriver *d, const gchar *database) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; msg_warning_once("WARNING: Using database() option is deprecated in mongodb driver," " please use uri() instead"); g_free(self->db); self->db = g_strdup(database); self->is_legacy = TRUE; } void afmongodb_dd_set_safe_mode(LogDriver *d, gboolean state) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; msg_warning_once("WARNING: Using safe_mode() option is deprecated in mongodb driver," " please use uri() instead"); self->safe_mode = state; self->is_legacy = TRUE; } syslog-ng-syslog-ng-3.13.2/modules/afmongodb/afmongodb-legacy-grammar.h000066400000000000000000000032011321171025300260300ustar00rootroot00000000000000/* * Copyright (c) 2010-2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFMONGODB_LEGACY_GRAMMAR_H_ #define AFMONGODB_LEGACY_GRAMMAR_H_ #include "syslog-ng.h" #include "driver.h" gboolean afmongodb_dd_validate_socket_combination(LogDriver *d); gboolean afmongodb_dd_validate_network_combination(LogDriver *d); void afmongodb_dd_set_servers(LogDriver *d, GList *servers); void afmongodb_dd_set_host(LogDriver *d, const gchar *host); void afmongodb_dd_set_port(LogDriver *d, gint port); void afmongodb_dd_set_database(LogDriver *d, const gchar *database); void afmongodb_dd_set_user(LogDriver *d, const gchar *user); void afmongodb_dd_set_password(LogDriver *d, const gchar *password); void afmongodb_dd_set_safe_mode(LogDriver *d, gboolean state); void afmongodb_dd_set_path(LogDriver *d, const gchar *path); #endif syslog-ng-syslog-ng-3.13.2/modules/afmongodb/afmongodb-legacy-private.h000066400000000000000000000020631321171025300260610ustar00rootroot00000000000000/* * Copyright (c) 2010-2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFMONGODB_LEGACY_PRIVATE_H_ #define AFMONGODB_LEGACY_PRIVATE_H_ #include "syslog-ng.h" #include "afmongodb-private.h" #define MONGO_CONN_LOCAL -1 #endif syslog-ng-syslog-ng-3.13.2/modules/afmongodb/afmongodb-legacy-uri.c000066400000000000000000000204111321171025300251760ustar00rootroot00000000000000/* * Copyright (c) 2010-2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afmongodb-legacy-uri.h" #include "afmongodb-legacy-private.h" #include "host-list.h" #define DEFAULTHOST "127.0.0.1" #define SOCKET_TIMEOUT_FOR_MONGO_CONNECTION_IN_MILLISECS 60000 static gboolean _parse_addr(const char *str, char **host, gint *port) { if (!host || !port) { msg_debug("Host or port reference should not be NULL"); return FALSE; } char *proto_str = g_strdup_printf("mongodb://%s", str); mongoc_uri_t *uri = mongoc_uri_new(proto_str); if (!uri) { msg_error("Cannot parse MongoDB URI", evt_tag_str("uri", proto_str)); g_free(proto_str); return FALSE; } const mongoc_host_list_t *hosts = mongoc_uri_get_hosts(uri); if (!hosts || hosts->next) { if (hosts) msg_error("Multiple hosts found in MongoDB URI", evt_tag_str("uri", proto_str)); else msg_error("No host found in MongoDB URI", evt_tag_str("uri", proto_str)); g_free(proto_str); mongoc_uri_destroy(uri); return FALSE; } *port = hosts->port; *host = g_strdup(hosts->host); mongoc_uri_destroy(uri); if (!*host) { msg_error("NULL hostname", evt_tag_str("uri", proto_str)); g_free(proto_str); return FALSE; } g_free(proto_str); return TRUE; } static gboolean _append_legacy_servers(MongoDBDestDriver *self) { if (self->port != MONGO_CONN_LOCAL) { if (self->address || self->port) { gchar *host = NULL; gint port = 0; if (!_parse_addr(self->address, &host, &port) || (!host)) { msg_error("Cannot parse the primary host", evt_tag_str("primary", self->address), evt_tag_str("driver", self->super.super.super.id)); return FALSE; } g_free(host); port = self->port ? self->port : MONGOC_DEFAULT_PORT; const gchar *address = self->address ? self->address : DEFAULTHOST; gchar *srv = g_strdup_printf("%s:%d", address, port); self->servers = g_list_prepend(self->servers, srv); g_free(self->address); self->address = NULL; self->port = MONGOC_DEFAULT_PORT; } if (self->servers) { GList *l; for (l = self->servers; l; l = g_list_next(l)) { gchar *host = NULL; gint port = MONGOC_DEFAULT_PORT; if (!_parse_addr(l->data, &host, &port)) { msg_warning("Cannot parse MongoDB server address, ignoring", evt_tag_str("address", l->data), evt_tag_str("driver", self->super.super.super.id)); continue; } host_list_append(&self->recovery_cache, host, port); msg_verbose("Added MongoDB server seed", evt_tag_str("host", host), evt_tag_int("port", port), evt_tag_str("driver", self->super.super.super.id)); g_free(host); } } else { gchar *localhost = g_strdup_printf(DEFAULTHOST ":%d", MONGOC_DEFAULT_PORT); self->servers = g_list_append(NULL, localhost); host_list_append(&self->recovery_cache, DEFAULTHOST, MONGOC_DEFAULT_PORT); } if (!_parse_addr(g_list_nth_data(self->servers, 0), &self->address, &self->port)) { msg_error("Cannot parse the primary host", evt_tag_str("primary", g_list_nth_data(self->servers, 0)), evt_tag_str("driver", self->super.super.super.id)); return FALSE; } } else { if (!self->address) { msg_error("Cannot parse address", evt_tag_str("primary", g_list_nth_data(self->servers, 0)), evt_tag_str("driver", self->super.super.super.id)); return FALSE; } host_list_append(&self->recovery_cache, self->address, 0); } return TRUE; } typedef struct _AppendServerState { GString *uri_str; gboolean *have_uri; gboolean have_path; } AppendServerState; static gboolean _append_server(gpointer user_data, const char *host, gint port) { AppendServerState *state = (AppendServerState *)user_data; if (state->have_path || *state->have_uri) g_string_append_printf(state->uri_str, ","); if (port) { *state->have_uri = TRUE; if (state->have_path) { msg_warning("Cannot specify both a domain socket and address"); return FALSE; } g_string_append_printf(state->uri_str, "%s:%d", host, port); } else { state->have_path = TRUE; if (*state->have_uri) { msg_warning("Cannot specify both a domain socket and address"); return FALSE; } g_string_append_printf(state->uri_str, "%s", host); } return TRUE; } static gboolean _append_servers(GString *uri_str, const HostList *host_list, gboolean *have_uri) { *have_uri = FALSE; AppendServerState state = {uri_str, have_uri, FALSE}; return host_list_iterate(host_list, _append_server, &state); } static gboolean _check_auth_options(MongoDBDestDriver *self) { if (self->user || self->password) { if (!self->user || !self->password) { msg_error("Neither the username, nor the password can be empty"); return FALSE; } } return TRUE; } gboolean _build_uri_from_legacy_options(MongoDBDestDriver *self) { if (!_append_legacy_servers(self)) return FALSE; self->uri_str = g_string_new("mongodb://"); if (self->user && self->password) g_string_append_printf(self->uri_str, "%s:%s@", self->user, self->password); if (!self->recovery_cache) { msg_error("Error in host server list", evt_tag_str("driver", self->super.super.super.id)); return FALSE; } gboolean have_uri; if (!_append_servers(self->uri_str, self->recovery_cache, &have_uri)) return FALSE; if (have_uri) g_string_append_printf(self->uri_str, "/%s", self->db); if (self->safe_mode) g_string_append_printf(self->uri_str, "?wtimeoutMS=%d", SOCKET_TIMEOUT_FOR_MONGO_CONNECTION_IN_MILLISECS); else g_string_append(self->uri_str, "?w=0&safe=false"); g_string_append_printf(self->uri_str, "&socketTimeoutMS=%d&connectTimeoutMS=%d", SOCKET_TIMEOUT_FOR_MONGO_CONNECTION_IN_MILLISECS, SOCKET_TIMEOUT_FOR_MONGO_CONNECTION_IN_MILLISECS); return TRUE; } gboolean afmongodb_dd_create_uri_from_legacy(MongoDBDestDriver *self) { if (!_check_auth_options(self)) return FALSE; if (self->uri_str && self->is_legacy) { msg_error("Error: either specify a MongoDB URI (and optional collection)" " or only legacy options", evt_tag_str("driver", self->super.super.super.id)); return FALSE; } else if (self->is_legacy) return _build_uri_from_legacy_options(self); else return TRUE; } void afmongodb_dd_init_legacy(MongoDBDestDriver *self) { self->db = g_strdup("syslog"); self->safe_mode = TRUE; } void afmongodb_dd_free_legacy(MongoDBDestDriver *self) { g_free(self->db); g_free(self->user); g_free(self->password); g_free(self->address); string_list_free(self->servers); host_list_free(self->recovery_cache); self->recovery_cache = NULL; } syslog-ng-syslog-ng-3.13.2/modules/afmongodb/afmongodb-legacy-uri.h000066400000000000000000000023061321171025300252060ustar00rootroot00000000000000/* * Copyright (c) 2010-2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFMONGODB_LEGACY_URI_H_ #define AFMONGODB_LEGACY_URI_H_ #include "syslog-ng.h" #include "afmongodb-private.h" void afmongodb_dd_init_legacy(MongoDBDestDriver *self); void afmongodb_dd_free_legacy(MongoDBDestDriver *self); gboolean afmongodb_dd_create_uri_from_legacy(MongoDBDestDriver *self); #endif syslog-ng-syslog-ng-3.13.2/modules/afmongodb/afmongodb-parser.c000066400000000000000000000046451321171025300244440ustar00rootroot00000000000000/* * Copyright (c) 2010-2015 Balabit * Copyright (c) 2010-2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afmongodb.h" #include "cfg-parser.h" #include "afmongodb-grammar.h" extern int afmongodb_debug; int afmongodb_parse(CfgLexer *lexer, LogDriver **instance, gpointer arg); static CfgLexerKeyword afmongodb_keywords[] = { { "mongodb", KW_MONGODB }, { "uri", KW_URI }, { "collection", KW_COLLECTION }, #if SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS { "servers", KW_SERVERS, KWS_OBSOLETE, "Use the uri() option instead of servers()" }, { "database", KW_DATABASE, KWS_OBSOLETE, "Use the uri() option instead of database()" }, { "username", KW_USERNAME, KWS_OBSOLETE, "Use the uri() option instead of username() and password()" }, { "password", KW_PASSWORD, KWS_OBSOLETE, "Use the uri() option instead of username() and password()" }, { "safe_mode", KW_SAFE_MODE, KWS_OBSOLETE, "Use the uri() option instead of safe_mode()" }, { "host", KW_HOST, KWS_OBSOLETE, "Use the uri() option instead of host() and port()" }, { "port", KW_PORT, KWS_OBSOLETE, "Use the uri() option instead of host() and port()" }, { "path", KW_PATH, KWS_OBSOLETE, "Use the uri() option instead of path()" }, #endif { } }; CfgParser afmongodb_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &afmongodb_debug, #endif .name = "afmongodb", .keywords = afmongodb_keywords, .parse = (int (*)(CfgLexer *lexer, gpointer *instance, gpointer)) afmongodb_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(afmongodb_, LogDriver **) syslog-ng-syslog-ng-3.13.2/modules/afmongodb/afmongodb-parser.h000066400000000000000000000024361321171025300244450ustar00rootroot00000000000000/* * Copyright (c) 2010-2012 Balabit * Copyright (c) 2010-2012 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFMONGODB_PARSER_H_INCLUDED #define AFMONGODB_PARSER_H_INCLUDED #include "syslog-ng.h" #include "cfg-parser.h" #include "afmongodb.h" #if SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS #include "afmongodb-legacy-grammar.h" #endif extern CfgParser afmongodb_parser; CFG_PARSER_DECLARE_LEXER_BINDING(afmongodb_, LogDriver **) #endif syslog-ng-syslog-ng-3.13.2/modules/afmongodb/afmongodb-private.h000066400000000000000000000036011321171025300246160ustar00rootroot00000000000000/* * Copyright (c) 2010-2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFMONGODB_PRIVATE_H_ #define AFMONGODB_PRIVATE_H_ #include "syslog-ng.h" #include "mongoc.h" #include "logthrdestdrv.h" #include "string-list.h" #include "value-pairs/value-pairs.h" #if SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS #include "host-list.h" #endif typedef struct _MongoDBDestDriver { LogThrDestDriver super; /* Shared between main/writer; only read by the writer, never written */ gchar *coll; GString *uri_str; #if SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS GList *servers; gchar *address; gint port; gboolean safe_mode; gchar *user; gchar *password; #endif LogTemplateOptions template_options; time_t last_msg_stamp; ValuePairs *vp; /* Writer-only stuff */ #if SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS HostList *recovery_cache; gboolean is_legacy; gchar *db; #endif const gchar *const_db; mongoc_uri_t *uri_obj; mongoc_client_t *client; mongoc_collection_t *coll_obj; GString *current_value; bson_t *bson; } MongoDBDestDriver; #endif syslog-ng-syslog-ng-3.13.2/modules/afmongodb/afmongodb.c000066400000000000000000000405201321171025300231420ustar00rootroot00000000000000/* * Copyright (c) 2010-2016 Balabit * Copyright (c) 2010-2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afmongodb.h" #include "afmongodb-parser.h" #include "messages.h" #include "stats/stats-registry.h" #include "logmsg/nvtable.h" #include "logqueue.h" #include "value-pairs/evttag.h" #include "plugin.h" #include "plugin-types.h" #include #include "afmongodb-private.h" #if SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS #include "afmongodb-legacy-uri.h" #endif #define DEFAULT_URI \ "mongodb://127.0.0.1:27017/syslog"\ "?wtimeoutMS=60000&socketTimeoutMS=60000&connectTimeoutMS=60000" /* * Configuration */ LogTemplateOptions * afmongodb_dd_get_template_options(LogDriver *s) { MongoDBDestDriver *self = (MongoDBDestDriver *)s; return &self->template_options; } void afmongodb_dd_set_uri(LogDriver *d, const gchar *uri) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; if (self->uri_str) g_string_assign(self->uri_str, uri); else self->uri_str = g_string_new(uri); } void afmongodb_dd_set_collection(LogDriver *d, const gchar *collection) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; g_free(self->coll); self->coll = g_strdup(collection); } void afmongodb_dd_set_value_pairs(LogDriver *d, ValuePairs *vp) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; value_pairs_unref(self->vp); self->vp = vp; } /* * Utilities */ static gchar * _format_instance_id(const LogThrDestDriver *d, const gchar *format) { const MongoDBDestDriver *self = (const MongoDBDestDriver *)d; static gchar args[1024]; static gchar id[1024]; if (((LogPipe *)d)->persist_name) { g_snprintf(args, sizeof(args), "%s", ((LogPipe *)d)->persist_name); } else { const mongoc_host_list_t *hosts = mongoc_uri_get_hosts(self->uri_obj); const gchar *first_host = ""; if (hosts) { if (hosts->family == AF_UNIX) first_host = hosts->host; else first_host = hosts->host_and_port; } const gchar *db = self->const_db ? self->const_db : ""; const gchar *replica_set = mongoc_uri_get_replica_set(self->uri_obj); if (!replica_set) replica_set = ""; const gchar *coll = self->coll ? self->coll : ""; g_snprintf(args, sizeof(args), "%s,%s,%s,%s", first_host, db, replica_set, coll); } g_snprintf(id, sizeof(id), format, args); return id; } static gchar * _format_stats_instance(LogThrDestDriver *d) { return _format_instance_id(d, "mongodb,%s"); } static const gchar * _format_persist_name(const LogPipe *s) { const LogThrDestDriver *self = (const LogThrDestDriver *)s; return s->persist_name ? _format_instance_id(self, "afmongodb.%s") : _format_instance_id(self, "afmongodb(%s)"); } static void _worker_disconnect(LogThrDestDriver *s) { MongoDBDestDriver *self = (MongoDBDestDriver *)s; mongoc_client_destroy(self->client); self->client = NULL; } static gboolean _connect(MongoDBDestDriver *self, gboolean reconnect) { if (!self->client) { self->client = mongoc_client_new_from_uri(self->uri_obj); if (!self->client) { msg_error("Error creating MongoDB URI", evt_tag_str("driver", self->super.super.super.id)); return FALSE; } } if (!self->coll_obj) { self->coll_obj = mongoc_client_get_collection(self->client, self->const_db, self->coll); if (!self->coll_obj) { msg_error("Error getting specified MongoDB collection", evt_tag_str("collection", self->coll), evt_tag_str("driver", self->super.super.super.id)); mongoc_client_destroy(self->client); self->client = NULL; return FALSE; } } bson_t reply; bson_error_t error; const mongoc_read_prefs_t *read_prefs = mongoc_collection_get_read_prefs(self->coll_obj); gboolean ok = mongoc_client_get_server_status(self->client, (mongoc_read_prefs_t *)read_prefs, &reply, &error); bson_destroy(&reply); if (!ok) { msg_error("Error connecting to MongoDB", evt_tag_str("driver", self->super.super.super.id), evt_tag_str("reason", error.message)); mongoc_collection_destroy(self->coll_obj); self->coll_obj = NULL; mongoc_client_destroy(self->client); self->client = NULL; return FALSE; } return TRUE; } /* * Worker thread */ static gboolean _vp_obj_start(const gchar *name, const gchar *prefix, gpointer *prefix_data, const gchar *prev, gpointer *prev_data, gpointer user_data) { bson_t *o; if (prefix_data) { o = bson_new(); *prefix_data = o; } return FALSE; } static gboolean _vp_obj_end(const gchar *name, const gchar *prefix, gpointer *prefix_data, const gchar *prev, gpointer *prev_data, gpointer user_data) { MongoDBDestDriver *self = (MongoDBDestDriver *)user_data; bson_t *root; if (prev_data) root = (bson_t *)*prev_data; else root = self->bson; if (prefix_data) { bson_t *d = (bson_t *)*prefix_data; bson_append_document(root, name, -1, d); bson_destroy(d); } return FALSE; } static gboolean _vp_process_value(const gchar *name, const gchar *prefix, TypeHint type, const gchar *value, gsize value_len, gpointer *prefix_data, gpointer user_data) { bson_t *o; MongoDBDestDriver *self = (MongoDBDestDriver *)user_data; gboolean fallback = self->template_options.on_error & ON_ERROR_FALLBACK_TO_STRING; if (prefix_data) o = (bson_t *)*prefix_data; else o = self->bson; switch (type) { case TYPE_HINT_BOOLEAN: { gboolean b; if (type_cast_to_boolean(value, &b, NULL)) bson_append_bool(o, name, -1, b); else { gboolean r = type_cast_drop_helper(self->template_options.on_error, value, "boolean"); if (fallback) bson_append_utf8(o, name, -1, value, value_len); else return r; } break; } case TYPE_HINT_INT32: { gint32 i; if (type_cast_to_int32(value, &i, NULL)) bson_append_int32(o, name, -1, i); else { gboolean r = type_cast_drop_helper(self->template_options.on_error, value, "int32"); if (fallback) bson_append_utf8(o, name, -1, value, value_len); else return r; } break; } case TYPE_HINT_INT64: { gint64 i; if (type_cast_to_int64(value, &i, NULL)) bson_append_int64(o, name, -1, i); else { gboolean r = type_cast_drop_helper(self->template_options.on_error, value, "int64"); if (fallback) bson_append_utf8(o, name, -1, value, value_len); else return r; } break; } case TYPE_HINT_DOUBLE: { gdouble d; if (type_cast_to_double(value, &d, NULL)) bson_append_double(o, name, -1, d); else { gboolean r = type_cast_drop_helper(self->template_options.on_error, value, "double"); if (fallback) bson_append_utf8(o, name, -1, value, value_len); else return r; } break; } case TYPE_HINT_DATETIME: { guint64 i; if (type_cast_to_datetime_int(value, &i, NULL)) bson_append_date_time(o, name, -1, (gint64)i); else { gboolean r = type_cast_drop_helper(self->template_options.on_error, value, "datetime"); if (fallback) bson_append_utf8(o, name, -1, value, value_len); else return r; } break; } case TYPE_HINT_STRING: case TYPE_HINT_LITERAL: bson_append_utf8(o, name, -1, value, value_len); break; default: return TRUE; } return FALSE; } static void _worker_retry_over_message(LogThrDestDriver *s, LogMessage *msg) { MongoDBDestDriver *self = (MongoDBDestDriver *)s; msg_error("Dropped message", evt_tag_str("driver", self->super.super.super.id), evt_tag_value_pairs("message", self->vp, msg, self->super.seq_num, LTZ_SEND, &self->template_options)); } static worker_insert_result_t _worker_insert(LogThrDestDriver *s, LogMessage *msg) { MongoDBDestDriver *self = (MongoDBDestDriver *)s; gboolean success; gboolean drop_silently = self->template_options.on_error & ON_ERROR_SILENT; if (!_connect(self, TRUE)) return WORKER_INSERT_RESULT_NOT_CONNECTED; bson_reinit(self->bson); success = value_pairs_walk(self->vp, _vp_obj_start, _vp_process_value, _vp_obj_end, msg, self->super.seq_num, LTZ_SEND, &self->template_options, self); if (!success) { if (!drop_silently) { msg_error("Failed to format message for MongoDB, dropping message", evt_tag_value_pairs("message", self->vp, msg, self->super.seq_num, LTZ_SEND, &self->template_options), evt_tag_str("driver", self->super.super.super.id)); } return WORKER_INSERT_RESULT_DROP; } msg_debug("Outgoing message to MongoDB destination", evt_tag_value_pairs("message", self->vp, msg, self->super.seq_num, LTZ_SEND, &self->template_options), evt_tag_str("driver", self->super.super.super.id)); bson_error_t error; success = mongoc_collection_insert(self->coll_obj, MONGOC_INSERT_NONE, (const bson_t *)self->bson, NULL, &error); if (!success) { if (error.domain == MONGOC_ERROR_STREAM) { msg_error("Network error while inserting into MongoDB", evt_tag_int("time_reopen", self->super.time_reopen), evt_tag_str("reason", error.message), evt_tag_str("driver", self->super.super.super.id)); return WORKER_INSERT_RESULT_NOT_CONNECTED; } else { msg_error("Failed to insert into MongoDB", evt_tag_int("time_reopen", self->super.time_reopen), evt_tag_str("reason", error.message), evt_tag_str("driver", self->super.super.super.id)); return WORKER_INSERT_RESULT_ERROR; } } return WORKER_INSERT_RESULT_SUCCESS; } gboolean afmongodb_dd_private_uri_init(LogDriver *d) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; #if SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS if (!afmongodb_dd_create_uri_from_legacy(self)) return FALSE; #endif if (!self->uri_str) self->uri_str = g_string_new(DEFAULT_URI); self->uri_obj = mongoc_uri_new(self->uri_str->str); if (!self->uri_obj) { msg_error("Error parsing MongoDB URI", evt_tag_str("uri", self->uri_str->str), evt_tag_str("driver", self->super.super.super.id)); return FALSE; } self->const_db = mongoc_uri_get_database(self->uri_obj); if (!self->const_db || !strlen(self->const_db)) { msg_error("Missing DB name from MongoDB URI", evt_tag_str("uri", self->uri_str->str), evt_tag_str("driver", self->super.super.super.id)); return FALSE; } msg_verbose("Initializing MongoDB destination", evt_tag_str("uri", self->uri_str->str), evt_tag_str("db", self->const_db), evt_tag_str("collection", self->coll), evt_tag_str("driver", self->super.super.super.id)); return TRUE; } static void _worker_thread_init(LogThrDestDriver *d) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; _connect(self, FALSE); self->current_value = g_string_sized_new(256); self->bson = bson_sized_new(4096); } static void _worker_thread_deinit(LogThrDestDriver *d) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; if (self->current_value) { g_string_free(self->current_value, TRUE); self->current_value = NULL; } bson_destroy(self->bson); self->bson = NULL; } /* * Main thread */ static void _init_value_pairs_dot_to_underscore_transformation(MongoDBDestDriver *self) { ValuePairsTransformSet *vpts; /* Always replace a leading dot with an underscore. */ vpts = value_pairs_transform_set_new(".*"); value_pairs_transform_set_add_func(vpts, value_pairs_new_transform_replace_prefix(".", "_")); value_pairs_add_transforms(self->vp, vpts); } static gboolean _init(LogPipe *s) { MongoDBDestDriver *self = (MongoDBDestDriver *)s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_dest_driver_init_method(s)) return FALSE; log_template_options_init(&self->template_options, cfg); _init_value_pairs_dot_to_underscore_transformation(self); if (!afmongodb_dd_private_uri_init(&self->super.super.super)) return FALSE; return log_threaded_dest_driver_start(s); } static void _free(LogPipe *d) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; log_template_options_destroy(&self->template_options); if (self->uri_str) { g_string_free(self->uri_str, TRUE); self->uri_str = NULL; } g_free(self->coll); #if SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS afmongodb_dd_free_legacy(self); #endif value_pairs_unref(self->vp); if (self->uri_obj) mongoc_uri_destroy(self->uri_obj); if (self->coll_obj) mongoc_collection_destroy(self->coll_obj); if (self->client) mongoc_cleanup(); log_threaded_dest_driver_free(d); } static void _logthrdest_queue_method(LogThrDestDriver *d) { MongoDBDestDriver *self = (MongoDBDestDriver *)d; self->last_msg_stamp = cached_g_current_time_sec(); } /* * Plugin glue. */ LogDriver * afmongodb_dd_new(GlobalConfig *cfg) { MongoDBDestDriver *self = g_new0(MongoDBDestDriver, 1); mongoc_init(); log_threaded_dest_driver_init_instance(&self->super, cfg); self->super.super.super.super.init = _init; self->super.super.super.super.free_fn = _free; self->super.super.super.super.generate_persist_name = _format_persist_name; self->super.queue_method = _logthrdest_queue_method; self->super.worker.thread_init = _worker_thread_init; self->super.worker.thread_deinit = _worker_thread_deinit; self->super.worker.disconnect = _worker_disconnect; self->super.worker.insert = _worker_insert; self->super.format.stats_instance = _format_stats_instance; self->super.stats_source = SCS_MONGODB; self->super.messages.retry_over = _worker_retry_over_message; #if SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS afmongodb_dd_init_legacy(self); #endif afmongodb_dd_set_collection(&self->super.super.super, "messages"); log_template_options_defaults(&self->template_options); afmongodb_dd_set_value_pairs(&self->super.super.super, value_pairs_new_default(cfg)); return &self->super.super.super; } extern CfgParser afmongodb_dd_parser; static Plugin afmongodb_plugin = { .type = LL_CONTEXT_DESTINATION, .name = "mongodb", .parser = &afmongodb_parser, }; gboolean afmongodb_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, &afmongodb_plugin, 1); return TRUE; } const ModuleInfo module_info = { .canonical_name = "afmongodb", .version = SYSLOG_NG_VERSION, .description = "The afmongodb module provides MongoDB destination support for syslog-ng.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = &afmongodb_plugin, .plugins_len = 1, }; syslog-ng-syslog-ng-3.13.2/modules/afmongodb/afmongodb.h000066400000000000000000000027271321171025300231560ustar00rootroot00000000000000/* * Copyright (c) 2010-2016 Balabit * Copyright (c) 2010-2013 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFMONGODB_H_INCLUDED #define AFMONGODB_H_INCLUDED #include "syslog-ng.h" #include "driver.h" #include "value-pairs/value-pairs.h" LogDriver *afmongodb_dd_new(GlobalConfig *cfg); void afmongodb_dd_set_uri(LogDriver *d, const gchar *uri); void afmongodb_dd_set_collection(LogDriver *d, const gchar *collection); void afmongodb_dd_set_value_pairs(LogDriver *d, ValuePairs *vp); LogTemplateOptions *afmongodb_dd_get_template_options(LogDriver *s); gboolean afmongodb_dd_private_uri_init(LogDriver *self); #endif syslog-ng-syslog-ng-3.13.2/modules/afmongodb/host-list.c000066400000000000000000000037251321171025300231420ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "host-list.h" typedef struct _MongoDBHostPort { char *host; gint port; } MongoDBHostPort; static MongoDBHostPort * _new_host_port(const char *host, gint port) { MongoDBHostPort *hp = g_new0(MongoDBHostPort, 1); hp->host = g_strdup(host); hp->port = port; return hp; } static void _free_host_port(gpointer data) { MongoDBHostPort *hp = (MongoDBHostPort *)data; g_free(hp->host); hp->host = NULL; g_free(hp); } gboolean host_list_append(HostList **list, const char *host, gint port) { if (!list) return FALSE; *list = g_list_append(*list, _new_host_port(host, port)); return TRUE; } gboolean host_list_iterate(const HostList *host_list, HostListProcessor processor, gpointer user_data) { for (const GList *iterator = host_list; iterator; iterator = iterator->next) { const MongoDBHostPort *hp = (const MongoDBHostPort *)iterator->data; if (!processor(user_data, hp->host, hp->port)) return FALSE; } return TRUE; } void host_list_free(HostList *host_list) { g_list_free_full(host_list, (GDestroyNotify)&_free_host_port); } syslog-ng-syslog-ng-3.13.2/modules/afmongodb/host-list.h000066400000000000000000000024641321171025300231460ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef HOST_LIST_H_ #define HOST_LIST_H_ #include "syslog-ng.h" #include typedef GList HostList; typedef gboolean (*HostListProcessor)(gpointer user_data, const char *host, gint port); gboolean host_list_append(HostList **list, const char *host, gint port); gboolean host_list_iterate(const HostList *host_list, HostListProcessor processor, gpointer user_data); void host_list_free(HostList *host_list); #endif syslog-ng-syslog-ng-3.13.2/modules/afmongodb/mongo-c-driver/000077500000000000000000000000001321171025300236715ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afmongodb/tests/000077500000000000000000000000001321171025300222035ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afmongodb/tests/Makefile.am000066400000000000000000000006711321171025300242430ustar00rootroot00000000000000modules_afmongodb_tests_TESTS = \ modules/afmongodb/tests/test-mongodb-config check_PROGRAMS += ${modules_afmongodb_tests_TESTS} modules_afmongodb_tests_test_mongodb_config_CFLAGS = \ $(LIBMONGO_CFLAGS) \ $(TEST_CFLAGS) modules_afmongodb_tests_test_mongodb_config_LDADD = \ $(TEST_LDADD) \ -dlpreopen $(top_builddir)/modules/afmongodb/libafmongodb.la \ ${lmc_EXTRA_DEPS} syslog-ng-syslog-ng-3.13.2/modules/afmongodb/tests/test-mongodb-config.c000066400000000000000000000250661321171025300262250ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "syslog-ng.h" #include "testutils.h" #include "mainloop.h" #include "modules/afmongodb/afmongodb-parser.h" #include "logthrdestdrv.h" static int _tests_failed = 0; static GlobalConfig *test_cfg; static LogDriver *mongodb; #define SAFEOPTS "?wtimeoutMS=60000&socketTimeoutMS=60000&connectTimeoutMS=60000" static void _before_test(void) { start_grabbing_messages(); mongodb = afmongodb_dd_new(test_cfg); } static gboolean _after_test(void) { gboolean uri_init_ok = afmongodb_dd_private_uri_init(mongodb); stop_grabbing_messages(); return uri_init_ok; } static void _free_test(void) { reset_grabbed_messages(); if (mongodb) { log_pipe_unref(&mongodb->super); mongodb = NULL; } } typedef gboolean (*Checks)(const gchar *user_data); static gboolean _execute(const gchar *testcase, Checks checks, const gchar *user_data) { gboolean uri_init_ok = _after_test(); testcase_begin("%s(%s, %s)", __FUNCTION__, testcase, user_data); if (!checks(user_data)) _tests_failed = 1; reset_grabbed_messages(); testcase_end(); _free_test(); _before_test(); return uri_init_ok; } static gboolean _execute_find_text_in_log(const gchar *pattern) { return assert_grabbed_messages_contain_non_fatal(pattern, "mismatch", NULL); } static void _log_error(const gchar *message) { fprintf(stderr, "error: %s\n", message); } static void _execute_correct(const gchar *testcase, Checks checks, const gchar *user_data) { if (!_execute(testcase, checks, user_data)) { _log_error("expected the subject to succeed, but it failed"); _tests_failed = 1; } } static void _execute_failing(const gchar *testcase, Checks checks, const gchar *user_data) { if (_execute(testcase, checks, user_data)) { _log_error("expected the subject to fail, but it succeeded"); _tests_failed = 1; } } static void _expect_error_in_log(const gchar *testcase, const gchar *pattern) { _execute_failing(testcase, _execute_find_text_in_log, pattern); } static void _expect_uri_in_log(const gchar *testcase, const gchar *uri, const gchar *db, const gchar *coll) { GString *pattern = g_string_sized_new(0); g_string_append_printf(pattern, "Initializing MongoDB destination;" " uri='mongodb://%s', db='%s', collection='%s'", uri, db, coll); _execute_correct(testcase, _execute_find_text_in_log, pattern->str); g_string_free(pattern, TRUE); } static gboolean _execute_compare_persist_name(const gchar *expected_name) { LogThrDestDriver *self = (LogThrDestDriver *)mongodb; const gchar *name = log_pipe_get_persist_name((const LogPipe *)self); return assert_nstring_non_fatal(name, -1, expected_name, -1, "mismatch"); } static void _test_persist_name(void) { afmongodb_dd_set_uri(mongodb, "mongodb://127.0.0.2:27018,localhost:1234/syslog" SAFEOPTS "&replicaSet=x"); _execute_correct("persist", _execute_compare_persist_name, "afmongodb(127.0.0.2:27018,syslog,x,messages)"); } static gboolean _execute_compare_stats_name(const gchar *expected_name) { LogThrDestDriver *self = (LogThrDestDriver *)mongodb; const gchar *name = self->format.stats_instance(self); return assert_nstring_non_fatal(name, -1, expected_name, -1, "mismatch"); } static void _test_stats_name(void) { afmongodb_dd_set_uri(mongodb, "mongodb://127.0.0.2:27018,localhost:1234/syslog" SAFEOPTS "&replicaSet=x"); _execute_correct("stats", _execute_compare_stats_name, "mongodb,127.0.0.2:27018,syslog,x,messages"); } static void _test_uri_correct(void) { _expect_uri_in_log("default_uri", "127.0.0.1:27017/syslog" SAFEOPTS, "syslog", "messages"); afmongodb_dd_set_uri(mongodb, "mongodb://%2Ftmp%2Fmongo.sock/syslog"); _expect_uri_in_log("socket", "%2Ftmp%2Fmongo.sock/syslog", "syslog", "messages"); afmongodb_dd_set_uri(mongodb, "mongodb://localhost:1234/syslog-ng"); _expect_uri_in_log("uri", "localhost:1234/syslog-ng", "syslog-ng", "messages"); afmongodb_dd_set_collection(mongodb, "messages2"); _expect_uri_in_log("collection", "127.0.0.1:27017/syslog" SAFEOPTS, "syslog", "messages2"); } static void _test_uri_error(void) { afmongodb_dd_set_uri(mongodb, "INVALID-URI"); _expect_error_in_log("invalid_uri", "Error parsing MongoDB URI; uri='INVALID-URI'"); afmongodb_dd_set_uri(mongodb, "mongodb://127.0.0.1:27017/"); _expect_error_in_log("missing_db", "Missing DB name from MongoDB URI;" " uri='mongodb://127.0.0.1:27017/'"); } #if SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS #define UNSAFEOPTS "?w=0&safe=false&socketTimeoutMS=60000&connectTimeoutMS=60000" static void _test_legacy_correct(void) { GList *servers = g_list_append(NULL, g_strdup("127.0.0.2:27018")); servers = g_list_append(servers, g_strdup("localhost:1234")); afmongodb_dd_set_servers(mongodb, servers); _expect_uri_in_log("servers_multi", "127.0.0.2:27018,localhost:1234/syslog" SAFEOPTS, "syslog", "messages"); servers = g_list_append(NULL, g_strdup("127.0.0.2")); afmongodb_dd_set_servers(mongodb, servers); _expect_uri_in_log("servers_single", "127.0.0.2:27017/syslog" SAFEOPTS, "syslog", "messages"); afmongodb_dd_set_host(mongodb, "localhost"); _expect_uri_in_log("host", "localhost:27017/syslog" SAFEOPTS, "syslog", "messages"); afmongodb_dd_set_host(mongodb, "localhost"); afmongodb_dd_set_port(mongodb, 1234); _expect_uri_in_log("host_port", "localhost:1234/syslog" SAFEOPTS, "syslog", "messages"); afmongodb_dd_set_port(mongodb, 27017); _expect_uri_in_log("port_default", "127.0.0.1:27017/syslog" SAFEOPTS, "syslog", "messages"); afmongodb_dd_set_port(mongodb, 1234); _expect_uri_in_log("port", "127.0.0.1:1234/syslog" SAFEOPTS, "syslog", "messages"); afmongodb_dd_set_database(mongodb, "syslog-ng"); _expect_uri_in_log("database", "127.0.0.1:27017/syslog-ng" SAFEOPTS, "syslog-ng", "messages"); afmongodb_dd_set_safe_mode(mongodb, TRUE); _expect_uri_in_log("safe_mode_true", "127.0.0.1:27017/syslog" SAFEOPTS, "syslog", "messages"); afmongodb_dd_set_safe_mode(mongodb, FALSE); _expect_uri_in_log("safe_mode_false", "127.0.0.1:27017/syslog" UNSAFEOPTS, "syslog", "messages"); afmongodb_dd_set_user(mongodb, "user"); afmongodb_dd_set_password(mongodb, "password"); _expect_uri_in_log("user_password", "user:password@127.0.0.1:27017/syslog" SAFEOPTS, "syslog", "messages"); afmongodb_dd_set_collection(mongodb, "messages2"); afmongodb_dd_set_safe_mode(mongodb, FALSE); _expect_uri_in_log("collection_safe_mode", "127.0.0.1:27017/syslog" UNSAFEOPTS, "syslog", "messages2"); afmongodb_dd_set_user(mongodb, ""); afmongodb_dd_set_password(mongodb, "password"); _expect_uri_in_log("empty_user", ":password@127.0.0.1:27017/syslog" SAFEOPTS, "syslog", "messages"); afmongodb_dd_set_user(mongodb, "user"); afmongodb_dd_set_password(mongodb, ""); _expect_uri_in_log("empty_password", "user:@127.0.0.1:27017/syslog" SAFEOPTS, "syslog", "messages"); afmongodb_dd_set_user(mongodb, ""); afmongodb_dd_set_password(mongodb, ""); _expect_uri_in_log("empty_user_password", ":@127.0.0.1:27017/syslog" SAFEOPTS, "syslog", "messages"); afmongodb_dd_set_user(mongodb, "127.0.0.1:27017/syslog?dont-care="); afmongodb_dd_set_password(mongodb, ""); _expect_uri_in_log("hijacked_user", "127.0.0.1:27017/syslog?dont-care=:@127.0.0.1:27017/syslog" SAFEOPTS, "syslog", "messages"); } static void _test_legacy_error(void) { afmongodb_dd_set_safe_mode(mongodb, FALSE); afmongodb_dd_set_uri(mongodb, "mongodb://127.0.0.1:27017/syslog"); _expect_error_in_log("uri_safe_mode", "Error: either specify a MongoDB URI " "(and optional collection) or only legacy options;"); afmongodb_dd_set_host(mongodb, "?"); _expect_error_in_log("host_invalid", "Cannot parse MongoDB URI; uri="); afmongodb_dd_set_host(mongodb, ""); _expect_error_in_log("host_none", "Cannot parse the primary host; primary=\'\'"); afmongodb_dd_set_host(mongodb, "localhost,127.0.0.1"); _expect_error_in_log("host_multi", "Multiple hosts found in MongoDB URI; uri="); GList *servers = g_list_append(NULL, g_strdup("localhost,127.0.0.1")); afmongodb_dd_set_servers(mongodb, servers); _expect_error_in_log("servers_multi", "Multiple hosts found in MongoDB URI; uri="); servers = g_list_append(NULL, g_strdup("")); afmongodb_dd_set_servers(mongodb, servers); _expect_error_in_log("servers_none", "Cannot parse MongoDB URI; uri="); afmongodb_dd_set_password(mongodb, "password"); _expect_error_in_log("missing_user", "Neither the username, nor the password can be empty;"); afmongodb_dd_set_user(mongodb, "user"); _expect_error_in_log("missing_password", "Neither the username, nor the password can be empty;"); } #endif static void _setup(void) { msg_init(FALSE); g_thread_init(NULL); debug_flag = TRUE; verbose_flag = TRUE; trace_flag = TRUE; log_msg_registry_init(); test_cfg = cfg_new_snippet(); g_assert(test_cfg); const gchar *persist_filename = ""; test_cfg->state = persist_state_new(persist_filename); _before_test(); } static void _teardown(void) { _free_test(); if (test_cfg->persist) { persist_config_free(test_cfg->persist); test_cfg->persist = NULL; } cfg_free(test_cfg); log_msg_registry_deinit(); msg_deinit(); } int main(int argc, char **argv) { _setup(); _test_persist_name(); _test_stats_name(); _test_uri_correct(); _test_uri_error(); #if SYSLOG_NG_ENABLE_LEGACY_MONGODB_OPTIONS _test_legacy_correct(); _test_legacy_error(); #endif _teardown(); return _tests_failed; } syslog-ng-syslog-ng-3.13.2/modules/afprog/000077500000000000000000000000001321171025300203635ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afprog/CMakeLists.txt000066400000000000000000000013231321171025300231220ustar00rootroot00000000000000set(AFPROG_HEADERS "afprog.h" "afprog-parser.h" "${CMAKE_CURRENT_BINARY_DIR}/afprog-grammar.h" ) set(AFPROG_SOURCES "afprog.c" "afprog-parser.c" "afprog-plugin.c" "${CMAKE_CURRENT_BINARY_DIR}/afprog-grammar.c" ) generate_y_from_ym(modules/afprog/afprog-grammar) bison_target(AfprogGrammar ${CMAKE_CURRENT_BINARY_DIR}/afprog-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/afprog-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) include_directories (${CMAKE_CURRENT_BINARY_DIR}) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) add_library(afprog MODULE ${AFPROG_SOURCES}) target_link_libraries(afprog PRIVATE syslog-ng) install(TARGETS afprog LIBRARY DESTINATION lib/syslog-ng/ COMPONENT afprog) syslog-ng-syslog-ng-3.13.2/modules/afprog/Makefile.am000066400000000000000000000016231321171025300224210ustar00rootroot00000000000000module_LTLIBRARIES += modules/afprog/libafprog.la modules_afprog_libafprog_la_SOURCES = \ modules/afprog/afprog.c \ modules/afprog/afprog.h \ modules/afprog/afprog-grammar.y \ modules/afprog/afprog-parser.c \ modules/afprog/afprog-parser.h \ modules/afprog/afprog-plugin.c BUILT_SOURCES += \ modules/afprog/afprog-grammar.y \ modules/afprog/afprog-grammar.c \ modules/afprog/afprog-grammar.h EXTRA_DIST += \ modules/afprog/afprog-grammar.ym modules_afprog_libafprog_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/afprog \ -I$(top_builddir)/modules/afprog modules_afprog_libafprog_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_afprog_libafprog_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_afprog_libafprog_la_DEPENDENCIES= \ $(MODULE_DEPS_LIBS) modules/afprog modules/afprog/ mod-afprog mod-prog: \ modules/afprog/libafprog.la .PHONY: modules/afprog/ mod-afprog mod-prog syslog-ng-syslog-ng-3.13.2/modules/afprog/afprog-grammar.ym000066400000000000000000000062061321171025300236400ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code top { #include "afprog-parser.h" } %code { #include "afprog.h" #include "cfg-parser.h" #include "afprog-grammar.h" #include "syslog-names.h" #include "messages.h" #include "plugin.h" #include "cfg-grammar.h" #include } %name-prefix "afprog_" /* this parameter is needed in order to instruct bison to use a complete * argument list for yylex/yyerror */ %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogDriver **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_PROGRAM %token KW_KEEP_ALIVE %token KW_INHERIT_ENVIRONMENT %type source_afprogram %type source_afprogram_params %type dest_afprogram %type dest_afprogram_params %% start : LL_CONTEXT_SOURCE source_afprogram { YYACCEPT; } | LL_CONTEXT_DESTINATION dest_afprogram { YYACCEPT; } ; source_afprogram : KW_PROGRAM '(' source_afprogram_params ')' { $$ = $3; } ; source_afprogram_params : string { last_driver = *instance = afprogram_sd_new($1, configuration); last_reader_options = &((AFProgramSourceDriver *) last_driver)->reader_options; } source_afprogram_options { $$ = last_driver; free($1); } ; source_afprogram_options : source_afprogram_option source_afprogram_options | ; source_afprogram_option : source_reader_option | KW_INHERIT_ENVIRONMENT '(' yesno ')' { afprogram_set_inherit_environment(&((AFProgramSourceDriver *)last_driver)->process_info, $3); } ; dest_afprogram : KW_PROGRAM '(' dest_afprogram_params ')' { $$ = $3; } ; dest_afprogram_params : string { last_driver = *instance = afprogram_dd_new($1, configuration); last_writer_options = &((AFProgramDestDriver *) last_driver)->writer_options; } dest_afprogram_options { $$ = last_driver; free($1); } ; dest_afprogram_options : dest_afprogram_option dest_afprogram_options | ; dest_afprogram_option : dest_writer_option | dest_driver_option | KW_KEEP_ALIVE '(' yesno ')' { afprogram_dd_set_keep_alive((AFProgramDestDriver *)last_driver, $3); } | KW_INHERIT_ENVIRONMENT '(' yesno ')' { afprogram_set_inherit_environment(&((AFProgramDestDriver *)last_driver)->process_info, $3); } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/afprog/afprog-parser.c000066400000000000000000000032031321171025300232750ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afprog.h" #include "cfg-parser.h" #include "afprog-grammar.h" extern int afprog_debug; int afprog_parse(CfgLexer *lexer, LogDriver **instance, gpointer arg); static CfgLexerKeyword afprog_keywords[] = { { "program", KW_PROGRAM }, { "keep_alive", KW_KEEP_ALIVE }, { "inherit_environment", KW_INHERIT_ENVIRONMENT }, { NULL } }; CfgParser afprog_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &afprog_debug, #endif .name = "afprog", .keywords = afprog_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer arg)) afprog_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(afprog_, LogDriver **) syslog-ng-syslog-ng-3.13.2/modules/afprog/afprog-parser.h000066400000000000000000000022151321171025300233040ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFPROG_PARSER_H_INCLUDED #define AFPROG_PARSER_H_INCLUDED #include "cfg-parser.h" #include "driver.h" extern CfgParser afprog_parser; CFG_PARSER_DECLARE_LEXER_BINDING(afprog_, LogDriver **) #endif syslog-ng-syslog-ng-3.13.2/modules/afprog/afprog-plugin.c000066400000000000000000000033521321171025300233040ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "plugin.h" #include "plugin-types.h" extern CfgParser afprog_parser; static Plugin afprog_plugins[] = { { .type = LL_CONTEXT_SOURCE, .name = "program", .parser = &afprog_parser, }, { .type = LL_CONTEXT_DESTINATION, .name = "program", .parser = &afprog_parser, }, }; gboolean afprog_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, afprog_plugins, G_N_ELEMENTS(afprog_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "afprog", .version = SYSLOG_NG_VERSION, .description = "The afprog module provides program source & destination drivers for syslog-ng.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = afprog_plugins, .plugins_len = G_N_ELEMENTS(afprog_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/afprog/afprog.c000066400000000000000000000372501321171025300220140ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afprog.h" #include "driver.h" #include "messages.h" #include "logwriter.h" #include "children.h" #include "fdhelpers.h" #include "stats/stats-registry.h" #include "transport/transport-pipe.h" #include "logproto/logproto-text-server.h" #include "logproto/logproto-text-client.h" #include "poll-fd-events.h" #include #include #include #include #include typedef struct _AFProgramReloadStoreItem { LogWriter *writer; pid_t pid; } AFProgramReloadStoreItem; static inline void _terminate_process_group_by_pid(const pid_t pid) { msg_verbose("Sending TERM signal to the process group", evt_tag_int("pid", pid)); pid_t pgid = getpgid(pid); if (pgid != -1 && pgid != getpgrp()) killpg(pgid, SIGTERM); } static inline void afprogram_reload_store_item_deinit(AFProgramReloadStoreItem *reload_info) { child_manager_unregister(reload_info->pid); _terminate_process_group_by_pid(reload_info->pid); } static inline void afprogram_reload_store_item_free(AFProgramReloadStoreItem *reload_info) { log_pipe_unref((LogPipe *)reload_info->writer); g_free(reload_info); } static inline void afprogram_reload_store_item_destroy_notify(gpointer data) { AFProgramReloadStoreItem *reload_info = (AFProgramReloadStoreItem *)data; afprogram_reload_store_item_deinit(reload_info); afprogram_reload_store_item_free(reload_info); } static inline void _exec_program_with_clean_environment(const gchar *cmdline) { execle("/bin/sh", "/bin/sh", "-c", cmdline, NULL, NULL); } static inline void _exec_program(const gchar *cmdline) { execl("/bin/sh", "/bin/sh", "-c", cmdline, NULL); } static gboolean afprogram_popen(AFProgramProcessInfo *process_info, GIOCondition cond, gint *fd) { int msg_pipe[2]; g_return_val_if_fail(cond == G_IO_IN || cond == G_IO_OUT, FALSE); if (pipe(msg_pipe) == -1) { msg_error("Error creating program pipe", evt_tag_str("cmdline", process_info->cmdline->str), evt_tag_errno(EVT_TAG_OSERROR, errno)); return FALSE; } if ((process_info->pid = fork()) < 0) { msg_error("Error in fork()", evt_tag_errno(EVT_TAG_OSERROR, errno)); close(msg_pipe[0]); close(msg_pipe[1]); return FALSE; } if (process_info->pid == 0) { /* child */ int devnull; setpgid(0, 0); devnull = open("/dev/null", O_WRONLY); if (devnull == -1) { _exit(127); } if (cond == G_IO_IN) { dup2(msg_pipe[1], 1); dup2(devnull, 0); dup2(devnull, 2); } else { dup2(msg_pipe[0], 0); dup2(devnull, 1); dup2(devnull, 2); } close(devnull); close(msg_pipe[0]); close(msg_pipe[1]); if (process_info->inherit_environment) _exec_program(process_info->cmdline->str); else _exec_program_with_clean_environment(process_info->cmdline->str); _exit(127); } if (cond == G_IO_IN) { *fd = msg_pipe[0]; close(msg_pipe[1]); } else { *fd = msg_pipe[1]; close(msg_pipe[0]); } return TRUE; } /* source driver */ static void afprogram_sd_kill_child(AFProgramSourceDriver *self) { if (self->process_info.pid != -1) { msg_verbose("Sending source program a TERM signal", evt_tag_str("cmdline", self->process_info.cmdline->str), evt_tag_int("child_pid", self->process_info.pid)); _terminate_process_group_by_pid(self->process_info.pid); self->process_info.pid = -1; } } static void afprogram_sd_exit(pid_t pid, int status, gpointer s) { AFProgramSourceDriver *self = (AFProgramSourceDriver *) s; /* Note: self->process_info.pid being -1 means that deinit was called, thus we don't * need to restart the command. self->process_info.pid might change due to EPIPE * handling restarting the command before this handler is run. */ if (self->process_info.pid != -1 && self->process_info.pid == pid) { msg_verbose("Child program exited", evt_tag_str("cmdline", self->process_info.cmdline->str), evt_tag_int("status", status)); self->process_info.pid = -1; } } static gboolean afprogram_sd_init(LogPipe *s) { AFProgramSourceDriver *self = (AFProgramSourceDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); gint fd; if (!log_src_driver_init_method(s)) return FALSE; if (cfg) log_reader_options_init(&self->reader_options, cfg, self->super.super.group); msg_verbose("Starting source program", evt_tag_str("cmdline", self->process_info.cmdline->str)); if (!afprogram_popen(&self->process_info, G_IO_IN, &fd)) return FALSE; /* parent */ child_manager_register(self->process_info.pid, afprogram_sd_exit, log_pipe_ref(&self->super.super.super), (GDestroyNotify) log_pipe_unref); g_fd_set_nonblock(fd, TRUE); g_fd_set_cloexec(fd, TRUE); if (!self->reader) { LogTransport *transport; LogProtoServer *proto; transport = log_transport_pipe_new(fd); proto = log_proto_text_server_new(transport, &self->reader_options.proto_options.super); self->reader = log_reader_new(s->cfg); log_reader_reopen(self->reader, proto, poll_fd_events_new(fd)); log_reader_set_options(self->reader, s, &self->reader_options, self->super.super.id, self->process_info.cmdline->str); } log_pipe_append((LogPipe *) self->reader, &self->super.super.super); if (!log_pipe_init((LogPipe *) self->reader)) { msg_error("Error initializing program source, closing fd", evt_tag_int("fd", fd)); log_pipe_unref((LogPipe *) self->reader); self->reader = NULL; close(fd); return FALSE; } return TRUE; } static gboolean afprogram_sd_deinit(LogPipe *s) { AFProgramSourceDriver *self = (AFProgramSourceDriver *) s; afprogram_sd_kill_child(self); if (self->reader) { log_pipe_deinit((LogPipe *) self->reader); log_pipe_unref((LogPipe *) self->reader); self->reader = NULL; } if (!log_src_driver_deinit_method(s)) return FALSE; return TRUE; } static void afprogram_sd_free(LogPipe *s) { AFProgramSourceDriver *self = (AFProgramSourceDriver *) s; log_reader_options_destroy(&self->reader_options); g_string_free(self->process_info.cmdline, TRUE); log_src_driver_free(s); } static void afprogram_sd_notify(LogPipe *s, gint notify_code, gpointer user_data) { switch (notify_code) { case NC_CLOSE: case NC_READ_ERROR: afprogram_sd_deinit(s); afprogram_sd_init(s); break; } } LogDriver * afprogram_sd_new(gchar *cmdline, GlobalConfig *cfg) { AFProgramSourceDriver *self = g_new0(AFProgramSourceDriver, 1); log_src_driver_init_instance(&self->super, cfg); self->super.super.super.init = afprogram_sd_init; self->super.super.super.deinit = afprogram_sd_deinit; self->super.super.super.free_fn = afprogram_sd_free; self->super.super.super.notify = afprogram_sd_notify; self->process_info.cmdline = g_string_new(cmdline); afprogram_set_inherit_environment(&self->process_info, TRUE); log_reader_options_defaults(&self->reader_options); self->reader_options.parse_options.flags |= LP_LOCAL; self->reader_options.super.stats_level = STATS_LEVEL0; self->reader_options.super.stats_source = SCS_PROGRAM; return &self->super.super; } /* dest driver */ static void afprogram_dd_exit(pid_t pid, int status, gpointer s); static gchar * afprogram_dd_format_queue_persist_name(AFProgramDestDriver *self) { static gchar persist_name[256]; g_snprintf(persist_name, sizeof(persist_name), "afprogram_dd_qname(%s,%s)", self->process_info.cmdline->str, self->super.super.id); return persist_name; } static const gchar * afprogram_dd_format_persist_name(const LogPipe *s) { const AFProgramDestDriver *self = (const AFProgramDestDriver *)s; static gchar persist_name[256]; if (s->persist_name) g_snprintf(persist_name, sizeof(persist_name), "afprogram_dd_name.%s", s->persist_name); else g_snprintf(persist_name, sizeof(persist_name), "afprogram_dd_name(%s,%s)", self->process_info.cmdline->str, self->super.super.id); return persist_name; } static void afprogram_dd_kill_child(AFProgramDestDriver *self) { if (self->process_info.pid != -1) { msg_verbose("Sending destination program a TERM signal", evt_tag_str("cmdline", self->process_info.cmdline->str), evt_tag_int("child_pid", self->process_info.pid)); _terminate_process_group_by_pid(self->process_info.pid); self->process_info.pid = -1; } } static inline gboolean afprogram_dd_open_program(AFProgramDestDriver *self, int *fd) { if (self->process_info.pid == -1) { msg_verbose("Starting destination program", evt_tag_str("cmdline", self->process_info.cmdline->str)); if (!afprogram_popen(&self->process_info, G_IO_OUT, fd)) return FALSE; g_fd_set_nonblock(*fd, TRUE); } child_manager_register(self->process_info.pid, afprogram_dd_exit, log_pipe_ref(&self->super.super.super), (GDestroyNotify)log_pipe_unref); return TRUE; } static gboolean afprogram_dd_reopen(AFProgramDestDriver *self) { int fd; afprogram_dd_kill_child(self); if (!afprogram_dd_open_program(self, &fd)) return FALSE; log_writer_reopen(self->writer, log_proto_text_client_new(log_transport_pipe_new(fd), &self->writer_options.proto_options.super)); return TRUE; } static void afprogram_dd_exit(pid_t pid, int status, gpointer s) { AFProgramDestDriver *self = (AFProgramDestDriver *) s; /* Note: self->process_info.pid being -1 means that deinit was called, thus we don't * need to restart the command. self->process_info.pid might change due to EPIPE * handling restarting the command before this handler is run. */ if (self->process_info.pid != -1 && self->process_info.pid == pid) { msg_verbose("Child program exited, restarting", evt_tag_str("cmdline", self->process_info.cmdline->str), evt_tag_int("status", status)); self->process_info.pid = -1; afprogram_dd_reopen(self); } } static gboolean afprogram_dd_restore_reload_store_item(AFProgramDestDriver *self, GlobalConfig *cfg) { const gchar *persist_name = afprogram_dd_format_persist_name((const LogPipe *)self); AFProgramReloadStoreItem *restored_info = (AFProgramReloadStoreItem *)cfg_persist_config_fetch(cfg, persist_name); if (restored_info) { self->process_info.pid = restored_info->pid; self->writer = restored_info->writer; child_manager_register(self->process_info.pid, afprogram_dd_exit, log_pipe_ref(&self->super.super.super), (GDestroyNotify)log_pipe_unref); g_free(restored_info); } return !!(self->writer); } static gboolean afprogram_dd_init(LogPipe *s) { AFProgramDestDriver *self = (AFProgramDestDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_dest_driver_init_method(s)) return FALSE; log_writer_options_init(&self->writer_options, cfg, 0); const gboolean restore_successful = afprogram_dd_restore_reload_store_item(self, cfg); if (!self->writer) self->writer = log_writer_new(LW_FORMAT_FILE, s->cfg); log_writer_set_options(self->writer, s, &self->writer_options, self->super.super.id, self->process_info.cmdline->str); log_writer_set_queue(self->writer, log_dest_driver_acquire_queue(&self->super, afprogram_dd_format_queue_persist_name(self))); if (!log_pipe_init((LogPipe *) self->writer)) { log_pipe_unref((LogPipe *) self->writer); return FALSE; } log_pipe_append(&self->super.super.super, (LogPipe *) self->writer); return restore_successful ? TRUE : afprogram_dd_reopen(self); } static inline void afprogram_dd_store_reload_store_item(AFProgramDestDriver *self, GlobalConfig *cfg) { AFProgramReloadStoreItem *reload_info = g_new0(AFProgramReloadStoreItem, 1); reload_info->pid = self->process_info.pid; reload_info->writer = self->writer; cfg_persist_config_add(cfg, afprogram_dd_format_persist_name((const LogPipe *)self), reload_info, afprogram_reload_store_item_destroy_notify, FALSE); } static gboolean afprogram_dd_deinit(LogPipe *s) { AFProgramDestDriver *self = (AFProgramDestDriver *) s; GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); if (self->writer) log_pipe_deinit((LogPipe *) self->writer); child_manager_unregister(self->process_info.pid); if (self->keep_alive) { afprogram_dd_store_reload_store_item(self, cfg); } else { afprogram_dd_kill_child(self); if (self->writer) log_pipe_unref((LogPipe *) self->writer); } if (self->writer) { self->writer = NULL; } return log_dest_driver_deinit_method(s); } static void afprogram_dd_free(LogPipe *s) { AFProgramDestDriver *self = (AFProgramDestDriver *) s; log_pipe_unref((LogPipe *) self->writer); g_string_free(self->process_info.cmdline, TRUE); log_writer_options_destroy(&self->writer_options); log_dest_driver_free(s); } static void afprogram_dd_notify(LogPipe *s, gint notify_code, gpointer user_data) { AFProgramDestDriver *self = (AFProgramDestDriver *) s; switch (notify_code) { case NC_CLOSE: case NC_WRITE_ERROR: afprogram_dd_reopen(self); break; } } LogDriver * afprogram_dd_new(gchar *cmdline, GlobalConfig *cfg) { AFProgramDestDriver *self = g_new0(AFProgramDestDriver, 1); log_dest_driver_init_instance(&self->super, cfg); self->super.super.super.init = afprogram_dd_init; self->super.super.super.deinit = afprogram_dd_deinit; self->super.super.super.free_fn = afprogram_dd_free; self->super.super.super.notify = afprogram_dd_notify; self->super.super.super.generate_persist_name = afprogram_dd_format_persist_name; self->process_info.cmdline = g_string_new(cmdline); self->process_info.pid = -1; afprogram_set_inherit_environment(&self->process_info, TRUE); log_writer_options_defaults(&self->writer_options); self->writer_options.stats_level = STATS_LEVEL0; self->writer_options.stats_source = SCS_PROGRAM; return &self->super.super; } void afprogram_dd_set_keep_alive(AFProgramDestDriver *self, gboolean keep_alive) { self->keep_alive = keep_alive; } void afprogram_set_inherit_environment(AFProgramProcessInfo *self, gboolean inherit_environment) { self->inherit_environment = inherit_environment; } syslog-ng-syslog-ng-3.13.2/modules/afprog/afprog.h000066400000000000000000000035621321171025300220200ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFPROG_H_INCLUDED #define AFPROG_H_INCLUDED #include "driver.h" #include "logwriter.h" #include "logreader.h" typedef struct _AFProgramProcessInfo { pid_t pid; GString *cmdline; gboolean inherit_environment; } AFProgramProcessInfo; typedef struct _AFProgramSourceDriver { LogSrcDriver super; AFProgramProcessInfo process_info; LogReader *reader; LogReaderOptions reader_options; } AFProgramSourceDriver; typedef struct _AFProgramDestDriver { LogDestDriver super; AFProgramProcessInfo process_info; LogWriter *writer; gboolean keep_alive; LogWriterOptions writer_options; } AFProgramDestDriver; LogDriver *afprogram_sd_new(gchar *cmdline, GlobalConfig *cfg); LogDriver *afprogram_dd_new(gchar *cmdline, GlobalConfig *cfg); void afprogram_dd_set_keep_alive(AFProgramDestDriver *self, gboolean keep_alive); void afprogram_set_inherit_environment(AFProgramProcessInfo *self, gboolean inherit_environment); #endif syslog-ng-syslog-ng-3.13.2/modules/afsmtp/000077500000000000000000000000001321171025300203775ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afsmtp/CMakeLists.txt000066400000000000000000000017541321171025300231460ustar00rootroot00000000000000set(AFSMTP_SOURCES afsmtp.c afsmtp.h afsmtp-parser.c afsmtp-parser.h ${CMAKE_CURRENT_BINARY_DIR}/afsmtp-grammar.h ${CMAKE_CURRENT_BINARY_DIR}/afsmtp-grammar.c ) find_package(ESMTP) bison_target(AfsmtpGrammar ${CMAKE_CURRENT_BINARY_DIR}/afsmtp-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/afsmtp-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) generate_y_from_ym(modules/afsmtp/afsmtp-grammar) if (ESMTP_FOUND) option(ENABLE_AFSMTP "Enable SMTP destination" ON) else() option(ENABLE_AFSMTP "Enable SMTP destination" OFF) endif() if (ENABLE_AFSMTP) add_library(afsmtp MODULE ${AFSMTP_SOURCES}) target_link_libraries (afsmtp PUBLIC ${ESMTP_LIBRARIES}) target_include_directories (afsmtp SYSTEM PRIVATE ${ESMTP_INCLUDE_DIR}) target_include_directories (afsmtp PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(afsmtp PRIVATE syslog-ng) install(TARGETS afsmtp LIBRARY DESTINATION lib/syslog-ng/ COMPONENT afsmtp) endif() syslog-ng-syslog-ng-3.13.2/modules/afsmtp/Makefile.am000066400000000000000000000017421321171025300224370ustar00rootroot00000000000000if ENABLE_SMTP module_LTLIBRARIES += modules/afsmtp/libafsmtp.la modules_afsmtp_libafsmtp_la_CFLAGS = \ $(AM_CFLAGS) \ $(LIBESMTP_CFLAGS) \ -I$(top_srcdir)/modules/afsmtp \ -I$(top_builddir)/modules/afsmtp modules_afsmtp_libafsmtp_la_SOURCES = \ modules/afsmtp/afsmtp-grammar.y \ modules/afsmtp/afsmtp.c \ modules/afsmtp/afsmtp.h \ modules/afsmtp/afsmtp-parser.c \ modules/afsmtp/afsmtp-parser.h modules_afsmtp_libafsmtp_la_LIBADD = \ $(MODULE_DEPS_LIBS) $(LIBESMTP_LIBS) modules_afsmtp_libafsmtp_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_afsmtp_libafsmtp_la_DEPENDENCIES= \ $(MODULE_DEPS_LIBS) modules/afsmtp modules/afsmtp/ mod-afsmtp mod-smtp: \ modules/afsmtp/libafsmtp.la else modules/afsmtp modules/afsmtp/ mod-afsmtp mod-smtp: endif BUILT_SOURCES += \ modules/afsmtp/afsmtp-grammar.y \ modules/afsmtp/afsmtp-grammar.c \ modules/afsmtp/afsmtp-grammar.h EXTRA_DIST += \ modules/afsmtp/afsmtp-grammar.ym .PHONY: modules/afsmtp/ mod-afsmtp mod-smtp syslog-ng-syslog-ng-3.13.2/modules/afsmtp/afsmtp-grammar.ym000066400000000000000000000117221321171025300236670ustar00rootroot00000000000000/* * Copyright (c) 2011-2012 Balabit * Copyright (c) 2011-2012 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code requires { #include "afsmtp-parser.h" } %code { #include "cfg-parser.h" #include "cfg-grammar.h" #include "afsmtp-grammar.h" #include "plugin.h" extern LogDriver *last_driver; } %name-prefix "afsmtp_" %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogDriver **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_SMTP %token KW_SUBJECT %token KW_FROM %token KW_TO %token KW_BODY %token KW_HEADER %token KW_CC %token KW_BCC %token KW_SENDER %token KW_REPLY_TO %% start : LL_CONTEXT_DESTINATION KW_SMTP { last_driver = *instance = afsmtp_dd_new(configuration); } '(' afsmtp_options ')' { YYACCEPT; } ; afsmtp_options : afsmtp_option afsmtp_options | ; afsmtp_option : KW_HOST '(' string ')' { afsmtp_dd_set_host(last_driver, $3); free($3); } | KW_PORT '(' positive_integer ')' { afsmtp_dd_set_port(last_driver, $3); } | KW_SUBJECT '(' template_content ')' { afsmtp_dd_set_subject(last_driver, $3); log_template_unref($3); } | KW_BODY '(' template_content ')' { afsmtp_dd_set_body(last_driver, $3); log_template_unref($3); } | KW_HEADER '(' string template_content ')' { afsmtp_dd_add_header(last_driver, $3, $4); free($3); log_template_unref($4); } | KW_FROM '(' template_content ')' { afsmtp_dd_set_from(last_driver, $3, $3); log_template_unref($3); } | KW_FROM '(' template_content template_content ')' { afsmtp_dd_set_from(last_driver, $3, $4); log_template_unref($3); log_template_unref($4); } | KW_SENDER '(' template_content ')' { afsmtp_dd_set_from(last_driver, $3, $3); log_template_unref($3); } | KW_SENDER '(' template_content template_content ')' { afsmtp_dd_set_from(last_driver, $3, $4); log_template_unref($3); log_template_unref($4); } | KW_TO '(' template_content ')' { afsmtp_dd_add_rcpt(last_driver, AFSMTP_RCPT_TYPE_TO, $3, $3); log_template_unref($3); } | KW_TO '(' template_content template_content ')' { afsmtp_dd_add_rcpt(last_driver, AFSMTP_RCPT_TYPE_TO, $3, $4); log_template_unref($3); log_template_unref($4); } | KW_CC '(' template_content ')' { afsmtp_dd_add_rcpt(last_driver, AFSMTP_RCPT_TYPE_CC, $3, $3); log_template_unref($3); } | KW_CC '(' template_content template_content ')' { afsmtp_dd_add_rcpt(last_driver, AFSMTP_RCPT_TYPE_CC, $3, $4); log_template_unref($3); log_template_unref($4); } | KW_BCC '(' template_content ')' { afsmtp_dd_add_rcpt(last_driver, AFSMTP_RCPT_TYPE_BCC, $3, $3); log_template_unref($3); } | KW_BCC '(' template_content template_content ')' { afsmtp_dd_add_rcpt(last_driver, AFSMTP_RCPT_TYPE_BCC, $3, $4); log_template_unref($3); log_template_unref($4); } | KW_REPLY_TO '(' template_content ')' { afsmtp_dd_add_rcpt(last_driver, AFSMTP_RCPT_TYPE_REPLY_TO, $3, $3); log_template_unref($3); } | KW_REPLY_TO '(' template_content template_content ')' { afsmtp_dd_add_rcpt(last_driver, AFSMTP_RCPT_TYPE_REPLY_TO, $3, $4); log_template_unref($3); log_template_unref($4); } | threaded_dest_driver_option | dest_driver_option | { last_template_options = afsmtp_dd_get_template_options(last_driver); } template_option ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/afsmtp/afsmtp-parser.c000066400000000000000000000035271321171025300233360ustar00rootroot00000000000000/* * Copyright (c) 2011-2014 Balabit * Copyright (c) 2011-2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afsmtp.h" #include "cfg-parser.h" #include "afsmtp-grammar.h" extern int afsmtp_debug; int afsmtp_parse(CfgLexer *lexer, LogDriver **instance, gpointer arg); static CfgLexerKeyword afsmtp_keywords[] = { { "smtp", KW_SMTP }, { "host", KW_HOST }, { "port", KW_PORT }, { "subject", KW_SUBJECT }, { "from", KW_FROM }, { "to", KW_TO }, { "cc", KW_CC }, { "bcc", KW_BCC }, { "reply_to", KW_REPLY_TO }, { "sender", KW_SENDER }, { "body", KW_BODY }, { "header", KW_HEADER }, { NULL } }; CfgParser afsmtp_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &afsmtp_debug, #endif .name = "afsmtp", .keywords = afsmtp_keywords, .parse = (int (*)(CfgLexer *lexer, gpointer *instance, gpointer)) afsmtp_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(afsmtp_, LogDriver **) syslog-ng-syslog-ng-3.13.2/modules/afsmtp/afsmtp-parser.h000066400000000000000000000022361321171025300233370ustar00rootroot00000000000000/* * Copyright (c) 2011-2012 Balabit * Copyright (c) 2011-2012 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSMTP_PARSER_H_INCLUDED #define AFSMTP_PARSER_H_INCLUDED #include "cfg-parser.h" #include "afsmtp.h" extern CfgParser afsmtp_parser; CFG_PARSER_DECLARE_LEXER_BINDING(afsmtp_, LogDriver **) #endif syslog-ng-syslog-ng-3.13.2/modules/afsmtp/afsmtp.c000066400000000000000000000447321321171025300220470ustar00rootroot00000000000000/* * Copyright (c) 2011-2014 Balabit * Copyright (c) 2011-2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afsmtp.h" #include "afsmtp-parser.h" #include "plugin.h" #include "messages.h" #include "stats/stats-registry.h" #include "logqueue.h" #include "plugin-types.h" #include "logthrdestdrv.h" #include #include typedef struct { gchar *name; LogTemplate *template; } AFSMTPHeader; typedef struct { gchar *phrase; LogTemplate *template; afsmtp_rcpt_type_t type; } AFSMTPRecipient; typedef struct { LogThrDestDriver super; /* Shared between main/writer; only read by the writer, never written */ gchar *host; gint port; AFSMTPRecipient *mail_from; GList *rcpt_tos; GList *headers; LogTemplate *subject_template; LogTemplate *body_template; /* Writer-only stuff */ GString *str; LogTemplateOptions template_options; } AFSMTPDriver; typedef struct { gboolean success; AFSMTPDriver *driver; } LogRcptStatusData; static gchar * afsmtp_wash_string (gchar *str) { gint i; for (i = 0; i < strlen (str); i++) if (str[i] == '\n' || str[i] == '\r') str[i] = ' '; return str; } LogTemplateOptions * afsmtp_dd_get_template_options(LogDriver *d) { AFSMTPDriver *self = (AFSMTPDriver *)d; return &self->template_options; } /* * Configuration */ void afsmtp_dd_set_host(LogDriver *d, const gchar *host) { AFSMTPDriver *self = (AFSMTPDriver *)d; g_free(self->host); self->host = g_strdup (host); } void afsmtp_dd_set_port(LogDriver *d, gint port) { AFSMTPDriver *self = (AFSMTPDriver *)d; self->port = (int)port; } void afsmtp_dd_set_subject(LogDriver *d, LogTemplate *subject) { AFSMTPDriver *self = (AFSMTPDriver *)d; log_template_unref(self->subject_template); self->subject_template = log_template_ref(subject); } void afsmtp_dd_set_from(LogDriver *d, LogTemplate *phrase, LogTemplate *mbox) { AFSMTPDriver *self = (AFSMTPDriver *)d; g_free(self->mail_from->phrase); self->mail_from->phrase = afsmtp_wash_string(g_strdup(phrase->template)); log_template_unref(self->mail_from->template); self->mail_from->template = log_template_ref(mbox); } void afsmtp_dd_add_rcpt(LogDriver *d, afsmtp_rcpt_type_t type, LogTemplate *phrase, LogTemplate *mbox) { AFSMTPDriver *self = (AFSMTPDriver *)d; AFSMTPRecipient *rcpt; rcpt = g_new0(AFSMTPRecipient, 1); rcpt->phrase = afsmtp_wash_string(g_strdup(phrase->template)); log_template_unref(rcpt->template); rcpt->template = log_template_ref(mbox); rcpt->type = type; self->rcpt_tos = g_list_append(self->rcpt_tos, rcpt); } void afsmtp_dd_set_body(LogDriver *d, LogTemplate *body) { AFSMTPDriver *self = (AFSMTPDriver *)d; log_template_unref(self->body_template); self->body_template = log_template_ref(body); } gboolean afsmtp_dd_add_header(LogDriver *d, const gchar *header, LogTemplate *value) { AFSMTPDriver *self = (AFSMTPDriver *)d; AFSMTPHeader *h; if (!g_ascii_strcasecmp(header, "to") || !g_ascii_strcasecmp(header, "cc") || !g_ascii_strcasecmp(header, "bcc") || !g_ascii_strcasecmp(header, "from") || !g_ascii_strcasecmp(header, "sender") || !g_ascii_strcasecmp(header, "reply-to") || !g_ascii_strcasecmp(header, "date")) return FALSE; h = g_new0(AFSMTPHeader, 1); h->name = g_strdup(header); log_template_unref(h->template); h->template = log_template_ref(value); self->headers = g_list_append(self->headers, h); return TRUE; } /* * Utilities */ void ignore_sigpipe (void) { struct sigaction sa; sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGPIPE, &sa, NULL); } static gchar * afsmtp_dd_format_stats_instance(LogThrDestDriver *d) { AFSMTPDriver *self = (AFSMTPDriver *)d; static gchar persist_name[1024]; if (d->super.super.super.persist_name) g_snprintf(persist_name, sizeof(persist_name), "smtp,%s", d->super.super.super.persist_name); else g_snprintf(persist_name, sizeof(persist_name), "smtp,%s,%u", self->host, self->port); return persist_name; } static const gchar * afsmtp_dd_format_persist_name(const LogPipe *s) { const AFSMTPDriver *self = (const AFSMTPDriver *)s; static gchar persist_name[1024]; if (s->persist_name) g_snprintf(persist_name, sizeof(persist_name), "smtp.%s", s->persist_name); else g_snprintf(persist_name, sizeof(persist_name), "smtp(%s,%u)", self->host, self->port); return persist_name; } /* * Worker thread */ static void _smtp_message_add_recipient_header(smtp_message_t self, AFSMTPRecipient *rcpt, AFSMTPDriver *driver) { gchar *hdr; switch (rcpt->type) { case AFSMTP_RCPT_TYPE_TO: hdr = "To"; break; case AFSMTP_RCPT_TYPE_CC: hdr = "Cc"; break; case AFSMTP_RCPT_TYPE_REPLY_TO: hdr = "Reply-To"; break; default: return; } smtp_set_header(self, hdr, rcpt->phrase, afsmtp_wash_string (driver->str->str)); smtp_set_header_option(self, hdr, Hdr_OVERRIDE, 1); } static void _smtp_message_add_recipient_from_template(smtp_message_t self, AFSMTPDriver *driver, LogTemplate *template, LogMessage *msg) { log_template_format(template, msg, &driver->template_options, LTZ_SEND, driver->super.seq_num, NULL, driver->str); smtp_add_recipient(self, afsmtp_wash_string (driver->str->str)); } static void afsmtp_dd_msg_add_recipient(AFSMTPRecipient *rcpt, gpointer user_data) { AFSMTPDriver *self = ((gpointer *)user_data)[0]; LogMessage *msg = ((gpointer *)user_data)[1]; smtp_message_t message = ((gpointer *)user_data)[2]; _smtp_message_add_recipient_from_template(message, self, rcpt->template, msg); _smtp_message_add_recipient_header(message, rcpt, self); } static void afsmtp_dd_msg_add_header(AFSMTPHeader *hdr, gpointer user_data) { AFSMTPDriver *self = ((gpointer *)user_data)[0]; LogMessage *msg = ((gpointer *)user_data)[1]; smtp_message_t message = ((gpointer *)user_data)[2]; log_template_format(hdr->template, msg, &self->template_options, LTZ_LOCAL, self->super.seq_num, NULL, self->str); smtp_set_header(message, hdr->name, afsmtp_wash_string (self->str->str), NULL); smtp_set_header_option(message, hdr->name, Hdr_OVERRIDE, 1); } static void afsmtp_dd_log_rcpt_status(smtp_recipient_t rcpt, const char *mailbox, gpointer user_data) { const smtp_status_t *status; LogRcptStatusData *status_data = (LogRcptStatusData *)user_data; status = smtp_recipient_status(rcpt); if (status->code != 250) { status_data->success = FALSE; msg_error("SMTP recipient result", evt_tag_str("driver", status_data->driver->super.super.super.id), evt_tag_str("recipient", mailbox), evt_tag_int("code", status->code), evt_tag_str("text", status->text)); } else { msg_debug("SMTP recipient result", evt_tag_str("driver", status_data->driver->super.super.super.id), evt_tag_str("recipient", mailbox), evt_tag_int("code", status->code), evt_tag_str("text", status->text)); } } static void afsmtp_dd_cb_event(smtp_session_t session, int event, AFSMTPDriver *self) { switch (event) { case SMTP_EV_CONNECT: msg_verbose("Connected to SMTP server", evt_tag_str("driver", self->super.super.super.id), evt_tag_str("host", self->host), evt_tag_int("port", self->port)); break; case SMTP_EV_MAILSTATUS: case SMTP_EV_RCPTSTATUS: case SMTP_EV_MESSAGEDATA: case SMTP_EV_MESSAGESENT: /* Ignore */ break; case SMTP_EV_DISCONNECT: msg_verbose("Disconnected from SMTP server", evt_tag_str("driver", self->super.super.super.id), evt_tag_str("host", self->host), evt_tag_int("port", self->port)); break; default: msg_verbose("Unknown SMTP event", evt_tag_str("driver", self->super.super.super.id), evt_tag_int("event_id", event)); break; } } static void afsmtp_dd_cb_monitor(const gchar *buf, gint buflen, gint writing, AFSMTPDriver *self) { gchar fmt[32]; g_snprintf(fmt, sizeof(fmt), "%%.%us", buflen); switch (writing) { case SMTP_CB_READING: msg_debug ("SMTP Session: SERVER", evt_tag_str("driver", self->super.super.super.id), evt_tag_printf("message", fmt, buf)); break; case SMTP_CB_WRITING: msg_debug("SMTP Session: CLIENT", evt_tag_str("driver", self->super.super.super.id), evt_tag_printf("message", fmt, buf)); break; case SMTP_CB_HEADERS: msg_debug("SMTP Session: HEADERS", evt_tag_str("driver", self->super.super.super.id), evt_tag_printf("data", fmt, buf)); break; } } static smtp_session_t __build_session(AFSMTPDriver *self, LogMessage *msg) { smtp_session_t session; session = smtp_create_session(); g_string_printf(self->str, "%s:%d", self->host, self->port); smtp_set_server(session, self->str->str); smtp_set_eventcb(session, (smtp_eventcb_t) afsmtp_dd_cb_event, (void *) self); smtp_set_monitorcb(session, (smtp_monitorcb_t) afsmtp_dd_cb_monitor, (void *) self, 1); return session; } static smtp_message_t __build_message(AFSMTPDriver *self, LogMessage *msg, smtp_session_t session) { smtp_message_t message; gpointer args[] = { self, NULL, NULL }; message = smtp_add_message(session); log_template_format(self->mail_from->template, msg, &self->template_options, LTZ_SEND, self->super.seq_num, NULL, self->str); smtp_set_reverse_path(message, afsmtp_wash_string(self->str->str)); /* Defaults */ smtp_set_header(message, "To", NULL, NULL); smtp_set_header(message, "From", NULL, NULL); log_template_format(self->subject_template, msg, &self->template_options, LTZ_SEND, self->super.seq_num, NULL, self->str); smtp_set_header(message, "Subject", afsmtp_wash_string(self->str->str)); smtp_set_header_option(message, "Subject", Hdr_OVERRIDE, 1); /* Add recipients */ args[1] = msg; args[2] = message; g_list_foreach(self->rcpt_tos, (GFunc) afsmtp_dd_msg_add_recipient, args); /* Add custom header (overrides anything set before, or in the body). */ g_list_foreach(self->headers, (GFunc) afsmtp_dd_msg_add_header, args); /* Set the body. * * We add a header to the body, otherwise libesmtp will not * recognise headers, and will append them to the end of the body. */ g_string_assign(self->str, "X-Mailer: syslog-ng " SYSLOG_NG_VERSION "\r\n\r\n"); log_template_append_format(self->body_template, msg, &self->template_options, LTZ_SEND, self->super.seq_num, NULL, self->str); smtp_set_message_str(message, self->str->str); return message; } static gboolean __check_transfer_status(AFSMTPDriver *self, smtp_message_t message) { LogRcptStatusData status_data; const smtp_status_t *status = smtp_message_transfer_status(message); status_data.success = TRUE; status_data.driver = self; if (status->code != 250) { status_data.success = FALSE; msg_error("Failed to send message", evt_tag_str("driver", self->super.super.super.id), evt_tag_int("code", status->code), evt_tag_str("text", status->text)); } else { msg_debug("SMTP result", evt_tag_str("driver", self->super.super.super.id), evt_tag_int("code", status->code), evt_tag_str("text", status->text)); smtp_enumerate_recipients(message, afsmtp_dd_log_rcpt_status, &status_data); } return status_data.success; } static gboolean __send_message(AFSMTPDriver *self, smtp_session_t session) { gboolean success = smtp_start_session(session); if (!(success)) { gchar error[1024] = {0}; smtp_strerror(smtp_errno(), error, sizeof (error) - 1); msg_error("SMTP server error, suspending", evt_tag_str("driver", self->super.super.super.id), evt_tag_str("error", error), evt_tag_int("time_reopen", self->super.time_reopen)); success = FALSE; } return success; } static worker_insert_result_t afsmtp_worker_insert(LogThrDestDriver *s, LogMessage *msg) { AFSMTPDriver *self = (AFSMTPDriver *)s; gboolean success = TRUE; gboolean message_sent = TRUE; smtp_session_t session = NULL; smtp_message_t message; if (msg->flags & LF_MARK) { msg_debug("Mark messages are dropped by SMTP destination", evt_tag_str("driver", self->super.super.super.id)); return WORKER_INSERT_RESULT_SUCCESS; } session = __build_session(self, msg); message = __build_message(self, msg, session); message_sent = __send_message(self, session); success = message_sent && __check_transfer_status(self, message); smtp_destroy_session(session); if (!success) { if (!message_sent) return WORKER_INSERT_RESULT_NOT_CONNECTED; else return WORKER_INSERT_RESULT_ERROR; } return WORKER_INSERT_RESULT_SUCCESS; } static void afsmtp_worker_thread_init(LogThrDestDriver *d) { AFSMTPDriver *self = (AFSMTPDriver *)d; self->str = g_string_sized_new(1024); ignore_sigpipe(); } static void afsmtp_worker_thread_deinit(LogThrDestDriver *d) { AFSMTPDriver *self = (AFSMTPDriver *)d; g_string_free(self->str, TRUE); } /* * Main thread */ static gboolean __check_rcpt_tos(AFSMTPDriver *self) { gboolean result = FALSE; GList *l = self->rcpt_tos; while (l) { AFSMTPRecipient *rcpt = (AFSMTPRecipient *)l->data; gboolean rcpt_type_accepted = rcpt->type == AFSMTP_RCPT_TYPE_BCC || rcpt->type == AFSMTP_RCPT_TYPE_CC || rcpt->type == AFSMTP_RCPT_TYPE_TO; if (rcpt->template && rcpt_type_accepted) { result = TRUE; break; } l = l->next; } return result; } static gboolean __check_required_options(AFSMTPDriver *self) { if (!self->mail_from->template) { msg_error("Error: from or sender option is required", evt_tag_str("driver", self->super.super.super.id)); return FALSE; } if (!__check_rcpt_tos(self)) { msg_error("Error: to or bcc option is required", evt_tag_str("driver", self->super.super.super.id)); return FALSE; } if (!self->subject_template) { msg_error("Error: subject is required option", evt_tag_str("driver", self->super.super.super.id)); return FALSE; } if (!self->body_template) { msg_error("Error: body is required option", evt_tag_str("driver", self->super.super.super.id)); return FALSE; } return TRUE; } static gboolean afsmtp_dd_init(LogPipe *s) { AFSMTPDriver *self = (AFSMTPDriver *)s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_dest_driver_init_method(s)) return FALSE; msg_verbose("Initializing SMTP destination", evt_tag_str("driver", self->super.super.super.id), evt_tag_str("host", self->host), evt_tag_int("port", self->port)); if (!__check_required_options(self)) return FALSE; log_template_options_init(&self->template_options, cfg); return log_threaded_dest_driver_start(s); } static void afsmtp_dd_free(LogPipe *d) { AFSMTPDriver *self = (AFSMTPDriver *)d; GList *l; g_free(self->host); g_free(self->mail_from->phrase); log_template_unref(self->mail_from->template); g_free(self->mail_from); log_template_unref(self->subject_template); log_template_unref(self->body_template); l = self->rcpt_tos; while (l) { AFSMTPRecipient *rcpt = (AFSMTPRecipient *)l->data; g_free(rcpt->phrase); log_template_unref(rcpt->template); g_free(rcpt); l = g_list_delete_link(l, l); } l = self->headers; while (l) { AFSMTPHeader *hdr = (AFSMTPHeader *)l->data; g_free(hdr->name); log_template_unref(hdr->template); g_free(hdr); l = g_list_delete_link(l, l); } log_template_options_destroy(&self->template_options); log_threaded_dest_driver_free(d); } /* * Plugin glue. */ LogDriver * afsmtp_dd_new(GlobalConfig *cfg) { AFSMTPDriver *self = g_new0(AFSMTPDriver, 1); log_threaded_dest_driver_init_instance(&self->super, cfg); self->super.super.super.super.init = afsmtp_dd_init; self->super.super.super.super.free_fn = afsmtp_dd_free; self->super.super.super.super.generate_persist_name = afsmtp_dd_format_persist_name; self->super.worker.thread_init = afsmtp_worker_thread_init; self->super.worker.thread_deinit = afsmtp_worker_thread_deinit; self->super.worker.insert = afsmtp_worker_insert; self->super.format.stats_instance = afsmtp_dd_format_stats_instance; self->super.stats_source = SCS_SMTP; afsmtp_dd_set_host((LogDriver *)self, "127.0.0.1"); afsmtp_dd_set_port((LogDriver *)self, 25); self->mail_from = g_new0(AFSMTPRecipient, 1); log_template_options_defaults(&self->template_options); return (LogDriver *)self; } extern CfgParser afsmtp_dd_parser; static Plugin afsmtp_plugin = { .type = LL_CONTEXT_DESTINATION, .name = "smtp", .parser = &afsmtp_parser, }; gboolean afsmtp_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, &afsmtp_plugin, 1); return TRUE; } const ModuleInfo module_info = { .canonical_name = "afsmtp", .version = SYSLOG_NG_VERSION, .description = "The afsmtp module provides SMTP destination support for syslog-ng.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = &afsmtp_plugin, .plugins_len = 1, }; syslog-ng-syslog-ng-3.13.2/modules/afsmtp/afsmtp.h000066400000000000000000000036061321171025300220470ustar00rootroot00000000000000/* * Copyright (c) 2011-2014 Balabit * Copyright (c) 2011-2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSMTP_H_INCLUDED #define AFSMTP_H_INCLUDED #include "driver.h" typedef enum { AFSMTP_RCPT_TYPE_NONE, AFSMTP_RCPT_TYPE_TO, AFSMTP_RCPT_TYPE_CC, AFSMTP_RCPT_TYPE_BCC, AFSMTP_RCPT_TYPE_REPLY_TO, AFSMTP_RCPT_TYPE_SENDER, } afsmtp_rcpt_type_t; LogDriver *afsmtp_dd_new(GlobalConfig *cfg); void afsmtp_dd_set_host(LogDriver *d, const gchar *host); void afsmtp_dd_set_port(LogDriver *d, gint port); void afsmtp_dd_set_subject(LogDriver *d, LogTemplate *subject); void afsmtp_dd_set_from(LogDriver *d, LogTemplate *phrase, LogTemplate *mbox); void afsmtp_dd_add_rcpt(LogDriver *d, afsmtp_rcpt_type_t type, LogTemplate *phrase, LogTemplate *mbox); void afsmtp_dd_set_body(LogDriver *d, LogTemplate *body); gboolean afsmtp_dd_add_header(LogDriver *d, const gchar *header, LogTemplate *value); LogTemplateOptions *afsmtp_dd_get_template_options(LogDriver *d); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/000077500000000000000000000000001321171025300207045ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afsocket/CMakeLists.txt000066400000000000000000000040301321171025300234410ustar00rootroot00000000000000set(AFSOCKET_SOURCES afsocket.c afsocket.h afsocket-source.c afsocket-source.h afsocket-dest.c afsocket-dest.h socket-options.c socket-options.h transport-mapper.c transport-mapper.h afinet.c afinet.h afinet-source.c afinet-source.h afinet-dest.c afinet-dest.h socket-options-inet.c socket-options-inet.h transport-mapper-inet.c transport-mapper-inet.h afunix-source.c afunix-source.h afunix-dest.c afunix-dest.h transport-mapper-unix.c transport-mapper-unix.h transport-unix-socket.c transport-unix-socket.h unix-credentials.c unix-credentials.h afsocket-grammar.y afsocket-parser.c afsocket-parser.h afsocket-plugin.c systemd-syslog-source.h systemd-syslog-source.c afsocket-systemd-override.h ${CMAKE_CURRENT_BINARY_DIR}/afsocket-grammar.c ${CMAKE_CURRENT_BINARY_DIR}/afsocket-grammar.h ) check_struct_member ("struct msghdr" "msg_control" "sys/types.h;sys/socket.h" SYSLOG_NG_HAVE_CTRLBUF_IN_MSGHDR) generate_y_from_ym(modules/afsocket/afsocket-grammar) bison_target(AFSocketGrammar ${CMAKE_CURRENT_BINARY_DIR}/afsocket-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/afsocket-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) find_package(ZLIB REQUIRED) find_package(OpenSSL REQUIRED) find_package(systemd) include_directories (${CMAKE_CURRENT_BINARY_DIR}) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) add_library(afsocket MODULE ${AFSOCKET_SOURCES}) target_link_libraries(afsocket PUBLIC ${WRAP_LIBRARIES} ${ZLIB_LIBRARIES} ${OPENSSL_LIBRARIES} ${LIBNET_LIBRARIES} ${Libsystemd_LIBRARIES}) target_link_libraries(afsocket PUBLIC syslog-ng) target_include_directories(afsocket PRIVATE SYSTEM ${ZLIB_INCLUDE_DIRS}) target_include_directories(afsocket PRIVATE SYSTEM ${WRAP_INCLUDE_DIRS}) target_include_directories(afsocket PRIVATE SYSTEM ${Libsystemd_INCLUDE_DIRS}) target_compile_definitions(afsocket PRIVATE ${LIBNET_DEFINES}) install(TARGETS afsocket LIBRARY DESTINATION lib/syslog-ng/ COMPONENT afsocket) syslog-ng-syslog-ng-3.13.2/modules/afsocket/Makefile.am000066400000000000000000000046321321171025300227450ustar00rootroot00000000000000modules_afsocket_libafsocket_la_SOURCES = \ modules/afsocket/afsocket.c \ modules/afsocket/afsocket.h \ modules/afsocket/afsocket-source.c \ modules/afsocket/afsocket-source.h \ modules/afsocket/afsocket-dest.c \ modules/afsocket/afsocket-dest.h \ modules/afsocket/socket-options.c \ modules/afsocket/socket-options.h \ modules/afsocket/transport-mapper.c \ modules/afsocket/transport-mapper.h \ modules/afsocket/afinet.c \ modules/afsocket/afinet.h \ modules/afsocket/afinet-source.c \ modules/afsocket/afinet-source.h \ modules/afsocket/afinet-dest.c \ modules/afsocket/afinet-dest.h \ modules/afsocket/socket-options-inet.c \ modules/afsocket/socket-options-inet.h \ modules/afsocket/transport-mapper-inet.c \ modules/afsocket/transport-mapper-inet.h \ modules/afsocket/afunix-source.c \ modules/afsocket/afunix-source.h \ modules/afsocket/afunix-dest.c \ modules/afsocket/afunix-dest.h \ modules/afsocket/transport-mapper-unix.c \ modules/afsocket/transport-mapper-unix.h \ modules/afsocket/transport-unix-socket.c \ modules/afsocket/transport-unix-socket.h \ modules/afsocket/unix-credentials.c \ modules/afsocket/unix-credentials.h \ modules/afsocket/afsocket-grammar.y \ modules/afsocket/afsocket-parser.c \ modules/afsocket/afsocket-parser.h \ modules/afsocket/afsocket-plugin.c \ modules/afsocket/systemd-syslog-source.h \ modules/afsocket/systemd-syslog-source.c \ modules/afsocket/afsocket-systemd-override.h module_LTLIBRARIES += modules/afsocket/libafsocket.la modules_afsocket_libafsocket_la_CPPFLAGS = \ $(AM_CPPFLAGS) $(libsystemd_CFLAGS) \ -I${top_srcdir}/modules/afsocket \ -I${top_builddir}/modules/afsocket modules_afsocket_libafsocket_la_LIBADD = \ $(MODULE_DEPS_LIBS) $(OPENSSL_LIBS) \ $(ZLIB_LIBS) $(LIBNET_LIBS) \ $(LIBWRAP_LIBS) $(libsystemd_LIBS) modules_afsocket_libafsocket_la_DEPENDENCIES= \ $(MODULE_DEPS_LIBS) modules_afsocket_libafsocket_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules/afsocket modules/afsocket/ mod-afsocket mod-socket: \ modules/afsocket/libafsocket.la BUILT_SOURCES += \ modules/afsocket/afsocket-grammar.y \ modules/afsocket/afsocket-grammar.c \ modules/afsocket/afsocket-grammar.h EXTRA_DIST += \ modules/afsocket/afsocket-grammar.ym CLEANFILES += \ modules/afsocket/libafsocket.la .PHONY: modules/afsocket/ mod-afsocket mod-socket include modules/afsocket/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/modules/afsocket/afinet-dest.c000066400000000000000000000357361321171025300232710ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afinet-dest.h" #include "transport-mapper-inet.h" #include "socket-options-inet.h" #include "messages.h" #include "gprocess.h" #include "compat/openssl_support.h" #include #include #include #include #include #include #include #ifdef _GNU_SOURCE # define _GNU_SOURCE_DEFINED 1 # undef _GNU_SOURCE #endif #if SYSLOG_NG_ENABLE_SPOOF_SOURCE #include #endif #if _GNU_SOURCE_DEFINED # undef _GNU_SOURCE # define _GNU_SOURCE 1 #endif void afinet_dd_set_localip(LogDriver *s, gchar *ip) { AFInetDestDriver *self = (AFInetDestDriver *) s; if (self->bind_ip) g_free(self->bind_ip); self->bind_ip = g_strdup(ip); } void afinet_dd_set_localport(LogDriver *s, gchar *service) { AFInetDestDriver *self = (AFInetDestDriver *) s; if (self->bind_port) g_free(self->bind_port); self->bind_port = g_strdup(service); } void afinet_dd_set_destport(LogDriver *s, gchar *service) { AFInetDestDriver *self = (AFInetDestDriver *) s; if (self->dest_port) g_free(self->dest_port); self->dest_port = g_strdup(service); } void afinet_dd_set_spoof_source(LogDriver *s, gboolean enable) { #if SYSLOG_NG_ENABLE_SPOOF_SOURCE AFInetDestDriver *self = (AFInetDestDriver *) s; self->spoof_source = enable; #else msg_error("Error enabling spoof-source, you need to compile syslog-ng with --enable-spoof-source"); #endif } static gint afinet_dd_verify_callback(gint ok, X509_STORE_CTX *ctx, gpointer user_data) { AFInetDestDriver *self G_GNUC_UNUSED = (AFInetDestDriver *) user_data; TransportMapperInet *transport_mapper_inet = (TransportMapperInet *) self->super.transport_mapper; X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx); X509 *cert = X509_STORE_CTX_get0_cert(ctx); if (ok && current_cert == cert && self->hostname && (tls_context_get_verify_mode(transport_mapper_inet->tls_context) & TVM_TRUSTED)) { ok = tls_verify_certificate_name(cert, self->hostname); } return ok; } void afinet_dd_set_tls_context(LogDriver *s, TLSContext *tls_context) { AFInetDestDriver *self = (AFInetDestDriver *) s; transport_mapper_inet_set_tls_context((TransportMapperInet *) self->super.transport_mapper, tls_context, afinet_dd_verify_callback, self); } static LogWriter * afinet_dd_construct_writer(AFSocketDestDriver *s) { AFInetDestDriver *self G_GNUC_UNUSED = (AFInetDestDriver *) s; LogWriter *writer; TransportMapperInet *transport_mapper_inet G_GNUC_UNUSED = ((TransportMapperInet *) (self->super.transport_mapper)); writer = afsocket_dd_construct_writer_method(s); /* SSL is duplex, so we can certainly expect input from the server, which * would cause the LogWriter to close this connection. In a better world * LW_DETECT_EOF would be implemented by the LogProto class and would * inherently work w/o mockery in LogWriter. Defer that change for now * (and possibly for all eternity :) */ if (((self->super.transport_mapper->sock_type == SOCK_STREAM) && transport_mapper_inet->tls_context)) log_writer_set_flags(writer, log_writer_get_flags(writer) & ~LW_DETECT_EOF); return writer; } static const gint _determine_port(const AFInetDestDriver *self) { gint port = 0; if (!self->dest_port) port = transport_mapper_inet_get_server_port(self->super.transport_mapper); else port = afinet_lookup_service(self->super.transport_mapper, self->dest_port); return port; } static gboolean afinet_dd_setup_addresses(AFSocketDestDriver *s) { AFInetDestDriver *self = (AFInetDestDriver *) s; if (!afsocket_dd_setup_addresses_method(s)) return FALSE; g_sockaddr_unref(self->super.bind_addr); g_sockaddr_unref(self->super.dest_addr); if (!resolve_hostname_to_sockaddr(&self->super.bind_addr, self->super.transport_mapper->address_family, self->bind_ip)) return FALSE; if (self->bind_port) g_sockaddr_set_port(self->super.bind_addr, afinet_lookup_service(self->super.transport_mapper, self->bind_port)); if (!resolve_hostname_to_sockaddr(&self->super.dest_addr, self->super.transport_mapper->address_family, self->hostname)) return FALSE; if (!self->dest_port) { const gchar *port_change_warning = transport_mapper_inet_get_port_change_warning(self->super.transport_mapper); if (port_change_warning) { msg_warning(port_change_warning, evt_tag_str("id", self->super.super.super.id)); } } g_sockaddr_set_port(self->super.dest_addr, _determine_port(self)); return TRUE; } static const gchar * afinet_dd_get_dest_name(const AFSocketDestDriver *s) { const AFInetDestDriver *self = (const AFInetDestDriver *)s; static gchar buf[256]; if (strchr(self->hostname, ':') != NULL) g_snprintf(buf, sizeof(buf), "[%s]:%d", self->hostname, _determine_port(self)); else g_snprintf(buf, sizeof(buf), "%s:%d", self->hostname, _determine_port(self)); return buf; } static gboolean afinet_dd_init(LogPipe *s) { AFInetDestDriver *self G_GNUC_UNUSED = (AFInetDestDriver *) s; #if SYSLOG_NG_ENABLE_SPOOF_SOURCE if (self->spoof_source) self->super.connections_kept_alive_accross_reloads = TRUE; #endif if (!afsocket_dd_init(s)) return FALSE; #if SYSLOG_NG_ENABLE_SPOOF_SOURCE if (self->super.transport_mapper->sock_type == SOCK_DGRAM) { if (self->spoof_source && !self->lnet_ctx) { gchar error[LIBNET_ERRBUF_SIZE]; cap_t saved_caps; saved_caps = g_process_cap_save(); g_process_cap_modify(CAP_NET_RAW, TRUE); self->lnet_ctx = libnet_init(self->super.bind_addr->sa.sa_family == AF_INET ? LIBNET_RAW4 : LIBNET_RAW6, NULL, error); g_process_cap_restore(saved_caps); if (!self->lnet_ctx) { msg_error("Error initializing raw socket, spoof-source support disabled", evt_tag_str("error", NULL)); } } } #endif return TRUE; } #if SYSLOG_NG_ENABLE_SPOOF_SOURCE static gboolean afinet_dd_construct_ipv4_packet(AFInetDestDriver *self, LogMessage *msg, GString *msg_line) { libnet_ptag_t ip, udp; struct sockaddr_in *src, *dst; if (msg->saddr->sa.sa_family != AF_INET) return FALSE; src = (struct sockaddr_in *) &msg->saddr->sa; dst = (struct sockaddr_in *) &self->super.dest_addr->sa; libnet_clear_packet(self->lnet_ctx); udp = libnet_build_udp(ntohs(src->sin_port), ntohs(dst->sin_port), LIBNET_UDP_H + msg_line->len, 0, (guchar *) msg_line->str, msg_line->len, self->lnet_ctx, 0); if (udp == -1) return FALSE; ip = libnet_build_ipv4(LIBNET_IPV4_H + msg_line->len + LIBNET_UDP_H, IPTOS_LOWDELAY, /* IP tos */ 0, /* IP ID */ 0, /* frag stuff */ 64, /* TTL */ IPPROTO_UDP, /* transport protocol */ 0, src->sin_addr.s_addr, /* source IP */ dst->sin_addr.s_addr, /* destination IP */ NULL, /* payload (none) */ 0, /* payload length */ self->lnet_ctx, 0); if (ip == -1) return FALSE; return TRUE; } #if SYSLOG_NG_ENABLE_IPV6 static gboolean afinet_dd_construct_ipv6_packet(AFInetDestDriver *self, LogMessage *msg, GString *msg_line) { libnet_ptag_t ip, udp; struct sockaddr_in *src4; struct sockaddr_in6 src, *dst; struct libnet_in6_addr ln_src, ln_dst; switch (msg->saddr->sa.sa_family) { case AF_INET: src4 = (struct sockaddr_in *) &msg->saddr->sa; memset(&src, 0, sizeof(src)); src.sin6_family = AF_INET6; src.sin6_port = src4->sin_port; ((guint32 *) &src.sin6_addr)[0] = 0; ((guint32 *) &src.sin6_addr)[1] = 0; ((guint32 *) &src.sin6_addr)[2] = htonl(0xffff); ((guint32 *) &src.sin6_addr)[3] = src4->sin_addr.s_addr; break; case AF_INET6: src = *((struct sockaddr_in6 *) &msg->saddr->sa); break; default: g_assert_not_reached(); break; } dst = (struct sockaddr_in6 *) &self->super.dest_addr->sa; libnet_clear_packet(self->lnet_ctx); udp = libnet_build_udp(ntohs(src.sin6_port), ntohs(dst->sin6_port), LIBNET_UDP_H + msg_line->len, 0, (guchar *) msg_line->str, msg_line->len, self->lnet_ctx, 0); if (udp == -1) return FALSE; /* There seems to be a bug in libnet 1.1.2 that is triggered when * checksumming UDP6 packets. This is a workaround below. */ libnet_toggle_checksum(self->lnet_ctx, udp, LIBNET_OFF); memcpy(&ln_src, &src.sin6_addr, sizeof(ln_src)); memcpy(&ln_dst, &dst->sin6_addr, sizeof(ln_dst)); ip = libnet_build_ipv6(0, 0, LIBNET_UDP_H + msg_line->len, IPPROTO_UDP, /* IPv6 next header */ 64, /* hop limit */ ln_src, ln_dst, NULL, 0, /* payload and its length */ self->lnet_ctx, 0); if (ip == -1) return FALSE; return TRUE; } #endif #endif static void afinet_dd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { #if SYSLOG_NG_ENABLE_SPOOF_SOURCE AFInetDestDriver *self = (AFInetDestDriver *) s; /* NOTE: this code should probably become a LogTransport instance so that * spoofed packets are also going through the LogWriter queue */ if (self->spoof_source && self->lnet_ctx && msg->saddr && (msg->saddr->sa.sa_family == AF_INET || msg->saddr->sa.sa_family == AF_INET6) && log_writer_opened(self->super.writer)) { gboolean success = FALSE; g_assert(self->super.transport_mapper->sock_type == SOCK_DGRAM); g_static_mutex_lock(&self->lnet_lock); if (!self->lnet_buffer) self->lnet_buffer = g_string_sized_new(self->spoof_source_maxmsglen); log_writer_format_log(self->super.writer, msg, self->lnet_buffer); if (self->lnet_buffer->len > self->spoof_source_maxmsglen) g_string_truncate(self->lnet_buffer, self->spoof_source_maxmsglen); switch (self->super.dest_addr->sa.sa_family) { case AF_INET: success = afinet_dd_construct_ipv4_packet(self, msg, self->lnet_buffer); break; #if SYSLOG_NG_ENABLE_IPV6 case AF_INET6: success = afinet_dd_construct_ipv6_packet(self, msg, self->lnet_buffer); break; #endif default: g_assert_not_reached(); } if (success) { if (libnet_write(self->lnet_ctx) >= 0) { /* we have finished processing msg */ log_msg_ack(msg, path_options, AT_PROCESSED); log_msg_unref(msg); g_static_mutex_unlock(&self->lnet_lock); return; } else { msg_error("Error sending raw frame", evt_tag_str("error", libnet_geterror(self->lnet_ctx))); } } g_static_mutex_unlock(&self->lnet_lock); } #endif log_dest_driver_queue_method(s, msg, path_options, user_data); } void afinet_dd_free(LogPipe *s) { AFInetDestDriver *self = (AFInetDestDriver *) s; g_free(self->hostname); g_free(self->bind_ip); g_free(self->bind_port); g_free(self->dest_port); #if SYSLOG_NG_ENABLE_SPOOF_SOURCE if (self->lnet_buffer) g_string_free(self->lnet_buffer, TRUE); g_static_mutex_free(&self->lnet_lock); #endif afsocket_dd_free(s); } static AFInetDestDriver * afinet_dd_new_instance(TransportMapper *transport_mapper, gchar *hostname, GlobalConfig *cfg) { AFInetDestDriver *self = g_new0(AFInetDestDriver, 1); afsocket_dd_init_instance(&self->super, socket_options_inet_new(), transport_mapper, cfg); self->super.super.super.super.init = afinet_dd_init; self->super.super.super.super.queue = afinet_dd_queue; self->super.super.super.super.free_fn = afinet_dd_free; self->super.construct_writer = afinet_dd_construct_writer; self->super.setup_addresses = afinet_dd_setup_addresses; self->super.get_dest_name = afinet_dd_get_dest_name; self->hostname = g_strdup(hostname); #if SYSLOG_NG_ENABLE_SPOOF_SOURCE g_static_mutex_init(&self->lnet_lock); self->spoof_source_maxmsglen = 1024; #endif return self; } AFInetDestDriver * afinet_dd_new_tcp(gchar *host, GlobalConfig *cfg) { return afinet_dd_new_instance(transport_mapper_tcp_new(), host, cfg); } AFInetDestDriver * afinet_dd_new_tcp6(gchar *host, GlobalConfig *cfg) { return afinet_dd_new_instance(transport_mapper_tcp6_new(), host, cfg); } AFInetDestDriver * afinet_dd_new_udp(gchar *host, GlobalConfig *cfg) { return afinet_dd_new_instance(transport_mapper_udp_new(), host, cfg); } AFInetDestDriver * afinet_dd_new_udp6(gchar *host, GlobalConfig *cfg) { return afinet_dd_new_instance(transport_mapper_udp6_new(), host, cfg); } static LogWriter * afinet_dd_syslog_construct_writer(AFSocketDestDriver *s) { AFInetDestDriver *self G_GNUC_UNUSED = (AFInetDestDriver *) s; LogWriter *writer; writer = afsocket_dd_construct_writer_method(s); log_writer_set_flags(writer, log_writer_get_flags(writer) | LW_SYSLOG_PROTOCOL); return writer; } AFInetDestDriver * afinet_dd_new_syslog(gchar *host, GlobalConfig *cfg) { AFInetDestDriver *self = afinet_dd_new_instance(transport_mapper_syslog_new(), host, cfg); self->super.construct_writer = afinet_dd_syslog_construct_writer; return self; } AFInetDestDriver * afinet_dd_new_network(gchar *host, GlobalConfig *cfg) { return afinet_dd_new_instance(transport_mapper_network_new(), host, cfg); } syslog-ng-syslog-ng-3.13.2/modules/afsocket/afinet-dest.h000066400000000000000000000051601321171025300232620ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFINET_DEST_H_INCLUDED #define AFINET_DEST_H_INCLUDED #include "afinet.h" #include "afsocket-dest.h" #include "tlscontext.h" #if SYSLOG_NG_ENABLE_SPOOF_SOURCE /* this forward declaration avoids having to include libnet, which requires * ugly playing with macros, see that for yourself in the implementation * file */ struct libnet_context; #endif typedef struct _AFInetDestDriver { AFSocketDestDriver super; #if SYSLOG_NG_ENABLE_SPOOF_SOURCE gboolean spoof_source; struct libnet_context *lnet_ctx; GStaticMutex lnet_lock; GString *lnet_buffer; gint spoof_source_maxmsglen; #endif gchar *hostname; /* character as it can contain a service name from /etc/services */ gchar *bind_port; gchar *bind_ip; /* character as it can contain a service name from /etc/services */ gchar *dest_port; /* destination hostname is stored in super.hostname */ } AFInetDestDriver; void afinet_dd_set_localport(LogDriver *self, gchar *service); void afinet_dd_set_destport(LogDriver *self, gchar *service); void afinet_dd_set_localip(LogDriver *self, gchar *ip); void afinet_dd_set_sync_freq(LogDriver *self, gint sync_freq); void afinet_dd_set_spoof_source(LogDriver *self, gboolean enable); void afinet_dd_set_tls_context(LogDriver *s, TLSContext *tls_context); AFInetDestDriver *afinet_dd_new_tcp(gchar *host, GlobalConfig *cfg); AFInetDestDriver *afinet_dd_new_tcp6(gchar *host, GlobalConfig *cfg); AFInetDestDriver *afinet_dd_new_udp(gchar *host, GlobalConfig *cfg); AFInetDestDriver *afinet_dd_new_udp6(gchar *host, GlobalConfig *cfg); AFInetDestDriver *afinet_dd_new_syslog(gchar *host, GlobalConfig *cfg); AFInetDestDriver *afinet_dd_new_network(gchar *host, GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/afinet-source.c000066400000000000000000000111111321171025300236070ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afinet-source.h" #include "messages.h" #include "transport-mapper-inet.h" #include "socket-options-inet.h" #include #include #include #include #include #include #include void afinet_sd_set_localport(LogDriver *s, gchar *service) { AFInetSourceDriver *self = (AFInetSourceDriver *) s; if (self->bind_port) g_free(self->bind_port); self->bind_port = g_strdup(service); } void afinet_sd_set_localip(LogDriver *s, gchar *ip) { AFInetSourceDriver *self = (AFInetSourceDriver *) s; if (self->bind_ip) g_free(self->bind_ip); self->bind_ip = g_strdup(ip); } void afinet_sd_set_tls_context(LogDriver *s, TLSContext *tls_context) { AFInetSourceDriver *self = (AFInetSourceDriver *) s; transport_mapper_inet_set_tls_context((TransportMapperInet *) self->super.transport_mapper, tls_context, NULL, NULL); } static gboolean afinet_sd_setup_addresses(AFSocketSourceDriver *s) { AFInetSourceDriver *self = (AFInetSourceDriver *) s; if (!afsocket_sd_setup_addresses_method(s)) return FALSE; g_sockaddr_unref(self->super.bind_addr); if (!resolve_hostname_to_sockaddr(&self->super.bind_addr, self->super.transport_mapper->address_family, self->bind_ip)) return FALSE; if (!self->bind_port) { const gchar *port_change_warning = transport_mapper_inet_get_port_change_warning(self->super.transport_mapper); if (port_change_warning) { msg_warning(port_change_warning, evt_tag_str("id", self->super.super.super.id)); } g_sockaddr_set_port(self->super.bind_addr, transport_mapper_inet_get_server_port(self->super.transport_mapper)); } else g_sockaddr_set_port(self->super.bind_addr, afinet_lookup_service(self->super.transport_mapper, self->bind_port)); return TRUE; } gboolean afinet_sd_init(LogPipe *s) { AFInetSourceDriver *self = (AFInetSourceDriver *) s; if (!afsocket_sd_init_method(&self->super.super.super.super)) return FALSE; return TRUE; } void afinet_sd_free(LogPipe *s) { AFInetSourceDriver *self = (AFInetSourceDriver *) s; g_free(self->bind_ip); g_free(self->bind_port); afsocket_sd_free_method(s); } static AFInetSourceDriver * afinet_sd_new_instance(TransportMapper *transport_mapper, GlobalConfig *cfg) { AFInetSourceDriver *self = g_new0(AFInetSourceDriver, 1); afsocket_sd_init_instance(&self->super, socket_options_inet_new(), transport_mapper, cfg); self->super.super.super.super.init = afinet_sd_init; self->super.super.super.super.free_fn = afinet_sd_free; self->super.setup_addresses = afinet_sd_setup_addresses; return self; } AFInetSourceDriver * afinet_sd_new_tcp(GlobalConfig *cfg) { return afinet_sd_new_instance(transport_mapper_tcp_new(), cfg); } AFInetSourceDriver * afinet_sd_new_tcp6(GlobalConfig *cfg) { return afinet_sd_new_instance(transport_mapper_tcp6_new(), cfg); } AFInetSourceDriver * afinet_sd_new_udp(GlobalConfig *cfg) { return afinet_sd_new_instance(transport_mapper_udp_new(), cfg); } AFInetSourceDriver * afinet_sd_new_udp6(GlobalConfig *cfg) { return afinet_sd_new_instance(transport_mapper_udp6_new(), cfg); } AFInetSourceDriver * afinet_sd_new_syslog(GlobalConfig *cfg) { AFInetSourceDriver *self = afinet_sd_new_instance(transport_mapper_syslog_new(), cfg); self->super.reader_options.parse_options.flags |= LP_SYSLOG_PROTOCOL; return self; } AFInetSourceDriver * afinet_sd_new_network(GlobalConfig *cfg) { AFInetSourceDriver *self = afinet_sd_new_instance(transport_mapper_network_new(), cfg); return self; } syslog-ng-syslog-ng-3.13.2/modules/afsocket/afinet-source.h000066400000000000000000000035221321171025300236230ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFINET_SOURCE_H_INCLUDED #define AFINET_SOURCE_H_INCLUDED #include "afinet.h" #include "afsocket-source.h" #include "tlscontext.h" typedef struct _AFInetSourceDriver { AFSocketSourceDriver super; /* character as it can contain a service name from /etc/services */ gchar *bind_port; gchar *bind_ip; gchar *ip_protocol; } AFInetSourceDriver; void afinet_sd_set_tls_context(LogDriver *s, TLSContext *tls_context); AFInetSourceDriver *afinet_sd_new_tcp(GlobalConfig *cfg); AFInetSourceDriver *afinet_sd_new_tcp6(GlobalConfig *cfg); AFInetSourceDriver *afinet_sd_new_udp(GlobalConfig *cfg); AFInetSourceDriver *afinet_sd_new_udp6(GlobalConfig *cfg); AFInetSourceDriver *afinet_sd_new_syslog(GlobalConfig *cfg); AFInetSourceDriver *afinet_sd_new_network(GlobalConfig *cfg); void afinet_sd_set_localport(LogDriver *self, gchar *service); void afinet_sd_set_localip(LogDriver *self, gchar *ip); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/afinet.c000066400000000000000000000044531321171025300223240ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afinet.h" #include "messages.h" #include "gprocess.h" #include #include #include #include #include #include #include static gint afinet_lookup_service_and_proto(const gchar *service, const gchar *proto) { gchar *end; gint port; /* check if service is numeric */ port = strtol(service, &end, 10); if ((*end != 0)) { struct servent *se; /* service is not numeric, check if it's a service in /etc/services */ se = getservbyname(service, proto); if (se) { port = ntohs(se->s_port); } else { msg_error("Error finding port number, falling back to default", evt_tag_printf("service", "%s/%s", proto, service)); return 0; } } return port; } static const gchar * afinet_lookup_proto(gint protocol_number, gint sock_type) { struct protoent *ipproto_ent = getprotobynumber(protocol_number); return ipproto_ent ? ipproto_ent->p_name : ((sock_type == SOCK_STREAM) ? "tcp" : "udp"); } guint16 afinet_lookup_service(TransportMapper *transport_mapper, const gchar *service) { const gchar *protocol_name = afinet_lookup_proto(transport_mapper->sock_proto, transport_mapper->sock_type); return afinet_lookup_service_and_proto(service, protocol_name); } syslog-ng-syslog-ng-3.13.2/modules/afsocket/afinet.h000066400000000000000000000022061321171025300223230ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFINET_H_INCLUDED #define AFINET_H_INCLUDED #include "afsocket.h" #include "transport-mapper.h" guint16 afinet_lookup_service(TransportMapper *transport_mapper, const gchar *service); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/afsocket-dest.c000066400000000000000000000410441321171025300236070ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afsocket-dest.h" #include "messages.h" #include "logwriter.h" #include "gsocket.h" #include "stats/stats-registry.h" #include "mainloop.h" #include #include #include typedef struct _ReloadStoreItem { LogProtoClientFactory *proto_factory; LogWriter *writer; } ReloadStoreItem; static ReloadStoreItem * _reload_store_item_new(AFSocketDestDriver *afsocket_dd) { ReloadStoreItem *item = g_new(ReloadStoreItem, 1); item->proto_factory = afsocket_dd->proto_factory; item->writer = afsocket_dd->writer; return item; } static void _reload_store_item_free(ReloadStoreItem *self) { if (!self) return; if (self->writer) log_pipe_unref((LogPipe *) self->writer); g_free(self); } static LogWriter * _reload_store_item_release_writer(ReloadStoreItem *self) { LogWriter *writer = self->writer; self->writer = NULL; return writer; } static inline gboolean _is_protocol_compatible_with_writer_after_reload(AFSocketDestDriver *self, ReloadStoreItem *item) { return (self->proto_factory->construct == item->proto_factory->construct); } void afsocket_dd_set_keep_alive(LogDriver *s, gboolean enable) { AFSocketDestDriver *self = (AFSocketDestDriver *) s; self->connections_kept_alive_accross_reloads = enable; } static const gchar *_module_name = "afsocket_dd"; static const gchar * _get_module_identifier(const AFSocketDestDriver *self) { static gchar module_identifier[128]; g_snprintf(module_identifier, sizeof(module_identifier), "%s,%s", (self->transport_mapper->sock_type == SOCK_STREAM) ? "stream" : "dgram", afsocket_dd_get_dest_name(self)); return self->super.super.super.persist_name ? self->super.super.super.persist_name : module_identifier; } static const gchar * afsocket_dd_format_name(const LogPipe *s) { const AFSocketDestDriver *self = (const AFSocketDestDriver *)s; static gchar persist_name[1024]; g_snprintf(persist_name, sizeof(persist_name), "%s.(%s)", _module_name, _get_module_identifier(self)); return persist_name; } static const gchar * afsocket_dd_format_qfile_name(const AFSocketDestDriver *self) { static gchar persist_name[1024]; g_snprintf(persist_name, sizeof(persist_name), "%s_qfile(%s)", _module_name, _get_module_identifier(self)); return persist_name; } static const gchar * afsocket_dd_format_connections_name(const AFSocketDestDriver *self) { static gchar persist_name[1024]; g_snprintf(persist_name, sizeof(persist_name), "%s_connections(%s)", _module_name, _get_module_identifier(self)); return persist_name; } static gchar * afsocket_dd_stats_instance(AFSocketDestDriver *self) { static gchar buf[256]; g_snprintf(buf, sizeof(buf), "%s,%s", self->transport_mapper->transport, afsocket_dd_get_dest_name(self)); return buf; } static gboolean afsocket_dd_connected(AFSocketDestDriver *self); static void afsocket_dd_reconnect(AFSocketDestDriver *self); static void afsocket_dd_try_connect(AFSocketDestDriver *self); static gboolean afsocket_dd_setup_connection(AFSocketDestDriver *self); static void afsocket_dd_init_watches(AFSocketDestDriver *self) { IV_FD_INIT(&self->connect_fd); self->connect_fd.cookie = self; self->connect_fd.handler_out = (void (*)(void *)) afsocket_dd_connected; IV_TIMER_INIT(&self->reconnect_timer); self->reconnect_timer.cookie = self; /* Using reinit as a handler before establishing the first successful connection. * We'll change this to afsocket_dd_reconnect when the initialization of the * connection succeeds.*/ self->reconnect_timer.handler = (void (*)(void *)) afsocket_dd_try_connect; } static void afsocket_dd_start_watches(AFSocketDestDriver *self) { main_loop_assert_main_thread(); self->connect_fd.fd = self->fd; iv_fd_register(&self->connect_fd); } static void afsocket_dd_stop_watches(AFSocketDestDriver *self) { main_loop_assert_main_thread(); if (iv_fd_registered(&self->connect_fd)) { iv_fd_unregister(&self->connect_fd); /* need to close the fd in this case as it wasn't established yet */ msg_verbose("Closing connecting fd", evt_tag_int("fd", self->fd)); close(self->fd); } if (iv_timer_registered(&self->reconnect_timer)) iv_timer_unregister(&self->reconnect_timer); } static void afsocket_dd_start_reconnect_timer(AFSocketDestDriver *self) { main_loop_assert_main_thread(); if (iv_timer_registered(&self->reconnect_timer)) iv_timer_unregister(&self->reconnect_timer); iv_validate_now(); self->reconnect_timer.expires = iv_now; timespec_add_msec(&self->reconnect_timer.expires, self->time_reopen * 1000); iv_timer_register(&self->reconnect_timer); } static LogTransport * afsocket_dd_construct_transport(AFSocketDestDriver *self, gint fd) { return transport_mapper_construct_log_transport(self->transport_mapper, fd); } static gboolean afsocket_dd_connected(AFSocketDestDriver *self) { gchar buf1[256], buf2[256]; int error = 0; socklen_t errorlen = sizeof(error); LogTransport *transport; LogProtoClient *proto; main_loop_assert_main_thread(); if (iv_fd_registered(&self->connect_fd)) iv_fd_unregister(&self->connect_fd); if (self->transport_mapper->sock_type == SOCK_STREAM) { if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &error, &errorlen) == -1) { msg_error("getsockopt(SOL_SOCKET, SO_ERROR) failed for connecting socket", evt_tag_int("fd", self->fd), evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_errno(EVT_TAG_OSERROR, errno), evt_tag_int("time_reopen", self->time_reopen)); goto error_reconnect; } if (error) { msg_error("Syslog connection failed", evt_tag_int("fd", self->fd), evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_errno(EVT_TAG_OSERROR, error), evt_tag_int("time_reopen", self->time_reopen)); goto error_reconnect; } } msg_notice("Syslog connection established", evt_tag_int("fd", self->fd), evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf1, sizeof(buf1), GSA_FULL))); transport = afsocket_dd_construct_transport(self, self->fd); if (!transport) goto error_reconnect; proto = log_proto_client_factory_construct(self->proto_factory, transport, &self->writer_options.proto_options.super); log_writer_reopen(self->writer, proto); return TRUE; error_reconnect: close(self->fd); self->fd = -1; afsocket_dd_start_reconnect_timer(self); return FALSE; } static gboolean afsocket_dd_start_connect(AFSocketDestDriver *self) { int sock, rc; gchar buf1[MAX_SOCKADDR_STRING], buf2[MAX_SOCKADDR_STRING]; main_loop_assert_main_thread(); g_assert(self->transport_mapper->transport); g_assert(self->bind_addr); if (!transport_mapper_open_socket(self->transport_mapper, self->socket_options, self->bind_addr, AFSOCKET_DIR_SEND, &sock)) { return FALSE; } g_assert(self->dest_addr); rc = g_connect(sock, self->dest_addr); if (rc == G_IO_STATUS_NORMAL) { self->fd = sock; afsocket_dd_connected(self); } else if (rc == G_IO_STATUS_ERROR && errno == EINPROGRESS) { /* we must wait until connect succeeds */ self->fd = sock; afsocket_dd_start_watches(self); } else { /* error establishing connection */ msg_error("Connection failed", evt_tag_int("fd", sock), evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_errno(EVT_TAG_OSERROR, errno)); close(sock); return FALSE; } return TRUE; } static void afsocket_dd_reconnect(AFSocketDestDriver *self) { if (!afsocket_dd_setup_addresses(self) || !afsocket_dd_start_connect(self)) { msg_error("Initiating connection failed, reconnecting", evt_tag_int("time_reopen", self->time_reopen)); afsocket_dd_start_reconnect_timer(self); } } static void afsocket_dd_try_connect(AFSocketDestDriver *self) { if (!afsocket_dd_setup_addresses(self) || !afsocket_dd_setup_connection(self)) { msg_error("Initiating connection failed, reconnecting", evt_tag_int("time_reopen", self->time_reopen)); afsocket_dd_start_reconnect_timer(self); return; } self->reconnect_timer.handler = (void (*)(void *)) afsocket_dd_reconnect; } static gboolean afsocket_dd_setup_proto_factory(AFSocketDestDriver *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); self->proto_factory = log_proto_client_get_factory(&cfg->plugin_context, self->transport_mapper->logproto); if (!self->proto_factory) { msg_error("Unknown value specified in the transport() option, no such LogProto plugin found", evt_tag_str("transport", self->transport_mapper->logproto)); return FALSE; } return TRUE; } static gboolean afsocket_dd_setup_writer_options(AFSocketDestDriver *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); log_writer_options_init(&self->writer_options, cfg, 0); return TRUE; } static gboolean afsocket_dd_setup_transport(AFSocketDestDriver *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); if (!transport_mapper_apply_transport(self->transport_mapper, cfg)) return FALSE; if (!afsocket_dd_setup_proto_factory(self)) return FALSE; if (!afsocket_dd_setup_writer_options(self)) return FALSE; return TRUE; } gboolean afsocket_dd_setup_addresses_method(AFSocketDestDriver *self) { return TRUE; } static void _afsocket_dd_try_to_restore_writer(AFSocketDestDriver *self) { /* If we are reinitializing an old config, an existing writer may be present */ if (self->writer) return; ReloadStoreItem *item = cfg_persist_config_fetch( log_pipe_get_config(&self->super.super.super), afsocket_dd_format_connections_name(self)); /* We don't have an item stored in the reload cache, which means */ /* it is the first time when we try to initialize the writer */ if (!item) return; if (_is_protocol_compatible_with_writer_after_reload(self, item)) self->writer = _reload_store_item_release_writer(item); _reload_store_item_free(item); } LogWriter * afsocket_dd_construct_writer_method(AFSocketDestDriver *self) { guint32 writer_flags = 0; writer_flags |= LW_FORMAT_PROTO; if (self->transport_mapper->sock_type == SOCK_STREAM) writer_flags |= LW_DETECT_EOF; return log_writer_new(writer_flags, self->super.super.super.cfg); } static gboolean afsocket_dd_setup_writer(AFSocketDestDriver *self) { _afsocket_dd_try_to_restore_writer(self); if (!self->writer) { /* NOTE: we open our writer with no fd, so we can send messages down there * even while the connection is not established */ self->writer = afsocket_dd_construct_writer(self); } log_pipe_set_config((LogPipe *)self->writer, log_pipe_get_config(&self->super.super.super)); log_writer_set_options(self->writer, &self->super.super.super, &self->writer_options, self->super.super.id, afsocket_dd_stats_instance(self)); log_writer_set_queue(self->writer, log_dest_driver_acquire_queue( &self->super, afsocket_dd_format_qfile_name(self))); if (!log_pipe_init((LogPipe *) self->writer)) { log_pipe_unref((LogPipe *) self->writer); return FALSE; } log_pipe_append(&self->super.super.super, (LogPipe *) self->writer); return TRUE; } static gboolean afsocket_dd_setup_connection(AFSocketDestDriver *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); self->time_reopen = cfg->time_reopen; if (!log_writer_opened(self->writer)) afsocket_dd_reconnect(self); self->connection_initialized = TRUE; return TRUE; } gboolean afsocket_dd_init(LogPipe *s) { AFSocketDestDriver *self = (AFSocketDestDriver *) s; if (!log_dest_driver_init_method(s) || !afsocket_dd_setup_transport(self)) { return FALSE; } if (!transport_mapper_init(self->transport_mapper)) return FALSE; if (!afsocket_dd_setup_writer(self)) return FALSE; afsocket_dd_try_connect(self); return TRUE; } static void afsocket_dd_stop_writer(AFSocketDestDriver *self) { if (self->writer) log_pipe_deinit((LogPipe *) self->writer); } static void afsocket_dd_save_connection(AFSocketDestDriver *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); if (self->connections_kept_alive_accross_reloads) { ReloadStoreItem *item = _reload_store_item_new(self); cfg_persist_config_add(cfg, afsocket_dd_format_connections_name(self), item, (GDestroyNotify)_reload_store_item_free, FALSE); self->writer = NULL; } } gboolean afsocket_dd_deinit(LogPipe *s) { AFSocketDestDriver *self = (AFSocketDestDriver *) s; afsocket_dd_stop_watches(self); afsocket_dd_stop_writer(self); if (self->connection_initialized) { afsocket_dd_save_connection(self); } return log_dest_driver_deinit_method(s); } static void afsocket_dd_notify(LogPipe *s, gint notify_code, gpointer user_data) { AFSocketDestDriver *self = (AFSocketDestDriver *) s; gchar buf[MAX_SOCKADDR_STRING]; switch (notify_code) { case NC_CLOSE: case NC_WRITE_ERROR: log_writer_reopen(self->writer, NULL); msg_notice("Syslog connection broken", evt_tag_int("fd", self->fd), evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf, sizeof(buf), GSA_FULL)), evt_tag_int("time_reopen", self->time_reopen)); afsocket_dd_start_reconnect_timer(self); break; } } void afsocket_dd_free(LogPipe *s) { AFSocketDestDriver *self = (AFSocketDestDriver *) s; log_writer_options_destroy(&self->writer_options); g_sockaddr_unref(self->bind_addr); g_sockaddr_unref(self->dest_addr); log_pipe_unref((LogPipe *) self->writer); transport_mapper_free(self->transport_mapper); socket_options_free(self->socket_options); log_dest_driver_free(s); } void afsocket_dd_init_instance(AFSocketDestDriver *self, SocketOptions *socket_options, TransportMapper *transport_mapper, GlobalConfig *cfg) { log_dest_driver_init_instance(&self->super, cfg); log_writer_options_defaults(&self->writer_options); self->super.super.super.init = afsocket_dd_init; self->super.super.super.deinit = afsocket_dd_deinit; self->super.super.super.free_fn = afsocket_dd_free; self->super.super.super.notify = afsocket_dd_notify; self->super.super.super.generate_persist_name = afsocket_dd_format_name; self->setup_addresses = afsocket_dd_setup_addresses; self->construct_writer = afsocket_dd_construct_writer_method; self->transport_mapper = transport_mapper; self->socket_options = socket_options; self->connections_kept_alive_accross_reloads = TRUE; self->time_reopen = cfg->time_reopen; self->connection_initialized = FALSE; self->writer_options.mark_mode = MM_GLOBAL; self->writer_options.stats_level = STATS_LEVEL0; self->writer_options.stats_source = self->transport_mapper->stats_source; afsocket_dd_init_watches(self); } syslog-ng-syslog-ng-3.13.2/modules/afsocket/afsocket-dest.h000066400000000000000000000052531321171025300236160ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSOCKET_DEST_H_INCLUDED #define AFSOCKET_DEST_H_INCLUDED #include "afsocket.h" #include "socket-options.h" #include "transport-mapper.h" #include "driver.h" #include "logwriter.h" #include typedef struct _AFSocketDestDriver AFSocketDestDriver; struct _AFSocketDestDriver { LogDestDriver super; gboolean connections_kept_alive_accross_reloads:1; gint fd; LogWriter *writer; LogWriterOptions writer_options; LogProtoClientFactory *proto_factory; GSockAddr *bind_addr; GSockAddr *dest_addr; gint time_reopen; gboolean connection_initialized; struct iv_fd connect_fd; struct iv_timer reconnect_timer; SocketOptions *socket_options; TransportMapper *transport_mapper; LogWriter *(*construct_writer)(AFSocketDestDriver *self); gboolean (*setup_addresses)(AFSocketDestDriver *s); const gchar *(*get_dest_name)(const AFSocketDestDriver *s); }; static inline LogWriter * afsocket_dd_construct_writer(AFSocketDestDriver *self) { return self->construct_writer(self); } static inline gboolean afsocket_dd_setup_addresses(AFSocketDestDriver *s) { return s->setup_addresses(s); } static inline const gchar * afsocket_dd_get_dest_name(const AFSocketDestDriver *s) { return s->get_dest_name(s); } LogWriter *afsocket_dd_construct_writer_method(AFSocketDestDriver *self); gboolean afsocket_dd_setup_addresses_method(AFSocketDestDriver *self); void afsocket_dd_set_keep_alive(LogDriver *self, gint enable); void afsocket_dd_init_instance(AFSocketDestDriver *self, SocketOptions *socket_options, TransportMapper *transport_mapper, GlobalConfig *cfg); LogTransport *afsocket_dd_construct_transport_method(AFSocketDestDriver *self, gint fd); gboolean afsocket_dd_init(LogPipe *s); void afsocket_dd_free(LogPipe *s); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/afsocket-grammar.ym000066400000000000000000000503101321171025300244750ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code top { #include "afsocket-parser.h" } %code { #include "afsocket.h" #include "cfg-parser.h" #include "afsocket-grammar.h" #include "afunix-source.h" #include "afunix-dest.h" #include "afinet-source.h" #include "afinet-dest.h" #include "messages.h" #include "syslog-names.h" #include "plugin.h" #include "cfg-grammar.h" #include "socket-options-inet.h" #include "transport-mapper-inet.h" #include "service-management.h" #include "systemd-syslog-source.h" #include "afsocket-systemd-override.h" #include "tlscontext.h" static SocketOptions *last_sock_options; static TransportMapper *last_transport_mapper; TLSContext *last_tls_context; #if ! SYSLOG_NG_ENABLE_IPV6 #undef AF_INET6 #define AF_INET6 0; g_assert_not_reached() #endif static void afsocket_grammar_set_source_driver(AFSocketSourceDriver *sd) { last_driver = &sd->super.super; last_reader_options = &((AFSocketSourceDriver *) last_driver)->reader_options; last_sock_options = ((AFSocketSourceDriver *) last_driver)->socket_options; last_transport_mapper = ((AFSocketSourceDriver *) last_driver)->transport_mapper; } static void afsocket_grammar_set_dest_driver(AFSocketDestDriver *dd) { last_driver = &dd->super.super; last_writer_options = &((AFSocketDestDriver *) last_driver)->writer_options; last_sock_options = ((AFSocketDestDriver *) last_driver)->socket_options; last_transport_mapper = ((AFSocketDestDriver *) last_driver)->transport_mapper; } void afunix_grammar_set_source_driver(AFUnixSourceDriver *sd) { afsocket_grammar_set_source_driver(&sd->super); last_file_perm_options = &sd->file_perm_options; } static void afinet_grammar_set_source_driver(AFInetSourceDriver *sd) { afsocket_grammar_set_source_driver(&sd->super); } static void afunix_grammar_set_dest_driver(AFUnixDestDriver *dd) { afsocket_grammar_set_dest_driver(&dd->super); } static void afinet_grammar_set_dest_driver(AFInetDestDriver *dd) { afsocket_grammar_set_dest_driver(&dd->super); } void systemd_syslog_grammar_set_source_driver(SystemDSyslogSourceDriver *sd) { afsocket_grammar_set_source_driver(&sd->super); } } %name-prefix "afsocket_" /* this parameter is needed in order to instruct bison to use a complete * argument list for yylex/yyerror */ %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogDriver **instance} %parse-param {gpointer arg} %token KW_UNIX_STREAM 20000 %token KW_UNIX_DGRAM %token KW_TCP %token KW_UDP %token KW_TCP6 %token KW_UDP6 %token KW_NETWORK %token KW_TRANSPORT %token KW_IP_PROTOCOL %token KW_SYSTEMD_SYSLOG %token KW_IP_TTL %token KW_SO_BROADCAST %token KW_IP_TOS %token KW_IP_FREEBIND %token KW_SO_SNDBUF %token KW_SO_RCVBUF %token KW_SO_KEEPALIVE %token KW_TCP_KEEPALIVE_TIME %token KW_TCP_KEEPALIVE_PROBES %token KW_TCP_KEEPALIVE_INTVL %token KW_LISTEN_BACKLOG %token KW_SPOOF_SOURCE %token KW_KEEP_ALIVE %token KW_MAX_CONNECTIONS %token KW_LOCALIP %token KW_IP %token KW_LOCALPORT %token KW_DESTPORT /* SSL support */ %token KW_TLS %token KW_PEER_VERIFY %token KW_KEY_FILE %token KW_CERT_FILE %token KW_DHPARAM_FILE %token KW_PKCS12_FILE %token KW_CA_DIR %token KW_CRL_DIR %token KW_TRUSTED_KEYS %token KW_TRUSTED_DN %token KW_CIPHER_SUITE %token KW_ECDH_CURVE_LIST %token KW_SSL_OPTIONS /* INCLUDE_DECLS */ %type driver %type source_afunix %type source_afunix_dgram_params %type source_afunix_stream_params %type source_afinet %type source_afinet_udp_params %type source_afinet_tcp_params %type source_afinet_udp6_params %type source_afinet_tcp6_params %type source_afsyslog %type source_afsyslog_params %type source_afnetwork %type source_afnetwork_params %type source_afsocket_stream_params %type source_systemd_syslog %type source_systemd_syslog_params %type dest_afunix %type dest_afunix_dgram_params %type dest_afunix_stream_params %type dest_afinet %type dest_afinet_udp_params %type dest_afinet_tcp_params %type dest_afinet_udp6_params %type dest_afinet_tcp6_params %type dest_afsyslog %type dest_afsyslog_params %type dest_afnetwork %type dest_afnetwork_params %type inet_ip_protocol_option %% start : driver { *instance = $1; if (yychar != YYEMPTY) cfg_lexer_unput_token(lexer, &yylval); YYACCEPT; } ; driver : LL_CONTEXT_SOURCE source_afunix { $$ = $2; } | LL_CONTEXT_SOURCE source_afinet { $$ = $2; } | LL_CONTEXT_SOURCE source_afsyslog { $$ = $2; } | LL_CONTEXT_SOURCE source_afnetwork { $$ = $2; } | LL_CONTEXT_SOURCE source_systemd_syslog { $$ = $2; } | LL_CONTEXT_DESTINATION dest_afunix { $$ = $2; } | LL_CONTEXT_DESTINATION dest_afinet { $$ = $2; } | LL_CONTEXT_DESTINATION dest_afsyslog { $$ = $2; } | LL_CONTEXT_DESTINATION dest_afnetwork { $$ = $2; } ; source_afunix : KW_UNIX_DGRAM '(' source_afunix_dgram_params ')' { $$ = $3; } | KW_UNIX_STREAM '(' source_afunix_stream_params ')' { $$ = $3; } ; source_afunix_dgram_params : string { create_and_set_unix_dgram_or_systemd_syslog_source($1, configuration); } source_afunix_options { $$ = last_driver; free($1); } ; source_afunix_stream_params : string { create_and_set_unix_stream_or_systemd_syslog_source($1, configuration); } source_afunix_options { $$ = last_driver; free($1); } ; /* options are common between dgram & stream */ source_afunix_options : source_afunix_option source_afunix_options | ; source_afunix_option : file_perm_option | source_afsocket_stream_params {} | source_reader_option {} | socket_option {} | KW_OPTIONAL '(' yesno ')' { last_driver->optional = $3; } | KW_PASS_UNIX_CREDENTIALS '(' yesno ')' { AFUnixSourceDriver *self = (AFUnixSourceDriver*) last_driver; afunix_sd_set_pass_unix_credentials(self, $3); } | KW_CREATE_DIRS '(' yesno ')' { AFUnixSourceDriver *self = (AFUnixSourceDriver*) last_driver; afunix_sd_set_create_dirs(self, $3); } ; source_afinet : KW_UDP '(' source_afinet_udp_params ')' { $$ = $3; } | KW_TCP '(' source_afinet_tcp_params ')' { $$ = $3; } | KW_UDP6 '(' source_afinet_udp6_params ')' { $$ = $3; } | KW_TCP6 '(' source_afinet_tcp6_params ')' { $$ = $3; } ; source_afinet_udp_params : { AFInetSourceDriver *d = afinet_sd_new_udp(configuration); afinet_grammar_set_source_driver(d); } source_afinet_udp_options { $$ = last_driver; } ; source_afinet_udp6_params : { AFInetSourceDriver *d = afinet_sd_new_udp6(configuration); afinet_grammar_set_source_driver(d); } source_afinet_udp_options { $$ = last_driver; } ; source_afinet_udp_options : source_afinet_udp_option source_afinet_udp_options | ; source_afinet_udp_option : source_afinet_option ; source_afinet_option : KW_LOCALIP '(' string ')' { afinet_sd_set_localip(last_driver, $3); free($3); } | KW_IP '(' string ')' { afinet_sd_set_localip(last_driver, $3); free($3); } | KW_LOCALPORT '(' string_or_number ')' { afinet_sd_set_localport(last_driver, $3); free($3); } | KW_PORT '(' string_or_number ')' { afinet_sd_set_localport(last_driver, $3); free($3); } | source_reader_option | inet_socket_option ; source_afinet_tcp_params : { AFInetSourceDriver *d = afinet_sd_new_tcp(configuration); afinet_grammar_set_source_driver(d); } source_afinet_tcp_options { $$ = last_driver; } ; source_afinet_tcp6_params : { AFInetSourceDriver *d = afinet_sd_new_tcp6(configuration); afinet_grammar_set_source_driver(d); } source_afinet_tcp_options { $$ = last_driver; } ; source_afinet_tcp_options : source_afinet_tcp_option source_afinet_tcp_options | ; source_afinet_tcp_option : source_afinet_option | KW_TLS { last_tls_context = tls_context_new(TM_SERVER); } '(' tls_options ')' { afinet_sd_set_tls_context(last_driver, last_tls_context); } | source_afsocket_stream_params {} ; source_afsocket_stream_params : KW_KEEP_ALIVE '(' yesno ')' { afsocket_sd_set_keep_alive(last_driver, $3); } | KW_MAX_CONNECTIONS '(' positive_integer ')' { afsocket_sd_set_max_connections(last_driver, $3); } | KW_LISTEN_BACKLOG '(' positive_integer ')' { afsocket_sd_set_listen_backlog(last_driver, $3); } ; source_afsyslog : KW_SYSLOG '(' source_afsyslog_params ')' { $$ = $3; } ; source_afsyslog_params : { /* we use transport(tcp) transport by default */ AFInetSourceDriver *d = afinet_sd_new_syslog(configuration); afinet_grammar_set_source_driver(d); } source_afsyslog_options { $$ = last_driver; } ; source_afsyslog_options : source_afsyslog_option source_afsyslog_options | ; source_afsyslog_option : source_afinet_option | source_afsocket_transport | source_afsocket_stream_params {} ; source_afnetwork : KW_NETWORK '(' source_afnetwork_params ')' { $$ = $3; } ; source_afnetwork_params : { /* we use transport(tcp) transport by default */ AFInetSourceDriver *d = afinet_sd_new_network(configuration); afinet_grammar_set_source_driver(d); } source_afnetwork_options { $$ = last_driver; } ; source_afnetwork_options : source_afnetwork_option source_afnetwork_options | ; source_afnetwork_option : source_afinet_option | source_afsocket_transport | source_afsocket_stream_params {} ; source_afsocket_transport : afsocket_transport | KW_TLS { last_tls_context = tls_context_new(TM_SERVER); } '(' tls_options ')' { afinet_sd_set_tls_context(last_driver, last_tls_context); } ; source_systemd_syslog : KW_SYSTEMD_SYSLOG '(' source_systemd_syslog_params ')' { $$ = $3; } ; source_systemd_syslog_params : { #if ! SYSLOG_NG_ENABLE_SYSTEMD msg_error("systemd-syslog() source cannot be enabled and it is not" " functioning. Please compile your syslog-ng with --enable-systemd" " flag", cfg_lexer_format_location_tag(lexer, &@0)); YYERROR; #else SystemDSyslogSourceDriver *d = systemd_syslog_sd_new(configuration, FALSE); systemd_syslog_grammar_set_source_driver(d); #endif } source_systemd_syslog_options { $$ = last_driver; } ; source_systemd_syslog_options : source_systemd_syslog_option source_systemd_syslog_options | ; source_systemd_syslog_option : source_reader_option | socket_option ; dest_afunix : KW_UNIX_DGRAM '(' dest_afunix_dgram_params ')' { $$ = $3; } | KW_UNIX_STREAM '(' dest_afunix_stream_params ')' { $$ = $3; } ; dest_afunix_dgram_params : string { AFUnixDestDriver *d = afunix_dd_new_dgram($1, configuration); afunix_grammar_set_dest_driver(d); } dest_afunix_options { $$ = last_driver; free($1); } ; dest_afunix_stream_params : string { AFUnixDestDriver *d = afunix_dd_new_stream($1, configuration); afunix_grammar_set_dest_driver(d); } dest_afunix_options { $$ = last_driver; free($1); } ; dest_afunix_options : dest_afunix_options dest_afunix_option | ; dest_afunix_option : dest_writer_option | dest_afsocket_option | socket_option | dest_driver_option ; dest_afinet : KW_UDP '(' dest_afinet_udp_params ')' { $$ = $3; } | KW_TCP '(' dest_afinet_tcp_params ')' { $$ = $3; } | KW_UDP6 '(' dest_afinet_udp6_params ')' { $$ = $3; } | KW_TCP6 '(' dest_afinet_tcp6_params ')' { $$ = $3; } ; dest_afinet_udp_params : string { AFInetDestDriver *d = afinet_dd_new_udp($1, configuration); afinet_grammar_set_dest_driver(d); } dest_afinet_udp_options { $$ = last_driver; free($1); } ; dest_afinet_udp6_params : string { AFInetDestDriver *d = afinet_dd_new_udp6($1, configuration); afinet_grammar_set_dest_driver(d); } dest_afinet_udp_options { $$ = last_driver; free($1); } ; dest_afinet_udp_options : dest_afinet_udp_options dest_afinet_udp_option | ; dest_afinet_option : KW_LOCALIP '(' string ')' { afinet_dd_set_localip(last_driver, $3); free($3); } | KW_LOCALPORT '(' string_or_number ')' { afinet_dd_set_localport(last_driver, $3); free($3); } | KW_PORT '(' string_or_number ')' { afinet_dd_set_destport(last_driver, $3); free($3); } | KW_DESTPORT '(' string_or_number ')' { afinet_dd_set_destport(last_driver, $3); free($3); } | inet_socket_option | dest_writer_option | dest_afsocket_option | dest_driver_option ; dest_afinet_udp_option : dest_afinet_option | KW_SPOOF_SOURCE '(' yesno ')' { afinet_dd_set_spoof_source(last_driver, $3); } ; dest_afinet_tcp_params : string { AFInetDestDriver *d = afinet_dd_new_tcp($1, configuration); afinet_grammar_set_dest_driver(d); } dest_afinet_tcp_options { $$ = last_driver; free($1); } ; dest_afinet_tcp6_params : string { AFInetDestDriver *d = afinet_dd_new_tcp6($1, configuration); afinet_grammar_set_dest_driver(d); } dest_afinet_tcp_options { $$ = last_driver; free($1); } ; dest_afinet_tcp_options : dest_afinet_tcp_options dest_afinet_tcp_option | ; dest_afinet_tcp_option : dest_afinet_option | KW_TLS { last_tls_context = tls_context_new(TM_CLIENT); } '(' tls_options ')' { afinet_dd_set_tls_context(last_driver, last_tls_context); } ; dest_afsocket_option : KW_KEEP_ALIVE '(' yesno ')' { afsocket_dd_set_keep_alive(last_driver, $3); } ; dest_afsyslog : KW_SYSLOG '(' dest_afsyslog_params ')' { $$ = $3; } dest_afsyslog_params : string { AFInetDestDriver *d = afinet_dd_new_syslog($1, configuration); afinet_grammar_set_dest_driver(d); } dest_afsyslog_options { $$ = last_driver; free($1); } ; dest_afsyslog_options : dest_afsyslog_options dest_afsyslog_option | ; dest_afsyslog_option : dest_afinet_option | dest_afsocket_transport ; dest_afnetwork : KW_NETWORK '(' dest_afnetwork_params ')' { $$ = $3; } ; dest_afnetwork_params : string { AFInetDestDriver *d = afinet_dd_new_network($1, configuration); afinet_grammar_set_dest_driver(d); } dest_afnetwork_options { $$ = last_driver; free($1); } ; dest_afnetwork_options : dest_afnetwork_options dest_afnetwork_option | ; dest_afnetwork_option : dest_afinet_option | dest_afsocket_transport ; dest_afsocket_transport : afsocket_transport | KW_SPOOF_SOURCE '(' yesno ')' { afinet_dd_set_spoof_source(last_driver, $3); } | KW_TLS { last_tls_context = tls_context_new(TM_CLIENT); } '(' tls_options ')' { afinet_dd_set_tls_context(last_driver, last_tls_context); } ; afsocket_transport : KW_TRANSPORT '(' string ')' { transport_mapper_set_transport(last_transport_mapper, $3); free($3); } | KW_TRANSPORT '(' KW_TCP ')' { transport_mapper_set_transport(last_transport_mapper, "tcp"); } | KW_TRANSPORT '(' KW_UDP ')' { transport_mapper_set_transport(last_transport_mapper, "udp"); } | KW_TRANSPORT '(' KW_TLS ')' { transport_mapper_set_transport(last_transport_mapper, "tls"); } | KW_IP_PROTOCOL '(' inet_ip_protocol_option ')' { transport_mapper_set_address_family(last_transport_mapper, $3); } ; tls_options : tls_option tls_options | ; tls_option : KW_IFDEF { } | KW_PEER_VERIFY '(' yesno ')' { gint verify_mode = $3 ? (TVM_REQUIRED | TVM_TRUSTED) : (TVM_OPTIONAL | TVM_UNTRUSTED); tls_context_set_verify_mode(last_tls_context, verify_mode); } | KW_PEER_VERIFY '(' string ')' { CHECK_ERROR(tls_context_set_verify_mode_by_name(last_tls_context, $3), @3, "unknown peer-verify() argument"); free($3); } | KW_KEY_FILE '(' string ')' { tls_context_set_key_file(last_tls_context, $3); free($3); } | KW_CERT_FILE '(' string ')' { tls_context_set_cert_file(last_tls_context, $3); free($3); } | KW_DHPARAM_FILE '(' string ')' { tls_context_set_dhparam_file(last_tls_context, $3); free($3); } | KW_PKCS12_FILE '(' string ')' { tls_context_set_pkcs12_file(last_tls_context, $3); free($3); } | KW_CA_DIR '(' string ')' { tls_context_set_ca_dir(last_tls_context, $3); free($3); } | KW_CRL_DIR '(' string ')' { tls_context_set_crl_dir(last_tls_context, $3); free($3); } | KW_TRUSTED_KEYS '(' string_list ')' { tls_session_set_trusted_fingerprints(last_tls_context, $3); } | KW_TRUSTED_DN '(' string_list ')' { tls_session_set_trusted_dn(last_tls_context, $3); } | KW_CIPHER_SUITE '(' string ')' { tls_context_set_cipher_suite(last_tls_context, $3); free($3); } | KW_ECDH_CURVE_LIST '(' string ')' { tls_context_set_ecdh_curve_list(last_tls_context, $3); free($3); } | KW_SSL_OPTIONS '(' string_list ')' { CHECK_ERROR(tls_context_set_ssl_options_by_name(last_tls_context, $3), @3, "unknown ssl-options() argument"); } | KW_ENDIF { } ; socket_option : KW_SO_SNDBUF '(' nonnegative_integer ')' { CHECK_ERROR($3 <= G_MAXINT, @3, "Invalid so_sndbuf, it has to be less than %d", G_MAXINT); last_sock_options->so_sndbuf = $3; } | KW_SO_RCVBUF '(' nonnegative_integer ')' { CHECK_ERROR($3 <= G_MAXINT, @3, "Invalid so_rcvbuf, it has to be less than %d", G_MAXINT); last_sock_options->so_rcvbuf = $3; } | KW_SO_BROADCAST '(' yesno ')' { last_sock_options->so_broadcast = $3; } | KW_SO_KEEPALIVE '(' yesno ')' { last_sock_options->so_keepalive = $3; } ; inet_socket_option : socket_option | KW_IP_TTL '(' nonnegative_integer ')' { ((SocketOptionsInet *) last_sock_options)->ip_ttl = $3; } | KW_IP_TOS '(' nonnegative_integer ')' { ((SocketOptionsInet *) last_sock_options)->ip_tos = $3; } | KW_IP_FREEBIND '(' yesno ')' { ((SocketOptionsInet *) last_sock_options)->ip_freebind = $3; } | KW_TCP_KEEPALIVE_TIME '(' nonnegative_integer ')' { ((SocketOptionsInet *) last_sock_options)->tcp_keepalive_time = $3; } | KW_TCP_KEEPALIVE_INTVL '(' nonnegative_integer ')' { ((SocketOptionsInet *) last_sock_options)->tcp_keepalive_intvl = $3; } | KW_TCP_KEEPALIVE_PROBES '(' nonnegative_integer ')' { ((SocketOptionsInet *) last_sock_options)->tcp_keepalive_probes = $3; } ; inet_ip_protocol_option : LL_NUMBER { CHECK_ERROR($1 == 4 || $1 == 6, @1, "ip-protocol option can only be 4 or 6!"); if ($1 == 4) { $$ = AF_INET; } else { $$ = AF_INET6; } } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/afsocket/afsocket-parser.c000066400000000000000000000072061321171025300241460ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afsocket.h" #include "driver.h" #include "cfg-parser.h" #include "afsocket-grammar.h" extern int afsocket_debug; int afsocket_parse(CfgLexer *lexer, LogDriver **instance, gpointer arg); static CfgLexerKeyword afsocket_keywords[] = { { "unix_dgram", KW_UNIX_DGRAM }, { "unix_stream", KW_UNIX_STREAM }, { "udp", KW_UDP }, { "tcp", KW_TCP }, { "syslog", KW_SYSLOG }, { "network", KW_NETWORK }, #if SYSLOG_NG_ENABLE_IPV6 { "udp6", KW_UDP6 }, { "tcp6", KW_TCP6 }, #endif /* ssl */ { "tls", KW_TLS }, { "peer_verify", KW_PEER_VERIFY }, { "key_file", KW_KEY_FILE }, { "cert_file", KW_CERT_FILE }, { "dhparam_file", KW_DHPARAM_FILE }, { "pkcs12_file", KW_PKCS12_FILE }, { "ca_dir", KW_CA_DIR }, { "crl_dir", KW_CRL_DIR }, { "trusted_keys", KW_TRUSTED_KEYS }, { "trusted_dn", KW_TRUSTED_DN }, { "cipher_suite", KW_CIPHER_SUITE }, { "ecdh_curve_list", KW_ECDH_CURVE_LIST }, { "curve_list", KW_ECDH_CURVE_LIST, KWS_OBSOLETE, "ecdh_curve_list"}, { "ssl_options", KW_SSL_OPTIONS }, { "localip", KW_LOCALIP }, { "ip", KW_IP }, { "localport", KW_LOCALPORT }, { "port", KW_PORT }, { "destport", KW_DESTPORT }, { "ip_ttl", KW_IP_TTL }, { "ip_tos", KW_IP_TOS }, { "ip_freebind", KW_IP_FREEBIND }, { "so_broadcast", KW_SO_BROADCAST }, { "so_rcvbuf", KW_SO_RCVBUF }, { "so_sndbuf", KW_SO_SNDBUF }, { "so_keepalive", KW_SO_KEEPALIVE }, { "tcp_keep_alive", KW_SO_KEEPALIVE }, /* old, once deprecated form, but revived in 3.4 */ { "tcp_keepalive", KW_SO_KEEPALIVE }, /* alias for so-keepalive, as tcp is the only option actually using it */ { "tcp_keepalive_time", KW_TCP_KEEPALIVE_TIME }, { "tcp_keepalive_probes", KW_TCP_KEEPALIVE_PROBES }, { "tcp_keepalive_intvl", KW_TCP_KEEPALIVE_INTVL }, { "spoof_source", KW_SPOOF_SOURCE }, { "transport", KW_TRANSPORT }, { "ip_protocol", KW_IP_PROTOCOL }, { "max_connections", KW_MAX_CONNECTIONS }, { "listen_backlog", KW_LISTEN_BACKLOG }, { "keep_alive", KW_KEEP_ALIVE }, { "systemd_syslog", KW_SYSTEMD_SYSLOG }, { NULL } }; CfgParser afsocket_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &afsocket_debug, #endif .name = "afsocket", .keywords = afsocket_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer)) afsocket_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(afsocket_, LogDriver **) syslog-ng-syslog-ng-3.13.2/modules/afsocket/afsocket-parser.h000066400000000000000000000022251321171025300241470ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSOCKET_PARSER_H_INCLUDED #define AFSOCKET_PARSER_H_INCLUDED #include "cfg-parser.h" #include "driver.h" extern CfgParser afsocket_parser; CFG_PARSER_DECLARE_LEXER_BINDING(afsocket_, LogDriver **) #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/afsocket-plugin.c000066400000000000000000000064111321171025300241450ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afsocket-parser.h" #include "cfg-parser.h" #include "plugin.h" #include "tlscontext.h" #include "plugin-types.h" static Plugin afsocket_plugins[] = { { .type = LL_CONTEXT_SOURCE, .name = "unix-stream", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_DESTINATION, .name = "unix-stream", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_SOURCE, .name = "unix-dgram", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_DESTINATION, .name = "unix-dgram", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_SOURCE, .name = "tcp", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_DESTINATION, .name = "tcp", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_SOURCE, .name = "tcp6", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_DESTINATION, .name = "tcp6", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_SOURCE, .name = "udp", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_DESTINATION, .name = "udp", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_SOURCE, .name = "udp6", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_DESTINATION, .name = "udp6", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_SOURCE, .name = "syslog", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_DESTINATION, .name = "syslog", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_SOURCE, .name = "network", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_DESTINATION, .name = "network", .parser = &afsocket_parser, }, { .type = LL_CONTEXT_SOURCE, .name = "systemd-syslog", .parser = &afsocket_parser, }, }; gboolean afsocket_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, afsocket_plugins, G_N_ELEMENTS(afsocket_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "afsocket", .version = SYSLOG_NG_VERSION, .description = "The afsocket module provides socket based transports for syslog-ng, such as the udp(), tcp() and syslog() drivers. This module is compiled with SSL support.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = afsocket_plugins, .plugins_len = G_N_ELEMENTS(afsocket_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/afsocket/afsocket-source.c000066400000000000000000000550731321171025300241570ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afsocket-source.h" #include "messages.h" #include "fdhelpers.h" #include "gsocket.h" #include "stats/stats-registry.h" #include "mainloop.h" #include "poll-fd-events.h" #include #include #include #if SYSLOG_NG_ENABLE_TCP_WRAPPER #include int allow_severity = 0; int deny_severity = 0; #endif typedef struct _AFSocketSourceConnection { LogPipe super; struct _AFSocketSourceDriver *owner; LogReader *reader; int sock; GSockAddr *peer_addr; } AFSocketSourceConnection; static void afsocket_sd_close_connection(AFSocketSourceDriver *self, AFSocketSourceConnection *sc); static gchar * afsocket_sc_stats_instance(AFSocketSourceConnection *self) { static gchar buf[256]; gchar peer_addr[MAX_SOCKADDR_STRING]; if (!self->peer_addr) { /* dgram connection, which means we have no peer, use the bind address */ if (self->owner->bind_addr) { g_sockaddr_format(self->owner->bind_addr, buf, sizeof(buf), GSA_ADDRESS_ONLY); return buf; } else return NULL; } g_sockaddr_format(self->peer_addr, peer_addr, sizeof(peer_addr), GSA_ADDRESS_ONLY); g_snprintf(buf, sizeof(buf), "%s,%s", self->owner->transport_mapper->transport, peer_addr); return buf; } static LogTransport * afsocket_sc_construct_transport(AFSocketSourceConnection *self, gint fd) { return transport_mapper_construct_log_transport(self->owner->transport_mapper, fd); } static gboolean afsocket_sc_init(LogPipe *s) { AFSocketSourceConnection *self = (AFSocketSourceConnection *) s; LogTransport *transport; LogProtoServer *proto; if (!self->reader) { transport = afsocket_sc_construct_transport(self, self->sock); /* transport_mapper_inet_construct_log_transport() can return NULL on TLS errors */ if (!transport) return FALSE; proto = log_proto_server_factory_construct(self->owner->proto_factory, transport, &self->owner->reader_options.proto_options.super); self->reader = log_reader_new(s->cfg); log_reader_reopen(self->reader, proto, poll_fd_events_new(self->sock)); log_reader_set_peer_addr(self->reader, self->peer_addr); } log_reader_set_options(self->reader, &self->super, &self->owner->reader_options, self->owner->super.super.id, afsocket_sc_stats_instance(self)); log_pipe_append((LogPipe *) self->reader, s); if (log_pipe_init((LogPipe *) self->reader)) { return TRUE; } else { log_pipe_unref((LogPipe *) self->reader); self->reader = NULL; } return FALSE; } static gboolean afsocket_sc_deinit(LogPipe *s) { AFSocketSourceConnection *self = (AFSocketSourceConnection *) s; log_pipe_unref(&self->owner->super.super.super); self->owner = NULL; log_pipe_deinit((LogPipe *) self->reader); return TRUE; } static void afsocket_sc_notify(LogPipe *s, gint notify_code, gpointer user_data) { AFSocketSourceConnection *self = (AFSocketSourceConnection *) s; switch (notify_code) { case NC_CLOSE: case NC_READ_ERROR: { if (self->owner->transport_mapper->sock_type == SOCK_STREAM) afsocket_sd_close_connection(self->owner, self); break; } } } static void afsocket_sc_set_owner(AFSocketSourceConnection *self, AFSocketSourceDriver *owner) { GlobalConfig *cfg = log_pipe_get_config(&owner->super.super.super); if (self->owner) log_pipe_unref(&self->owner->super.super.super); log_pipe_ref(&owner->super.super.super); self->owner = owner; self->super.expr_node = owner->super.super.super.expr_node; log_pipe_set_config(&self->super, cfg); if (self->reader) log_pipe_set_config((LogPipe *) self->reader, cfg); log_pipe_append(&self->super, &owner->super.super.super); } /* This should be called by log_reader_free -> log_pipe_unref because this is the control pipe of the reader */ static void afsocket_sc_free(LogPipe *s) { AFSocketSourceConnection *self = (AFSocketSourceConnection *) s; g_sockaddr_unref(self->peer_addr); log_pipe_free_method(s); } AFSocketSourceConnection * afsocket_sc_new(GSockAddr *peer_addr, int fd, GlobalConfig *cfg) { AFSocketSourceConnection *self = g_new0(AFSocketSourceConnection, 1); log_pipe_init_instance(&self->super, cfg); self->super.init = afsocket_sc_init; self->super.deinit = afsocket_sc_deinit; self->super.notify = afsocket_sc_notify; self->super.free_fn = afsocket_sc_free; self->peer_addr = g_sockaddr_ref(peer_addr); self->sock = fd; return self; } void afsocket_sd_add_connection(AFSocketSourceDriver *self, AFSocketSourceConnection *connection) { self->connections = g_list_prepend(self->connections, connection); } static void afsocket_sd_kill_connection(AFSocketSourceConnection *connection) { log_pipe_deinit(&connection->super); /* Remove the circular reference between the connection and its * reader (through the connection->reader and reader->control * pointers these have a circular references). */ log_pipe_unref((LogPipe *) connection->reader); connection->reader = NULL; log_pipe_unref(&connection->super); } static void afsocket_sd_kill_connection_list(GList *list) { GList *l, *next; /* NOTE: the list may contain a list of * - deinitialized AFSocketSourceConnection instances (in case the persist-config list is * freed), or * - initialized AFSocketSourceConnection instances (in case keep-alive is turned off) */ for (l = list; l; l = next) { AFSocketSourceConnection *connection = (AFSocketSourceConnection *) l->data; next = l->next; if (connection->owner) connection->owner->connections = g_list_remove(connection->owner->connections, connection); afsocket_sd_kill_connection(connection); } } void afsocket_sd_set_keep_alive(LogDriver *s, gint enable) { AFSocketSourceDriver *self = (AFSocketSourceDriver *) s; self->connections_kept_alive_accross_reloads = enable; } void afsocket_sd_set_max_connections(LogDriver *s, gint max_connections) { AFSocketSourceDriver *self = (AFSocketSourceDriver *) s; self->max_connections = max_connections; } void afsocket_sd_set_listen_backlog(LogDriver *s, gint listen_backlog) { AFSocketSourceDriver *self = (AFSocketSourceDriver *) s; self->listen_backlog = listen_backlog; } static const gchar * afsocket_sd_format_name(const LogPipe *s) { const AFSocketSourceDriver *self = (const AFSocketSourceDriver *)s; static gchar persist_name[1024]; if (s->persist_name) { g_snprintf(persist_name, sizeof(persist_name), "afsocket_sd.%s", self->super.super.super.persist_name); } else { gchar buf[64]; g_snprintf(persist_name, sizeof(persist_name), "afsocket_sd.(%s,%s)", (self->transport_mapper->sock_type == SOCK_STREAM) ? "stream" : "dgram", g_sockaddr_format(self->bind_addr, buf, sizeof(buf), GSA_FULL)); } return persist_name; } static const gchar * afsocket_sd_format_listener_name(const AFSocketSourceDriver *self) { static gchar persist_name[1024]; g_snprintf(persist_name, sizeof(persist_name), "%s.listen_fd", afsocket_sd_format_name((const LogPipe *)self)); return persist_name; } static const gchar * afsocket_sd_format_connections_name(const AFSocketSourceDriver *self) { static gchar persist_name[1024]; g_snprintf(persist_name, sizeof(persist_name), "%s.connections", afsocket_sd_format_name((const LogPipe *)self)); return persist_name; } static gboolean afsocket_sd_process_connection(AFSocketSourceDriver *self, GSockAddr *client_addr, GSockAddr *local_addr, gint fd) { gchar buf[MAX_SOCKADDR_STRING], buf2[MAX_SOCKADDR_STRING]; #if SYSLOG_NG_ENABLE_TCP_WRAPPER if (client_addr && (client_addr->sa.sa_family == AF_INET #if SYSLOG_NG_ENABLE_IPV6 || client_addr->sa.sa_family == AF_INET6 #endif )) { struct request_info req; request_init(&req, RQ_DAEMON, "syslog-ng", RQ_FILE, fd, 0); fromhost(&req); if (hosts_access(&req) == 0) { msg_error("Syslog connection rejected by tcpd", evt_tag_str("client", g_sockaddr_format(client_addr, buf, sizeof(buf), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(local_addr, buf2, sizeof(buf2), GSA_FULL))); return FALSE; } } #endif if (self->num_connections >= self->max_connections) { msg_error("Number of allowed concurrent connections reached, rejecting connection", evt_tag_str("client", g_sockaddr_format(client_addr, buf, sizeof(buf), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(local_addr, buf2, sizeof(buf2), GSA_FULL)), evt_tag_int("max", self->max_connections)); return FALSE; } else { AFSocketSourceConnection *conn; conn = afsocket_sc_new(client_addr, fd, self->super.super.super.cfg); afsocket_sc_set_owner(conn, self); if (log_pipe_init(&conn->super)) { afsocket_sd_add_connection(self, conn); self->num_connections++; log_pipe_append(&conn->super, &self->super.super.super); } else { log_pipe_unref(&conn->super); return FALSE; } } return TRUE; } #define MAX_ACCEPTS_AT_A_TIME 30 static void afsocket_sd_accept(gpointer s) { AFSocketSourceDriver *self = (AFSocketSourceDriver *) s; GSockAddr *peer_addr; gchar buf1[256], buf2[256]; gint new_fd; gboolean res; int accepts = 0; while (accepts < MAX_ACCEPTS_AT_A_TIME) { GIOStatus status; status = g_accept(self->fd, &new_fd, &peer_addr); if (status == G_IO_STATUS_AGAIN) { /* no more connections to accept */ break; } else if (status != G_IO_STATUS_NORMAL) { msg_error("Error accepting new connection", evt_tag_errno(EVT_TAG_OSERROR, errno)); return; } g_fd_set_nonblock(new_fd, TRUE); g_fd_set_cloexec(new_fd, TRUE); res = afsocket_sd_process_connection(self, peer_addr, self->bind_addr, new_fd); if (res) { if (peer_addr->sa.sa_family != AF_UNIX) msg_notice("Syslog connection accepted", evt_tag_int("fd", new_fd), evt_tag_str("client", g_sockaddr_format(peer_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL))); else msg_verbose("Syslog connection accepted", evt_tag_int("fd", new_fd), evt_tag_str("client", g_sockaddr_format(peer_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL))); } else { close(new_fd); } g_sockaddr_unref(peer_addr); accepts++; } return; } static void afsocket_sd_close_connection(AFSocketSourceDriver *self, AFSocketSourceConnection *sc) { gchar buf1[MAX_SOCKADDR_STRING], buf2[MAX_SOCKADDR_STRING]; if (sc->peer_addr->sa.sa_family != AF_UNIX) msg_notice("Syslog connection closed", evt_tag_int("fd", sc->sock), evt_tag_str("client", g_sockaddr_format(sc->peer_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL))); else msg_verbose("Syslog connection closed", evt_tag_int("fd", sc->sock), evt_tag_str("client", g_sockaddr_format(sc->peer_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL))); log_pipe_deinit(&sc->super); self->connections = g_list_remove(self->connections, sc); afsocket_sd_kill_connection(sc); self->num_connections--; } static void afsocket_sd_start_watches(AFSocketSourceDriver *self) { IV_FD_INIT(&self->listen_fd); self->listen_fd.fd = self->fd; self->listen_fd.cookie = self; self->listen_fd.handler_in = afsocket_sd_accept; iv_fd_register(&self->listen_fd); } static void afsocket_sd_stop_watches(AFSocketSourceDriver *self) { if (iv_fd_registered (&self->listen_fd)) iv_fd_unregister(&self->listen_fd); } static gboolean afsocket_sd_setup_reader_options(AFSocketSourceDriver *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); if (self->transport_mapper->sock_type == SOCK_STREAM && !self->window_size_initialized) { /* distribute the window evenly between each of our possible * connections. This is quite pessimistic and can result in very low * window sizes. Increase that but warn the user at the same time */ self->reader_options.super.init_window_size /= self->max_connections; if (self->reader_options.super.init_window_size < 100) { msg_warning("WARNING: window sizing for tcp sources were changed in " VERSION_3_3 ", the configuration value was divided by the value of max-connections(). The result was too small, clamping to 100 entries. Ensure you have a proper log_fifo_size setting to avoid message loss.", evt_tag_int("orig_log_iw_size", self->reader_options.super.init_window_size), evt_tag_int("new_log_iw_size", 100), evt_tag_int("min_log_fifo_size", 100 * self->max_connections)); self->reader_options.super.init_window_size = 100; } self->window_size_initialized = TRUE; } log_reader_options_init(&self->reader_options, cfg, self->super.super.group); return TRUE; } static gboolean afsocket_sd_setup_transport(AFSocketSourceDriver *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); if (!transport_mapper_apply_transport(self->transport_mapper, cfg)) return FALSE; self->proto_factory = log_proto_server_get_factory(&cfg->plugin_context, self->transport_mapper->logproto); if (!self->proto_factory) { msg_error("Unknown value specified in the transport() option, no such LogProto plugin found", evt_tag_str("transport", self->transport_mapper->logproto)); return FALSE; } afsocket_sd_setup_reader_options(self); return TRUE; } static gboolean afsocket_sd_restore_kept_alive_connections(AFSocketSourceDriver *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); /* fetch persistent connections first */ if (self->connections_kept_alive_accross_reloads) { GList *p = NULL; self->connections = cfg_persist_config_fetch(cfg, afsocket_sd_format_connections_name(self)); self->num_connections = 0; for (p = self->connections; p; p = p->next) { afsocket_sc_set_owner((AFSocketSourceConnection *) p->data, self); if (log_pipe_init((LogPipe *) p->data)) { self->num_connections++; } else { AFSocketSourceConnection *sc = (AFSocketSourceConnection *)p->data; self->connections = g_list_remove(self->connections, sc); afsocket_sd_kill_connection((AFSocketSourceConnection *)sc); } } } return TRUE; } static gboolean afsocket_sd_open_listener(AFSocketSourceDriver *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); gint sock; gboolean res = FALSE; /* ok, we have connection list, check if we need to open a listener */ sock = -1; if (self->transport_mapper->sock_type == SOCK_STREAM) { if (self->connections_kept_alive_accross_reloads) { /* NOTE: this assumes that fd 0 will never be used for listening fds, * main.c opens fd 0 so this assumption can hold */ sock = GPOINTER_TO_UINT( cfg_persist_config_fetch(cfg, afsocket_sd_format_listener_name(self))) - 1; } if (sock == -1) { if (!afsocket_sd_acquire_socket(self, &sock)) return self->super.super.optional; if (sock == -1 && !transport_mapper_open_socket(self->transport_mapper, self->socket_options, self->bind_addr, AFSOCKET_DIR_RECV, &sock)) return self->super.super.optional; } /* set up listening source */ if (listen(sock, self->listen_backlog) < 0) { msg_error("Error during listen()", evt_tag_errno(EVT_TAG_OSERROR, errno)); close(sock); return FALSE; } self->fd = sock; afsocket_sd_start_watches(self); res = TRUE; } else { if (!self->connections) { if (!afsocket_sd_acquire_socket(self, &sock)) return self->super.super.optional; if (sock == -1 && !transport_mapper_open_socket(self->transport_mapper, self->socket_options, self->bind_addr, AFSOCKET_DIR_RECV, &sock)) return self->super.super.optional; } self->fd = -1; /* we either have self->connections != NULL, or sock contains a new fd */ if (self->connections || afsocket_sd_process_connection(self, NULL, self->bind_addr, sock)) res = TRUE; } return res; } static void afsocket_sd_close_fd(gpointer value) { gint fd = GPOINTER_TO_UINT(value) - 1; close(fd); } static void afsocket_sd_save_connections(AFSocketSourceDriver *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); if (!self->connections_kept_alive_accross_reloads || !cfg->persist) { afsocket_sd_kill_connection_list(self->connections); } else { GList *p; /* for SOCK_STREAM source drivers this is a list, for * SOCK_DGRAM this is a single connection */ for (p = self->connections; p; p = p->next) { log_pipe_deinit((LogPipe *) p->data); } cfg_persist_config_add(cfg, afsocket_sd_format_connections_name(self), self->connections, (GDestroyNotify)afsocket_sd_kill_connection_list, FALSE); } self->connections = NULL; } static void afsocket_sd_save_listener(AFSocketSourceDriver *self) { GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); if (self->transport_mapper->sock_type == SOCK_STREAM) { afsocket_sd_stop_watches(self); if (!self->connections_kept_alive_accross_reloads) { msg_verbose("Closing listener fd", evt_tag_int("fd", self->fd)); close(self->fd); } else { /* NOTE: the fd is incremented by one when added to persistent config * as persist config cannot store NULL */ cfg_persist_config_add(cfg, afsocket_sd_format_listener_name(self), GUINT_TO_POINTER(self->fd + 1), afsocket_sd_close_fd, FALSE); } } } gboolean afsocket_sd_setup_addresses_method(AFSocketSourceDriver *self) { return TRUE; } gboolean afsocket_sd_init_method(LogPipe *s) { AFSocketSourceDriver *self = (AFSocketSourceDriver *) s; return log_src_driver_init_method(s) && afsocket_sd_setup_transport(self) && afsocket_sd_setup_addresses(self) && afsocket_sd_restore_kept_alive_connections(self) && afsocket_sd_open_listener(self) && transport_mapper_init(self->transport_mapper); } gboolean afsocket_sd_deinit_method(LogPipe *s) { AFSocketSourceDriver *self = (AFSocketSourceDriver *) s; afsocket_sd_save_connections(self); afsocket_sd_save_listener(self); return log_src_driver_deinit_method(s); } static void afsocket_sd_notify(LogPipe *s, gint notify_code, gpointer user_data) { switch (notify_code) { case NC_CLOSE: case NC_READ_ERROR: { g_assert_not_reached(); break; } } } void afsocket_sd_free_method(LogPipe *s) { AFSocketSourceDriver *self = (AFSocketSourceDriver *) s; log_reader_options_destroy(&self->reader_options); transport_mapper_free(self->transport_mapper); socket_options_free(self->socket_options); g_sockaddr_unref(self->bind_addr); self->bind_addr = NULL; log_src_driver_free(s); } void afsocket_sd_init_instance(AFSocketSourceDriver *self, SocketOptions *socket_options, TransportMapper *transport_mapper, GlobalConfig *cfg) { log_src_driver_init_instance(&self->super, cfg); self->super.super.super.init = afsocket_sd_init_method; self->super.super.super.deinit = afsocket_sd_deinit_method; self->super.super.super.free_fn = afsocket_sd_free_method; self->super.super.super.notify = afsocket_sd_notify; self->super.super.super.generate_persist_name = afsocket_sd_format_name; self->setup_addresses = afsocket_sd_setup_addresses_method; self->socket_options = socket_options; self->transport_mapper = transport_mapper; self->max_connections = 10; self->listen_backlog = 255; self->connections_kept_alive_accross_reloads = TRUE; log_reader_options_defaults(&self->reader_options); self->reader_options.super.stats_level = STATS_LEVEL1; self->reader_options.super.stats_source = transport_mapper->stats_source; /* NOTE: this changes the initial window size from 100 to 1000. Reasons: * Starting with syslog-ng 3.3, window-size is distributed evenly between * _all_ possible connections to avoid starving. With the defaults this * means that we get a window size of 10 messages log_iw_size(100) / * max_connections(10), but that is incredibly slow, thus bump this value here. */ self->reader_options.super.init_window_size = 1000; } syslog-ng-syslog-ng-3.13.2/modules/afsocket/afsocket-source.h000066400000000000000000000064471321171025300241650ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSOCKET_SOURCE_H_INCLUDED #define AFSOCKET_SOURCE_H_INCLUDED #include "afsocket.h" #include "socket-options.h" #include "transport-mapper.h" #include "driver.h" #include "logreader.h" #include #define AFSOCKET_WNDSIZE_INITED 0x10000 typedef struct _AFSocketSourceDriver AFSocketSourceDriver; struct _AFSocketSourceDriver { LogSrcDriver super; guint32 recvd_messages_are_local:1, connections_kept_alive_accross_reloads:1, require_tls:1, window_size_initialized:1; struct iv_fd listen_fd; gint fd; LogReaderOptions reader_options; LogProtoServerFactory *proto_factory; GSockAddr *bind_addr; gint max_connections; gint num_connections; gint listen_backlog; GList *connections; SocketOptions *socket_options; TransportMapper *transport_mapper; /* * Apply transport options, set up bind_addr based on the * information processed during parse time. This used to be * constructed during the parser, however that made the ordering of * various options matter and behave incorrectly when the port() was * specified _after_ transport(). Now, it collects the information, * and then applies them with a separate call to apply_transport() * during init(). */ gboolean (*setup_addresses)(AFSocketSourceDriver *s); /* optionally acquire a socket from the runtime environment (e.g. systemd) */ gboolean (*acquire_socket)(AFSocketSourceDriver *s, gint *fd); }; void afsocket_sd_set_keep_alive(LogDriver *self, gint enable); void afsocket_sd_set_max_connections(LogDriver *self, gint max_connections); void afsocket_sd_set_listen_backlog(LogDriver *self, gint listen_backlog); static inline gboolean afsocket_sd_acquire_socket(AFSocketSourceDriver *s, gint *fd) { if (s->acquire_socket) return s->acquire_socket(s, fd); *fd = -1; return TRUE; } static inline gboolean afsocket_sd_setup_addresses(AFSocketSourceDriver *s) { return s->setup_addresses(s); } LogTransport *afsocket_sd_construct_transport_method(AFSocketSourceDriver *self, gint fd); gboolean afsocket_sd_setup_addresses_method(AFSocketSourceDriver *self); gboolean afsocket_sd_init_method(LogPipe *s); gboolean afsocket_sd_deinit_method(LogPipe *s); void afsocket_sd_free_method(LogPipe *self); void afsocket_sd_init_instance(AFSocketSourceDriver *self, SocketOptions *socket_options, TransportMapper *transport_mapper, GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/afsocket-systemd-override.h000066400000000000000000000022261321171025300261610ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Tibor Benke * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSOCKET_GRAMMAR_EXTRA_H_INCLUDED #define AFSOCKET_GRAMMAR_EXTRA_H_INCLUDED void afunix_grammar_set_source_driver(AFUnixSourceDriver *sd); void systemd_syslog_grammar_set_source_driver(SystemDSyslogSourceDriver *sd); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/afsocket.c000066400000000000000000000017211321171025300226500ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afsocket.h" syslog-ng-syslog-ng-3.13.2/modules/afsocket/afsocket.h000066400000000000000000000020241321171025300226520ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSOCKET_H_INCLUDED #define AFSOCKET_H_INCLUDED #include "syslog-ng.h" #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/afunix-dest.c000066400000000000000000000054111321171025300233000ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afunix-dest.h" #include "messages.h" #include "gprocess.h" #include #include #include #include #include #include #include static const gchar * afunix_dd_get_dest_name(const AFSocketDestDriver *s) { const AFUnixDestDriver *self = (const AFUnixDestDriver *)s; static gchar buf[256]; g_snprintf(buf, sizeof(buf), "localhost.afunix:%s", self->filename); return buf; } static gboolean afunix_dd_setup_addresses(AFSocketDestDriver *s) { AFUnixDestDriver *self = (AFUnixDestDriver *) s; if (!afsocket_dd_setup_addresses_method(s)) return FALSE; if (!self->super.bind_addr) self->super.bind_addr = g_sockaddr_unix_new(NULL); if (!self->super.dest_addr) self->super.dest_addr = g_sockaddr_unix_new(self->filename); return TRUE; } static void afunix_dd_free(LogPipe *s) { AFUnixDestDriver *self = (AFUnixDestDriver *) s; g_free(self->filename); afsocket_dd_free(s); } AFUnixDestDriver * afunix_dd_new_instance(TransportMapper *transport_mapper, gchar *filename, GlobalConfig *cfg) { AFUnixDestDriver *self = g_new0(AFUnixDestDriver, 1); afsocket_dd_init_instance(&self->super, socket_options_new(), transport_mapper, cfg); self->super.super.super.super.free_fn = afunix_dd_free; self->super.setup_addresses = afunix_dd_setup_addresses; self->super.writer_options.mark_mode = MM_NONE; self->super.get_dest_name = afunix_dd_get_dest_name; self->filename = g_strdup(filename); return self; } AFUnixDestDriver * afunix_dd_new_dgram(gchar *filename, GlobalConfig *cfg) { return afunix_dd_new_instance(transport_mapper_unix_dgram_new(), filename, cfg); } AFUnixDestDriver * afunix_dd_new_stream(gchar *filename, GlobalConfig *cfg) { return afunix_dd_new_instance(transport_mapper_unix_stream_new(), filename, cfg); } syslog-ng-syslog-ng-3.13.2/modules/afsocket/afunix-dest.h000066400000000000000000000025001321171025300233010ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFUNIX_DEST_H_INCLUDED #define AFUNIX_DEST_H_INCLUDED #include "afsocket-dest.h" #include "transport-mapper-unix.h" typedef struct _AFUnixDestDriver { AFSocketDestDriver super; gchar *filename; } AFUnixDestDriver; AFUnixDestDriver *afunix_dd_new_dgram(gchar *filename, GlobalConfig *cfg); AFUnixDestDriver *afunix_dd_new_stream(gchar *filename, GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/afunix-source.c000066400000000000000000000117511321171025300236450ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afunix-source.h" #include "messages.h" #include "gprocess.h" #include "transport-mapper-unix.h" #include #include #include #include #include #include #include static gboolean afunix_sd_setup_addresses(AFSocketSourceDriver *s) { AFUnixSourceDriver *self = (AFUnixSourceDriver *) s; if (!afsocket_sd_setup_addresses_method(s)) return FALSE; if (self->create_dirs) { if (!file_perm_options_create_containing_directory(&self->file_perm_options, self->filename)) return FALSE; } if (!self->super.bind_addr) self->super.bind_addr = g_sockaddr_unix_new(self->filename); return TRUE; } static gboolean afunix_sd_adjust_reader_options(AFUnixSourceDriver *self, GlobalConfig *cfg) { self->super.reader_options.parse_options.flags |= LP_LOCAL; if (cfg_is_config_version_older(cfg, 0x0302)) { msg_warning_once("WARNING: the expected message format is being changed for unix-domain transports to improve " "syslogd compatibity with " VERSION_3_2 ". If you are using custom " "applications which bypass the syslog() API, you might " "need the 'expect-hostname' flag to get the old behaviour back"); } else { self->super.reader_options.parse_options.flags &= ~LP_EXPECT_HOSTNAME; } return TRUE; } static gboolean afunix_sd_apply_perms_to_socket(AFUnixSourceDriver *self) { cap_t saved_caps; saved_caps = g_process_cap_save(); g_process_cap_modify(CAP_CHOWN, TRUE); g_process_cap_modify(CAP_FOWNER, TRUE); g_process_cap_modify(CAP_DAC_OVERRIDE, TRUE); file_perm_options_apply_file(&self->file_perm_options, self->filename); g_process_cap_restore(saved_caps); return TRUE; } static gboolean afunix_sd_init(LogPipe *s) { AFUnixSourceDriver *self = (AFUnixSourceDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (self->create_dirs == -1) self->create_dirs = cfg->create_dirs; if (self->pass_unix_credentials == -1) self->pass_unix_credentials = cfg->pass_unix_credentials; file_perm_options_inherit_dont_change(&self->file_perm_options); afunix_sd_set_pass_unix_credentials(self, self->pass_unix_credentials); return afsocket_sd_init_method(s) && afunix_sd_apply_perms_to_socket(self); } static void afunix_sd_free(LogPipe *s) { AFUnixSourceDriver *self = (AFUnixSourceDriver *) s; g_free(self->filename); afsocket_sd_free_method(s); } AFUnixSourceDriver * afunix_sd_new_instance(TransportMapper *transport_mapper, gchar *filename, GlobalConfig *cfg) { AFUnixSourceDriver *self = g_new0(AFUnixSourceDriver, 1); afsocket_sd_init_instance(&self->super, socket_options_new(), transport_mapper, cfg); self->super.super.super.super.init = afunix_sd_init; self->super.super.super.super.free_fn = afunix_sd_free; self->super.setup_addresses = afunix_sd_setup_addresses; self->super.max_connections = 256; self->super.recvd_messages_are_local = TRUE; self->filename = g_strdup(filename); file_perm_options_defaults(&self->file_perm_options); file_perm_options_set_file_perm(&self->file_perm_options, 0666); self->pass_unix_credentials = -1; self->create_dirs = -1; afunix_sd_adjust_reader_options(self, cfg); return self; } void afunix_sd_set_pass_unix_credentials(AFUnixSourceDriver *self, gboolean pass) { self->pass_unix_credentials = pass; transport_mapper_unix_set_pass_unix_credentials(self->super.transport_mapper, pass); } void afunix_sd_set_create_dirs(AFUnixSourceDriver *self, gboolean create_dirs) { self->create_dirs = create_dirs; } AFUnixSourceDriver * afunix_sd_new_dgram(gchar *filename, GlobalConfig *cfg) { return afunix_sd_new_instance(transport_mapper_unix_dgram_new(), filename, cfg); } AFUnixSourceDriver * afunix_sd_new_stream(gchar *filename, GlobalConfig *cfg) { AFUnixSourceDriver *self = afunix_sd_new_instance(transport_mapper_unix_stream_new(), filename, cfg); self->super.reader_options.super.init_window_size = self->super.max_connections * 100; return self; } syslog-ng-syslog-ng-3.13.2/modules/afsocket/afunix-source.h000066400000000000000000000031421321171025300236450ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFUNIX_SOURCE_H_INCLUDED #define AFUNIX_SOURCE_H_INCLUDED #include "afsocket-source.h" #include "transport-mapper-unix.h" #include "file-perms.h" typedef struct _AFUnixSourceDriver { AFSocketSourceDriver super; gchar *filename; FilePermOptions file_perm_options; gint pass_unix_credentials; gint create_dirs; } AFUnixSourceDriver; AFUnixSourceDriver *afunix_sd_new_stream(gchar *filename, GlobalConfig *cfg); AFUnixSourceDriver *afunix_sd_new_dgram(gchar *filename, GlobalConfig *cfg); void afunix_sd_set_pass_unix_credentials(AFUnixSourceDriver *self, gboolean pass); void afunix_sd_set_create_dirs(AFUnixSourceDriver *self, gboolean create_dirs); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/socket-options-inet.c000066400000000000000000000132151321171025300247700ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "socket-options-inet.h" #include "gsockaddr.h" #include "messages.h" #include #include #ifndef SOL_IP #define SOL_IP IPPROTO_IP #endif #ifndef SOL_IPV6 #define SOL_IPV6 IPPROTO_IPV6 #endif #ifndef SOL_TCP #define SOL_TCP IPPROTO_TCP #endif static gboolean socket_options_inet_setup_socket(SocketOptions *s, gint fd, GSockAddr *addr, AFSocketDirection dir) { SocketOptionsInet *self = (SocketOptionsInet *) s; gint off = 0; gint on = 1; if (!socket_options_setup_socket_method(s, fd, addr, dir)) return FALSE; if (self->tcp_keepalive_time > 0) { #ifdef TCP_KEEPIDLE setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &self->tcp_keepalive_time, sizeof(self->tcp_keepalive_time)); #else msg_error("tcp-keepalive-time() is set but no TCP_KEEPIDLE setsockopt on this platform"); return FALSE; #endif } if (self->tcp_keepalive_probes > 0) { #ifdef TCP_KEEPCNT setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &self->tcp_keepalive_probes, sizeof(self->tcp_keepalive_probes)); #else msg_error("tcp-keepalive-probes() is set but no TCP_KEEPCNT setsockopt on this platform"); return FALSE; #endif } if (self->tcp_keepalive_intvl > 0) { #ifdef TCP_KEEPINTVL setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &self->tcp_keepalive_intvl, sizeof(self->tcp_keepalive_intvl)); #else msg_error("tcp-keepalive-intvl() is set but no TCP_KEEPINTVL setsockopt on this platform"); return FALSE; #endif } switch (addr->sa.sa_family) { case AF_INET: { struct ip_mreq mreq; if (IN_MULTICAST(ntohl(g_sockaddr_inet_get_address(addr).s_addr))) { if (dir & AFSOCKET_DIR_RECV) { memset(&mreq, 0, sizeof(mreq)); mreq.imr_multiaddr = g_sockaddr_inet_get_address(addr); mreq.imr_interface.s_addr = INADDR_ANY; setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &off, sizeof(off)); } if (dir & AFSOCKET_DIR_SEND) { if (self->ip_ttl) setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &self->ip_ttl, sizeof(self->ip_ttl)); } } else { if (self->ip_ttl && (dir & AFSOCKET_DIR_SEND)) setsockopt(fd, SOL_IP, IP_TTL, &self->ip_ttl, sizeof(self->ip_ttl)); } if (self->ip_tos && (dir & AFSOCKET_DIR_SEND)) setsockopt(fd, SOL_IP, IP_TOS, &self->ip_tos, sizeof(self->ip_tos)); if (self->ip_freebind && (dir & AFSOCKET_DIR_RECV)) { #ifdef IP_FREEBIND setsockopt(fd, SOL_IP, IP_FREEBIND, &on, sizeof(on)); #else msg_error("ip-freebind() is set but no IP_FREEBIND setsockopt on this platform"); return FALSE; #endif } break; } #if SYSLOG_NG_ENABLE_IPV6 case AF_INET6: { struct ipv6_mreq mreq6; if (IN6_IS_ADDR_MULTICAST(&g_sockaddr_inet6_get_sa(addr)->sin6_addr)) { if (dir & AFSOCKET_DIR_RECV) { memset(&mreq6, 0, sizeof(mreq6)); mreq6.ipv6mr_multiaddr = *g_sockaddr_inet6_get_address(addr); mreq6.ipv6mr_interface = 0; setsockopt(fd, SOL_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof(mreq6)); setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &off, sizeof(off)); } if (dir & AFSOCKET_DIR_SEND) { if (self->ip_ttl) setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &self->ip_ttl, sizeof(self->ip_ttl)); } } else { if (self->ip_ttl && (dir & AFSOCKET_DIR_SEND)) setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &self->ip_ttl, sizeof(self->ip_ttl)); } if (self->ip_freebind && (dir & AFSOCKET_DIR_RECV)) { #ifdef IP_FREEBIND /* NOTE: there's no separate IP_FREEBIND option for IPV6, it re-uses the IPv4 one */ setsockopt(fd, SOL_IP, IP_FREEBIND, &on, sizeof(on)); #else msg_error("ip-freebind() is set but no IP_FREEBIND setsockopt on this platform"); return FALSE; #endif } break; } #endif } return TRUE; } SocketOptionsInet * socket_options_inet_new_instance(void) { SocketOptionsInet *self = g_new0(SocketOptionsInet, 1); socket_options_init_instance(&self->super); self->super.setup_socket = socket_options_inet_setup_socket; self->super.so_keepalive = TRUE; #if defined(TCP_KEEPTIME) && defined(TCP_KEEPIDLE) && defined(TCP_KEEPCNT) self->tcp_keepalive_time = 60; self->tcp_keepalive_intvl = 10; self->tcp_keepalive_probes = 6; #endif return self; } SocketOptions * socket_options_inet_new(void) { return &socket_options_inet_new_instance()->super; } syslog-ng-syslog-ng-3.13.2/modules/afsocket/socket-options-inet.h000066400000000000000000000026111321171025300247730ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef SOCKET_OPTIONS_INET_H_INCLUDED #define SOCKET_OPTIONS_INET_H_INCLUDED #include "socket-options.h" typedef struct _SocketOptionsInet { SocketOptions super; /* user settings */ gint ip_ttl; gint ip_tos; gboolean ip_freebind; gint tcp_keepalive_time; gint tcp_keepalive_intvl; gint tcp_keepalive_probes; } SocketOptionsInet; SocketOptionsInet *socket_options_inet_new_instance(void); SocketOptions *socket_options_inet_new(void); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/socket-options.c000066400000000000000000000063761321171025300240450ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "socket-options.h" #include "messages.h" #include #include gboolean socket_options_setup_socket_method(SocketOptions *self, gint fd, GSockAddr *bind_addr, AFSocketDirection dir) { gint rc; if (dir & AFSOCKET_DIR_RECV) { if (self->so_rcvbuf) { gint so_rcvbuf_set = 0; socklen_t sz = sizeof(so_rcvbuf_set); rc = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &self->so_rcvbuf, sizeof(self->so_rcvbuf)); if (rc < 0 || getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &so_rcvbuf_set, &sz) < 0 || sz != sizeof(so_rcvbuf_set) || so_rcvbuf_set < self->so_rcvbuf) { msg_warning("The kernel refused to set the receive buffer (SO_RCVBUF) to the requested size, you probably need to adjust buffer related kernel parameters", evt_tag_int("so_rcvbuf", self->so_rcvbuf), evt_tag_int("so_rcvbuf_set", so_rcvbuf_set)); } } } if (dir & AFSOCKET_DIR_SEND) { if (self->so_sndbuf) { gint so_sndbuf_set = 0; socklen_t sz = sizeof(so_sndbuf_set); rc = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &self->so_sndbuf, sizeof(self->so_sndbuf)); if (rc < 0 || getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &so_sndbuf_set, &sz) < 0 || sz != sizeof(so_sndbuf_set) || so_sndbuf_set < self->so_sndbuf) { msg_warning("The kernel refused to set the send buffer (SO_SNDBUF) to the requested size, you probably need to adjust buffer related kernel parameters", evt_tag_int("so_sndbuf", self->so_sndbuf), evt_tag_int("so_sndbuf_set", so_sndbuf_set)); } } if (self->so_broadcast) setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &self->so_broadcast, sizeof(self->so_broadcast)); } setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &self->so_keepalive, sizeof(self->so_keepalive)); return TRUE; } void socket_options_init_instance(SocketOptions *self) { self->setup_socket = socket_options_setup_socket_method; self->free = g_free; } SocketOptions * socket_options_new(void) { SocketOptions *self = g_new0(SocketOptions, 1); socket_options_init_instance(self); return self; } syslog-ng-syslog-ng-3.13.2/modules/afsocket/socket-options.h000066400000000000000000000036101321171025300240360ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef SOCKET_OPTIONS_H_INCLUDED #define SOCKET_OPTIONS_H_INCLUDED #include "gsockaddr.h" typedef enum { AFSOCKET_DIR_RECV = 0x01, AFSOCKET_DIR_SEND = 0x02, } AFSocketDirection; typedef struct _SocketOptions SocketOptions; struct _SocketOptions { /* socket options */ gint so_sndbuf; gint so_rcvbuf; gint so_broadcast; gint so_keepalive; gboolean (*setup_socket)(SocketOptions *s, gint sock, GSockAddr *bind_addr, AFSocketDirection dir); void (*free)(gpointer s); }; gboolean socket_options_setup_socket_method(SocketOptions *self, gint fd, GSockAddr *bind_addr, AFSocketDirection dir); void socket_options_init_instance(SocketOptions *self); SocketOptions *socket_options_new(void); static inline gboolean socket_options_setup_socket(SocketOptions *s, gint sock, GSockAddr *bind_addr, AFSocketDirection dir) { return s->setup_socket(s, sock, bind_addr, dir); } static inline void socket_options_free(SocketOptions *s) { s->free(s); } #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/systemd-syslog-source.c000066400000000000000000000142401321171025300253550ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 2013-2014 Tibor Benke * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "systemd-syslog-source.h" #include "afunix-source.h" #include "afsocket-systemd-override.h" #include "service-management.h" #include "fdhelpers.h" #include #include #if SYSLOG_NG_ENABLE_SYSTEMD #include static gboolean systemd_syslog_sd_acquire_socket(AFSocketSourceDriver *s, gint *acquired_fd) { gint fd, number_of_fds; *acquired_fd = -1; fd = -1; number_of_fds = sd_listen_fds(0); if (number_of_fds > 1) { msg_error("Systemd socket activation failed: got more than one fd", evt_tag_int("number", number_of_fds)); return TRUE; } else if (number_of_fds < 1) { msg_error("Failed to acquire /run/systemd/journal/syslog socket, disabling systemd-syslog source"); return TRUE; } else { fd = SD_LISTEN_FDS_START; msg_debug("Systemd socket activation", evt_tag_int("file-descriptor", fd)); if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, NULL, 0)) { *acquired_fd = fd; } else { msg_error("The systemd supplied UNIX domain socket is of a" " different type, check the configured driver and" " the matching systemd unit file", evt_tag_int("systemd-sock-fd", fd), evt_tag_str("expecting", "unix-dgram()")); *acquired_fd = -1; return TRUE; } } if (*acquired_fd != -1) { g_fd_set_nonblock(*acquired_fd, TRUE); msg_verbose("Acquired systemd syslog socket", evt_tag_int("systemd-syslog-sock-fd", *acquired_fd)); return TRUE; } return TRUE; } #else static gboolean systemd_syslog_sd_acquire_socket(AFSocketSourceDriver *s, gint *acquired_fd) { return TRUE; } #endif static gboolean systemd_syslog_sd_init_method(LogPipe *s) { SystemDSyslogSourceDriver *self = (SystemDSyslogSourceDriver *) s; if (service_management_get_type() != SMT_SYSTEMD) { msg_error("Error initializing systemd-syslog() source", evt_tag_str("systemd_status", "not-running")); return FALSE; } if (self->from_unix_source) { msg_warning("systemd-syslog() source ignores configuration options. " "Please, do not set anything on it"); socket_options_free(self->super.socket_options); self->super.socket_options = socket_options_new(); socket_options_init_instance(self->super.socket_options); } return afsocket_sd_init_method((LogPipe *) &self->super); } SystemDSyslogSourceDriver * systemd_syslog_sd_new(GlobalConfig *cfg, gboolean fallback) { SystemDSyslogSourceDriver *self; TransportMapper *transport_mapper; self = g_new0(SystemDSyslogSourceDriver, 1); transport_mapper = transport_mapper_unix_dgram_new(); afsocket_sd_init_instance(&self->super, socket_options_new(), transport_mapper, cfg); self->super.super.super.super.init = systemd_syslog_sd_init_method; self->super.acquire_socket = systemd_syslog_sd_acquire_socket; self->super.max_connections = 256; self->super.recvd_messages_are_local = TRUE; if (!self->super.bind_addr) self->super.bind_addr = g_sockaddr_unix_new(NULL); return self; } static gboolean should_use_systemd_syslog_instead_of_unix_socket(gchar *filename) { return (service_management_get_type() == SMT_SYSTEMD && (strncmp("/dev/log", filename, 9) == 0 || strncmp("/run/systemd/journal/syslog", filename, 28) == 0))? TRUE : FALSE; } typedef enum _SocketType { ST_DGRAM, ST_STREAM } SocketType; AFSocketSourceDriver * create_afunix_sd(gchar *filename, GlobalConfig *cfg, SocketType socket_type) { AFUnixSourceDriver *ud = NULL; if (socket_type == ST_DGRAM) { ud = afunix_sd_new_dgram(filename, cfg); } else if (socket_type == ST_STREAM) { ud = afunix_sd_new_stream(filename, cfg); } afunix_grammar_set_source_driver(ud); return &ud->super; } static AFSocketSourceDriver * create_and_set_unix_socket_or_systemd_syslog_source(gchar *filename, GlobalConfig *cfg, SocketType socket_type) { SystemDSyslogSourceDriver *sd; if (should_use_systemd_syslog_instead_of_unix_socket(filename)) { msg_warning("Using /dev/log Unix socket with systemd is not" " possible. Changing to systemd-syslog source, which supports" " socket activation."); sd = systemd_syslog_sd_new(configuration, TRUE); systemd_syslog_grammar_set_source_driver(sd); return &sd->super; } else return create_afunix_sd(filename, cfg, socket_type); } AFSocketSourceDriver * create_and_set_unix_dgram_or_systemd_syslog_source(gchar *filename, GlobalConfig *cfg) { return create_and_set_unix_socket_or_systemd_syslog_source(filename, cfg, ST_DGRAM); } AFSocketSourceDriver * create_and_set_unix_stream_or_systemd_syslog_source(gchar *filename, GlobalConfig *cfg) { return create_and_set_unix_socket_or_systemd_syslog_source(filename, cfg, ST_STREAM); } syslog-ng-syslog-ng-3.13.2/modules/afsocket/systemd-syslog-source.h000066400000000000000000000030751321171025300253660ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * Copyright (c) 2013-2014 Tibor Benke * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef SYSTEMD_SYSLOG_SOURCE_H_INCLUDED #define SYSTEMD_SYSLOG_SOURCE_H_INCLUDED 1 #include "afsocket-source.h" #include "transport-mapper-unix.h" typedef struct _SystemDSyslogSourceDriver { AFSocketSourceDriver super; gboolean from_unix_source; } SystemDSyslogSourceDriver; SystemDSyslogSourceDriver *systemd_syslog_sd_new(GlobalConfig *cfg, gboolean fallback); AFSocketSourceDriver *create_and_set_unix_dgram_or_systemd_syslog_source(gchar *filename, GlobalConfig *cfg); AFSocketSourceDriver *create_and_set_unix_stream_or_systemd_syslog_source(gchar *filename, GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/tests/000077500000000000000000000000001321171025300220465ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afsocket/tests/Makefile.am000066400000000000000000000034501321171025300241040ustar00rootroot00000000000000TEST_TRANSPORT_MAPPER_CFLAGS = $(TEST_CFLAGS) TRANSPORT_MAPPER_LIB = \ modules/afsocket/tests/transport-mapper-lib.c \ modules/afsocket/tests/transport-mapper-lib.h modules_afsocket_tests_TESTS = \ modules/afsocket/tests/test-transport-mapper \ modules/afsocket/tests/test-transport-mapper-inet \ modules/afsocket/tests/test-transport-mapper-unix check_PROGRAMS += \ $(modules_afsocket_tests_TESTS) modules_afsocket_tests_test_transport_mapper_CFLAGS = \ $(TEST_TRANSPORT_MAPPER_CFLAGS) \ -I$(top_srcdir)/modules/afsocket modules_afsocket_tests_test_transport_mapper_LDADD = \ $(TEST_LDADD) modules_afsocket_tests_test_transport_mapper_LDFLAGS = \ -dlpreopen $(top_builddir)/modules/afsocket/libafsocket.la modules_afsocket_tests_test_transport_mapper_SOURCES = \ modules/afsocket/tests/test-transport-mapper.c \ $(TRANSPORT_MAPPER_LIB) modules_afsocket_tests_test_transport_mapper_inet_CFLAGS = \ $(TEST_TRANSPORT_MAPPER_CFLAGS) \ -I$(top_srcdir)/modules/afsocket modules_afsocket_tests_test_transport_mapper_inet_LDADD = \ $(TEST_LDADD) modules_afsocket_tests_test_transport_mapper_inet_LDFLAGS = \ -dlpreopen $(top_builddir)/modules/afsocket/libafsocket.la modules_afsocket_tests_test_transport_mapper_inet_SOURCES = \ modules/afsocket/tests/test-transport-mapper-inet.c \ $(TRANSPORT_MAPPER_LIB) modules_afsocket_tests_test_transport_mapper_unix_CFLAGS = \ $(TEST_TRANSPORT_MAPPER_CFLAGS) \ -I$(top_srcdir)/modules/afsocket modules_afsocket_tests_test_transport_mapper_unix_LDADD = \ $(TEST_LDADD) modules_afsocket_tests_test_transport_mapper_unix_LDFLAGS = \ -dlpreopen $(top_builddir)/modules/afsocket/libafsocket.la modules_afsocket_tests_test_transport_mapper_unix_SOURCES = \ modules/afsocket/tests/test-transport-mapper-unix.c \ $(TRANSPORT_MAPPER_LIB) syslog-ng-syslog-ng-3.13.2/modules/afsocket/tests/test-transport-mapper-inet.c000066400000000000000000000335261321171025300274530ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afinet.h" #include "afsocket.h" #include "stats/stats-registry.h" #include "apphook.h" #include "transport-mapper-inet.h" #include "socket-options-inet.h" #include "transport-mapper-lib.h" #include TransportMapper *transport_mapper; #define transport_mapper_inet_testcase_begin(init_name, func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ transport_mapper = transport_mapper_ ## init_name ## _new(); \ } \ while (0) #define transport_mapper_inet_testcase_end() \ do \ { \ transport_mapper_free(transport_mapper); \ testcase_end(); \ } \ while (0) static inline void assert_transport_mapper_inet_server_port(TransportMapper *s, gint server_port) { assert_gint(transport_mapper_inet_get_server_port(s), server_port, "TransportMapper server_port mismatch"); } static void assert_transport_mapper_tcp_socket(TransportMapper *self) { assert_transport_mapper_address_family(self, AF_INET); assert_transport_mapper_sock_type(self, SOCK_STREAM); assert_transport_mapper_sock_proto(self, IPPROTO_TCP); } static void assert_transport_mapper_tcp6_socket(TransportMapper *self) { assert_transport_mapper_address_family(self, AF_INET6); assert_transport_mapper_sock_type(self, SOCK_STREAM); assert_transport_mapper_sock_proto(self, IPPROTO_TCP); } static void assert_transport_mapper_udp_socket(TransportMapper *self) { assert_transport_mapper_address_family(self, AF_INET); assert_transport_mapper_sock_type(self, SOCK_DGRAM); assert_transport_mapper_sock_proto(self, IPPROTO_UDP); } static void assert_transport_mapper_udp6_socket(TransportMapper *self) { assert_transport_mapper_address_family(self, AF_INET6); assert_transport_mapper_sock_type(self, SOCK_DGRAM); assert_transport_mapper_sock_proto(self, IPPROTO_UDP); } static gboolean create_socket_with_address(GSockAddr *addr, gint *sock) { SocketOptionsInet *sock_options; gboolean result; sock_options = socket_options_inet_new_instance(); result = transport_mapper_open_socket(transport_mapper, &sock_options->super, addr, AFSOCKET_DIR_RECV, sock); socket_options_free(&sock_options->super); return result; } static gboolean create_socket(gint *sock) { GSockAddr *addr = g_sockaddr_inet_new("127.0.0.1", 0); gboolean success; success = create_socket_with_address(addr, sock); g_sockaddr_unref(addr); return success; } static void assert_create_socket_fails_with_address(GSockAddr *addr) { gint sock; assert_false(create_socket_with_address(addr, &sock), "transport_mapper_open_socket() suceeded unexpectedly"); assert_gint(sock, -1, "failed create_socket returned a non-extremal value on failure"); } static void assert_create_socket_fails(void) { gint sock; assert_false(create_socket(&sock), "transport_mapper_open_socket() suceeded unexpectedly"); assert_gint(sock, -1, "failed create_socket returned a non-extremal value on failure"); } static void assert_create_socket_succeeds(void) { gint sock; assert_true(create_socket(&sock), "transport_mapper_open_socket() failed unexpectedly"); close(sock); } static TLSContext * create_dummy_tls_context(void) { TLSContext *tls_context; tls_context = tls_context_new(TM_SERVER); return tls_context; } /****************************************************************************** * Tests start here ******************************************************************************/ static void test_tcp_apply_transport_sets_defaults(void) { assert_transport_mapper_apply(transport_mapper, NULL); assert_transport_mapper_tcp_socket(transport_mapper); assert_transport_mapper_transport(transport_mapper, "tcp"); assert_transport_mapper_logproto(transport_mapper, "text"); assert_transport_mapper_stats_source(transport_mapper, SCS_TCP); assert_transport_mapper_inet_server_port(transport_mapper, 514); } static void test_tcp6_apply_transport_sets_defaults(void) { assert_transport_mapper_apply(transport_mapper, NULL); assert_transport_mapper_tcp6_socket(transport_mapper); assert_transport_mapper_transport(transport_mapper, "tcp"); assert_transport_mapper_logproto(transport_mapper, "text"); assert_transport_mapper_stats_source(transport_mapper, SCS_TCP6); assert_transport_mapper_inet_server_port(transport_mapper, 514); } static void test_udp_apply_transport_sets_defaults(void) { assert_transport_mapper_apply(transport_mapper, NULL); assert_transport_mapper_udp_socket(transport_mapper); assert_transport_mapper_transport(transport_mapper, "udp"); assert_transport_mapper_logproto(transport_mapper, "dgram"); assert_transport_mapper_stats_source(transport_mapper, SCS_UDP); assert_transport_mapper_inet_server_port(transport_mapper, 514); } static void test_udp_apply_fails_when_tls_context_is_set(void) { transport_mapper_inet_set_tls_context((TransportMapperInet *) transport_mapper, create_dummy_tls_context(), NULL, NULL); assert_transport_mapper_apply_fails(transport_mapper, "udp"); } static void test_udp6_apply_transport_sets_defaults(void) { assert_transport_mapper_apply(transport_mapper, NULL); assert_transport_mapper_udp6_socket(transport_mapper); assert_transport_mapper_transport(transport_mapper, "udp"); assert_transport_mapper_logproto(transport_mapper, "dgram"); assert_transport_mapper_stats_source(transport_mapper, SCS_UDP6); assert_transport_mapper_inet_server_port(transport_mapper, 514); } static void test_network_transport_udp_apply_transport_sets_defaults(void) { assert_transport_mapper_apply(transport_mapper, "udp"); assert_transport_mapper_udp_socket(transport_mapper); assert_transport_mapper_transport(transport_mapper, "udp"); assert_transport_mapper_logproto(transport_mapper, "dgram"); assert_transport_mapper_stats_source(transport_mapper, SCS_NETWORK); assert_transport_mapper_inet_server_port(transport_mapper, 514); } static void test_network_transport_udp_apply_fails_when_tls_context_is_set(void) { transport_mapper_inet_set_tls_context((TransportMapperInet *) transport_mapper, create_dummy_tls_context(), NULL, NULL); assert_transport_mapper_apply_fails(transport_mapper, "udp"); } static void test_network_transport_tcp_apply_transport_sets_defaults(void) { assert_transport_mapper_apply(transport_mapper, "tcp"); assert_transport_mapper_tcp_socket(transport_mapper); assert_transport_mapper_transport(transport_mapper, "tcp"); assert_transport_mapper_logproto(transport_mapper, "text"); assert_transport_mapper_stats_source(transport_mapper, SCS_NETWORK); assert_transport_mapper_inet_server_port(transport_mapper, 514); } static void test_network_transport_tls_apply_fails_without_tls_context(void) { assert_transport_mapper_apply_fails(transport_mapper, "tls"); } static void test_network_transport_tls_apply_transport_sets_defaults(void) { transport_mapper_inet_set_tls_context((TransportMapperInet *) transport_mapper, create_dummy_tls_context(), NULL, NULL); assert_transport_mapper_apply(transport_mapper, "tls"); assert_transport_mapper_tcp_socket(transport_mapper); assert_transport_mapper_transport(transport_mapper, "tls"); assert_transport_mapper_logproto(transport_mapper, "text"); assert_transport_mapper_stats_source(transport_mapper, SCS_NETWORK); assert_transport_mapper_inet_server_port(transport_mapper, 514); } static void test_network_transport_foo_apply_transport_sets_defaults(void) { assert_transport_mapper_apply(transport_mapper, "foo"); assert_transport_mapper_tcp_socket(transport_mapper); assert_transport_mapper_transport(transport_mapper, "foo"); assert_transport_mapper_logproto(transport_mapper, "foo"); assert_transport_mapper_stats_source(transport_mapper, SCS_NETWORK); assert_transport_mapper_inet_server_port(transport_mapper, 514); } static void test_syslog_transport_udp_apply_transport_sets_defaults(void) { assert_transport_mapper_apply(transport_mapper, "udp"); assert_transport_mapper_udp_socket(transport_mapper); assert_transport_mapper_transport(transport_mapper, "udp"); assert_transport_mapper_logproto(transport_mapper, "dgram"); assert_transport_mapper_stats_source(transport_mapper, SCS_SYSLOG); assert_transport_mapper_inet_server_port(transport_mapper, 514); } static void test_syslog_transport_udp_apply_fails_when_tls_context_is_set(void) { transport_mapper_inet_set_tls_context((TransportMapperInet *) transport_mapper, create_dummy_tls_context(), NULL, NULL); assert_transport_mapper_apply_fails(transport_mapper, "udp"); } static void test_syslog_transport_tcp_apply_transport_sets_defaults(void) { assert_transport_mapper_apply(transport_mapper, "tcp"); assert_transport_mapper_tcp_socket(transport_mapper); assert_transport_mapper_transport(transport_mapper, "tcp"); assert_transport_mapper_logproto(transport_mapper, "framed"); assert_transport_mapper_stats_source(transport_mapper, SCS_SYSLOG); assert_transport_mapper_inet_server_port(transport_mapper, 601); } static void test_syslog_transport_tls_apply_fails_without_tls_context(void) { assert_transport_mapper_apply_fails(transport_mapper, "tls"); } static void test_syslog_transport_tls_apply_transport_sets_defaults(void) { transport_mapper_inet_set_tls_context((TransportMapperInet *) transport_mapper, create_dummy_tls_context(), NULL, NULL); assert_transport_mapper_apply(transport_mapper, "tls"); assert_transport_mapper_tcp_socket(transport_mapper); assert_transport_mapper_transport(transport_mapper, "tls"); assert_transport_mapper_logproto(transport_mapper, "framed"); assert_transport_mapper_stats_source(transport_mapper, SCS_SYSLOG); assert_transport_mapper_inet_server_port(transport_mapper, 6514); } static void test_syslog_transport_foo_apply_transport_sets_defaults(void) { assert_transport_mapper_apply(transport_mapper, "foo"); assert_transport_mapper_tcp_socket(transport_mapper); assert_transport_mapper_transport(transport_mapper, "foo"); assert_transport_mapper_logproto(transport_mapper, "foo"); assert_transport_mapper_stats_source(transport_mapper, SCS_SYSLOG); assert_transport_mapper_inet_server_port(transport_mapper, 514); } static void test_open_socket_opens_a_socket_and_applies_socket_options(void) { assert_create_socket_succeeds(); } static void test_open_socket_fails_properly_on_socket_failure(void) { transport_mapper_set_address_family(transport_mapper, 0xdeadbeef); assert_create_socket_fails(); } static void test_open_socket_fails_properly_on_bind_failure(void) { GSockAddr *addr = g_sockaddr_unix_new("/foo/bar/no/such/dir"); transport_mapper_set_address_family(transport_mapper, AF_UNIX); assert_create_socket_fails_with_address(addr); g_sockaddr_unref(addr); } static void test_transport_mapper_inet(void) { TRANSPORT_MAPPER_TESTCASE(tcp, test_tcp_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(tcp6, test_tcp6_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(udp, test_udp_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(udp, test_udp_apply_fails_when_tls_context_is_set); TRANSPORT_MAPPER_TESTCASE(udp6, test_udp6_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(network, test_network_transport_udp_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(network, test_network_transport_udp_apply_fails_when_tls_context_is_set); TRANSPORT_MAPPER_TESTCASE(network, test_network_transport_tcp_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(network, test_network_transport_tls_apply_fails_without_tls_context); TRANSPORT_MAPPER_TESTCASE(network, test_network_transport_tls_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(network, test_network_transport_foo_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(syslog, test_syslog_transport_udp_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(syslog, test_syslog_transport_udp_apply_fails_when_tls_context_is_set); TRANSPORT_MAPPER_TESTCASE(syslog, test_syslog_transport_tcp_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(syslog, test_syslog_transport_tls_apply_fails_without_tls_context); TRANSPORT_MAPPER_TESTCASE(syslog, test_syslog_transport_tls_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(syslog, test_syslog_transport_foo_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(tcp, test_open_socket_opens_a_socket_and_applies_socket_options); TRANSPORT_MAPPER_TESTCASE(tcp, test_open_socket_fails_properly_on_socket_failure); TRANSPORT_MAPPER_TESTCASE(tcp, test_open_socket_fails_properly_on_bind_failure); } int main(int argc, char *argv[]) { app_startup(); test_transport_mapper_inet(); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/modules/afsocket/tests/test-transport-mapper-unix.c000066400000000000000000000047651321171025300275020ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "transport-mapper-unix.h" #include "apphook.h" #include "stats/stats-registry.h" #include "transport-mapper-lib.h" static void test_transport_mapper_unix_stream_apply_transport_sets_defaults(void) { assert_transport_mapper_apply(transport_mapper, NULL); assert_transport_mapper_transport(transport_mapper, "unix-stream"); assert_transport_mapper_address_family(transport_mapper, AF_UNIX); assert_transport_mapper_sock_type(transport_mapper, SOCK_STREAM); assert_transport_mapper_sock_proto(transport_mapper, 0); assert_transport_mapper_logproto(transport_mapper, "text"); assert_transport_mapper_stats_source(transport_mapper, SCS_UNIX_STREAM); } static void test_transport_mapper_unix_dgram_apply_transport_sets_defaults(void) { assert_transport_mapper_apply(transport_mapper, NULL); assert_transport_mapper_transport(transport_mapper, "unix-dgram"); assert_transport_mapper_address_family(transport_mapper, AF_UNIX); assert_transport_mapper_sock_type(transport_mapper, SOCK_DGRAM); assert_transport_mapper_sock_proto(transport_mapper, 0); assert_transport_mapper_logproto(transport_mapper, "dgram"); assert_transport_mapper_stats_source(transport_mapper, SCS_UNIX_DGRAM); } static void test_transport_mapper_unix(void) { TRANSPORT_MAPPER_TESTCASE(unix_stream, test_transport_mapper_unix_stream_apply_transport_sets_defaults); TRANSPORT_MAPPER_TESTCASE(unix_dgram, test_transport_mapper_unix_dgram_apply_transport_sets_defaults); } int main(int argc, char *argv[]) { app_startup(); test_transport_mapper_unix(); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/modules/afsocket/tests/test-transport-mapper.c000066400000000000000000000043461321171025300265140ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afsocket.h" #include "transport-mapper.h" #include "transport-mapper-lib.h" #include "apphook.h" TransportMapper * transport_mapper_dummy_new(void) { TransportMapper *self = g_new0(TransportMapper, 1); transport_mapper_init_instance(self, "dummy"); return self; } static void test_set_transport_stores_value(void) { transport_mapper_set_transport(transport_mapper, "foobar"); assert_transport_mapper_transport(transport_mapper, "foobar"); } static void test_set_address_value_stores_value(void) { transport_mapper_set_address_family(transport_mapper, AF_UNIX); assert_transport_mapper_address_family(transport_mapper, AF_UNIX); transport_mapper_set_address_family(transport_mapper, AF_INET); assert_transport_mapper_address_family(transport_mapper, AF_INET); } static void test_apply_transport_returns_success(void) { assert_transport_mapper_apply(transport_mapper, "transport_mapper_apply_transport() failed"); } static void test_transport_mapper(void) { TRANSPORT_MAPPER_TESTCASE(dummy, test_set_transport_stores_value); TRANSPORT_MAPPER_TESTCASE(dummy, test_set_address_value_stores_value); TRANSPORT_MAPPER_TESTCASE(dummy, test_apply_transport_returns_success); } int main(int argc, char *argv[]) { app_startup(); test_transport_mapper(); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/modules/afsocket/tests/transport-mapper-lib.c000066400000000000000000000017671321171025300263070ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "transport-mapper-lib.h" TransportMapper *transport_mapper; syslog-ng-syslog-ng-3.13.2/modules/afsocket/tests/transport-mapper-lib.h000066400000000000000000000101161321171025300263000ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSOCKET_OPTIONS_LIB_H_INCLUDED #define AFSOCKET_OPTIONS_LIB_H_INCLUDED #include "transport-mapper.h" #include "testutils.h" extern TransportMapper *transport_mapper; #define transport_mapper_testcase_begin(init_name, func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ transport_mapper = transport_mapper_ ## init_name ## _new(); \ } \ while (0) #define transport_mapper_testcase_end() \ do \ { \ transport_mapper_free(transport_mapper); \ testcase_end(); \ } \ while (0) #define TRANSPORT_MAPPER_TESTCASE(init_name, x, ...) \ do { \ transport_mapper_testcase_begin(init_name, #x, #__VA_ARGS__); \ x(__VA_ARGS__); \ transport_mapper_testcase_end(); \ } while(0) static inline void assert_transport_mapper_apply(TransportMapper *self, const gchar *transport) { if (transport) transport_mapper_set_transport(self, transport); assert_true(transport_mapper_apply_transport(self, configuration), "afsocket_apply_transport() failed"); } static inline void assert_transport_mapper_apply_fails(TransportMapper *self, const gchar *transport) { if (transport) transport_mapper_set_transport(self, transport); assert_false(transport_mapper_apply_transport(self, configuration), "afsocket_apply_transport() succeeded while we expected failure"); } static inline void assert_transport_mapper_transport(TransportMapper *options, const gchar *expected_transport) { assert_string(options->transport, expected_transport, "TransportMapper contains a mismatching transport name"); } static inline void assert_transport_mapper_logproto(TransportMapper *options, const gchar *expected_logproto) { assert_string(options->logproto, expected_logproto, "TransportMapper contains a mismatching log_proto name"); } static inline void assert_transport_mapper_stats_source(TransportMapper *options, gint stats_source) { assert_gint(options->stats_source, stats_source, "TransportMapper contains a mismatching stats_source"); } static inline void assert_transport_mapper_address_family(TransportMapper *options, gint address_family) { assert_gint(options->address_family, address_family, "TransportMapper address family mismatch"); } static inline void assert_transport_mapper_sock_type(TransportMapper *options, gint sock_type) { assert_gint(options->sock_type, sock_type, "TransportMapper sock_type mismatch"); } static inline void assert_transport_mapper_sock_proto(TransportMapper *options, gint sock_proto) { assert_gint(options->sock_proto, sock_proto, "TransportMapper sock_proto mismatch"); } #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/transport-mapper-inet.c000066400000000000000000000224711321171025300253310ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "transport-mapper-inet.h" #include "afinet.h" #include "cfg.h" #include "messages.h" #include "stats/stats-registry.h" #include "transport/transport-tls.h" #include #include #include #include #include #define UDP_PORT 514 #define TCP_PORT 514 #define NETWORK_PORT 514 #define SYSLOG_TRANSPORT_UDP_PORT 514 #define SYSLOG_TRANSPORT_TCP_PORT 601 #define SYSLOG_TRANSPORT_TLS_PORT 6514 static inline gboolean _is_tls_required(TransportMapperInet *self) { return self->require_tls; } static inline gboolean _is_tls_allowed(TransportMapperInet *self) { return self->require_tls || self->allow_tls; } static gboolean transport_mapper_inet_validate_tls_options(TransportMapperInet *self) { if (!self->tls_context && _is_tls_required(self)) { msg_error("transport(tls) was specified, but tls() options missing"); // evt_tag_str("id", self->super.super.super.id), return FALSE; } else if (self->tls_context && !_is_tls_allowed(self)) { msg_error("tls() options specified for a transport that doesn't allow TLS encryption", //evt_tag_str("id", self->super.super.super.id), evt_tag_str("transport", self->super.transport)); return FALSE; } return TRUE; } static gboolean transport_mapper_inet_apply_transport_method(TransportMapper *s, GlobalConfig *cfg) { TransportMapperInet *self = (TransportMapperInet *) s; if (!transport_mapper_apply_transport_method(s, cfg)) return FALSE; return transport_mapper_inet_validate_tls_options(self); } static LogTransport * transport_mapper_inet_construct_log_transport(TransportMapper *s, gint fd) { TransportMapperInet *self = (TransportMapperInet *) s; if (self->tls_context) { TLSSession *tls_session; tls_session = tls_context_setup_session(self->tls_context); if (!tls_session) return NULL; tls_session_set_verify(tls_session, self->tls_verify_callback, self->tls_verify_data, NULL); return log_transport_tls_new(tls_session, fd); } else return transport_mapper_construct_log_transport_method(s, fd); } static gboolean transport_mapper_inet_init(TransportMapper *s) { TransportMapperInet *self = (TransportMapperInet *) s; if (self->tls_context && !tls_context_setup_context(self->tls_context)) return FALSE; return TRUE; } void transport_mapper_inet_free_method(TransportMapper *s) { TransportMapperInet *self = (TransportMapperInet *) s; if (self->tls_context) tls_context_free(self->tls_context); transport_mapper_free_method(s); } void transport_mapper_inet_init_instance(TransportMapperInet *self, const gchar *transport) { transport_mapper_init_instance(&self->super, transport); self->super.apply_transport = transport_mapper_inet_apply_transport_method; self->super.construct_log_transport = transport_mapper_inet_construct_log_transport; self->super.init = transport_mapper_inet_init; self->super.free_fn = transport_mapper_inet_free_method; self->super.address_family = AF_INET; } TransportMapperInet * transport_mapper_inet_new_instance(const gchar *transport) { TransportMapperInet *self = g_new0(TransportMapperInet, 1); transport_mapper_inet_init_instance(self, transport); return self; } TransportMapper * transport_mapper_tcp_new(void) { TransportMapperInet *self = transport_mapper_inet_new_instance("tcp"); self->super.sock_type = SOCK_STREAM; self->super.sock_proto = IPPROTO_TCP; self->super.logproto = "text"; self->super.stats_source = SCS_TCP; self->server_port = TCP_PORT; self->allow_tls = TRUE; return &self->super; } TransportMapper * transport_mapper_tcp6_new(void) { TransportMapper *self = transport_mapper_tcp_new(); self->address_family = AF_INET6; self->stats_source = SCS_TCP6; return self; } TransportMapper * transport_mapper_udp_new(void) { TransportMapperInet *self = transport_mapper_inet_new_instance("udp"); self->super.sock_type = SOCK_DGRAM; self->super.sock_proto = IPPROTO_UDP; self->super.logproto = "dgram"; self->super.stats_source = SCS_UDP; self->server_port = UDP_PORT; return &self->super; } TransportMapper * transport_mapper_udp6_new(void) { TransportMapper *self = transport_mapper_udp_new(); self->address_family = AF_INET6; self->stats_source = SCS_UDP6; return self; } static gboolean transport_mapper_network_apply_transport(TransportMapper *s, GlobalConfig *cfg) { TransportMapperInet *self = (TransportMapperInet *) s; const gchar *transport; /* determine default port, apply transport setting to afsocket flags */ if (!transport_mapper_apply_transport_method(s, cfg)) return FALSE; transport = self->super.transport; self->server_port = NETWORK_PORT; if (strcasecmp(transport, "udp") == 0) { self->super.sock_type = SOCK_DGRAM; self->super.sock_proto = IPPROTO_UDP; self->super.logproto = "dgram"; } else if (strcasecmp(transport, "tcp") == 0) { self->super.logproto = "text"; self->super.sock_type = SOCK_STREAM; self->super.sock_proto = IPPROTO_TCP; } else if (strcasecmp(transport, "tls") == 0) { self->super.logproto = "text"; self->super.sock_type = SOCK_STREAM; self->super.sock_proto = IPPROTO_TCP; self->require_tls = TRUE; } else { self->super.logproto = self->super.transport; self->super.sock_type = SOCK_STREAM; self->super.sock_proto = IPPROTO_TCP; /* FIXME: look up port/protocol from the logproto */ self->server_port = TCP_PORT; self->allow_tls = TRUE; } g_assert(self->server_port != 0); if (!transport_mapper_inet_validate_tls_options(self)) return FALSE; return TRUE; } TransportMapper * transport_mapper_network_new(void) { TransportMapperInet *self = transport_mapper_inet_new_instance("tcp"); self->super.apply_transport = transport_mapper_network_apply_transport; self->super.stats_source = SCS_NETWORK; return &self->super; } static gboolean transport_mapper_syslog_apply_transport(TransportMapper *s, GlobalConfig *cfg) { TransportMapperInet *self = (TransportMapperInet *) s; const gchar *transport = self->super.transport; /* determine default port, apply transport setting to afsocket flags */ if (!transport_mapper_apply_transport_method(s, cfg)) return FALSE; if (strcasecmp(transport, "udp") == 0) { if (cfg_is_config_version_older(cfg, 0x0303)) { self->server_port_change_warning = "WARNING: Default port for syslog(transport(udp)) has changed from 601 to 514 in " VERSION_3_3 ", please update your configuration"; self->server_port = 601; } else self->server_port = SYSLOG_TRANSPORT_UDP_PORT; self->super.sock_type = SOCK_DGRAM; self->super.sock_proto = IPPROTO_UDP; self->super.logproto = "dgram"; } else if (strcasecmp(transport, "tcp") == 0) { self->server_port = SYSLOG_TRANSPORT_TCP_PORT; self->super.logproto = "framed"; self->super.sock_type = SOCK_STREAM; self->super.sock_proto = IPPROTO_TCP; } else if (strcasecmp(transport, "tls") == 0) { if (cfg_is_config_version_older(cfg, 0x0303)) { self->server_port_change_warning = "WARNING: Default port for syslog(transport(tls)) has changed from 601 to 6514 in " VERSION_3_3 ", please update your configuration"; self->server_port = 601; } else self->server_port = SYSLOG_TRANSPORT_TLS_PORT; self->super.logproto = "framed"; self->super.sock_type = SOCK_STREAM; self->super.sock_proto = IPPROTO_TCP; self->require_tls = TRUE; } else { self->super.logproto = self->super.transport; self->super.sock_type = SOCK_STREAM; /* FIXME: look up port/protocol from the logproto */ self->server_port = 514; self->super.sock_proto = IPPROTO_TCP; self->allow_tls = TRUE; } g_assert(self->server_port != 0); if (!transport_mapper_inet_validate_tls_options(self)) return FALSE; return TRUE; } TransportMapper * transport_mapper_syslog_new(void) { TransportMapperInet *self = transport_mapper_inet_new_instance("tcp"); self->super.apply_transport = transport_mapper_syslog_apply_transport; self->super.stats_source = SCS_SYSLOG; return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/afsocket/transport-mapper-inet.h000066400000000000000000000046131321171025300253340ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TRANSPORT_MAPPER_INET_H_INCLUDED #define TRANSPORT_MAPPER_INET_H_INCLUDED #include "transport-mapper.h" #include "tlscontext.h" typedef struct _TransportMapperInet { TransportMapper super; gint server_port; const gchar *server_port_change_warning; gboolean require_tls; gboolean allow_tls; TLSContext *tls_context; TLSSessionVerifyFunc tls_verify_callback; gpointer tls_verify_data; } TransportMapperInet; static inline gint transport_mapper_inet_get_server_port(TransportMapper *self) { return ((TransportMapperInet *) self)->server_port; } static inline const gchar * transport_mapper_inet_get_port_change_warning(TransportMapper *s) { TransportMapperInet *self = (TransportMapperInet *) s; return self->server_port_change_warning; } static inline void transport_mapper_inet_set_tls_context(TransportMapperInet *self, TLSContext *tls_context, TLSSessionVerifyFunc tls_verify_callback, gpointer tls_verify_data) { self->tls_context = tls_context; self->tls_verify_callback = tls_verify_callback; self->tls_verify_data = tls_verify_data; } void transport_mapper_inet_init_instance(TransportMapperInet *self, const gchar *transport); TransportMapper *transport_mapper_tcp_new(void); TransportMapper *transport_mapper_tcp6_new(void); TransportMapper *transport_mapper_udp_new(void); TransportMapper *transport_mapper_udp6_new(void); TransportMapper *transport_mapper_network_new(void); TransportMapper *transport_mapper_syslog_new(void); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/transport-mapper-unix.c000066400000000000000000000054761321171025300253630ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "transport-mapper-unix.h" #include "transport-unix-socket.h" #include "unix-credentials.h" #include "stats/stats-registry.h" #include #include #include struct _TransportMapperUnix { TransportMapper super; gchar *filename; gboolean pass_unix_credentials; }; static LogTransport * _create_log_transport(TransportMapper *s, gint fd) { if (s->sock_type == SOCK_DGRAM) return log_transport_unix_dgram_socket_new(fd); else return log_transport_unix_stream_socket_new(fd); } static LogTransport * _construct_log_transport(TransportMapper *s, gint fd) { TransportMapperUnix *self = (TransportMapperUnix *) s; LogTransport *transport = _create_log_transport(s, fd); if (self->pass_unix_credentials) socket_set_pass_credentials(fd); return transport; } static TransportMapperUnix * transport_mapper_unix_new_instance(const gchar *transport, gint sock_type) { TransportMapperUnix *self = g_new0(TransportMapperUnix, 1); transport_mapper_init_instance(&self->super, transport); self->super.construct_log_transport = _construct_log_transport; self->super.address_family = AF_UNIX; self->super.sock_type = sock_type; return self; } void transport_mapper_unix_set_pass_unix_credentials(TransportMapper *s, gboolean pass) { TransportMapperUnix *self = (TransportMapperUnix *) s; self->pass_unix_credentials = pass; } TransportMapper * transport_mapper_unix_dgram_new(void) { TransportMapperUnix *self = transport_mapper_unix_new_instance("unix-dgram", SOCK_DGRAM); self->super.logproto = "dgram"; self->super.stats_source = SCS_UNIX_DGRAM; return &self->super; } TransportMapper * transport_mapper_unix_stream_new(void) { TransportMapperUnix *self = transport_mapper_unix_new_instance("unix-stream", SOCK_STREAM); self->super.logproto = "text"; self->super.stats_source = SCS_UNIX_STREAM; return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/afsocket/transport-mapper-unix.h000066400000000000000000000024741321171025300253630ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TRANSPORT_MAPPER_UNIX_H_INCLUDED #define TRANSPORT_MAPPER_UNIX_H_INCLUDED #include "transport-mapper.h" typedef struct _TransportMapperUnix TransportMapperUnix; TransportMapper *transport_mapper_unix_dgram_new(void); TransportMapper *transport_mapper_unix_stream_new(void); void transport_mapper_unix_set_pass_unix_credentials(TransportMapper *self, gboolean pass); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/transport-mapper.c000066400000000000000000000074041321171025300243730ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "transport-mapper.h" #include "gprocess.h" #include "gsockaddr.h" #include "gsocket.h" #include "messages.h" #include "fdhelpers.h" #include "transport/transport-socket.h" #include #include static gboolean transport_mapper_privileged_bind(gint sock, GSockAddr *bind_addr) { cap_t saved_caps; GIOStatus status; saved_caps = g_process_cap_save(); g_process_cap_modify(CAP_NET_BIND_SERVICE, TRUE); g_process_cap_modify(CAP_DAC_OVERRIDE, TRUE); status = g_bind(sock, bind_addr); g_process_cap_restore(saved_caps); return status == G_IO_STATUS_NORMAL; } gboolean transport_mapper_open_socket(TransportMapper *self, SocketOptions *socket_options, GSockAddr *bind_addr, AFSocketDirection dir, int *fd) { gint sock; sock = socket(self->address_family, self->sock_type, self->sock_proto); if (sock < 0) { msg_error("Error creating socket", evt_tag_errno(EVT_TAG_OSERROR, errno)); goto error; } g_fd_set_nonblock(sock, TRUE); g_fd_set_cloexec(sock, TRUE); if (!socket_options_setup_socket(socket_options, sock, bind_addr, dir)) goto error_close; if (!transport_mapper_privileged_bind(sock, bind_addr)) { gchar buf[256]; msg_error("Error binding socket", evt_tag_str("addr", g_sockaddr_format(bind_addr, buf, sizeof(buf), GSA_FULL)), evt_tag_errno(EVT_TAG_OSERROR, errno)); goto error_close; } *fd = sock; return TRUE; error_close: close(sock); error: *fd = -1; return FALSE; } gboolean transport_mapper_apply_transport_method(TransportMapper *self, GlobalConfig *cfg) { return TRUE; } LogTransport * transport_mapper_construct_log_transport_method(TransportMapper *self, gint fd) { if (self->sock_type == SOCK_DGRAM) return log_transport_dgram_socket_new(fd); else return log_transport_stream_socket_new(fd); } void transport_mapper_set_transport(TransportMapper *self, const gchar *transport) { g_free(self->transport); self->transport = g_strdup(transport); } void transport_mapper_set_address_family(TransportMapper *self, gint address_family) { self->address_family = address_family; } void transport_mapper_free_method(TransportMapper *self) { g_free(self->transport); } void transport_mapper_init_instance(TransportMapper *self, const gchar *transport) { self->transport = g_strdup(transport); self->address_family = -1; self->sock_type = -1; self->free_fn = transport_mapper_free_method; self->apply_transport = transport_mapper_apply_transport_method; self->construct_log_transport = transport_mapper_construct_log_transport_method; } void transport_mapper_free(TransportMapper *self) { if (self->free_fn) self->free_fn(self); g_free(self); } syslog-ng-syslog-ng-3.13.2/modules/afsocket/transport-mapper.h000066400000000000000000000061331321171025300243760ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TRANSPORT_MAPPER_H_INCLUDED #define TRANSPORT_MAPPER_H_INCLUDED #include "socket-options.h" #include "transport/logtransport.h" #include "gsockaddr.h" typedef struct _TransportMapper TransportMapper; struct _TransportMapper { /* the transport() option as specified by the user */ gchar *transport; /* output parameters as determinted by TransportMapper */ gint address_family; /* SOCK_DGRAM or SOCK_STREAM or other SOCK_XXX values used by the socket() call */ gint sock_type; /* protocol parameter for the socket() call, 0 for default or IPPROTO_XXX for specific transports */ gint sock_proto; const gchar *logproto; gint stats_source; gboolean (*apply_transport)(TransportMapper *self, GlobalConfig *cfg); LogTransport *(*construct_log_transport)(TransportMapper *self, gint fd); gboolean (*init)(TransportMapper *self); void (*free_fn)(TransportMapper *self); }; void transport_mapper_set_transport(TransportMapper *self, const gchar *transport); void transport_mapper_set_address_family(TransportMapper *self, gint address_family); gboolean transport_mapper_open_socket(TransportMapper *self, SocketOptions *socket_options, GSockAddr *bind_addr, AFSocketDirection dir, int *fd); gboolean transport_mapper_apply_transport_method(TransportMapper *self, GlobalConfig *cfg); LogTransport *transport_mapper_construct_log_transport_method(TransportMapper *self, gint fd); void transport_mapper_init_instance(TransportMapper *self, const gchar *transport); void transport_mapper_free(TransportMapper *self); void transport_mapper_free_method(TransportMapper *self); static inline gboolean transport_mapper_apply_transport(TransportMapper *self, GlobalConfig *cfg) { return self->apply_transport(self, cfg); } static inline LogTransport * transport_mapper_construct_log_transport(TransportMapper *self, gint fd) { return self->construct_log_transport(self, fd); } static inline gboolean transport_mapper_init(TransportMapper *self) { if (self->init) return self->init(self); return TRUE; } #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/transport-unix-socket.c000066400000000000000000000176611321171025300253660ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * Copyright (c) 2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "transport-unix-socket.h" #include "transport/transport-socket.h" #include "scratch-buffers.h" #include "str-format.h" #include "unix-credentials.h" #include #include #include #include #include #include static void _add_nv_pair_int(LogTransportAuxData *aux, const gchar *name, gint value) { ScratchBuffersMarker marker; GString *buf = scratch_buffers_alloc_and_mark(&marker); g_string_truncate(buf, 0); format_uint32_padded(buf, -1, 0, 10, value); log_transport_aux_data_add_nv_pair(aux, name, buf->str); scratch_buffers_reclaim_marked(marker); } static void _format_proc_file_name(gchar *buf, gsize buflen, pid_t pid, const gchar *proc_file) { g_snprintf(buf, buflen, "/proc/%d/%s", pid, proc_file); } static gssize _read_text_file_content(const gchar *filename, gchar *buf, gsize buflen) { gint fd; gssize rc; gssize pos = 0; fd = open(filename, O_RDONLY); if (fd < 0) return -1; rc = 1; /* this loop leaves the last character of buf untouched, thus -1 in the * condition and the number of bytes to be read */ while (rc > 0 && pos < buflen - 1) { gsize count = (buflen - 1) - pos; rc = read(fd, buf + pos, count); if (rc < 0) { close(fd); return -1; } pos += rc; } /* zero terminate the buffer */ buf[pos] = 0; close(fd); return pos; } static gssize _read_text_file_content_without_trailing_newline(const gchar *filename, gchar *buf, gsize buflen) { gssize content_len; content_len = _read_text_file_content(filename, buf, buflen); if (content_len <= 0) return content_len; if (buf[content_len - 1] == '\n') content_len--; buf[content_len] = 0; return content_len; } static void _add_nv_pair_proc_read_unless_unset(LogTransportAuxData *aux, const gchar *name, pid_t pid, const gchar *proc_file, const gchar *unset_value) { gchar filename[64]; gchar content[4096]; gssize content_len; _format_proc_file_name(filename, sizeof(filename), pid, proc_file); content_len = _read_text_file_content_without_trailing_newline(filename, content, sizeof(content)); if (content_len > 0 && (!unset_value || strcmp(content, unset_value) != 0)) log_transport_aux_data_add_nv_pair(aux, name, content); } static void _add_nv_pair_proc_read_argv(LogTransportAuxData *aux, const gchar *name, pid_t pid, const gchar *proc_file) { gchar filename[64]; gchar content[4096]; gssize content_len; gint i; _format_proc_file_name(filename, sizeof(filename), pid, proc_file); content_len = _read_text_file_content(filename, content, sizeof(content)); for (i = 0; i < content_len; i++) { if (!g_ascii_isprint(content[i])) content[i] = ' '; } if (content_len > 0) log_transport_aux_data_add_nv_pair(aux, name, content); } static void _add_nv_pair_proc_readlink(LogTransportAuxData *aux, const gchar *name, pid_t pid, const gchar *proc_file) { gchar filename[64]; gchar content[4096]; gssize content_len; _format_proc_file_name(filename, sizeof(filename), pid, proc_file); content_len = readlink(filename, content, sizeof(content)); if (content_len > 0) { if (content_len == sizeof(content)) content_len--; content[content_len] = 0; log_transport_aux_data_add_nv_pair(aux, name, content); } } #if defined (CRED_PASS_SUPPORTED) static void _feed_aux_from_ucred(LogTransportAuxData *aux, cred_t *uc) { _add_nv_pair_int(aux, ".unix.pid", cred_get(uc, pid)); _add_nv_pair_int(aux, ".unix.uid", cred_get(uc, uid)); _add_nv_pair_int(aux, ".unix.gid", cred_get(uc, gid)); } #endif #if defined(__linux__) && defined(CRED_PASS_SUPPORTED) static void _feed_aux_from_procfs(LogTransportAuxData *aux, pid_t pid) { _add_nv_pair_proc_read_argv(aux, ".unix.cmdline", pid, "cmdline"); _add_nv_pair_proc_readlink(aux, ".unix.exe", pid, "exe"); /* NOTE: we use the names the audit subsystem does, so if in the future we'd be * processing audit records, the nvpair names would match up. */ _add_nv_pair_proc_read_unless_unset(aux, ".audit.auid", pid, "loginuid", "4294967295"); _add_nv_pair_proc_read_unless_unset(aux, ".audit.ses", pid, "sessionid", "4294967295"); } #elif defined(__FreeBSD__) && defined(CRED_PASS_SUPPORTED) static void _feed_aux_from_procfs(LogTransportAuxData *aux, pid_t pid) { _add_nv_pair_proc_read_argv(aux, ".unix.cmdline", pid, "cmdline"); _add_nv_pair_proc_readlink(aux, ".unix.exe", pid, "file"); } #endif static void _feed_credentials_from_cmsg(LogTransportAuxData *aux, struct msghdr *msg) { #if defined(CRED_PASS_SUPPORTED) struct cmsghdr *cmsg; for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { cred_t *uc = (cred_t *) CMSG_DATA(cmsg); _feed_aux_from_procfs(aux, cred_get(uc, pid)); _feed_aux_from_ucred(aux, uc); break; } } #endif } static void _feed_aux_from_cmsg(LogTransportAuxData *aux, struct msghdr *msg) { _feed_credentials_from_cmsg(aux, msg); } static gssize _unix_socket_read(gint fd, gpointer buf, gsize buflen, LogTransportAuxData *aux) { gint rc; struct msghdr msg; struct iovec iov[1]; struct sockaddr_storage ss; #if defined(SYSLOG_NG_HAVE_CTRLBUF_IN_MSGHDR) gchar ctlbuf[32]; msg.msg_control = ctlbuf; msg.msg_controllen = sizeof(ctlbuf); #endif msg.msg_name = (struct sockaddr *) &ss; msg.msg_namelen = sizeof(ss); msg.msg_iovlen = 1; msg.msg_iov = iov; iov[0].iov_base = buf; iov[0].iov_len = buflen; do { rc = recvmsg(fd, &msg, 0); } while (rc == -1 && errno == EINTR); if (rc >= 0) { if (msg.msg_namelen && aux) log_transport_aux_data_set_peer_addr_ref(aux, g_sockaddr_new((struct sockaddr *) &ss, msg.msg_namelen)); _feed_aux_from_cmsg(aux, &msg); } return rc; } static gssize log_transport_unix_dgram_socket_read_method(LogTransport *s, gpointer buf, gsize buflen, LogTransportAuxData *aux) { gint rc; rc = _unix_socket_read(s->fd, buf, buflen, aux); if (rc == 0) { /* DGRAM sockets should never return EOF, they just need to be read again */ rc = -1; errno = EAGAIN; } return rc; } LogTransport * log_transport_unix_dgram_socket_new(gint fd) { LogTransportSocket *self = g_new0(LogTransportSocket, 1); log_transport_dgram_socket_init_instance(self, fd); self->super.read = log_transport_unix_dgram_socket_read_method; return &self->super; } static gssize log_transport_unix_stream_socket_read_method(LogTransport *s, gpointer buf, gsize buflen, LogTransportAuxData *aux) { return _unix_socket_read(s->fd, buf, buflen, aux); } LogTransport * log_transport_unix_stream_socket_new(gint fd) { LogTransportSocket *self = g_new0(LogTransportSocket, 1); log_transport_stream_socket_init_instance(self, fd); self->super.read = log_transport_unix_stream_socket_read_method; return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/afsocket/transport-unix-socket.h000066400000000000000000000023071321171025300253620ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSOCKET_TRANSPORT_UNIX_SOCKET_H_INCLUDED #define AFSOCKET_TRANSPORT_UNIX_SOCKET_H_INCLUDED #include "transport/logtransport.h" LogTransport *log_transport_unix_dgram_socket_new(gint fd); LogTransport *log_transport_unix_stream_socket_new(gint fd); #endif syslog-ng-syslog-ng-3.13.2/modules/afsocket/unix-credentials.c000066400000000000000000000024671321171025300243370ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "syslog-ng.h" #include "unix-credentials.h" void socket_set_pass_credentials(gint fd) { #if defined(CRED_PASS_SUPPORTED) #if defined(LOCAL_CREDS) || defined(SO_PASSCRED) static gint one = 1; #endif #ifdef LOCAL_CREDS setsockopt(fd, 0, LOCAL_CREDS, &one, sizeof(one)); #else #ifdef SO_PASSCRED setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); #endif #endif #endif } syslog-ng-syslog-ng-3.13.2/modules/afsocket/unix-credentials.h000066400000000000000000000030571321171025300243400ustar00rootroot00000000000000/* * Copyright (c) 2014 Balabit * Copyright (c) 2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef _SYSLOG_NG_UNIX_CREDENTIALS_H #define _SYSLOG_NG_UNIX_CREDENTIALS_H #include #include #include "syslog-ng.h" #if defined(__linux__) # if SYSLOG_NG_HAVE_STRUCT_UCRED && SYSLOG_NG_HAVE_CTRLBUF_IN_MSGHDR # define CRED_PASS_SUPPORTED # define cred_t struct ucred # define cred_get(c,x) (c->x) # endif #elif defined(__FreeBSD__) # if SYSLOG_NG_HAVE_STRUCT_CMSGCRED && SYSLOG_NG_HAVE_CTRLBUF_IN_MSGHDR # define CRED_PASS_SUPPORTED # define SCM_CREDENTIALS SCM_CREDS # define cred_t struct cmsgcred # define cred_get(c,x) (c->cmcred_##x) # endif #endif void socket_set_pass_credentials(gint fd); #endif syslog-ng-syslog-ng-3.13.2/modules/afsql/000077500000000000000000000000001321171025300202135ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afsql/CMakeLists.txt000066400000000000000000000020461321171025300227550ustar00rootroot00000000000000set(AFSQL_SOURCES afsql.c afsql.h afsql-parser.c afsql-parser.h afsql-plugin.c ${CMAKE_CURRENT_BINARY_DIR}/afsql-grammar.h ${CMAKE_CURRENT_BINARY_DIR}/afsql-grammar.c ) find_package(LibDBI) find_package(OpenSSL) if(LIBDBI_FOUND) option(ENABLE_SQL "Enable SQL plugin" ON) else() option(ENABLE_SQL "Enable SQL plugin" OFF) endif() if (ENABLE_SQL) generate_y_from_ym(modules/afsql/afsql-grammar) bison_target(SqlGrammar ${CMAKE_CURRENT_BINARY_DIR}/afsql-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/afsql-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) add_library(afsql MODULE ${AFSQL_SOURCES}) target_link_libraries (afsql PUBLIC ${LIBDBI_LIBRARIES} PUBLIC ${OPENSSL_LIBRARIES}) target_include_directories (afsql SYSTEM PRIVATE ${LIBDBI_INCLUDE_DIRS}) target_include_directories (afsql PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(afsql PRIVATE syslog-ng) install(TARGETS afsql LIBRARY DESTINATION lib/syslog-ng/ COMPONENT afsql) endif() syslog-ng-syslog-ng-3.13.2/modules/afsql/Makefile.am000066400000000000000000000017301321171025300222500ustar00rootroot00000000000000if ENABLE_SQL module_LTLIBRARIES += modules/afsql/libafsql.la modules_afsql_libafsql_la_SOURCES = \ modules/afsql/afsql.c \ modules/afsql/afsql.h \ modules/afsql/afsql-grammar.y \ modules/afsql/afsql-parser.c \ modules/afsql/afsql-parser.h \ modules/afsql/afsql-plugin.c modules_afsql_libafsql_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/afsql \ -I$(top_builddir)/modules/afsql modules_afsql_libafsql_la_LIBADD = \ $(MODULE_DEPS_LIBS) $(LIBDBI_LIBS) \ $(OPENSSL_LIBS) modules_afsql_libafsql_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_afsql_libafsql_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) modules/afsql modules/afsql/ mod-afsql mod-sql: \ modules/afsql/libafsql.la else modules/afsql modules/afsql/ mod-afsql mod-sql: endif BUILT_SOURCES += \ modules/afsql/afsql-grammar.y \ modules/afsql/afsql-grammar.c \ modules/afsql/afsql-grammar.h EXTRA_DIST += \ modules/afsql/afsql-grammar.ym .PHONY: modules/afsql/ mod-afsql mod-sql syslog-ng-syslog-ng-3.13.2/modules/afsql/afsql-grammar.ym000066400000000000000000000116251321171025300233210ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code top { #include "afsql-parser.h" } %code { #include "afsql.h" #include "cfg-grammar.h" #include "cfg-parser.h" #include "afsql-grammar.h" #include "messages.h" #include "plugin.h" } %name-prefix "afsql_" /* this parameter is needed in order to instruct bison to use a complete * argument list for yylex/yyerror */ %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogDriver **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_DEFAULT %token KW_DBD_OPTION %token KW_INDEXES %token KW_VALUES %token KW_SQL %token KW_PASSWORD %token KW_USERNAME %token KW_DATABASE %token KW_TABLE %token KW_SESSION_STATEMENTS %token KW_CREATE_STATEMENT_APPEND %token KW_COLUMNS %token KW_NULL %type dest_afsql %type dest_afsql_params %type dest_afsql_values %type dest_afsql_values_build %type dest_afsql_flags %% start : LL_CONTEXT_DESTINATION dest_afsql { YYACCEPT; } ; dest_afsql : KW_SQL '(' dest_afsql_params ')' { $$ = $3; } ; dest_afsql_params : { last_driver = *instance = afsql_dd_new(configuration); } dest_afsql_options { $$ = last_driver; } ; dest_afsql_options : dest_afsql_option dest_afsql_options | ; dest_afsql_option : KW_TYPE '(' string ')' { afsql_dd_set_type(last_driver, $3); free($3); } | KW_HOST '(' string ')' { afsql_dd_set_host(last_driver, $3); free($3); } | KW_PORT '(' string_or_number ')' { CHECK_ERROR(afsql_dd_check_port($3), @3, "Illegal sql port number: %s", $3); afsql_dd_set_port(last_driver, $3); free($3); } | KW_USERNAME '(' string ')' { afsql_dd_set_user(last_driver, $3); free($3); } | KW_DBD_OPTION '(' string LL_NUMBER ')' { afsql_dd_add_dbd_option_numeric(last_driver, $3, $4); free($3); } | KW_DBD_OPTION '(' string string ')' { afsql_dd_add_dbd_option(last_driver, $3, $4); free($3); free($4); } | KW_PASSWORD '(' string ')' { afsql_dd_set_password(last_driver, $3); free($3); } | KW_DATABASE '(' string ')' { afsql_dd_set_database(last_driver, $3); free($3); } | KW_TABLE '(' string ')' { afsql_dd_set_table(last_driver, $3); free($3); } | KW_COLUMNS '(' string_list ')' { afsql_dd_set_columns(last_driver, $3); } | KW_INDEXES '(' string_list ')' { afsql_dd_set_indexes(last_driver, $3); } | KW_VALUES '(' dest_afsql_values ')' { afsql_dd_set_values(last_driver, $3); } | KW_NULL '(' string ')' { afsql_dd_set_null_value(last_driver, $3); free($3); } | KW_RETRIES '(' nonnegative_integer ')' { afsql_dd_set_retries(last_driver, $3); } | KW_FLUSH_LINES '(' nonnegative_integer ')' { afsql_dd_set_flush_lines(last_driver, $3); } | KW_FLUSH_TIMEOUT '(' positive_integer ')' { afsql_dd_set_flush_timeout(last_driver, $3); } | KW_SESSION_STATEMENTS '(' string_list ')' { afsql_dd_set_session_statements(last_driver, $3); } | KW_FLAGS '(' dest_afsql_flags ')' { afsql_dd_set_flags(last_driver, $3); } | KW_CREATE_STATEMENT_APPEND '(' string ')' { afsql_dd_set_create_statement_append(last_driver, $3); free($3); } | { last_template_options = &((AFSqlDestDriver *) last_driver)->template_options; } template_option | dest_driver_option ; dest_afsql_values : dest_afsql_values_build { $$ = g_list_reverse($1); } ; dest_afsql_values_build : string dest_afsql_values_build { $$ = g_list_append($2, g_strdup($1)); free($1); } | KW_DEFAULT dest_afsql_values_build { $$ = g_list_append($2, GUINT_TO_POINTER(AFSQL_COLUMN_DEFAULT)); } | { $$ = NULL; } ; dest_afsql_flags : string dest_afsql_flags { $$ = afsql_dd_lookup_flag($1) | $2; free($1); } | { $$ = 0; } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/afsql/afsql-parser.c000066400000000000000000000046011321171025300227600ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afsql.h" #include "cfg-parser.h" #include "afsql-grammar.h" extern int afsql_debug; int afsql_parse(CfgLexer *lexer, LogDriver **instance, gpointer arg); static CfgLexerKeyword afsql_keywords[] = { { "sql", KW_SQL }, { "username", KW_USERNAME }, { "password", KW_PASSWORD }, { "database", KW_DATABASE }, { "table", KW_TABLE }, { "columns", KW_COLUMNS }, { "indexes", KW_INDEXES }, { "values", KW_VALUES }, { "log_fifo_size", KW_LOG_FIFO_SIZE }, { "frac_digits", KW_FRAC_DIGITS }, { "session_statements", KW_SESSION_STATEMENTS }, { "host", KW_HOST }, { "port", KW_PORT }, { "default", KW_DEFAULT }, { "local_time_zone", KW_LOCAL_TIME_ZONE }, { "null", KW_NULL }, { "retry_sql_inserts", KW_RETRIES }, { "flush_lines", KW_FLUSH_LINES }, { "flush_timeout", KW_FLUSH_TIMEOUT }, { "flags", KW_FLAGS }, { "create_statement_append", KW_CREATE_STATEMENT_APPEND }, { "dbd_option", KW_DBD_OPTION }, { NULL } }; CfgParser afsql_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &afsql_debug, #endif .name = "afsql", .keywords = afsql_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer)) afsql_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(afsql_, LogDriver **) syslog-ng-syslog-ng-3.13.2/modules/afsql/afsql-parser.h000066400000000000000000000022171321171025300227660ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSOCKET_PARSER_H_INCLUDED #define AFSOCKET_PARSER_H_INCLUDED #include "cfg-parser.h" #include "driver.h" extern CfgParser afsql_parser; CFG_PARSER_DECLARE_LEXER_BINDING(afsql_, LogDriver **) #endif syslog-ng-syslog-ng-3.13.2/modules/afsql/afsql-plugin.c000066400000000000000000000031611321171025300227620ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "plugin.h" #include "plugin-types.h" extern CfgParser afsql_parser; static Plugin afsql_plugins[] = { { .type = LL_CONTEXT_DESTINATION, .name = "sql", .parser = &afsql_parser, }, }; gboolean afsql_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, afsql_plugins, G_N_ELEMENTS(afsql_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "afsql", .version = SYSLOG_NG_VERSION, .description = "The afsql module provides SQL destination support for syslog-ng", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = afsql_plugins, .plugins_len = G_N_ELEMENTS(afsql_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/afsql/afsql.c000066400000000000000000001203301321171025300214640ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afsql.h" #include "logqueue.h" #include "template/templates.h" #include "messages.h" #include "string-list.h" #include "str-format.h" #include "seqnum.h" #include "stats/stats-registry.h" #include "apphook.h" #include "timeutils.h" #include "mainloop-worker.h" #include #include #include static gboolean dbi_initialized = FALSE; static const char *s_oracle = "oracle"; static const char *s_freetds = "freetds"; static dbi_inst dbi_instance; #define MAX_FAILED_ATTEMPTS 3 void afsql_dd_add_dbd_option(LogDriver *s, const gchar *name, const gchar *value) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; g_hash_table_insert(self->dbd_options, g_strdup(name), g_strdup(value)); } void afsql_dd_add_dbd_option_numeric(LogDriver *s, const gchar *name, gint value) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; g_hash_table_insert(self->dbd_options_numeric, g_strdup(name), GINT_TO_POINTER(value)); } void afsql_dd_set_type(LogDriver *s, const gchar *type) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; g_free(self->type); if (strcmp(type, "mssql") == 0) type = s_freetds; self->type = g_strdup(type); } void afsql_dd_set_host(LogDriver *s, const gchar *host) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; g_free(self->host); self->host = g_strdup(host); } gboolean afsql_dd_check_port(const gchar *port) { /* only digits (->numbers) are allowed */ int len = strlen(port); for (int i = 0; i < len; ++i) if (port[i] < '0' || port[i] > '9') return FALSE; return TRUE; } void afsql_dd_set_port(LogDriver *s, const gchar *port) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; g_free(self->port); self->port = g_strdup(port); } void afsql_dd_set_user(LogDriver *s, const gchar *user) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; g_free(self->user); self->user = g_strdup(user); } void afsql_dd_set_password(LogDriver *s, const gchar *password) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; g_free(self->password); self->password = g_strdup(password); } void afsql_dd_set_database(LogDriver *s, const gchar *database) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; g_free(self->database); self->database = g_strdup(database); } void afsql_dd_set_table(LogDriver *s, const gchar *table) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; log_template_compile(self->table, table, NULL); } void afsql_dd_set_columns(LogDriver *s, GList *columns) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; string_list_free(self->columns); self->columns = columns; } void afsql_dd_set_indexes(LogDriver *s, GList *indexes) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; string_list_free(self->indexes); self->indexes = indexes; } void afsql_dd_set_values(LogDriver *s, GList *values) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; string_list_free(self->values); self->values = values; } void afsql_dd_set_null_value(LogDriver *s, const gchar *null) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; if (self->null_value) g_free(self->null_value); self->null_value = g_strdup(null); } void afsql_dd_set_retries(LogDriver *s, gint num_retries) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; self->num_retries = num_retries; } void afsql_dd_set_flush_lines(LogDriver *s, gint flush_lines) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; self->flush_lines = flush_lines; } void afsql_dd_set_flush_timeout(LogDriver *s, gint flush_timeout) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; self->flush_timeout = flush_timeout; } void afsql_dd_set_session_statements(LogDriver *s, GList *session_statements) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; self->session_statements = session_statements; } void afsql_dd_set_flags(LogDriver *s, gint flags) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; self->flags = flags; } void afsql_dd_set_create_statement_append(LogDriver *s, const gchar *create_statement_append) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; g_free(self->create_statement_append); self->create_statement_append = g_strdup(create_statement_append); } /** * afsql_dd_run_query: * * Run an SQL query on the connected database. * * NOTE: This function can only be called from the database thread. **/ static gboolean afsql_dd_run_query(AFSqlDestDriver *self, const gchar *query, gboolean silent, dbi_result *result) { dbi_result db_res; msg_debug("Running SQL query", evt_tag_str("query", query)); db_res = dbi_conn_query(self->dbi_ctx, query); if (!db_res) { const gchar *dbi_error; if (!silent) { dbi_conn_error(self->dbi_ctx, &dbi_error); msg_error("Error running SQL query", evt_tag_str("type", self->type), evt_tag_str("host", self->host), evt_tag_str("port", self->port), evt_tag_str("user", self->user), evt_tag_str("database", self->database), evt_tag_str("error", dbi_error), evt_tag_str("query", query)); } return FALSE; } if (result) *result = db_res; else dbi_result_free(db_res); return TRUE; } /** * afsql_dd_handle_transaction_error: * * Handle errors inside during a SQL transaction (e.g. INSERT or COMMIT failures). * * NOTE: This function can only be called from the database thread. **/ static void afsql_dd_handle_transaction_error(AFSqlDestDriver *self) { log_queue_rewind_backlog_all(self->queue); self->flush_lines_queued = 0; } /** * afsql_dd_commit_transaction: * * Commit SQL transaction. * * NOTE: This function can only be called from the database thread. **/ static gboolean afsql_dd_commit_transaction(AFSqlDestDriver *self) { gboolean success; if (!self->transaction_active) return TRUE; success = afsql_dd_run_query(self, "COMMIT", FALSE, NULL); if (success) { log_queue_ack_backlog(self->queue, self->flush_lines_queued); self->flush_lines_queued = 0; self->transaction_active = FALSE; } else { msg_error("SQL transaction commit failed, rewinding backlog and starting again"); afsql_dd_handle_transaction_error(self); } return success; } /** * afsql_dd_begin_transaction: * * Begin SQL transaction. * * NOTE: This function can only be called from the database thread. **/ static gboolean afsql_dd_begin_transaction(AFSqlDestDriver *self) { gboolean success = TRUE; const char *s_begin = "BEGIN"; if (!strcmp(self->type, s_freetds)) { /* the mssql requires this command */ s_begin = "BEGIN TRANSACTION"; } if (strcmp(self->type, s_oracle) != 0) { /* oracle db has no BEGIN TRANSACTION command, it implicitly starts one, after every commit. */ success = afsql_dd_run_query(self, s_begin, FALSE, NULL); } self->transaction_active = success; return success; } static gboolean afsql_dd_rollback_transaction(AFSqlDestDriver *self) { if (!self->transaction_active) return TRUE; self->transaction_active = FALSE; return afsql_dd_run_query(self, "ROLLBACK", FALSE, NULL); } static gboolean afsql_dd_begin_new_transaction(AFSqlDestDriver *self) { if (self->transaction_active) { if (!afsql_dd_commit_transaction(self)) { afsql_dd_rollback_transaction(self); return FALSE; } } return afsql_dd_begin_transaction(self); } static gboolean _sql_identifier_is_valid_char(gchar c) { return ((c == '.') || (c == '_') || (c >= '0' && c <= '9') || (g_ascii_tolower(c) >= 'a' && g_ascii_tolower(c) <= 'z')); } static gboolean _is_sql_identifier_sanitized(const gchar *token) { gint i; for (i = 0; token[i]; i++) { if (!_sql_identifier_is_valid_char(token[i])) return FALSE; } return TRUE; } static void _sanitize_sql_identifier(gchar *token) { gint i; for (i = 0; token[i]; i++) { if (!_sql_identifier_is_valid_char(token[i])) token[i] = '_'; } } /** * afsql_dd_create_index: * * This function creates an index for the column specified and returns * TRUE to indicate success. * * NOTE: This function can only be called from the database thread. **/ static gboolean afsql_dd_create_index(AFSqlDestDriver *self, const gchar *table, const gchar *column) { GString *query_string; gboolean success = TRUE; query_string = g_string_sized_new(64); if (strcmp(self->type, s_oracle) == 0) { /* NOTE: oracle index indentifier length is max 30 characters * so we use the first 30 characters of the table_column md5 hash */ if ((strlen(table) + strlen(column)) > 25) { guchar hash[MD5_DIGEST_LENGTH]; gchar hash_str[31]; gchar *cat = g_strjoin("_", table, column, NULL); MD5((guchar *)cat, strlen(cat), hash); g_free(cat); format_hex_string(hash, sizeof(hash), hash_str, sizeof(hash_str)); hash_str[0] = 'i'; g_string_printf(query_string, "CREATE INDEX %s ON %s (%s)", hash_str, table, column); } else g_string_printf(query_string, "CREATE INDEX %s_%s_idx ON %s (%s)", table, column, table, column); } else g_string_printf(query_string, "CREATE INDEX %s_%s_idx ON %s (%s)", table, column, table, column); if (!afsql_dd_run_query(self, query_string->str, FALSE, NULL)) { msg_error("Error adding missing index", evt_tag_str("table", table), evt_tag_str("column", column)); success = FALSE; } g_string_free(query_string, TRUE); return success; } static inline gboolean _is_table_syslogng_conform(AFSqlDestDriver *self, const gchar *table) { return (g_hash_table_lookup(self->syslogng_conform_tables, table) != NULL); } static inline void _remember_table_as_syslogng_conform(AFSqlDestDriver *self, const gchar *table) { g_hash_table_insert(self->syslogng_conform_tables, g_strdup(table), GUINT_TO_POINTER(TRUE)); } static gboolean _is_table_present(AFSqlDestDriver *self, const gchar *table, dbi_result *metadata) { gboolean res = FALSE; GString *query_string; if (!afsql_dd_begin_new_transaction(self)) { msg_error("Starting new transaction has failed"); return FALSE; } query_string = g_string_sized_new(32); g_string_printf(query_string, "SELECT * FROM %s WHERE 0=1", table); res = afsql_dd_run_query(self, query_string->str, TRUE, metadata); g_string_free(query_string, TRUE); afsql_dd_commit_transaction(self); return res; } static gboolean _ensure_table_is_syslogng_conform(AFSqlDestDriver *self, dbi_result db_res, const gchar *table) { gboolean success = TRUE; gboolean new_transaction_started = FALSE; gint i; GString *query_string = g_string_sized_new(32); for (i = 0; success && (i < self->fields_len); i++) { if (dbi_result_get_field_idx(db_res, self->fields[i].name) == 0) { GList *l; if (!new_transaction_started) { if (!afsql_dd_begin_new_transaction(self)) { msg_error("Starting new transaction for modifying(ALTER) table has failed", evt_tag_str("table", table)); success = FALSE; break; } new_transaction_started = TRUE; } /* field does not exist, add this column */ g_string_printf(query_string, "ALTER TABLE %s ADD %s %s", table, self->fields[i].name, self->fields[i].type); if (!afsql_dd_run_query(self, query_string->str, FALSE, NULL)) { msg_error("Error adding missing column, giving up", evt_tag_str("table", table), evt_tag_str("column", self->fields[i].name)); success = FALSE; break; } for (l = self->indexes; l; l = l->next) { if (strcmp((gchar *) l->data, self->fields[i].name) == 0) { /* this is an indexed column, create index */ afsql_dd_create_index(self, table, self->fields[i].name); } } } } if (new_transaction_started && ( !success || !afsql_dd_commit_transaction(self))) { afsql_dd_rollback_transaction(self); success = FALSE; } g_string_free(query_string, TRUE); return success; } static gboolean _table_create_indexes(AFSqlDestDriver *self, const gchar *table) { gboolean success = TRUE; GList *l; if (!afsql_dd_begin_new_transaction(self)) { msg_error("Starting new transaction for table creation has failed", evt_tag_str("table", table)); return FALSE; } for (l = self->indexes; l && success; l = l->next) { success = afsql_dd_create_index(self, table, (gchar *) l->data); } if (!success || !afsql_dd_commit_transaction(self)) { afsql_dd_rollback_transaction(self); } return success; } static gboolean _table_create(AFSqlDestDriver *self, const gchar *table) { gint i; GString *query_string = g_string_sized_new(32); gboolean success = FALSE; if (!afsql_dd_begin_new_transaction(self)) { msg_error("Starting new transaction for table creation has failed", evt_tag_str("table", table)); return FALSE; } g_string_printf(query_string, "CREATE TABLE %s (", table); for (i = 0; i < self->fields_len; i++) { g_string_append_printf(query_string, "%s %s", self->fields[i].name, self->fields[i].type); if (i != self->fields_len - 1) g_string_append(query_string, ", "); } g_string_append(query_string, ")"); if (self->create_statement_append) g_string_append(query_string, self->create_statement_append); if (afsql_dd_run_query(self, query_string->str, FALSE, NULL)) { success = TRUE; } else { msg_error("Error creating table, giving up", evt_tag_str("table", table)); } if (!success || !afsql_dd_commit_transaction(self)) { afsql_dd_rollback_transaction(self); } g_string_free(query_string, TRUE); return success; } /** * afsql_dd_validate_table: * * Check if the given table exists in the database. If it doesn't * create it, if it does, check if all the required fields are * present and create them if they don't. * * NOTE: This function can only be called from the database thread. **/ static gboolean afsql_dd_ensure_table_is_syslogng_conform(AFSqlDestDriver *self, GString *table) { dbi_result db_res = NULL; gboolean success = FALSE; if (self->flags & AFSQL_DDF_DONT_CREATE_TABLES) return TRUE; _sanitize_sql_identifier(table->str); if (_is_table_syslogng_conform(self, table->str)) return TRUE; if (_is_table_present(self, table->str, &db_res)) { /* table exists, check structure */ success = _ensure_table_is_syslogng_conform(self, db_res, table->str); if (db_res) dbi_result_free(db_res); } else { /* table does not exist, create it */ success = _table_create(self, table->str) && _table_create_indexes(self, table->str); } if (success) { /* we have successfully created/altered the destination table, record this information */ _remember_table_as_syslogng_conform(self, table->str); } return success; } /** * afsql_dd_suspend: * timeout: in milliseconds * * This function is assumed to be called from the database thread * only! **/ static void afsql_dd_suspend(AFSqlDestDriver *self) { self->db_thread_suspended = TRUE; g_get_current_time(&self->db_thread_suspend_target); g_time_val_add(&self->db_thread_suspend_target, self->time_reopen * 1000 * 1000); /* the timeout expects microseconds */ } static void afsql_dd_disconnect(AFSqlDestDriver *self) { dbi_conn_close(self->dbi_ctx); self->dbi_ctx = NULL; g_hash_table_remove_all(self->syslogng_conform_tables); } static void afsql_dd_set_dbd_opt(gpointer key, gpointer value, gpointer user_data) { dbi_conn_set_option((dbi_conn)user_data, (gchar *)key, (gchar *)value); } static void afsql_dd_set_dbd_opt_numeric(gpointer key, gpointer value, gpointer user_data) { dbi_conn_set_option_numeric((dbi_conn)user_data, (gchar *)key, GPOINTER_TO_INT(value)); } static gboolean afsql_dd_ensure_initialized_connection(AFSqlDestDriver *self) { if (self->dbi_ctx) return TRUE; self->dbi_ctx = dbi_conn_new_r(self->type, dbi_instance); if (!self->dbi_ctx) { msg_error("No such DBI driver", evt_tag_str("type", self->type)); return FALSE; } dbi_conn_set_option(self->dbi_ctx, "host", self->host); if (strcmp(self->type, "mysql")) dbi_conn_set_option(self->dbi_ctx, "port", self->port); else dbi_conn_set_option_numeric(self->dbi_ctx, "port", atoi(self->port)); dbi_conn_set_option(self->dbi_ctx, "username", self->user); dbi_conn_set_option(self->dbi_ctx, "password", self->password); dbi_conn_set_option(self->dbi_ctx, "dbname", self->database); dbi_conn_set_option(self->dbi_ctx, "encoding", self->encoding); dbi_conn_set_option(self->dbi_ctx, "auto-commit", self->flags & AFSQL_DDF_EXPLICIT_COMMITS ? "false" : "true"); /* database specific hacks */ dbi_conn_set_option(self->dbi_ctx, "sqlite_dbdir", ""); dbi_conn_set_option(self->dbi_ctx, "sqlite3_dbdir", ""); /* Set user-specified options */ g_hash_table_foreach(self->dbd_options, afsql_dd_set_dbd_opt, self->dbi_ctx); g_hash_table_foreach(self->dbd_options_numeric, afsql_dd_set_dbd_opt_numeric, self->dbi_ctx); if (dbi_conn_connect(self->dbi_ctx) < 0) { const gchar *dbi_error; dbi_conn_error(self->dbi_ctx, &dbi_error); msg_error("Error establishing SQL connection", evt_tag_str("type", self->type), evt_tag_str("host", self->host), evt_tag_str("port", self->port), evt_tag_str("username", self->user), evt_tag_str("database", self->database), evt_tag_str("error", dbi_error)); return FALSE; } if (self->session_statements != NULL) { GList *l; for (l = self->session_statements; l; l = l->next) { if (!afsql_dd_run_query(self, (gchar *) l->data, FALSE, NULL)) { msg_error("Error executing SQL connection statement", evt_tag_str("statement", (gchar *) l->data)); return FALSE; } } } return TRUE; } static GString * afsql_dd_ensure_accessible_database_table(AFSqlDestDriver *self, LogMessage *msg) { GString *table = g_string_sized_new(32); log_template_format(self->table, msg, &self->template_options, LTZ_LOCAL, 0, NULL, table); if (!afsql_dd_ensure_table_is_syslogng_conform(self, table)) { /* If validate table is FALSE then close the connection and wait time_reopen time (next call) */ msg_error("Error checking table, disconnecting from database, trying again shortly", evt_tag_int("time_reopen", self->time_reopen)); g_string_free(table, TRUE); return NULL; } return table; } static GString * afsql_dd_build_insert_command(AFSqlDestDriver *self, LogMessage *msg, GString *table) { GString *insert_command = g_string_sized_new(256); GString *value = g_string_sized_new(512); gint i, j; g_string_printf(insert_command, "INSERT INTO %s (", table->str); for (i = 0; i < self->fields_len; i++) { if ((self->fields[i].flags & AFSQL_FF_DEFAULT) == 0 && self->fields[i].value != NULL) { g_string_append(insert_command, self->fields[i].name); j = i + 1; while (j < self->fields_len && (self->fields[j].flags & AFSQL_FF_DEFAULT) == AFSQL_FF_DEFAULT) j++; if (j < self->fields_len) g_string_append(insert_command, ", "); } } g_string_append(insert_command, ") VALUES ("); for (i = 0; i < self->fields_len; i++) { gchar *quoted; if ((self->fields[i].flags & AFSQL_FF_DEFAULT) == 0 && self->fields[i].value != NULL) { log_template_format(self->fields[i].value, msg, &self->template_options, LTZ_SEND, self->seq_num, NULL, value); if (self->null_value && strcmp(self->null_value, value->str) == 0) { g_string_append(insert_command, "NULL"); } else { dbi_conn_quote_string_copy(self->dbi_ctx, value->str, "ed); if (quoted) { g_string_append(insert_command, quoted); free(quoted); } else { g_string_append(insert_command, "''"); } } j = i + 1; while (j < self->fields_len && (self->fields[j].flags & AFSQL_FF_DEFAULT) == AFSQL_FF_DEFAULT) j++; if (j < self->fields_len) g_string_append(insert_command, ", "); } } g_string_append(insert_command, ")"); g_string_free(value, TRUE); return insert_command; } static inline gboolean afsql_dd_is_transaction_handling_enabled(const AFSqlDestDriver *self) { return self->flush_lines_queued != -1; } static inline gboolean afsql_dd_should_begin_new_transaction(const AFSqlDestDriver *self) { return self->flush_lines_queued == 0; } static inline gboolean afsql_dd_should_commit_transaction(const AFSqlDestDriver *self) { return afsql_dd_is_transaction_handling_enabled(self) && self->flush_lines_queued == self->flush_lines; } static inline void afsql_dd_rollback_msg(AFSqlDestDriver *self, LogMessage *msg, LogPathOptions *path_options) { if (self->flags & AFSQL_DDF_EXPLICIT_COMMITS) log_queue_rewind_backlog(self->queue, 1); else log_queue_push_head(self->queue, msg, path_options); } static inline gboolean afsql_dd_handle_insert_row_error_depending_on_connection_availability(AFSqlDestDriver *self, LogMessage *msg, LogPathOptions *path_options) { const gchar *dbi_error, *error_message; if (dbi_conn_ping(self->dbi_ctx) == 1) { afsql_dd_rollback_msg(self, msg, path_options); return TRUE; } if (afsql_dd_is_transaction_handling_enabled(self)) { error_message = "SQL connection lost in the middle of a transaction," " rewinding backlog and starting again"; afsql_dd_handle_transaction_error(self); } else { error_message = "Error, no SQL connection after failed query attempt"; afsql_dd_rollback_msg(self, msg, path_options); } dbi_conn_error(self->dbi_ctx, &dbi_error); msg_error(error_message, evt_tag_str("type", self->type), evt_tag_str("host", self->host), evt_tag_str("port", self->port), evt_tag_str("username", self->user), evt_tag_str("database", self->database), evt_tag_str("error", dbi_error)); return FALSE; } /** * afsql_dd_insert_db: * * This function is running in the database thread * * Returns: FALSE to indicate that the connection should be closed and * this destination suspended for time_reopen() time. **/ static gboolean afsql_dd_insert_db(AFSqlDestDriver *self) { GString *table = NULL; GString *insert_command = NULL; LogMessage *msg; gboolean success = TRUE; LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; if (!afsql_dd_ensure_initialized_connection(self)) return FALSE; /* connection established, try to insert a message */ msg = log_queue_pop_head(self->queue, &path_options); if (!msg) return TRUE; msg_set_context(msg); table = afsql_dd_ensure_accessible_database_table(self, msg); if (!table) { success = FALSE; goto out; } if (afsql_dd_should_begin_new_transaction(self) && !afsql_dd_begin_transaction(self)) { success = FALSE; goto out; } insert_command = afsql_dd_build_insert_command(self, msg, table); success = afsql_dd_run_query(self, insert_command->str, FALSE, NULL); if (success && self->flush_lines_queued != -1) { self->flush_lines_queued++; if (afsql_dd_should_commit_transaction(self) && !afsql_dd_commit_transaction(self)) { /* Assuming that in case of error, the queue is rewound by afsql_dd_commit_transaction() */ afsql_dd_rollback_transaction(self); g_string_free(insert_command, TRUE); msg_set_context(NULL); success = FALSE; } } out: if (table != NULL) g_string_free(table, TRUE); if (insert_command != NULL) g_string_free(insert_command, TRUE); msg_set_context(NULL); if (success) { log_msg_ack(msg, &path_options, AT_PROCESSED); log_msg_unref(msg); step_sequence_number(&self->seq_num); self->failed_message_counter = 0; } else { if (self->failed_message_counter < self->num_retries) { if (!afsql_dd_handle_insert_row_error_depending_on_connection_availability(self, msg, &path_options)) return FALSE; self->failed_message_counter++; } else { msg_error("Multiple failures while inserting this record into the database, message dropped", evt_tag_int("attempts", self->num_retries)); stats_counter_inc(self->dropped_messages); log_msg_drop(msg, &path_options, AT_PROCESSED); self->failed_message_counter = 0; success = TRUE; } } return success; } static void afsql_dd_message_became_available_in_the_queue(gpointer user_data) { AFSqlDestDriver *self = (AFSqlDestDriver *) user_data; g_mutex_lock(self->db_thread_mutex); g_cond_signal(self->db_thread_wakeup_cond); g_mutex_unlock(self->db_thread_mutex); } /* assumes that db_thread_mutex is held */ static void afsql_dd_wait_for_suspension_wakeup(AFSqlDestDriver *self) { /* we got suspended, probably because of a connection error, * during this time we only get wakeups if we need to be * terminated. */ if (!self->db_thread_terminate) g_cond_timed_wait(self->db_thread_wakeup_cond, self->db_thread_mutex, &self->db_thread_suspend_target); self->db_thread_suspended = FALSE; } /** * afsql_dd_database_thread: * * This is the thread inserting records into the database. **/ static void afsql_dd_database_thread(gpointer arg) { AFSqlDestDriver *self = (AFSqlDestDriver *) arg; msg_verbose("Database thread started", evt_tag_str("driver", self->super.super.id)); while (!self->db_thread_terminate) { main_loop_worker_run_gc(); g_mutex_lock(self->db_thread_mutex); if (self->db_thread_suspended) { afsql_dd_wait_for_suspension_wakeup(self); /* we loop back to check if the thread was requested to terminate */ } else if (!log_queue_check_items(self->queue, NULL, afsql_dd_message_became_available_in_the_queue, self, NULL)) { /* we have nothing to INSERT into the database, let's wait we get some new stuff */ if (self->flush_lines_queued > 0) { if (!afsql_dd_commit_transaction(self)) { if (!afsql_dd_rollback_transaction(self)) { afsql_dd_disconnect(self); afsql_dd_suspend(self); } g_mutex_unlock(self->db_thread_mutex); continue; } } else if (!self->db_thread_terminate) { g_cond_wait(self->db_thread_wakeup_cond, self->db_thread_mutex); } /* we loop back to check if the thread was requested to terminate */ } g_mutex_unlock(self->db_thread_mutex); if (self->db_thread_terminate) break; if (!afsql_dd_insert_db(self)) { afsql_dd_disconnect(self); afsql_dd_suspend(self); } } while (log_queue_get_length(self->queue) > 0) { if (!afsql_dd_insert_db(self)) { goto exit; } } if (self->flush_lines_queued > 0) { /* we can't do anything with the return value here. if commit isn't * successful, we get our backlog back, but we have no chance * submitting that back to the SQL engine. */ if (!afsql_dd_commit_transaction(self)) afsql_dd_rollback_transaction(self); } exit: afsql_dd_disconnect(self); msg_verbose("Database thread finished", evt_tag_str("driver", self->super.super.id)); } static void afsql_dd_stop_thread(gpointer s) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; g_mutex_lock(self->db_thread_mutex); self->db_thread_terminate = TRUE; g_cond_signal(self->db_thread_wakeup_cond); g_mutex_unlock(self->db_thread_mutex); } static void afsql_dd_start_thread(AFSqlDestDriver *self) { self->db_thread_terminate = FALSE; main_loop_create_worker_thread(afsql_dd_database_thread, afsql_dd_stop_thread, self, &self->worker_options); } static gchar * afsql_dd_format_stats_instance(AFSqlDestDriver *self) { static gchar persist_name[64]; g_snprintf(persist_name, sizeof(persist_name), "%s,%s,%s,%s,%s", self->type, self->host, self->port, self->database, self->table->template); return persist_name; } static inline const gchar * afsql_dd_format_persist_name(const LogPipe *s) { AFSqlDestDriver *self = (AFSqlDestDriver *)s; static gchar persist_name[256]; if (s->persist_name) g_snprintf(persist_name, sizeof(persist_name), "afsql_dd.%s", s->persist_name); else g_snprintf(persist_name, sizeof(persist_name), "afsql_dd(%s,%s,%s,%s,%s)", self->type, self->host, self->port, self->database, self->table->template); return persist_name; } static inline gchar * afsql_dd_format_persist_sequence_number(AFSqlDestDriver *self) { static gchar persist_name[256]; g_snprintf(persist_name, sizeof(persist_name), "afsql_dd_sequence_number(%s,%s,%s,%s,%s)", self->type,self->host, self->port, self->database, self->table->template); return persist_name; } static gboolean afsql_dd_init(LogPipe *s) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); gint len_cols, len_values; if (!log_dest_driver_init_method(s)) return FALSE; if (!self->columns || !self->values) { msg_error("Default columns and values must be specified for database destinations", evt_tag_str("database type", self->type)); return FALSE; } stats_lock(); { StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_SQL | SCS_DESTINATION, self->super.super.id, afsql_dd_format_stats_instance(self) ); stats_register_counter(0, &sc_key, SC_TYPE_QUEUED, &self->queued_messages); stats_register_counter(0, &sc_key, SC_TYPE_DROPPED, &self->dropped_messages); stats_register_counter(STATS_LEVEL1, &sc_key, SC_TYPE_MEMORY_USAGE, &self->memory_usage); } stats_unlock(); self->seq_num = GPOINTER_TO_INT(cfg_persist_config_fetch(cfg, afsql_dd_format_persist_sequence_number(self))); if (!self->seq_num) init_sequence_number(&self->seq_num); self->queue = log_dest_driver_acquire_queue(&self->super, afsql_dd_format_persist_name((const LogPipe *)self)); if (self->queue == NULL) { return FALSE; } else { if (self->flags & AFSQL_DDF_EXPLICIT_COMMITS) log_queue_set_use_backlog(self->queue, TRUE); } log_queue_set_counters(self->queue, self->queued_messages, self->dropped_messages, self->memory_usage); if (!self->fields) { GList *col, *value; gint i; len_cols = g_list_length(self->columns); len_values = g_list_length(self->values); if (len_cols != len_values) { msg_error("The number of columns and values do not match", evt_tag_int("len_columns", len_cols), evt_tag_int("len_values", len_values)); goto error; } self->fields_len = len_cols; self->fields = g_new0(AFSqlField, len_cols); for (i = 0, col = self->columns, value = self->values; col && value; i++, col = col->next, value = value->next) { gchar *space; space = strchr(col->data, ' '); if (space) { self->fields[i].name = g_strndup(col->data, space - (gchar *) col->data); while (*space == ' ') space++; if (*space != '\0') self->fields[i].type = g_strdup(space); else self->fields[i].type = g_strdup("text"); } else { self->fields[i].name = g_strdup(col->data); self->fields[i].type = g_strdup("text"); } if (!_is_sql_identifier_sanitized(self->fields[i].name)) { msg_error("Column name is not a proper SQL name", evt_tag_str("column", self->fields[i].name)); return FALSE; } if (GPOINTER_TO_UINT(value->data) > 4096) { self->fields[i].value = log_template_new(cfg, NULL); log_template_compile(self->fields[i].value, (gchar *) value->data, NULL); } else { switch (GPOINTER_TO_UINT(value->data)) { case AFSQL_COLUMN_DEFAULT: self->fields[i].flags |= AFSQL_FF_DEFAULT; break; default: g_assert_not_reached(); break; } } } } self->time_reopen = cfg->time_reopen; log_template_options_init(&self->template_options, cfg); if (self->flush_lines == -1) self->flush_lines = cfg->flush_lines; if (self->flush_timeout == -1) self->flush_timeout = cfg->flush_timeout; if ((self->flags & AFSQL_DDF_EXPLICIT_COMMITS) && (self->flush_lines > 0 || self->flush_timeout > 0)) self->flush_lines_queued = 0; if (!dbi_initialized) { errno = 0; gint rc = dbi_initialize_r(NULL, &dbi_instance); if (rc < 0) { /* NOTE: errno might be unreliable, but that's all we have */ msg_error("Unable to initialize database access (DBI)", evt_tag_int("rc", rc), evt_tag_errno("error", errno)); goto error; } else if (rc == 0) { msg_error("The database access library (DBI) reports no usable SQL drivers, perhaps DBI drivers are not installed properly"); goto error; } else { dbi_initialized = TRUE; } } afsql_dd_start_thread(self); return TRUE; error: stats_lock(); { StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_SQL | SCS_DESTINATION, self->super.super.id, afsql_dd_format_stats_instance(self) ); stats_unregister_counter(&sc_key, SC_TYPE_QUEUED, &self->queued_messages); stats_unregister_counter(&sc_key, SC_TYPE_DROPPED, &self->dropped_messages); stats_unregister_counter(&sc_key, SC_TYPE_MEMORY_USAGE, &self->memory_usage); } stats_unlock(); return FALSE; } static gboolean afsql_dd_deinit(LogPipe *s) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; log_queue_reset_parallel_push(self->queue); log_queue_set_counters(self->queue, NULL, NULL, NULL); cfg_persist_config_add(log_pipe_get_config(s), afsql_dd_format_persist_sequence_number(self), GINT_TO_POINTER(self->seq_num), NULL, FALSE); stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_SQL | SCS_DESTINATION, self->super.super.id, afsql_dd_format_stats_instance(self) ); stats_unregister_counter(&sc_key, SC_TYPE_QUEUED, &self->queued_messages); stats_unregister_counter(&sc_key, SC_TYPE_DROPPED, &self->dropped_messages); stats_unlock(); if (!log_dest_driver_deinit_method(s)) return FALSE; return TRUE; } static void afsql_dd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; LogPathOptions local_options; if (!path_options->flow_control_requested) path_options = log_msg_break_ack(msg, path_options, &local_options); log_msg_add_ack(msg, path_options); log_queue_push_tail(self->queue, log_msg_ref(msg), path_options); log_dest_driver_queue_method(s, msg, path_options, user_data); } static void afsql_dd_free(LogPipe *s) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; gint i; log_template_options_destroy(&self->template_options); for (i = 0; i < self->fields_len; i++) { g_free(self->fields[i].name); g_free(self->fields[i].type); log_template_unref(self->fields[i].value); } g_free(self->fields); g_free(self->type); g_free(self->host); g_free(self->port); g_free(self->user); g_free(self->password); g_free(self->database); g_free(self->encoding); g_free(self->create_statement_append); if (self->null_value) g_free(self->null_value); string_list_free(self->columns); string_list_free(self->indexes); string_list_free(self->values); log_template_unref(self->table); g_hash_table_destroy(self->syslogng_conform_tables); g_hash_table_destroy(self->dbd_options); g_hash_table_destroy(self->dbd_options_numeric); if (self->session_statements) string_list_free(self->session_statements); g_mutex_free(self->db_thread_mutex); g_cond_free(self->db_thread_wakeup_cond); log_dest_driver_free(s); } LogDriver * afsql_dd_new(GlobalConfig *cfg) { AFSqlDestDriver *self = g_new0(AFSqlDestDriver, 1); log_dest_driver_init_instance(&self->super, cfg); self->super.super.super.init = afsql_dd_init; self->super.super.super.deinit = afsql_dd_deinit; self->super.super.super.queue = afsql_dd_queue; self->super.super.super.free_fn = afsql_dd_free; self->super.super.super.generate_persist_name = afsql_dd_format_persist_name; self->type = g_strdup("mysql"); self->host = g_strdup(""); self->port = g_strdup(""); self->user = g_strdup("syslog-ng"); self->password = g_strdup(""); self->database = g_strdup("logs"); self->encoding = g_strdup("UTF-8"); self->transaction_active = FALSE; self->table = log_template_new(configuration, NULL); log_template_compile(self->table, "messages", NULL); self->failed_message_counter = 0; self->flush_lines = -1; self->flush_timeout = -1; self->flush_lines_queued = -1; self->session_statements = NULL; self->num_retries = MAX_FAILED_ATTEMPTS; self->syslogng_conform_tables = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); self->dbd_options = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); self->dbd_options_numeric = g_hash_table_new_full(g_str_hash, g_int_equal, g_free, NULL); log_template_options_defaults(&self->template_options); self->db_thread_wakeup_cond = g_cond_new(); self->db_thread_mutex = g_mutex_new(); self->worker_options.is_output_thread = TRUE; return &self->super.super; } gint afsql_dd_lookup_flag(const gchar *flag) { if (strcmp(flag, "explicit-commits") == 0 || strcmp(flag, "explicit_commits") == 0) return AFSQL_DDF_EXPLICIT_COMMITS; else if (strcmp(flag, "dont-create-tables") == 0 || strcmp(flag, "dont_create_tables") == 0) return AFSQL_DDF_DONT_CREATE_TABLES; else msg_warning("Unknown SQL flag", evt_tag_str("flag", flag)); return 0; } syslog-ng-syslog-ng-3.13.2/modules/afsql/afsql.h000066400000000000000000000107011321171025300214710ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSQL_H_INCLUDED #define AFSQL_H_INCLUDED #include "driver.h" #include "mainloop-worker.h" #include "string-list.h" #include enum { AFSQL_COLUMN_DEFAULT = 1, }; /* field flags */ enum { AFSQL_FF_DEFAULT = 0x0001, }; /* destination driver flags */ enum { AFSQL_DDF_EXPLICIT_COMMITS = 0x0001, AFSQL_DDF_DONT_CREATE_TABLES = 0x0002, }; typedef struct _AFSqlField { guint32 flags; gchar *name; gchar *type; LogTemplate *value; } AFSqlField; /** * AFSqlDestDriver: * * This structure encapsulates an SQL destination driver. SQL insert * statements are generated from a separate thread because of the blocking * nature of the DBI API. It is ensured that while the thread is running, * the reference count to the driver structure is increased, thus the db * thread can read any of the fields in this structure. To do anything more * than simple reading out a value, some kind of locking mechanism shall be * used. **/ typedef struct _AFSqlDestDriver { LogDestDriver super; /* read by the db thread */ gchar *type; gchar *host; gchar *port; gchar *user; gchar *password; gchar *database; gchar *encoding; gchar *create_statement_append; GList *columns; GList *values; GList *indexes; LogTemplate *table; gint fields_len; AFSqlField *fields; gchar *null_value; gint time_reopen; gint num_retries; gint flush_lines; gint flush_timeout; gint flush_lines_queued; gint flags; GList *session_statements; LogTemplateOptions template_options; StatsCounterItem *dropped_messages; StatsCounterItem *queued_messages; StatsCounterItem *memory_usage; GHashTable *dbd_options; GHashTable *dbd_options_numeric; /* shared by the main/db thread */ GMutex *db_thread_mutex; GCond *db_thread_wakeup_cond; gboolean db_thread_terminate; gboolean db_thread_suspended; GTimeVal db_thread_suspend_target; LogQueue *queue; /* used exclusively by the db thread */ gint32 seq_num; dbi_conn dbi_ctx; GHashTable *syslogng_conform_tables; guint32 failed_message_counter; WorkerOptions worker_options; gboolean transaction_active; } AFSqlDestDriver; void afsql_dd_set_type(LogDriver *s, const gchar *type); void afsql_dd_set_host(LogDriver *s, const gchar *host); gboolean afsql_dd_check_port(const gchar *port); void afsql_dd_set_port(LogDriver *s, const gchar *port); void afsql_dd_set_user(LogDriver *s, const gchar *user); void afsql_dd_set_password(LogDriver *s, const gchar *password); void afsql_dd_set_database(LogDriver *s, const gchar *database); void afsql_dd_set_table(LogDriver *s, const gchar *table); void afsql_dd_set_columns(LogDriver *s, GList *columns); void afsql_dd_set_values(LogDriver *s, GList *values); void afsql_dd_set_null_value(LogDriver *s, const gchar *null); void afsql_dd_set_indexes(LogDriver *s, GList *indexes); void afsql_dd_set_retries(LogDriver *s, gint num_retries); void afsql_dd_set_flush_lines(LogDriver *s, gint flush_lines); void afsql_dd_set_flush_timeout(LogDriver *s, gint flush_timeout); void afsql_dd_set_session_statements(LogDriver *s, GList *session_statements); void afsql_dd_set_flags(LogDriver *s, gint flags); void afsql_dd_set_create_statement_append(LogDriver *s, const gchar *create_statement_append); LogDriver *afsql_dd_new(GlobalConfig *cfg); gint afsql_dd_lookup_flag(const gchar *flag); void afsql_dd_set_retries(LogDriver *s, gint num_retries); void afsql_dd_add_dbd_option(LogDriver *s, const gchar *name, const gchar *value); void afsql_dd_add_dbd_option_numeric(LogDriver *s, const gchar *name, gint value); #endif syslog-ng-syslog-ng-3.13.2/modules/afstomp/000077500000000000000000000000001321171025300205565ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afstomp/CMakeLists.txt000066400000000000000000000014651321171025300233240ustar00rootroot00000000000000set(AFSTOMP_SOURCES afstomp.c afstomp.h afstomp-parser.c afstomp-parser.h stomp.c stomp.h ${CMAKE_CURRENT_BINARY_DIR}/afstomp-grammar.h ${CMAKE_CURRENT_BINARY_DIR}/afstomp-grammar.c ) option(ENABLE_STOMP "Enable STOMP destination" ON) if (ENABLE_STOMP) generate_y_from_ym(modules/afstomp/afstomp-grammar) bison_target(StompGrammar ${CMAKE_CURRENT_BINARY_DIR}/afstomp-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/afstomp-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) add_library(afstomp MODULE ${AFSTOMP_SOURCES}) target_include_directories (afstomp PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(afstomp PRIVATE syslog-ng) install(TARGETS afstomp LIBRARY DESTINATION lib/syslog-ng/ COMPONENT afstomp) endif() syslog-ng-syslog-ng-3.13.2/modules/afstomp/Makefile.am000066400000000000000000000021731321171025300226150ustar00rootroot00000000000000if ENABLE_STOMP module_LTLIBRARIES += modules/afstomp/libafstomp.la modules_afstomp_libafstomp_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/afstomp \ -I$(top_builddir)/modules/afstomp modules_afstomp_libafstomp_la_SOURCES = \ modules/afstomp/afstomp-grammar.y \ modules/afstomp/afstomp.c \ modules/afstomp/afstomp.h \ modules/afstomp/afstomp-parser.c \ modules/afstomp/afstomp-parser.h \ modules/afstomp/stomp.c \ modules/afstomp/stomp.h modules_afstomp_libafstomp_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_afstomp_libafstomp_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_afstomp_libafstomp_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) modules/afstomp modules/afstomp/ mod-afstomp mod-stomp: \ modules/afstomp/libafstomp.la else modules/afstomp modules/afstomp/ mod-afstomp mod-stomp: endif BUILT_SOURCES += \ modules/afstomp/afstomp-grammar.y \ modules/afstomp/afstomp-grammar.c \ modules/afstomp/afstomp-grammar.h EXTRA_DIST += \ modules/afstomp/afstomp-grammar.ym .PHONY: modules/afstomp/ mod-afstomp mod-stomp include modules/afstomp/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/modules/afstomp/afstomp-grammar.ym000066400000000000000000000053111321171025300242220ustar00rootroot00000000000000/* * Copyright (c) 2012 Nagy, Attila * Copyright (c) 2014 Balabit * Copyright (c) 2013 Viktor Tusa * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code requires { #include "afstomp-parser.h" } %code { #include "cfg-parser.h" #include "cfg-grammar.h" #include "plugin.h" #include "value-pairs/value-pairs.h" } %name-prefix "afstomp_" %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogDriver **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_STOMP %token KW_STOMP_DESTINATION %token KW_PERSISTENT %token KW_ACK %token KW_BODY %token KW_PASSWORD %token KW_USERNAME %% start : LL_CONTEXT_DESTINATION KW_STOMP { last_driver = *instance = afstomp_dd_new(configuration); } '(' afstomp_options ')' { YYACCEPT; } ; afstomp_options : afstomp_option afstomp_options | ; afstomp_option : KW_HOST '(' string ')' { afstomp_dd_set_host(last_driver, $3); free($3); } | KW_PORT '(' positive_integer ')' { afstomp_dd_set_port(last_driver, $3); } | KW_STOMP_DESTINATION '(' string ')' { afstomp_dd_set_destination(last_driver, $3); free($3); } | KW_BODY '(' string ')' { afstomp_dd_set_body(last_driver, $3); free($3); } | KW_PERSISTENT '(' yesno ')' { afstomp_dd_set_persistent(last_driver, $3); } | KW_ACK '(' yesno ')' { afstomp_dd_set_ack(last_driver, $3); } | KW_USERNAME '(' string ')' { afstomp_dd_set_user(last_driver, $3); free($3); } | KW_PASSWORD '(' string ')' { afstomp_dd_set_password(last_driver, $3); free($3); } | value_pair_option { afstomp_dd_set_value_pairs(last_driver, $1); } | dest_driver_option | threaded_dest_driver_option | { last_template_options = afstomp_dd_get_template_options(last_driver); } template_option ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/afstomp/afstomp-parser.c000066400000000000000000000036001321171025300236640ustar00rootroot00000000000000/* * Copyright (c) 2012 Nagy, Attila * Copyright (c) 2013 Balabit * Copyright (c) 2013 Viktor Tusa * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afstomp.h" #include "cfg-parser.h" #include "afstomp-grammar.h" extern int afstomp_debug; int afstomp_parse(CfgLexer *lexer, LogDriver **instance, gpointer arg); static CfgLexerKeyword afstomp_keywords[] = { { "stomp", KW_STOMP }, { "host", KW_HOST }, { "port", KW_PORT }, { "destination", KW_STOMP_DESTINATION }, { "persistent", KW_PERSISTENT }, { "ack", KW_ACK }, { "username", KW_USERNAME }, { "password", KW_PASSWORD }, { "log_fifo_size", KW_LOG_FIFO_SIZE }, { "body", KW_BODY }, { NULL } }; CfgParser afstomp_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &afstomp_debug, #endif .name = "afstomp", .keywords = afstomp_keywords, .parse = (int (*)(CfgLexer *lexer, gpointer *instance, gpointer)) afstomp_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(afstomp_, LogDriver **) syslog-ng-syslog-ng-3.13.2/modules/afstomp/afstomp-parser.h000066400000000000000000000023041321171025300236710ustar00rootroot00000000000000/* * Copyright (c) 2012 Nagy, Attila * Copyright (c) 2013 Balabit * Copyright (c) 2013 Viktor Tusa * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSTOMP_PARSER_H_INCLUDED #define AFSTOMP_PARSER_H_INCLUDED #include "cfg-parser.h" #include "afstomp.h" extern CfgParser afstomp_parser; CFG_PARSER_DECLARE_LEXER_BINDING(afstomp_, LogDriver **) #endif syslog-ng-syslog-ng-3.13.2/modules/afstomp/afstomp.c000066400000000000000000000251051321171025300223760ustar00rootroot00000000000000/* * Copyright (c) 2012 Nagy, Attila * Copyright (c) 2014 Balabit * Copyright (c) 2013 Viktor Tusa * Copyright (c) 2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afstomp.h" #include "afstomp-parser.h" #include "plugin.h" #include "messages.h" #include "stats/stats-registry.h" #include "logmsg/nvtable.h" #include "logqueue.h" #include "scratch-buffers.h" #include "plugin-types.h" #include #include #include "logthrdestdrv.h" typedef struct { LogThrDestDriver super; gchar *destination; LogTemplate *body_template; gboolean persistent; gboolean ack_needed; gchar *host; gint port; gchar *user; gchar *password; LogTemplateOptions template_options; ValuePairs *vp; stomp_connection *conn; } STOMPDestDriver; /* * Configuration */ void afstomp_dd_set_user(LogDriver *d, const gchar *user) { STOMPDestDriver *self = (STOMPDestDriver *) d; g_free(self->user); self->user = g_strdup(user); } void afstomp_dd_set_password(LogDriver *d, const gchar *password) { STOMPDestDriver *self = (STOMPDestDriver *) d; g_free(self->password); self->password = g_strdup(password); } void afstomp_dd_set_host(LogDriver *d, const gchar *host) { STOMPDestDriver *self = (STOMPDestDriver *) d; g_free(self->host); self->host = g_strdup(host); } void afstomp_dd_set_port(LogDriver *d, gint port) { STOMPDestDriver *self = (STOMPDestDriver *) d; self->port = (int) port; } void afstomp_dd_set_destination(LogDriver *d, const gchar *destination) { STOMPDestDriver *self = (STOMPDestDriver *) d; g_free(self->destination); self->destination = g_strdup(destination); } void afstomp_dd_set_body(LogDriver *d, const gchar *body) { STOMPDestDriver *self = (STOMPDestDriver *) d; GlobalConfig *cfg = log_pipe_get_config((LogPipe *)d); if (!self->body_template) self->body_template = log_template_new(cfg, NULL); log_template_compile(self->body_template, body, NULL); } void afstomp_dd_set_persistent(LogDriver *s, gboolean persistent) { STOMPDestDriver *self = (STOMPDestDriver *) s; self->persistent = persistent; } void afstomp_dd_set_ack(LogDriver *s, gboolean ack_needed) { STOMPDestDriver *self = (STOMPDestDriver *) s; self->ack_needed = ack_needed; } void afstomp_dd_set_value_pairs(LogDriver *s, ValuePairs *vp) { STOMPDestDriver *self = (STOMPDestDriver *) s; value_pairs_unref(self->vp); self->vp = vp; } LogTemplateOptions * afstomp_dd_get_template_options(LogDriver *s) { STOMPDestDriver *self = (STOMPDestDriver *) s; return &self->template_options; } /* * Utilities */ static gchar * afstomp_dd_format_stats_instance(LogThrDestDriver *s) { STOMPDestDriver *self = (STOMPDestDriver *) s; static gchar persist_name[1024]; if (s->super.super.super.persist_name) g_snprintf(persist_name, sizeof(persist_name), "afstomp,%s", s->super.super.super.persist_name); else g_snprintf(persist_name, sizeof(persist_name), "afstomp,%s,%u,%s", self->host, self->port, self->destination); return persist_name; } static const gchar * afstomp_dd_format_persist_name(const LogPipe *s) { const STOMPDestDriver *self = (const STOMPDestDriver *)s; static gchar persist_name[1024]; if (s->persist_name) g_snprintf(persist_name, sizeof(persist_name), "afstomp.%s", s->persist_name); else g_snprintf(persist_name, sizeof(persist_name), "afstomp(%s,%u,%s)", self->host, self->port, self->destination); return persist_name; } static void afstomp_create_connect_frame(STOMPDestDriver *self, stomp_frame *frame) { stomp_frame_init(frame, "CONNECT", sizeof("CONNECT")); stomp_frame_add_header(frame, "login", self->user); stomp_frame_add_header(frame, "passcode", self->password); }; static gboolean afstomp_try_connect(STOMPDestDriver *self) { return stomp_connect(&self->conn, self->host, self->port); }; static gboolean afstomp_send_frame(STOMPDestDriver *self, stomp_frame *frame) { return stomp_write(self->conn, frame); } static gboolean afstomp_dd_connect(STOMPDestDriver *self, gboolean reconnect) { stomp_frame frame; if (reconnect && self->conn) return TRUE; if (!afstomp_try_connect(self)) return FALSE; afstomp_create_connect_frame(self, &frame); if (!afstomp_send_frame(self, &frame)) { msg_error("Sending CONNECT frame to STOMP server failed!"); return FALSE; } stomp_receive_frame(self->conn, &frame); if (strcmp(frame.command, "CONNECTED")) { msg_debug("Error connecting to STOMP server, stomp server did not accept CONNECT request"); stomp_frame_deinit(&frame); return FALSE; } msg_debug("Connecting to STOMP succeeded", evt_tag_str("driver", self->super.super.super.id)); stomp_frame_deinit(&frame); return TRUE; } static void afstomp_dd_disconnect(LogThrDestDriver *s) { STOMPDestDriver *self = (STOMPDestDriver *)s; stomp_disconnect(&self->conn); self->conn = NULL; } /* TODO escape '\0' when passing down the value */ static gboolean afstomp_vp_foreach(const gchar *name, TypeHint type, const gchar *value, gsize value_len, gpointer user_data) { stomp_frame *frame = (stomp_frame *) (user_data); stomp_frame_add_header(frame, name, value); return FALSE; } static void afstomp_set_frame_body(STOMPDestDriver *self, GString *body, stomp_frame *frame, LogMessage *msg) { if (self->body_template) { log_template_format(self->body_template, msg, NULL, LTZ_LOCAL, self->super.seq_num, NULL, body); stomp_frame_set_body(frame, body->str, body->len); } } static gboolean afstomp_worker_publish(STOMPDestDriver *self, LogMessage *msg) { gboolean success = TRUE; GString *body = NULL; stomp_frame frame; stomp_frame recv_frame; gchar seq_num[16]; if (!self->conn) { msg_error("STOMP server is not connected, not sending message!"); return FALSE; } body = scratch_buffers_alloc(); stomp_frame_init(&frame, "SEND", sizeof("SEND")); if (self->persistent) stomp_frame_add_header(&frame, "persistent", "true"); stomp_frame_add_header(&frame, "destination", self->destination); if (self->ack_needed) { g_snprintf(seq_num, sizeof(seq_num), "%i", self->super.seq_num); stomp_frame_add_header(&frame, "receipt", seq_num); }; value_pairs_foreach(self->vp, afstomp_vp_foreach, msg, self->super.seq_num, LTZ_SEND, &self->template_options, &frame); afstomp_set_frame_body(self, body, &frame, msg); if (!afstomp_send_frame(self, &frame)) { msg_error("Error while inserting into STOMP server"); success = FALSE; } if (success && self->ack_needed) success = stomp_receive_frame(self->conn, &recv_frame); return success; } static worker_insert_result_t afstomp_worker_insert(LogThrDestDriver *s, LogMessage *msg) { STOMPDestDriver *self = (STOMPDestDriver *)s; if (!afstomp_dd_connect(self, TRUE)) return WORKER_INSERT_RESULT_NOT_CONNECTED; if (!afstomp_worker_publish (self, msg)) return WORKER_INSERT_RESULT_ERROR; return WORKER_INSERT_RESULT_SUCCESS; } static void afstomp_worker_thread_init(LogThrDestDriver *s) { STOMPDestDriver *self = (STOMPDestDriver *) s; afstomp_dd_connect(self, FALSE); } static gboolean afstomp_dd_init(LogPipe *s) { STOMPDestDriver *self = (STOMPDestDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!log_dest_driver_init_method(s)) return FALSE; log_template_options_init(&self->template_options, cfg); self->conn = NULL; msg_verbose("Initializing STOMP destination", evt_tag_str("host", self->host), evt_tag_int("port", self->port), evt_tag_str("destination", self->destination)); return log_threaded_dest_driver_start(s); } static void afstomp_dd_free(LogPipe *d) { STOMPDestDriver *self = (STOMPDestDriver *) d; log_template_options_destroy(&self->template_options); g_free(self->destination); log_template_unref(self->body_template); g_free(self->user); g_free(self->password); g_free(self->host); value_pairs_unref(self->vp); log_threaded_dest_driver_free(d); } LogDriver * afstomp_dd_new(GlobalConfig *cfg) { STOMPDestDriver *self = g_new0(STOMPDestDriver, 1); log_threaded_dest_driver_init_instance(&self->super, cfg); self->super.super.super.super.init = afstomp_dd_init; self->super.super.super.super.free_fn = afstomp_dd_free; self->super.super.super.super.generate_persist_name = afstomp_dd_format_persist_name; self->super.worker.thread_init = afstomp_worker_thread_init; self->super.worker.disconnect = afstomp_dd_disconnect; self->super.worker.insert = afstomp_worker_insert; self->super.format.stats_instance = afstomp_dd_format_stats_instance; self->super.stats_source = SCS_STOMP; afstomp_dd_set_host((LogDriver *) self, "127.0.0.1"); afstomp_dd_set_port((LogDriver *) self, 61613); afstomp_dd_set_destination((LogDriver *) self, "/topic/syslog"); afstomp_dd_set_persistent((LogDriver *) self, TRUE); afstomp_dd_set_ack((LogDriver *) self, FALSE); log_template_options_defaults(&self->template_options); afstomp_dd_set_value_pairs(&self->super.super.super, value_pairs_new_default(cfg)); return (LogDriver *) self; } extern CfgParser afstomp_dd_parser; static Plugin afstomp_plugin = { .type = LL_CONTEXT_DESTINATION, .name = "stomp", .parser = &afstomp_parser }; gboolean afstomp_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, &afstomp_plugin, 1); return TRUE; } const ModuleInfo module_info = { .canonical_name = "afstomp", .version = SYSLOG_NG_VERSION, .description = "The afstomp module provides STOMP destination support for syslog-ng.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = &afstomp_plugin, .plugins_len = 1, }; syslog-ng-syslog-ng-3.13.2/modules/afstomp/afstomp.h000066400000000000000000000034021321171025300223770ustar00rootroot00000000000000/* * Copyright (c) 2012 Nagy, Attila * Copyright (c) 2014 Balabit * Copyright (c) 2013 Viktor Tusa * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSTOMP_H_INCLUDED #define AFSTOMP_H_INCLUDED #include "driver.h" #include "value-pairs/value-pairs.h" LogDriver *afstomp_dd_new(GlobalConfig *cfg); void afstomp_dd_set_host(LogDriver *d, const gchar *host); void afstomp_dd_set_port(LogDriver *d, gint port); void afstomp_dd_set_destination(LogDriver *d, const gchar *destination); void afstomp_dd_set_body(LogDriver *d, const gchar *body); void afstomp_dd_set_persistent(LogDriver *d, gboolean persistent); void afstomp_dd_set_ack(LogDriver *d, gboolean ack); void afstomp_dd_set_user(LogDriver *d, const gchar *user); void afstomp_dd_set_password(LogDriver *d, const gchar *password); void afstomp_dd_set_value_pairs(LogDriver *d, ValuePairs *vp); LogTemplateOptions *afstomp_dd_get_template_options(LogDriver *s); #endif syslog-ng-syslog-ng-3.13.2/modules/afstomp/stomp.c000066400000000000000000000200751321171025300220700ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Viktor Tusa * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stomp.h" #include "host-resolve.h" #include "str-utils.h" #include "messages.h" #include #include #include #include #include #include #define STOMP_PARSE_HEADER 1 #define STOMP_PARSE_DATA 2 #define STOMP_PARSE_ERROR 0 void stomp_frame_init(stomp_frame *frame, const char *command, int command_len) { frame->command = g_strndup(command, command_len); frame->headers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); frame->body_length = -1; frame->body = NULL; }; void stomp_frame_add_header(stomp_frame *frame, const char *name, const char *value) { msg_debug("Adding header", evt_tag_str("name",name), evt_tag_str("value",value)); g_hash_table_insert(frame->headers, g_strdup(name), g_strdup(value)); }; void stomp_frame_add_header_len(stomp_frame *frame, const char *name, int name_len, const char *value, int value_len) { char *name_slice = g_strndup(name, name_len); char *value_slice = g_strndup(value, value_len); msg_debug("Adding header", evt_tag_str("name",name_slice), evt_tag_str("value",value_slice)); g_hash_table_insert(frame->headers, name_slice, value_slice); }; void stomp_frame_set_body(stomp_frame *frame, const char *body, int body_len) { frame->body = g_strndup(body, body_len); frame->body_length = body_len; }; int stomp_frame_deinit(stomp_frame *frame) { g_hash_table_destroy(frame->headers); g_free(frame->command); g_free(frame->body); return TRUE; } static void _stomp_connection_free(stomp_connection *conn) { g_sockaddr_unref(conn->remote_sa); g_free(conn); } int stomp_connect(stomp_connection **connection_ref, char *hostname, int port) { stomp_connection *conn; conn = g_new0(stomp_connection, 1); conn->socket = socket(AF_INET, SOCK_STREAM, 0); if (conn->socket == -1) { msg_error("Failed to create socket!"); return FALSE; } if (!resolve_hostname_to_sockaddr(&conn->remote_sa, AF_INET, hostname)) { msg_error("Failed to resolve hostname in stomp driver", evt_tag_str("hostname", hostname)); return FALSE; } g_sockaddr_set_port(conn->remote_sa, port); if (!g_connect(conn->socket, conn->remote_sa)) { msg_error("Stomp connection failed", evt_tag_str("host", hostname)); _stomp_connection_free(conn); return FALSE; } (*connection_ref) = conn; return TRUE; }; int stomp_disconnect(stomp_connection **connection_ref) { stomp_connection *conn = *connection_ref; if (!conn) return TRUE; shutdown(conn->socket, SHUT_RDWR); close(conn->socket); _stomp_connection_free(conn); *connection_ref = NULL; return TRUE; }; static void write_header_into_gstring(gpointer key, gpointer value, gpointer userdata) { GString *str = (GString *) userdata; if (key == NULL || value == NULL) return; g_string_append(str, key); g_string_append_c(str, ':'); g_string_append(str, value); g_string_append_c(str, '\n'); } static int write_gstring_to_socket(int fd, GString *data) { int res = 0; int remaining = data->len; while ((remaining > 0) && (res >= 0)) { res = write(fd, data->str + (data->len - remaining), remaining); if (res > 0) remaining = remaining - res; } if (res < 0) { msg_error("Error happened during write", evt_tag_errno("errno", errno)); return FALSE; } return TRUE; } static int stomp_read_data(stomp_connection *connection, GString *buffer) { char tmp_buf[4096]; int res; res = read(connection->socket, tmp_buf, sizeof(tmp_buf)); if (res < 0) return FALSE; g_string_assign_len(buffer, tmp_buf, res); while (res == sizeof(tmp_buf)) { res = read(connection->socket, tmp_buf, sizeof(tmp_buf)); g_string_append_len(buffer, tmp_buf, res); } return TRUE; } static int stomp_parse_command(char *buffer, int buflen, stomp_frame *frame, char **out_pos) { char *pos; pos = g_strstr_len(buffer, buflen, "\n"); if (pos == NULL) return STOMP_PARSE_ERROR; stomp_frame_init(frame, buffer, pos - buffer); *out_pos = pos + 1; return STOMP_PARSE_HEADER; } static int stomp_parse_header(char *buffer, int buflen, stomp_frame *frame, char **out_pos) { char *pos, *colon; if (buflen <= 1) { *out_pos = buffer; return STOMP_PARSE_DATA; } pos = g_strstr_len(buffer, buflen, "\n"); if (pos == buffer) { *out_pos = pos + 1; return STOMP_PARSE_DATA; } colon = g_strstr_len(buffer, pos - buffer, ":"); stomp_frame_add_header_len(frame, buffer, colon - buffer, colon + 1, pos - colon - 1); *out_pos = pos + 1; return STOMP_PARSE_HEADER; }; int stomp_parse_frame(GString *data, stomp_frame *frame) { char *pos; int res; res = stomp_parse_command(data->str, data->len, frame, &pos); if (!res) return FALSE; res = stomp_parse_header(pos, data->str + data->len - pos, frame, &pos); while (res == STOMP_PARSE_HEADER) { res = stomp_parse_header(pos, data->str + data->len - pos, frame, &pos); } frame->body = g_strndup(pos, data->len - (pos - data->str)); return TRUE; } int stomp_receive_frame(stomp_connection *connection, stomp_frame *frame) { GString *data = g_string_sized_new(4096); int res; if (!stomp_read_data(connection, data)) { g_string_free(data, TRUE); return FALSE; } res = stomp_parse_frame(data, frame); msg_debug("Frame received", evt_tag_str("command",frame->command)); g_string_free(data, TRUE); return res; } static int stomp_check_for_frame(stomp_connection *connection) { struct pollfd pfd; pfd.fd = connection->socket; pfd.events = POLLIN | POLLPRI; poll(&pfd, 1, 0); if (pfd.revents & ( POLLIN | POLLPRI)) { stomp_frame frame; if (!stomp_receive_frame(connection, &frame)) return FALSE; if (!strcmp(frame.command, "ERROR")) { msg_error("ERROR frame received from stomp_server"); stomp_frame_deinit(&frame); return FALSE; } /* According to stomp protocol, here only ERROR or RECEIPT frames can come, so we missed a RECEIPT frame here, our bad. */ stomp_frame_deinit(&frame); return TRUE; } return TRUE; } GString * create_gstring_from_frame(stomp_frame *frame) { GString *data = g_string_new(""); g_string_append(data, frame->command); g_string_append_c(data, '\n'); g_hash_table_foreach(frame->headers, write_header_into_gstring, data); g_string_append_c(data, '\n'); if (frame->body) g_string_append_len(data, frame->body, frame->body_length); g_string_append_c(data, 0); return data; } int stomp_write(stomp_connection *connection, stomp_frame *frame) { GString *data; if (!stomp_check_for_frame(connection)) return FALSE; data = create_gstring_from_frame(frame); if (!write_gstring_to_socket(connection->socket, data)) { msg_error("Write error, partial write"); stomp_frame_deinit(frame); g_string_free(data, TRUE); return FALSE; } g_string_free(data, TRUE); stomp_frame_deinit(frame); return TRUE; } syslog-ng-syslog-ng-3.13.2/modules/afstomp/stomp.h000066400000000000000000000040021321171025300220650ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Viktor Tusa * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STOMP_H #define STOMP_H #include "gsocket.h" #include typedef struct stomp_connection { int socket; GSockAddr *remote_sa; char *remote_ip; } stomp_connection; typedef struct stomp_frame { char *command; GHashTable* headers; char *body; int body_length; } stomp_frame; void stomp_frame_init(stomp_frame *frame, const char *command, int command_len); void stomp_frame_add_header(stomp_frame *frame, const char *name, const char *value); void stomp_frame_set_body(stomp_frame *frame, const char *body, int body_len); int stomp_frame_deinit(stomp_frame *frame); int stomp_connect(stomp_connection **connection_ref, char *hostname, int port); int stomp_disconnect(stomp_connection **connection_ref); int stomp_write(stomp_connection *connection, stomp_frame *frame); int stomp_read(stomp_connection *connection, stomp_frame **frame); int stomp_parse_frame(GString *data, stomp_frame *frame); int stomp_receive_frame(stomp_connection *connection, stomp_frame *frame); GString *create_gstring_from_frame(stomp_frame *frame); #endif syslog-ng-syslog-ng-3.13.2/modules/afstomp/tests/000077500000000000000000000000001321171025300217205ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afstomp/tests/Makefile.am000066400000000000000000000007221321171025300237550ustar00rootroot00000000000000if ENABLE_STOMP modules_afstomp_tests_test_stomp_proto_CFLAGS = \ $(TEST_CFLAGS) \ -I$(top_srcdir)/modules/afstomp modules_afstomp_tests_test_stomp_proto_LDADD = \ $(TEST_LDADD) $(MODULE_DEPS_LIBS) modules_afstomp_tests_test_stomp_proto_LDFLAGS = \ -dlpreopen $(top_builddir)/modules/afstomp/libafstomp.la modules_afstomp_tests_TESTS = \ modules/afstomp/tests/test_stomp_proto check_PROGRAMS += \ $(modules_afstomp_tests_TESTS) endif syslog-ng-syslog-ng-3.13.2/modules/afstomp/tests/test_stomp_proto.c000066400000000000000000000061601321171025300255130ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Viktor Tusa * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stomp.h" #include "testutils.h" void assert_stomp_header(stomp_frame *frame, char *key, char *value) { char *myvalue = g_hash_table_lookup(frame->headers, key); assert_string(myvalue, value, "Stomp header assertion failed!"); } void assert_stomp_command(stomp_frame *frame, char *command) { assert_string(frame->command, command, "Stomp command assertion failed"); } void assert_stomp_body(stomp_frame *frame, char *body) { assert_string(frame->body, body, "Stomp body assertion failed"); } void test_only_command(void) { stomp_frame frame; stomp_parse_frame(g_string_new("CONNECTED\n\n"), &frame); assert_stomp_command(&frame, "CONNECTED"); stomp_frame_deinit(&frame); } void test_command_and_data(void) { stomp_frame frame; stomp_parse_frame(g_string_new("CONNECTED\n\nalmafa"), &frame); assert_stomp_command(&frame, "CONNECTED"); assert_stomp_body(&frame, "almafa"); stomp_frame_deinit(&frame); }; void test_command_and_header_and_data(void) { stomp_frame frame; stomp_parse_frame(g_string_new("CONNECTED\nheader_name:header_value\n\nbelafa"), &frame); assert_stomp_command(&frame, "CONNECTED"); assert_stomp_header(&frame, "header_name", "header_value"); assert_stomp_body(&frame, "belafa"); stomp_frame_deinit(&frame); }; void test_command_and_header(void) { stomp_frame frame; stomp_parse_frame(g_string_new("CONNECTED\nsession:ID:tusa-38077-1378214843533-2:1\n"), &frame); assert_stomp_command(&frame, "CONNECTED"); assert_stomp_header(&frame, "session", "ID:tusa-38077-1378214843533-2:1"); stomp_frame_deinit(&frame); }; void test_generate_gstring_from_frame(void) { stomp_frame frame; GString *actual; stomp_frame_init(&frame, "SEND", sizeof("SEND")); stomp_frame_add_header(&frame, "header_name", "header_value"); stomp_frame_set_body(&frame, "body", sizeof("body")); actual = create_gstring_from_frame(&frame); assert_string(actual->str, "SEND\nheader_name:header_value\n\nbody", "Generated stomp frame does not match"); stomp_frame_deinit(&frame); }; int main(void) { test_only_command(); test_command_and_data(); test_command_and_header_and_data(); test_command_and_header(); test_generate_gstring_from_frame(); } syslog-ng-syslog-ng-3.13.2/modules/afstreams/000077500000000000000000000000001321171025300210725ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afstreams/CMakeLists.txt000066400000000000000000000021141321171025300236300ustar00rootroot00000000000000set(AFSTREAMS_SOURCES afstreams.c afstreams.h afstreams-parser.c afstreams-parser.h afstreams-plugin.c ${CMAKE_CURRENT_BINARY_DIR}/afstreams-grammar.h ${CMAKE_CURRENT_BINARY_DIR}/afstreams-grammar.c ) include (CheckIncludeFile) check_include_file(sys/strlog.h HAVE_STRLOG) check_include_file(stropts.h HAVE_STROPTS) if(HAVE_STRLOG AND HAVE_STROPTS) option(ENABLE_SUN_STREAMS "Enable Sun Streams source" ON) else() option(ENABLE_SUN_STREAMS "Enable Sun Streams source" OFF) endif() if (ENABLE_SUN_STREAMS) generate_y_from_ym(modules/afstreams/afstreams-grammar) bison_target(StreamsGrammar ${CMAKE_CURRENT_BINARY_DIR}/afstreams-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/afstreams-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) add_library(afstreams MODULE ${AFSTREAMS_SOURCES}) target_include_directories (afstreams PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(afstreams PRIVATE syslog-ng) install(TARGETS afstreams LIBRARY DESTINATION lib/syslog-ng/ COMPONENT afstreams) endif() syslog-ng-syslog-ng-3.13.2/modules/afstreams/Makefile.am000066400000000000000000000021671321171025300231340ustar00rootroot00000000000000if ENABLE_SUN_STREAMS module_LTLIBRARIES += modules/afstreams/libafstreams.la modules_afstreams_libafstreams_la_SOURCES = \ modules/afstreams/afstreams.c \ modules/afstreams/afstreams.h \ modules/afstreams/afstreams-grammar.y \ modules/afstreams/afstreams-parser.c \ modules/afstreams/afstreams-parser.h \ modules/afstreams/afstreams-plugin.c modules_afstreams_libafstreams_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/afstreams \ -I$(top_builddir)/modules/afstreams modules_afstreams_libafstreams_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_afstreams_libafstreams_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_afstreams_libafstreams_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) modules/afstreams modules/afstreams/ mod-afstreams mod-streams: \ modules/afstreams/libafstreams.la else modules/afstreams modules/afstreams/ mod-afstreams mod-streams: endif BUILT_SOURCES += \ modules/afstreams/afstreams-grammar.y \ modules/afstreams/afstreams-grammar.c \ modules/afstreams/afstreams-grammar.h EXTRA_DIST += \ modules/afstreams/afstreams-grammar.ym .PHONY: modules/afstreams/ mod-afstreams mod-streams syslog-ng-syslog-ng-3.13.2/modules/afstreams/afstreams-grammar.ym000066400000000000000000000041631321171025300250560ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code top { #include "afstreams-parser.h" } %code { #include "afstreams.h" #include "cfg-parser.h" #include "afstreams-grammar.h" #include "messages.h" extern LogDriver *last_driver; } %name-prefix "afstreams_" /* this parameter is needed in order to instruct bison to use a complete * argument list for yylex/yyerror */ %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogDriver **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_DOOR 10020 %token KW_SUN_STREAMS 10021 %type source_afstreams %type source_afstreams_params %% start : LL_CONTEXT_SOURCE source_afstreams { YYACCEPT; } ; source_afstreams : KW_SUN_STREAMS '(' source_afstreams_params ')' { $$ = $3; } ; source_afstreams_params : string { last_driver = *instance = afstreams_sd_new($1, configuration); } source_afstreams_options { $$ = last_driver; free($1); } ; source_afstreams_options : source_afstreams_option source_afstreams_options | ; source_afstreams_option : KW_DOOR '(' string ')' { afstreams_sd_set_sundoor(last_driver, $3); free($3); } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/afstreams/afstreams-parser.c000066400000000000000000000032071321171025300245170ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afstreams.h" #include "cfg-parser.h" #include "afstreams-grammar.h" extern int afstreams_debug; int afstreams_parse(CfgLexer *lexer, LogDriver **instance, gpointer arg); static CfgLexerKeyword afstreams_keywords[] = { { "sun_stream", KW_SUN_STREAMS }, { "sun_streams", KW_SUN_STREAMS }, { "door", KW_DOOR }, { NULL } }; CfgParser afstreams_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &afstreams_debug, #endif .name = "afstreams", .keywords = afstreams_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer)) afstreams_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(afstreams_, LogDriver **) syslog-ng-syslog-ng-3.13.2/modules/afstreams/afstreams-parser.h000066400000000000000000000022271321171025300245250ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSOCKET_PARSER_H_INCLUDED #define AFSOCKET_PARSER_H_INCLUDED #include "cfg-parser.h" #include "driver.h" extern CfgParser afstreams_parser; CFG_PARSER_DECLARE_LEXER_BINDING(afstreams_, LogDriver **) #endif syslog-ng-syslog-ng-3.13.2/modules/afstreams/afstreams-plugin.c000066400000000000000000000032531321171025300245220ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "plugin.h" #include "plugin-types.h" extern CfgParser afstreams_parser; static Plugin afstreams_plugins[] = { { .type = LL_CONTEXT_SOURCE, .name = "sun-streams", .parser = &afstreams_parser, }, }; gboolean afstreams_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, afstreams_plugins, G_N_ELEMENTS(afstreams_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "afstreams", .version = SYSLOG_NG_VERSION, .description = "The afstreams module provides Solaris STREAMS logging device support for syslog-ng", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = afstreams_plugins, .plugins_len = G_N_ELEMENTS(afstreams_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/afstreams/afstreams.c000066400000000000000000000176261321171025300232370ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afstreams.h" #include "messages.h" #include "logreader.h" #include "fdhelpers.h" #include "apphook.h" #include "stats/stats-registry.h" #include "poll-fd-events.h" #include "logproto/logproto-dgram-server.h" typedef struct _AFStreamsSourceDriver { LogSrcDriver super; GString *dev_filename; GString *door_filename; gint door_fd; LogReader *reader; LogReaderOptions reader_options; } AFStreamsSourceDriver; #include #include #include #include #include #include #include #if SYSLOG_NG_HAVE_DOOR_H #include #endif static gssize log_transport_streams_read(LogTransport *self, void *buf, gsize buflen, GSockAddr **sa) { struct strbuf ctl, data; struct log_ctl lc; gint flags; gint res; gchar tmpbuf[buflen]; gint len; ctl.maxlen = ctl.len = sizeof(lc); ctl.buf = (char *) &lc; data.maxlen = buflen; data.len = 0; data.buf = tmpbuf; flags = 0; res = getmsg(self->fd, &ctl, &data, &flags); if (res == -1) return -1; else if ((res & (MORECTL+MOREDATA)) == 0) { len = g_snprintf(buf, buflen, "<%d>%.*s", lc.pri, data.len, data.buf); return MIN(len, buflen); } else { msg_error("Insufficient buffer space for retrieving STREAMS log message", evt_tag_printf("res", "%x", res)); } return 0; } LogTransport * log_transport_streams_new(gint fd) { LogTransport *self = g_new0(LogTransport, 1); log_transport_init_instance(self, fd); self->cond = G_IO_IN; self->read = log_transport_streams_read; self->free_fn = log_transport_free_method; return self; } void afstreams_sd_set_sundoor(LogDriver *s, gchar *filename) { AFStreamsSourceDriver *self = (AFStreamsSourceDriver *) s; self->door_filename = g_string_new(filename); } static void afstreams_sd_door_server_proc(void *cookie, char *argp, size_t arg_size, door_desc_t *dp, uint_t n_desc) { door_return(NULL, 0, NULL, 0); return; } static void afstreams_init_door(int hook_type G_GNUC_UNUSED, gpointer user_data) { AFStreamsSourceDriver *self = (AFStreamsSourceDriver *) user_data; struct stat st; gint fd; if (stat(self->door_filename->str, &st) == -1) { /* file does not exist, create it */ fd = creat(self->door_filename->str, 0666); if (fd == -1) { msg_error("Error creating syslog door file", evt_tag_str(EVT_TAG_FILENAME, self->door_filename->str), evt_tag_errno(EVT_TAG_OSERROR, errno)); close(fd); return; } } fdetach(self->door_filename->str); self->door_fd = door_create(afstreams_sd_door_server_proc, NULL, 0); if (self->door_fd == -1) { msg_error("Error creating syslog door", evt_tag_str(EVT_TAG_FILENAME, self->door_filename->str), evt_tag_errno(EVT_TAG_OSERROR, errno)); return; } g_fd_set_cloexec(self->door_fd, TRUE); if (fattach(self->door_fd, self->door_filename->str) == -1) { msg_error("Error attaching syslog door", evt_tag_str(EVT_TAG_FILENAME, self->door_filename->str), evt_tag_errno(EVT_TAG_OSERROR, errno)); close(self->door_fd); self->door_fd = -1; return; } } static gboolean afstreams_sd_init(LogPipe *s) { AFStreamsSourceDriver *self = (AFStreamsSourceDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); gint fd; if (!log_src_driver_init_method(s)) return FALSE; log_reader_options_init(&self->reader_options, cfg, self->super.super.group); fd = open(self->dev_filename->str, O_RDONLY | O_NOCTTY | O_NONBLOCK); if (fd != -1) { struct strioctl ioc; g_fd_set_cloexec(fd, TRUE); memset(&ioc, 0, sizeof(ioc)); ioc.ic_cmd = I_CONSLOG; if (ioctl(fd, I_STR, &ioc) < 0) { msg_error("Error in ioctl(I_STR, I_CONSLOG)", evt_tag_str(EVT_TAG_FILENAME, self->dev_filename->str), evt_tag_errno(EVT_TAG_OSERROR, errno)); close(fd); return FALSE; } g_fd_set_nonblock(fd, TRUE); self->reader = log_reader_new(cfg); log_reader_reopen(self->reader, log_proto_dgram_server_new(log_transport_streams_new(fd), &self->reader_options.proto_options.super), poll_fd_events_new(fd)); log_reader_set_options(self->reader, s, &self->reader_options, self->super.super.id, self->dev_filename->str); log_pipe_append((LogPipe *) self->reader, s); if (self->door_filename) { /* door creation is deferred, because it creates threads which is * not inherited through forks, and syslog-ng forks during * startup, but _after_ the configuration was initialized */ register_application_hook(AH_POST_DAEMONIZED, afstreams_init_door, self); } if (!log_pipe_init((LogPipe *) self->reader)) { msg_error("Error initializing log_reader, closing fd", evt_tag_int("fd", fd)); log_pipe_unref((LogPipe *) self->reader); self->reader = NULL; close(fd); return FALSE; } } else { msg_error("Error opening syslog device", evt_tag_str(EVT_TAG_FILENAME, self->dev_filename->str), evt_tag_errno(EVT_TAG_OSERROR, errno)); return FALSE; } return TRUE; } static gboolean afstreams_sd_deinit(LogPipe *s) { AFStreamsSourceDriver *self = (AFStreamsSourceDriver *) s; if (self->reader) { log_pipe_deinit((LogPipe *) self->reader); log_pipe_unref((LogPipe *) self->reader); self->reader = NULL; } if (self->door_fd != -1) { door_revoke(self->door_fd); close(self->door_fd); } if (!log_src_driver_deinit_method(s)) return FALSE; return TRUE; } static void afstreams_sd_free(LogPipe *s) { AFStreamsSourceDriver *self = (AFStreamsSourceDriver *) s; log_reader_options_destroy(&self->reader_options); if (self->dev_filename) g_string_free(self->dev_filename, TRUE); if (self->door_filename) g_string_free(self->door_filename, TRUE); log_src_driver_free(s); } LogDriver * afstreams_sd_new(gchar *filename, GlobalConfig *cfg) { AFStreamsSourceDriver *self = g_new0(AFStreamsSourceDriver, 1); log_src_driver_init_instance(&self->super, cfg); self->dev_filename = g_string_new(filename); self->super.super.super.init = afstreams_sd_init; self->super.super.super.deinit = afstreams_sd_deinit; self->super.super.super.free_fn = afstreams_sd_free; log_reader_options_defaults(&self->reader_options); self->reader_options.parse_options.flags |= LP_LOCAL; self->reader_options.parse_options.flags &= ~LP_EXPECT_HOSTNAME; self->reader_options.super.stats_level = STATS_LEVEL1; self->reader_options.super.stats_source = SCS_SUN_STREAMS; return &self->super.super; } syslog-ng-syslog-ng-3.13.2/modules/afstreams/afstreams.h000066400000000000000000000022261321171025300232320ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFSTREAMS_H_INCLUDED #define AFSTREAMS_H_INCLUDED #include "driver.h" LogDriver *afstreams_sd_new(gchar *filename, GlobalConfig *cfg); void afstreams_sd_set_sundoor(LogDriver *self, gchar *filename); #endif syslog-ng-syslog-ng-3.13.2/modules/afuser/000077500000000000000000000000001321171025300203725ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/afuser/CMakeLists.txt000066400000000000000000000014431321171025300231340ustar00rootroot00000000000000set(AFUSER_HEADERS "${CMAKE_CURRENT_BINARY_DIR}/afuser-grammar.h" "afuser-parser.h" "afuser.h" ) set(AFUSER_SOURCES "afuser-plugin.c" "afuser.c" "${CMAKE_CURRENT_BINARY_DIR}/afuser-grammar.c" "afuser-parser.c" ) generate_y_from_ym(modules/afuser/afuser-grammar) bison_target(AfuserGrammar ${CMAKE_CURRENT_BINARY_DIR}/afuser-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/afuser-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) option(ENABLE_AFUSER "Enable afuser module" ON) if (ENABLE_AFUSER) include_directories (${CMAKE_CURRENT_BINARY_DIR}) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) add_library(afuser MODULE ${AFUSER_SOURCES}) target_link_libraries(afuser PRIVATE syslog-ng) install(TARGETS afuser LIBRARY DESTINATION lib/syslog-ng COMPONENT afuser) endif() syslog-ng-syslog-ng-3.13.2/modules/afuser/Makefile.am000066400000000000000000000016271321171025300224340ustar00rootroot00000000000000module_LTLIBRARIES += modules/afuser/libafuser.la modules_afuser_libafuser_la_SOURCES = \ modules/afuser/afuser.c \ modules/afuser/afuser.h \ modules/afuser/afuser-grammar.y \ modules/afuser/afuser-parser.c \ modules/afuser/afuser-parser.h \ modules/afuser/afuser-plugin.c modules_afuser_libafuser_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/afuser \ -I$(top_builddir)/modules/afuser modules_afuser_libafuser_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_afuser_libafuser_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_afuser_libafuser_la_DEPENDENCIES= \ $(MODULE_DEPS_LIBS) BUILT_SOURCES += \ modules/afuser/afuser-grammar.y \ modules/afuser/afuser-grammar.c \ modules/afuser/afuser-grammar.h EXTRA_DIST += \ modules/afuser/afuser-grammar.ym modules/afuser modules/afuser/ mod-afuser mod-usertty: \ modules/afuser/libafuser.la .PHONY: modules/afuser/ mod-afuser mod-usertty syslog-ng-syslog-ng-3.13.2/modules/afuser/afuser-grammar.ym000066400000000000000000000032721321171025300236560ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code top { #include "afuser-parser.h" } %code { #include "afuser.h" #include "cfg-parser.h" #include "afuser-grammar.h" #include "syslog-names.h" #include "messages.h" extern LogDriver *last_driver; } %name-prefix "afuser_" /* this parameter is needed in order to instruct bison to use a complete * argument list for yylex/yyerror */ %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogDriver **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %type dest_afuser %token KW_USERTTY %% start : LL_CONTEXT_DESTINATION dest_afuser { last_driver = *instance = $2; YYACCEPT; } ; dest_afuser : KW_USERTTY '(' string ')' { $$ = afuser_dd_new($3, configuration); free($3); } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/afuser/afuser-parser.c000066400000000000000000000030251321171025300233150ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afuser.h" #include "cfg-parser.h" #include "afuser-grammar.h" extern int afuser_debug; int afuser_parse(CfgLexer *lexer, LogDriver **instance, gpointer arg); static CfgLexerKeyword afuser_keywords[] = { { "usertty", KW_USERTTY }, { NULL } }; CfgParser afuser_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &afuser_debug, #endif .name = "afuser", .keywords = afuser_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer)) afuser_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(afuser_, LogDriver **) syslog-ng-syslog-ng-3.13.2/modules/afuser/afuser-parser.h000066400000000000000000000022151321171025300233220ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFUSER_PARSER_H_INCLUDED #define AFUSER_PARSER_H_INCLUDED #include "cfg-parser.h" #include "driver.h" extern CfgParser afuser_parser; CFG_PARSER_DECLARE_LEXER_BINDING(afuser_, LogDriver **) #endif syslog-ng-syslog-ng-3.13.2/modules/afuser/afuser-plugin.c000066400000000000000000000032011321171025300233130ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "plugin.h" #include "plugin-types.h" extern CfgParser afuser_parser; static Plugin afuser_plugins[] = { { .type = LL_CONTEXT_DESTINATION, .name = "usertty", .parser = &afuser_parser, }, }; gboolean afuser_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, afuser_plugins, G_N_ELEMENTS(afuser_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "afuser", .version = SYSLOG_NG_VERSION, .description = "The afuser module provides the usertty() destination for syslog-ng", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = afuser_plugins, .plugins_len = G_N_ELEMENTS(afuser_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/afuser/afuser.c000066400000000000000000000107251321171025300220300ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "afuser.h" #include "messages.h" #include "compat/getutent.h" #include #include #include #include typedef struct _AFUserDestDriver { LogDestDriver super; GString *username; time_t disable_until; } AFUserDestDriver; #ifdef SYSLOG_NG_HAVE_UTMPX_H typedef struct utmpx UtmpEntry; static UtmpEntry * _fetch_utmp_entry(void) { return getutxent(); } static void _close_utmp(void) { endutxent(); } #else typedef struct utmp UtmpEntry; static UtmpEntry * _fetch_utmp_entry(void) { return getutent(); } static void _close_utmp(void) { endutent(); } #endif static gboolean _utmp_entry_matches(UtmpEntry *ut, GString *username) { #ifdef SYSLOG_NG_HAVE_MODERN_UTMP if (ut->ut_type != USER_PROCESS) return FALSE; #endif if (strcmp(username->str, "*") == 0) return TRUE; #ifdef SYSLOG_NG_HAVE_MODERN_UTMP if (strncmp(username->str, ut->ut_user, sizeof(ut->ut_user)) == 0) #else if (strncmp(username->str, ut->ut_name, sizeof(ut->ut_name)) == 0) #endif return TRUE; return FALSE; } G_LOCK_DEFINE_STATIC(utmp_lock); static void afuser_dd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data) { AFUserDestDriver *self = (AFUserDestDriver *) s; gchar buf[8192]; GString *timestamp; UtmpEntry *ut; time_t now; now = msg->timestamps[LM_TS_RECVD].tv_sec; if (self->disable_until && self->disable_until > now) goto finish; timestamp = g_string_sized_new(0); log_stamp_format(&msg->timestamps[LM_TS_STAMP], timestamp, TS_FMT_FULL, -1, 0); g_snprintf(buf, sizeof(buf), "%s %s %s\n", timestamp->str, log_msg_get_value(msg, LM_V_HOST, NULL), log_msg_get_value(msg, LM_V_MESSAGE, NULL)); g_string_free(timestamp, TRUE); G_LOCK(utmp_lock); while ((ut = _fetch_utmp_entry())) { if (_utmp_entry_matches(ut, self->username)) { gchar line[128]; gchar *p = line; int fd; if (ut->ut_line[0] != '/') { strcpy(line, "/dev/"); p = line + 5; } else line[0] = 0; strncpy(p, ut->ut_line, sizeof(line) - (p - line)); msg_debug("Posting message to user terminal", #ifdef SYSLOG_NG_HAVE_MODERN_UTMP evt_tag_str("user", ut->ut_user), #else evt_tag_str("user", ut->ut_name), #endif evt_tag_str("line", line)); fd = open(line, O_NOCTTY | O_APPEND | O_WRONLY | O_NONBLOCK); if (fd != -1) { if (write(fd, buf, strlen(buf)) < 0 && errno == EAGAIN) { msg_notice("Writing to the user terminal has blocked for writing, disabling for 10 minutes", evt_tag_str("user", self->username->str)); self->disable_until = now + 600; } close(fd); } } } _close_utmp(); G_UNLOCK(utmp_lock); finish: log_dest_driver_queue_method(s, msg, path_options, user_data); } void afuser_dd_free(LogPipe *s) { AFUserDestDriver *self = (AFUserDestDriver *) s; g_string_free(self->username, TRUE); log_dest_driver_free(s); } LogDriver * afuser_dd_new(gchar *user, GlobalConfig *cfg) { AFUserDestDriver *self = g_new0(AFUserDestDriver, 1); log_dest_driver_init_instance(&self->super, cfg); self->super.super.super.queue = afuser_dd_queue; self->super.super.super.free_fn = afuser_dd_free; self->username = g_string_new(user); return &self->super.super; } syslog-ng-syslog-ng-3.13.2/modules/afuser/afuser.h000066400000000000000000000021121321171025300220240ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef AFUSER_H_INCLUDED #define AFUSER_H_INCLUDED #include "driver.h" LogDriver *afuser_dd_new(gchar *user, GlobalConfig *cfg); #endif syslog-ng-syslog-ng-3.13.2/modules/appmodel/000077500000000000000000000000001321171025300207065ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/appmodel/Makefile.am000066400000000000000000000024011321171025300227370ustar00rootroot00000000000000 appmodel_sources = module_LTLIBRARIES += modules/appmodel/libappmodel.la modules_appmodel_libappmodel_la_SOURCES = \ modules/appmodel/appmodel.c \ modules/appmodel/appmodel.h \ modules/appmodel/appmodel-parser.c \ modules/appmodel/appmodel-parser.h \ modules/appmodel/appmodel-plugin.c \ modules/appmodel/appmodel-context.c \ modules/appmodel/appmodel-context.h \ modules/appmodel/app-parser-generator.c \ modules/appmodel/app-parser-generator.h \ modules/appmodel/application.c \ modules/appmodel/application.h \ modules/appmodel/appmodel-grammar.y modules_appmodel_libappmodel_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/appmodel \ -I$(top_builddir)/modules/appmodel modules_appmodel_libappmodel_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_appmodel_libappmodel_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_appmodel_libappmodel_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) BUILT_SOURCES += \ modules/appmodel/appmodel-grammar.y \ modules/appmodel/appmodel-grammar.c \ modules/appmodel/appmodel-grammar.h EXTRA_DIST += \ modules/appmodel/appmodel-grammar.ym modules/appmodel modules/appmodel/ mod-tags-parser: modules/appmodel/libappmodel.la .PHONY: modules/appmodel/ mod-tags-parser include modules/appmodel/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/modules/appmodel/app-parser-generator.c000066400000000000000000000135451321171025300251200ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "app-parser-generator.h" #include "appmodel.h" #include typedef struct _AppParserGenerator { CfgBlockGenerator super; GString *block; const gchar *topic; const gchar *included_apps; const gchar *excluded_apps; gboolean is_parsing_enabled; } AppParserGenerator; static const gchar * _get_filter_expr(Application *app, Application *base_app) { if (app->filter_expr) return app->filter_expr; if (base_app) return base_app->filter_expr; return NULL; } static const gchar * _get_parser_expr(Application *app, Application *base_app) { if (app->parser_expr) return app->parser_expr; if (base_app) return base_app->parser_expr; return NULL; } static void _generate_filter(AppParserGenerator *self, const gchar *filter_expr) { if (filter_expr) g_string_append_printf(self->block, " filter { %s };\n", filter_expr); } static void _generate_parser(AppParserGenerator *self, const gchar *parser_expr) { if (parser_expr) g_string_append_printf(self->block, " parser { %s };\n", parser_expr); } static void _generate_action(AppParserGenerator *self, Application *app) { g_string_append_printf(self->block, " rewrite { set-tag('.app.%s'); };\n", app->name); g_string_append(self->block, " flags(final);\n"); } static gboolean _is_application_included(AppParserGenerator *self, Application *app) { /* include everything if we don't have the option */ if (!self->included_apps) return TRUE; return strstr(self->included_apps, app->name) != NULL; } static gboolean _is_application_excluded(AppParserGenerator *self, Application *app) { if (!self->excluded_apps) return FALSE; return strstr(self->excluded_apps, app->name) != NULL; } static void _generate_application(Application *app, Application *base_app, gpointer user_data) { AppParserGenerator *self = (AppParserGenerator *) user_data; if (strcmp(self->topic, app->topic) != 0) return; if (!_is_application_included(self, app)) return; if (_is_application_excluded(self, app)) return; g_string_append(self->block, "channel {\n"); _generate_filter(self, _get_filter_expr(app, base_app)); _generate_parser(self, _get_parser_expr(app, base_app)); _generate_action(self, app); g_string_append(self->block, "};\n"); } static void _generate_applications(AppParserGenerator *self, AppModelContext *appmodel) { appmodel_context_iter_applications(appmodel, _generate_application, self); } static void _generate_framing(AppParserGenerator *self, AppModelContext *appmodel) { g_string_append(self->block, "\nchannel {\n" " junction {\n"); _generate_applications(self, appmodel); g_string_append(self->block, " };\n"); g_string_append(self->block, "}"); } static void _generate_empty_frame(AppParserGenerator *self) { g_string_append(self->block, "\nchannel {}"); } static gboolean _parse_auto_parse_arg(AppParserGenerator *self, CfgArgs *args) { const gchar *v = cfg_args_get(args, "auto-parse"); if (v) self->is_parsing_enabled = cfg_process_yesno(v); else self->is_parsing_enabled = TRUE; return TRUE; } static gboolean _parse_auto_parse_exclude_arg(AppParserGenerator *self, CfgArgs *args) { const gchar *v = cfg_args_get(args, "auto-parse-exclude"); if (!v) return TRUE; self->excluded_apps = g_strdup(v); return TRUE; } static gboolean _parse_auto_parse_include_arg(AppParserGenerator *self, CfgArgs *args) { const gchar *v = cfg_args_get(args, "auto-parse-include"); if (!v) return TRUE; self->included_apps = g_strdup(v); return TRUE; } static gboolean _parse_topic_arg(AppParserGenerator *self, CfgArgs *args) { self->topic = cfg_args_get(args, "topic"); if (!self->topic) { msg_error("app-parser() requires a topic() argument"); return FALSE; } return TRUE; } static gboolean _parse_arguments(AppParserGenerator *self, CfgArgs *args) { g_assert(args != NULL); if (!_parse_topic_arg(self, args)) return FALSE; if (!_parse_auto_parse_arg(self, args)) return FALSE; if (!_parse_auto_parse_exclude_arg(self, args)) return FALSE; if (!_parse_auto_parse_include_arg(self, args)) return FALSE; return TRUE; } static gboolean _generate(CfgBlockGenerator *s, GlobalConfig *cfg, CfgArgs *args, GString *result) { AppParserGenerator *self = (AppParserGenerator *) s; AppModelContext *appmodel = appmodel_get_context(cfg); if (!_parse_arguments(self, args)) return FALSE; self->block = result; if (self->is_parsing_enabled) _generate_framing(self, appmodel); else _generate_empty_frame(self); self->block = NULL; return TRUE; } CfgBlockGenerator * app_parser_generator_new(gint context, const gchar *name) { AppParserGenerator *self = g_new0(AppParserGenerator, 1); cfg_block_generator_init_instance(&self->super, context, name); self->super.generate = _generate; return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/appmodel/app-parser-generator.h000066400000000000000000000023151321171025300251160ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef APPMODEL_APPPARSER_GENERATOR_H_INCLUDED #define APPMODEL_APPPARSER_GENERATOR_H_INCLUDED #include "plugin.h" CfgBlockGenerator *app_parser_generator_new(gint context, const gchar *name); #endif syslog-ng-syslog-ng-3.13.2/modules/appmodel/application.c000066400000000000000000000031621321171025300233570ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "application.h" void application_set_filter(Application *self, const gchar *filter_expr) { g_free(self->filter_expr); self->filter_expr = g_strdup(filter_expr); } void application_set_parser(Application *self, const gchar *parser_expr) { g_free(self->parser_expr); self->parser_expr = g_strdup(parser_expr); } Application * application_new(const gchar *name, const gchar *topic) { Application *self = g_new0(Application, 1); self->name = g_strdup(name); self->topic = g_strdup(topic); return self; } void application_free(Application *self) { g_free(self->name); g_free(self->topic); g_free(self->filter_expr); g_free(self->parser_expr); g_free(self); } syslog-ng-syslog-ng-3.13.2/modules/appmodel/application.h000066400000000000000000000026471321171025300233730ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef APPMODEL_APPLICATION_H_INCLUDED #define APPMODEL_APPLICATION_H_INCLUDED #include "syslog-ng.h" typedef struct _Application { gchar *name; gchar *topic; gchar *filter_expr; gchar *parser_expr; } Application; void application_set_filter(Application *self, const gchar *filter_expr); void application_set_parser(Application *self, const gchar *parser_expr); Application *application_new(const gchar *name, const gchar *topic); void application_free(Application *s); #endif syslog-ng-syslog-ng-3.13.2/modules/appmodel/appmodel-context.c000066400000000000000000000073441321171025300243450ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "appmodel.h" #include typedef struct _AppModelContext { /* the context structure is registered into GlobalConfig, thus it must be * derived from ModuleConfig */ ModuleConfig super; GHashTable *applications; GPtrArray *application_ptrs; } AppModelContext; static gboolean _application_equal(gconstpointer v1, gconstpointer v2) { Application *r1 = (Application *) v1; Application *r2 = (Application *) v2; if (strcmp(r1->name, r2->name) != 0) return FALSE; if (strcmp(r1->topic, r2->topic) != 0) return FALSE; return TRUE; } static guint _application_hash(gconstpointer v) { Application *r = (Application *) v; return g_str_hash(r->name) + g_str_hash(r->topic); } void appmodel_context_register_application(AppModelContext *self, Application *app) { Application *orig_app; orig_app = g_hash_table_lookup(self->applications, app); if (!orig_app) { g_hash_table_insert(self->applications, app, app); g_ptr_array_add(self->application_ptrs, app); } else { g_hash_table_replace(self->applications, app, app); g_ptr_array_remove(self->application_ptrs, orig_app); g_ptr_array_add(self->application_ptrs, app); } } Application * appmodel_context_lookup_application(AppModelContext *self, const gchar *name, const gchar *topic) { Application lookup_app = { 0 }; lookup_app.name = (gchar *) name; lookup_app.topic = (gchar *) topic; return (Application *) g_hash_table_lookup(self->applications, &lookup_app); } void appmodel_context_iter_applications(AppModelContext *self, void (*foreach)(Application *app, Application *base_app, gpointer user_data), gpointer user_data) { gint i; for (i = 0; i < self->application_ptrs->len; i++) { Application *app = g_ptr_array_index(self->application_ptrs, i); if (strcmp(app->topic, "*") == 0) continue; Application *base_app = appmodel_context_lookup_application(self, app->name, "*"); foreach(app, base_app, user_data); } } void appmodel_context_free_method(ModuleConfig *s) { AppModelContext *self = (AppModelContext *) s; g_hash_table_destroy(self->applications); g_ptr_array_free(self->application_ptrs, TRUE); module_config_free_method(s); } AppModelContext * appmodel_context_new(void) { AppModelContext *self = g_new0(AppModelContext, 1); self->super.free_fn = appmodel_context_free_method; self->applications = g_hash_table_new_full(_application_hash, _application_equal, NULL, (GDestroyNotify) application_free); self->application_ptrs = g_ptr_array_new(); return self; } void appmodel_context_free(AppModelContext *self) { return module_config_free(&self->super); } syslog-ng-syslog-ng-3.13.2/modules/appmodel/appmodel-context.h000066400000000000000000000032401321171025300243410ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef APPMODEL_CONTEXT_H_INCLUDED #define APPMODEL_CONTEXT_H_INCLUDED 1 #include "module-config.h" #include "application.h" typedef struct _AppModelContext AppModelContext; void appmodel_context_iter_applications(AppModelContext *self, void (*foreach)(Application *app, Application *base_app, gpointer user_data), gpointer user_data); Application *appmodel_context_lookup_application(AppModelContext *self, const gchar *name, const gchar *topic); void appmodel_context_register_application(AppModelContext *self, Application *app); void appmodel_context_free(AppModelContext *self); AppModelContext *appmodel_context_new(void); #endif syslog-ng-syslog-ng-3.13.2/modules/appmodel/appmodel-grammar.ym000066400000000000000000000050301321171025300245000ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code top { #include "appmodel.h" #include "appmodel-parser.h" } %code { #include "cfg-parser.h" #include "cfg-grammar.h" #include "appmodel-grammar.h" #include "messages.h" Application *last_application; } %name-prefix "appmodel_" /* this parameter is needed in order to instruct bison to use a complete * argument list for yylex/yyerror */ %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {gpointer *instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_APPLICATION %type application_definition %% start : LL_CONTEXT_ROOT application_definition { appmodel_register_application(configuration, last_application); *instance = last_application; YYACCEPT; } ; application_definition : KW_APPLICATION string '[' string ']' { last_application = application_new($2, $4); } '{' application_options '}' { $$ = last_application; } ; application_options : application_option ';' application_options | ; application_option : KW_FILTER { cfg_lexer_push_context(lexer, LL_CONTEXT_BLOCK_CONTENT, NULL, "app filter block"); } LL_BLOCK { cfg_lexer_pop_context(lexer); } { application_set_filter(last_application, $3); } | KW_PARSER { cfg_lexer_push_context(lexer, LL_CONTEXT_BLOCK_CONTENT, NULL, "app parser block"); } LL_BLOCK { cfg_lexer_pop_context(lexer); } { application_set_parser(last_application, $3); } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/appmodel/appmodel-parser.c000066400000000000000000000030021321171025300241400ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "appmodel.h" #include "cfg-parser.h" #include "appmodel-grammar.h" extern int appmodel_debug; int appmodel_parse(CfgLexer *lexer, gpointer *instance, gpointer arg); static CfgLexerKeyword appmodel_keywords[] = { { "application", KW_APPLICATION }, { NULL } }; CfgParser appmodel_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &appmodel_debug, #endif .name = "appmodel", .keywords = appmodel_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer)) appmodel_parse, .cleanup = NULL, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(appmodel_, gpointer *) syslog-ng-syslog-ng-3.13.2/modules/appmodel/appmodel-parser.h000066400000000000000000000022261321171025300241540ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef APPMODEL_PARSER_H_INCLUDED #define APPMODEL_PARSER_H_INCLUDED #include "cfg-parser.h" #include "cfg-lexer.h" extern CfgParser appmodel_parser; CFG_PARSER_DECLARE_LEXER_BINDING(appmodel_, gpointer *) #endif syslog-ng-syslog-ng-3.13.2/modules/appmodel/appmodel-plugin.c000066400000000000000000000037401321171025300241530ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "appmodel-parser.h" #include "app-parser-generator.h" #include "plugin.h" #include "plugin-types.h" extern CfgParser appmodel_parser; static gpointer app_parser_construct(Plugin *p) { return app_parser_generator_new(p->type, p->name); } static Plugin appmodel_plugins[] = { { .type = LL_CONTEXT_ROOT, .name = "application", .parser = &appmodel_parser, }, { .type = LL_CONTEXT_PARSER | LL_CONTEXT_FLAG_GENERATOR, .name = "app-parser", .construct = app_parser_construct } }; gboolean appmodel_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, appmodel_plugins, G_N_ELEMENTS(appmodel_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "appmodel", .version = SYSLOG_NG_VERSION, .description = "The appmodel module provides parsing support for restoring message tags as produced by the TAGS macro.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = appmodel_plugins, .plugins_len = G_N_ELEMENTS(appmodel_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/appmodel/appmodel.c000066400000000000000000000030721321171025300226550ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "appmodel.h" #include "cfg.h" #define MODULE_CONFIG_KEY "appmodel" AppModelContext * appmodel_get_context(GlobalConfig *cfg) { AppModelContext *ac = g_hash_table_lookup(cfg->module_config, MODULE_CONFIG_KEY); if (!ac) { ac = appmodel_context_new(); g_hash_table_insert(cfg->module_config, g_strdup(MODULE_CONFIG_KEY), ac); } return ac; } void appmodel_register_application(GlobalConfig *cfg, Application *application) { AppModelContext *ac = appmodel_get_context(cfg); appmodel_context_register_application(ac, application); } syslog-ng-syslog-ng-3.13.2/modules/appmodel/appmodel.h000066400000000000000000000023271321171025300226640ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef APPMODEL_H_INCLUDED #define APPMODEL_H_INCLUDED 1 #include "module-config.h" #include "appmodel-context.h" AppModelContext *appmodel_get_context(GlobalConfig *cfg); void appmodel_register_application(GlobalConfig *cfg, Application *application); #endif syslog-ng-syslog-ng-3.13.2/modules/appmodel/tests/000077500000000000000000000000001321171025300220505ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/appmodel/tests/Makefile.am000066400000000000000000000040021321171025300241000ustar00rootroot00000000000000if ENABLE_CRITERION modules_appmodel_tests_TESTS = \ modules/appmodel/tests/test_appmodel \ modules/appmodel/tests/test_appmodel_context \ modules/appmodel/tests/test_app_parser_generator \ modules/appmodel/tests/test_application check_PROGRAMS += \ ${modules_appmodel_tests_TESTS} modules_appmodel_tests_test_appmodel_CFLAGS = \ $(TEST_CFLAGS) -I$(top_srcdir)/modules/appmodel modules_appmodel_tests_test_appmodel_LDADD = \ $(TEST_LDADD) modules_appmodel_tests_test_appmodel_LDFLAGS = \ $(PREOPEN_SYSLOGFORMAT) \ -dlpreopen $(top_builddir)/modules/appmodel/libappmodel.la modules_appmodel_tests_test_appmodel_DEPENDENCIES = \ $(top_builddir)/modules/appmodel/libappmodel.la modules_appmodel_tests_test_appmodel_context_CFLAGS = \ $(TEST_CFLAGS) -I$(top_srcdir)/modules/appmodel modules_appmodel_tests_test_appmodel_context_LDADD = \ $(TEST_LDADD) modules_appmodel_tests_test_appmodel_context_LDFLAGS = \ $(PREOPEN_SYSLOGFORMAT) \ -dlpreopen $(top_builddir)/modules/appmodel/libappmodel.la modules_appmodel_tests_test_appmodel_context_DEPENDENCIES = \ $(top_builddir)/modules/appmodel/libappmodel.la modules_appmodel_tests_test_app_parser_generator_CFLAGS = \ $(TEST_CFLAGS) -I$(top_srcdir)/modules/appmodel modules_appmodel_tests_test_app_parser_generator_LDADD = \ $(TEST_LDADD) modules_appmodel_tests_test_app_parser_generator_LDFLAGS = \ $(PREOPEN_SYSLOGFORMAT) \ -dlpreopen $(top_builddir)/modules/appmodel/libappmodel.la modules_appmodel_tests_test_app_parser_generator_DEPENDENCIES = \ $(top_builddir)/modules/appmodel/libappmodel.la modules_appmodel_tests_test_application_CFLAGS = \ $(TEST_CFLAGS) -I$(top_srcdir)/modules/appmodel modules_appmodel_tests_test_application_LDADD = \ $(TEST_LDADD) modules_appmodel_tests_test_application_LDFLAGS = \ $(PREOPEN_SYSLOGFORMAT) \ -dlpreopen $(top_builddir)/modules/appmodel/libappmodel.la modules_appmodel_tests_test_application_DEPENDENCIES = \ $(top_builddir)/modules/appmodel/libappmodel.la endif syslog-ng-syslog-ng-3.13.2/modules/appmodel/tests/test_app_parser_generator.c000066400000000000000000000202461321171025300274610ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include "app-parser-generator.h" #include "apphook.h" #include "plugin-types.h" #include "config_parse_lib.h" static CfgBlockGenerator *app_parser; static GString *result; void _register_application(const char *appmodel) { cr_assert(parse_config(appmodel, LL_CONTEXT_ROOT, NULL, NULL), "Parsing the given configuration failed: %s", appmodel); } void _register_sample_application(const gchar *name, const gchar *topic) { gchar *app; app = g_strdup_printf("application %s[%s] {\n" " filter { program('%s'); };\n" " parser { kv-parser(prefix('%s.')); };\n" "};", name, topic, name, name); _register_application(app); g_free(app); } static CfgBlockGenerator * _construct_app_parser(void) { return app_parser_generator_new(LL_CONTEXT_PARSER, "app-parser"); } static CfgArgs * _build_cfg_args(const gchar *key, const gchar *value, ...) { CfgArgs *args = cfg_args_new(); va_list va; va_start(va, value); while (key) { cfg_args_set(args, key, value); key = va_arg(va, gchar *); if (!key) break; value = va_arg(va, gchar *); } va_end(va); return args; } static void _app_parser_generate_with_args(const gchar *topic, CfgArgs *args) { cfg_args_set(args, "topic", topic); cfg_block_generator_generate(app_parser, configuration, args, result); cfg_args_unref(args); } static void _app_parser_generate(const gchar *topic) { _app_parser_generate_with_args(topic, cfg_args_new()); } static void _assert_config_is_valid(const gchar *topic, const gchar *varargs) { const gchar *config_fmt = "" "parser p_test {\n" " app-parser(topic(\"%s\") %s);\n" "};\n"; gchar *config; config = g_strdup_printf(config_fmt, topic, varargs ? : ""); cr_assert(parse_config(config, LL_CONTEXT_ROOT, NULL, NULL), "Parsing the given configuration failed: %s", config); g_free(config); } static void _assert_snippet_is_present(const gchar *snippet) { cr_assert(strstr(result->str, snippet), "Can't find config snippet in generated output: %s, config: >>>%s<<<", snippet, result->str); } static void _assert_snippet_is_not_present(const gchar *snippet) { cr_assert(strstr(result->str, snippet) == NULL, "Could find config snippet which shouldn't be there in generated output: %s, config: >>>%s<<<", snippet, result->str); } static void _assert_application_is_present(const gchar *application) { const gchar *settag_fmt = "set-tag('.app.%s');"; gchar *settag_snippet = g_strdup_printf(settag_fmt, application); cr_assert(strstr(result->str, settag_snippet), "Can't find set-tag() invocation for this application: %s, snippet: %s, config: >>>%s<<<", application, settag_snippet, result->str); g_free(settag_snippet); } static void _assert_parser_framing_is_present(void) { cr_assert(g_str_has_prefix(result->str, "\nchannel"), "Cannot find app-parser() framing (prefix) >>>%s<<<", result->str); cr_assert(g_str_has_suffix(result->str, "};\n}"), "Cannot find app-parser() framing (suffix): >>>%s<<<", result->str); } static void startup(void) { app_startup(); configuration = cfg_new_snippet(); cfg_load_module(configuration, "appmodel"); app_parser = _construct_app_parser(); result = g_string_new(""); } static void teardown(void) { g_string_free(result, TRUE); app_shutdown(); } Test(app_parser_generator, app_parser_with_no_apps_registered_generates_empty_framing) { _app_parser_generate("port514"); _assert_parser_framing_is_present(); _assert_config_is_valid("port514", NULL); } Test(app_parser_generator, app_parser_generates_references_to_apps) { _register_sample_application("foo", "port514"); _register_sample_application("bar", "port514"); _app_parser_generate("port514"); _assert_parser_framing_is_present(); _assert_application_is_present("foo"); _assert_application_is_present("bar"); _assert_config_is_valid("port514", NULL); } Test(app_parser_generator, app_parser_uses_filter_or_parser_from_base_topics) { _register_application("application foo[port514] {\n" "};"); _register_sample_application("foo", "*"); _app_parser_generate("port514"); _assert_parser_framing_is_present(); _assert_application_is_present("foo"); _assert_snippet_is_present("program('foo')"); _assert_snippet_is_present("kv-parser(prefix('foo.'))"); _assert_config_is_valid("port514", NULL); } Test(app_parser_generator, app_parser_base_topics_are_skipped) { _register_sample_application("foo", "*"); _register_sample_application("bar", "*"); _app_parser_generate("port514"); _assert_parser_framing_is_present(); _assert_snippet_is_not_present("program('foo')"); _assert_snippet_is_not_present("program('bar')"); _assert_config_is_valid("port514", NULL); } Test(app_parser_generator, app_parser_is_disabled_if_auto_parse_is_set_to_no) { _register_sample_application("foo", "port514"); _register_sample_application("bar", "port514"); _app_parser_generate_with_args("port514", _build_cfg_args("auto-parse", "no", NULL)); cr_assert_str_eq(result->str, "\nchannel {}", "result is expected to be an empty channel, but it is %s", result->str); _app_parser_generate_with_args("port514", _build_cfg_args("auto-parse", "yes", NULL)); _assert_parser_framing_is_present(); _assert_snippet_is_present("program('foo')"); _assert_snippet_is_present("program('bar')"); _assert_config_is_valid("port514", "auto-parse(yes)"); } Test(app_parser_generator, app_parser_excludes_apps) { _register_sample_application("foo", "port514"); _register_sample_application("bar", "port514"); _app_parser_generate_with_args("port514", _build_cfg_args("auto-parse-exclude", "foo", NULL)); _assert_parser_framing_is_present(); _assert_snippet_is_not_present("program('foo')"); _assert_snippet_is_present("program('bar')"); } Test(app_parser_generator, app_parser_includes_apps) { _register_sample_application("foo", "port514"); _register_sample_application("bar", "port514"); _register_sample_application("baz", "port514"); _app_parser_generate_with_args("port514", _build_cfg_args("auto-parse-include", "foo", NULL)); _assert_parser_framing_is_present(); _assert_snippet_is_present("program('foo')"); _assert_snippet_is_not_present("program('bar')"); _assert_snippet_is_not_present("program('baz')"); } Test(app_parser_generator, app_parser_includes_and_excludes_apps) { _register_sample_application("foo", "port514"); _register_sample_application("bar", "port514"); _register_sample_application("baz", "port514"); _app_parser_generate_with_args("port514", _build_cfg_args("auto-parse-include", "foo,bar", "auto-parse-exclude", "bar", NULL)); _assert_parser_framing_is_present(); _assert_snippet_is_present("program('foo')"); _assert_snippet_is_not_present("program('bar')"); _assert_snippet_is_not_present("program('baz')"); } TestSuite(app_parser_generator, .init = startup, .fini = teardown); syslog-ng-syslog-ng-3.13.2/modules/appmodel/tests/test_application.c000066400000000000000000000040401321171025300255540ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include "application.h" Test(application, empty_application_can_be_created_and_freed) { Application *app; app = application_new("foobar", "*"); application_free(app); } Test(application, filter_can_be_set_and_queried) { Application *app; const gchar *filter_expr = "'1' eq '1'"; const gchar *filter_expr2 = "'2' eq '2'"; app = application_new("foobar", "*"); application_set_filter(app, filter_expr); cr_assert_str_eq(app->filter_expr, filter_expr); application_set_filter(app, filter_expr2); cr_assert_str_eq(app->filter_expr, filter_expr2); application_free(app); } Test(application, parser_can_be_set_and_queried) { Application *app; const gchar *parser_expr = "kv-parser();"; const gchar *parser_expr2 = "csv-parser();"; app = application_new("foobar", "*"); application_set_parser(app, parser_expr); cr_assert_str_eq(app->parser_expr, parser_expr); application_set_parser(app, parser_expr2); cr_assert_str_eq(app->parser_expr, parser_expr2); application_free(app); } syslog-ng-syslog-ng-3.13.2/modules/appmodel/tests/test_appmodel.c000066400000000000000000000064061321171025300250620ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include "appmodel.h" #include "application.h" #include "plugin.h" #include "apphook.h" #include "cfg-grammar.h" #include "config_parse_lib.h" Application * _parse_application(const char *appmodel, const gchar *name, const gchar *topic) { AppModelContext *ac; cfg_load_module(configuration, "appmodel"); cr_assert(parse_config(appmodel, LL_CONTEXT_ROOT, NULL, NULL), "Parsing the given configuration failed: %s", appmodel); ac = appmodel_get_context(configuration); return appmodel_context_lookup_application(ac, name, topic); } Test(appmodel, empty_application_can_be_parsed_properly) { Application *app; app = _parse_application("application foobar[*] {};", "foobar", "*"); cr_assert(app != NULL); cr_assert_str_eq(app->name, "foobar"); cr_assert_str_eq(app->topic, "*"); } Test(appmodel, name_is_parsed_into_name_member) { Application *app; app = _parse_application("application name[*] {};", "name", "*"); cr_assert(app != NULL); } Test(appmodel, topic_in_brackets_is_parsed_into_topic) { Application *app; app = _parse_application("application name[port514] {};", "name", "port514"); cr_assert(app != NULL); cr_assert_str_eq(app->topic, "port514"); } Test(appmodel, filter_expressions_can_be_specified_with_a_filter_keyword) { Application *app; app = _parse_application( "application name[port514] {" " filter { program(\"kernel\"); };" " parser { kv-parser(); };" "};", "name", "port514"); cr_assert(app != NULL); cr_assert_str_eq(app->topic, "port514"); cr_assert_str_eq(app->filter_expr, " program(\"kernel\"); "); } Test(appmodel, parser_expressions_can_be_specified_with_a_parser_keyword) { Application *app; app = _parse_application( "application name[port514] {" " parser { kv-parser(); };" " filter { program(\"kernel\"); };" "};", "name", "port514"); cr_assert(app != NULL); cr_assert_str_eq(app->topic, "port514"); cr_assert_str_eq(app->parser_expr, " kv-parser(); "); } static void setup(void) { app_startup(); configuration = cfg_new_snippet(); } void teardown(void) { cfg_free(configuration); app_shutdown(); } TestSuite(appmodel, .init = setup, .fini = teardown); syslog-ng-syslog-ng-3.13.2/modules/appmodel/tests/test_appmodel_context.c000066400000000000000000000061311321171025300266210ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balazs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include "appmodel.h" static AppModelContext *ac; static void startup(void) { ac = appmodel_context_new(); } static void teardown(void) { appmodel_context_free(ac); ac = NULL; } Test(appmodel_context, register_application_makes_the_app_available) { appmodel_context_register_application(ac, application_new("foobar", "*")); appmodel_context_lookup_application(ac, "foobar", "*"); } static void _foreach_app(Application *app, Application *base_app, gpointer user_data) { GString *result = (GString *) user_data; g_string_append(result, app->name); } Test(appmodel_context, iter_applications_enumerates_apps_without_asterisk) { GString *result = g_string_sized_new(128); appmodel_context_register_application(ac, application_new("foo", "*")); appmodel_context_register_application(ac, application_new("foo", "port514")); appmodel_context_register_application(ac, application_new("bar", "*")); appmodel_context_register_application(ac, application_new("bar", "port514")); appmodel_context_register_application(ac, application_new("baz", "*")); appmodel_context_register_application(ac, application_new("baz", "port514")); appmodel_context_iter_applications(ac, _foreach_app, result); cr_assert_str_eq(result->str, "foobarbaz"); g_string_free(result, TRUE); } Test(appmodel_context, iter_applications_enumerates_apps_in_the_order_of_registration) { GString *result = g_string_sized_new(128); appmodel_context_register_application(ac, application_new("baz", "*")); appmodel_context_register_application(ac, application_new("baz", "port514")); appmodel_context_register_application(ac, application_new("bar", "*")); appmodel_context_register_application(ac, application_new("bar", "port514")); appmodel_context_register_application(ac, application_new("foo", "*")); appmodel_context_register_application(ac, application_new("foo", "port514")); appmodel_context_iter_applications(ac, _foreach_app, result); cr_assert_str_eq(result->str, "bazbarfoo"); g_string_free(result, TRUE); } TestSuite(appmodel_context, .init = startup, .fini = teardown); syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/000077500000000000000000000000001321171025300212255ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/CMakeLists.txt000066400000000000000000000004651321171025300237720ustar00rootroot00000000000000set (BASICFUNCS_SOURCES basic-funcs.c ) add_library(basicfuncs MODULE ${BASICFUNCS_SOURCES}) target_include_directories (basicfuncs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(basicfuncs PRIVATE syslog-ng) install(TARGETS basicfuncs LIBRARY DESTINATION lib/syslog-ng/ COMPONENT basicfuncs) syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/Makefile.am000066400000000000000000000017431321171025300232660ustar00rootroot00000000000000module_LTLIBRARIES += modules/basicfuncs/libbasicfuncs.la modules_basicfuncs_libbasicfuncs_la_SOURCES = \ modules/basicfuncs/basic-funcs.c modules_basicfuncs_libbasicfuncs_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/basicfuncs modules_basicfuncs_libbasicfuncs_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_basicfuncs_libbasicfuncs_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_basicfuncs_libbasicfuncs_la_DEPENDENCIES= \ $(MODULE_DEPS_LIBS) EXTRA_DIST += \ modules/basicfuncs/cond-funcs.c \ modules/basicfuncs/context-funcs.c \ modules/basicfuncs/numeric-funcs.c \ modules/basicfuncs/str-funcs.c \ modules/basicfuncs/fname-funcs.c \ modules/basicfuncs/ip-funcs.c \ modules/basicfuncs/misc-funcs.c \ modules/basicfuncs/list-funcs.c \ modules/basicfuncs/tf-template.c modules/basicfuncs modules/basicfuncs/ mod-basicfuncs: modules/basicfuncs/libbasicfuncs.la .PHONY: modules/basicfuncs/ mod-basicfuncs include modules/basicfuncs/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/basic-funcs.c000066400000000000000000000104641321171025300235730ustar00rootroot00000000000000/* * Copyright (c) 2010-2015 Balabit * Copyright (c) 2010-2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "plugin.h" #include "template/simple-function.h" #include "filter/filter-expr.h" #include "filter/filter-expr-parser.h" #include "cfg.h" #include "parse-number.h" #include "str-format.h" #include "plugin-types.h" #include #include #include /* in order to avoid having to declare all construct functions, we * include them all here. If it causes compilation times to increase * drastically, we should probably make them into separate compilation * units. (Bazsi) */ #include "numeric-funcs.c" #include "str-funcs.c" #include "cond-funcs.c" #include "ip-funcs.c" #include "misc-funcs.c" #include "list-funcs.c" #include "tf-template.c" #include "context-funcs.c" #include "fname-funcs.c" static Plugin basicfuncs_plugins[] = { /* cond-funcs */ TEMPLATE_FUNCTION_PLUGIN(tf_grep, "grep"), TEMPLATE_FUNCTION_PLUGIN(tf_if, "if"), TEMPLATE_FUNCTION_PLUGIN(tf_or, "or"), /* context related funcs */ TEMPLATE_FUNCTION_PLUGIN(tf_context_lookup, "context-lookup"), TEMPLATE_FUNCTION_PLUGIN(tf_context_length, "context-length"), TEMPLATE_FUNCTION_PLUGIN(tf_context_values, "context-values"), /* str-funcs */ TEMPLATE_FUNCTION_PLUGIN(tf_echo, "echo"), TEMPLATE_FUNCTION_PLUGIN(tf_length, "length"), TEMPLATE_FUNCTION_PLUGIN(tf_substr, "substr"), TEMPLATE_FUNCTION_PLUGIN(tf_strip, "strip"), TEMPLATE_FUNCTION_PLUGIN(tf_sanitize, "sanitize"), TEMPLATE_FUNCTION_PLUGIN(tf_lowercase, "lowercase"), TEMPLATE_FUNCTION_PLUGIN(tf_uppercase, "uppercase"), TEMPLATE_FUNCTION_PLUGIN(tf_replace_delimiter, "replace-delimiter"), TEMPLATE_FUNCTION_PLUGIN(tf_string_padding, "padding"), TEMPLATE_FUNCTION_PLUGIN(tf_binary, "binary"), /* fname-funcs */ TEMPLATE_FUNCTION_PLUGIN(tf_dirname, "dirname"), TEMPLATE_FUNCTION_PLUGIN(tf_basename, "basename"), /* list-funcs */ TEMPLATE_FUNCTION_PLUGIN(tf_list_concat, "list-concat"), TEMPLATE_FUNCTION_PLUGIN(tf_list_head, "list-head"), TEMPLATE_FUNCTION_PLUGIN(tf_list_nth, "list-nth"), TEMPLATE_FUNCTION_PLUGIN(tf_list_tail, "list-tail"), TEMPLATE_FUNCTION_PLUGIN(tf_list_slice, "list-slice"), TEMPLATE_FUNCTION_PLUGIN(tf_list_count, "list-count"), TEMPLATE_FUNCTION_PLUGIN(tf_list_append, "list-append"), /* numeric-funcs */ TEMPLATE_FUNCTION_PLUGIN(tf_num_plus, "+"), TEMPLATE_FUNCTION_PLUGIN(tf_num_minus, "-"), TEMPLATE_FUNCTION_PLUGIN(tf_num_multi, "*"), TEMPLATE_FUNCTION_PLUGIN(tf_num_div, "/"), TEMPLATE_FUNCTION_PLUGIN(tf_num_mod, "%"), TEMPLATE_FUNCTION_PLUGIN(tf_num_sum, "sum"), TEMPLATE_FUNCTION_PLUGIN(tf_num_min, "min"), TEMPLATE_FUNCTION_PLUGIN(tf_num_max, "max"), TEMPLATE_FUNCTION_PLUGIN(tf_num_average, "average"), /* ip-funcs */ TEMPLATE_FUNCTION_PLUGIN(tf_ipv4_to_int, "ipv4-to-int"), TEMPLATE_FUNCTION_PLUGIN(tf_indent_multi_line, "indent-multi-line"), /* misc funcs */ TEMPLATE_FUNCTION_PLUGIN(tf_env, "env"), TEMPLATE_FUNCTION_PLUGIN(tf_template, "template") }; gboolean basicfuncs_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, basicfuncs_plugins, G_N_ELEMENTS(basicfuncs_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "basicfuncs", .version = SYSLOG_NG_VERSION, .description = "The basicfuncs module provides various template functions for syslog-ng.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = basicfuncs_plugins, .plugins_len = G_N_ELEMENTS(basicfuncs_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/cond-funcs.c000066400000000000000000000131321321171025300234300ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * Copyright (c) 2013-2014 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ typedef struct _TFCondState { TFSimpleFuncState super; FilterExprNode *filter; gint grep_max_count; } TFCondState; gboolean tf_cond_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent, gint argc, gchar *argv[], GError **error) { TFCondState *state = (TFCondState *) s; CfgLexer *lexer; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); lexer = cfg_lexer_new_buffer(parent->cfg, argv[1], strlen(argv[1])); if (!cfg_run_parser(parent->cfg, lexer, &filter_expr_parser, (gpointer *) &state->filter, NULL)) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "$(%s) Error parsing conditional filter expression", argv[0]); return FALSE; } memmove(&argv[1], &argv[2], sizeof(argv[0]) * (argc - 2)); if (!tf_simple_func_prepare(self, s, parent, argc - 1, argv, error)) return FALSE; return TRUE; } static void tf_cond_free_state(gpointer s) { TFCondState *state = (TFCondState *) s; if (state->filter) filter_expr_unref(state->filter); tf_simple_func_free_state(&state->super); } gboolean tf_grep_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent, gint argc, gchar *argv[], GError **error) { TFCondState *state = (TFCondState *) s; GOptionContext *ctx; gint max_count = 0; GOptionEntry grep_options[] = { { "max-count", 'm', 0, G_OPTION_ARG_INT, &max_count, NULL, NULL }, { NULL } }; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); ctx = g_option_context_new(argv[0]); g_option_context_add_main_entries(ctx, grep_options, NULL); if (!g_option_context_parse(ctx, &argc, &argv, error)) { g_option_context_free(ctx); g_free(argv); return FALSE; } g_option_context_free(ctx); if (argc < 3) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "$(%s) requires at least two arguments", argv[0]); return FALSE; } state->grep_max_count = max_count; return tf_cond_prepare(self, s, parent, argc, argv, error); } /* * $(grep [opts] filter $nv1 $n2 ...) * * Options: * --max-count or -m The maximum number of matches, 0 for unlimited */ void tf_grep_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { gint i, msg_ndx; gboolean first = TRUE; TFCondState *state = (TFCondState *) s; gint count = 0; for (msg_ndx = 0; msg_ndx < args->num_messages; msg_ndx++) { LogMessage *msg = args->messages[msg_ndx]; if (filter_expr_eval(state->filter, msg)) { count++; for (i = 0; i < state->super.argc; i++) { if (!first) g_string_append_c(result, ','); /* NOTE: not recursive, as the message context is just one message */ log_template_append_format(state->super.argv[i], msg, args->opts, args->tz, args->seq_num, args->context_id, result); first = FALSE; } if (state->grep_max_count && count >= state->grep_max_count) break; } } } TEMPLATE_FUNCTION(TFCondState, tf_grep, tf_grep_prepare, NULL, tf_grep_call, tf_cond_free_state, NULL); gboolean tf_if_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent, gint argc, gchar *argv[], GError **error) { g_return_val_if_fail(error == NULL || *error == NULL, FALSE); if (argc != 4) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "$(if) requires three arguments"); return FALSE; } return tf_cond_prepare(self, s, parent, argc, argv, error); } void tf_if_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { TFCondState *state = (TFCondState *) s; if (filter_expr_eval_with_context(state->filter, args->messages, args->num_messages)) { log_template_append_format_with_context(state->super.argv[0], args->messages, args->num_messages, args->opts, args->tz, args->seq_num, args->context_id, result); } else { log_template_append_format_with_context(state->super.argv[1], args->messages, args->num_messages, args->opts, args->tz, args->seq_num, args->context_id, result); } } TEMPLATE_FUNCTION(TFCondState, tf_if, tf_if_prepare, NULL, tf_if_call, tf_cond_free_state, NULL); static void tf_or (LogMessage *msg, gint argc, GString *argv[], GString *result) { gint i; for (i = 0; i < argc; i++) { if (argv[i]->len == 0) continue; g_string_append_len (result, argv[i]->str, argv[i]->len); break; } } TEMPLATE_FUNCTION_SIMPLE(tf_or); syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/context-funcs.c000066400000000000000000000100061321171025300241660ustar00rootroot00000000000000/* * Copyright (c) 2012-2016 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ static gboolean tf_context_length_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent, gint argc, gchar *argv[], GError **error) { return TRUE; } static void tf_context_length_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { g_string_append_printf(result, "%d", args->num_messages); } static void tf_context_length_free_state(gpointer s) { } TEMPLATE_FUNCTION(NULL, tf_context_length, tf_context_length_prepare, NULL, tf_context_length_call, tf_context_length_free_state, NULL); /* * $(context-lookup [opts] filter $nv1 $n2 ...) * * Options: * --max-count or -m The maximum number of matches, 0 for unlimited * * Returns in a syslog-ng style list of all elements */ void tf_context_lookup_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { gboolean first = TRUE; TFCondState *state = (TFCondState *) s; gint count = 0; GString *buf = g_string_sized_new(64); for (gint msg_ndx = 0; msg_ndx < args->num_messages; msg_ndx++) { LogMessage *msg = args->messages[msg_ndx]; if (filter_expr_eval(state->filter, msg)) { count++; for (gint i = 0; i < state->super.argc; i++) { if (!first) g_string_append_c(result, ','); /* NOTE: not recursive, as the message context is just one message */ log_template_format(state->super.argv[i], msg, args->opts, args->tz, args->seq_num, args->context_id, buf); str_repr_encode_append(result, buf->str, buf->len, ","); first = FALSE; } if (state->grep_max_count && count >= state->grep_max_count) break; } } g_string_free(buf, TRUE); } TEMPLATE_FUNCTION(TFCondState, tf_context_lookup, tf_grep_prepare, NULL, tf_context_lookup_call, tf_cond_free_state, NULL); /* * $(context-values $nv1 $n2 ...) * * Returns in a syslog-ng style list of all specified name value pairs in the entire context. */ void tf_context_values_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { gboolean first = TRUE; TFSimpleFuncState *state = (TFSimpleFuncState *) s; GString *buf = g_string_sized_new(64); for (gint msg_ndx = 0; msg_ndx < args->num_messages; msg_ndx++) { LogMessage *msg = args->messages[msg_ndx]; for (gint i = 0; i < state->argc; i++) { if (!first) g_string_append_c(result, ','); /* NOTE: not recursive, as the message context is just one message */ log_template_format(state->argv[i], msg, args->opts, args->tz, args->seq_num, args->context_id, buf); str_repr_encode_append(result, buf->str, buf->len, ","); first = FALSE; } } g_string_free(buf, TRUE); } TEMPLATE_FUNCTION(TFSimpleFuncState, tf_context_values, tf_simple_func_prepare, tf_simple_func_eval, tf_context_values_call, tf_simple_func_free_state, NULL); syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/fname-funcs.c000066400000000000000000000026621321171025300236010ustar00rootroot00000000000000/* * Copyright (c) 2017 Balabit * Copyright (c) 2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include static void tf_basename(LogMessage *msg, gint argc, GString *argv[], GString *result) { gchar *base; base = g_path_get_basename(argv[0]->str); g_string_assign(result, base); g_free(base); } TEMPLATE_FUNCTION_SIMPLE(tf_basename); static void tf_dirname(LogMessage *msg, gint argc, GString *argv[], GString *result) { gchar *dir; dir = g_path_get_dirname(argv[0]->str); g_string_assign(result, dir); g_free(dir); } TEMPLATE_FUNCTION_SIMPLE(tf_dirname); syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/ip-funcs.c000066400000000000000000000025311321171025300231160ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "gsocket.h" static void tf_ipv4_to_int(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint i; for (i = 0; i < argc; i++) { struct in_addr ina; g_inet_aton(argv[i]->str, &ina); g_string_append_printf(result, "%lu", (gulong) ntohl(ina.s_addr)); if (i < argc - 1) g_string_append_c(result, ','); } } TEMPLATE_FUNCTION_SIMPLE(tf_ipv4_to_int); syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/list-funcs.c000066400000000000000000000144541321171025300234700ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * Copyright (c) 2016 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "scanner/list-scanner/list-scanner.h" #include "str-repr/encode.h" static void _append_comma(GString *result) { if (result->len == 0) return; if (result->str[result->len - 1] != ',') g_string_append_c(result, ','); } static void tf_list_concat(LogMessage *msg, gint argc, GString *argv[], GString *result) { ListScanner scanner; list_scanner_init(&scanner); list_scanner_input_gstring_array(&scanner, argc, argv); while (list_scanner_scan_next(&scanner)) { _append_comma(result); str_repr_encode_append(result, list_scanner_get_current_value(&scanner), -1, ","); } list_scanner_deinit(&scanner); } TEMPLATE_FUNCTION_SIMPLE(tf_list_concat); static void tf_list_append(LogMessage *msg, gint argc, GString *argv[], GString *result) { if (argc == 0) return; g_string_append_len(result, argv[0]->str, argv[0]->len); for (gint i = 1; i < argc; i++) { _append_comma(result); str_repr_encode_append(result, argv[i]->str, argv[i]->len, ","); } } TEMPLATE_FUNCTION_SIMPLE(tf_list_append); static gint _list_count(gint argc, GString *argv[]) { ListScanner scanner; gint count = 0; if (argc != 0) { list_scanner_init(&scanner); list_scanner_input_gstring_array(&scanner, argc, argv); while (list_scanner_scan_next(&scanner)) count++; list_scanner_deinit(&scanner); } return count; } static void _adjust_list_slice(gint argc, GString *argv[], gint *first_ndx, gint *last_ndx) { gint count = -1; if (*first_ndx < 0 || *last_ndx < 0) count = _list_count(argc, argv); if (*first_ndx < 0) *first_ndx += count; if (*last_ndx < 0) *last_ndx += count; } static void _list_slice(gint argc, GString *argv[], GString *result, gint first_ndx, gint last_ndx) { ListScanner scanner; gint i; if (argc == 0) return; _adjust_list_slice(argc, argv, &first_ndx, &last_ndx); /* NOTE: first_ndx and last_ndx may be negative, so these loops must cover * that case, by interpreting negative first_ndx as "0", and negative * last_ndx as "0". * * $(list-slice -100: a,b,c) - should return "a,b,c" * $(list-slice :-100 a,b,c) - should return "" */ list_scanner_init(&scanner); list_scanner_input_gstring_array(&scanner, argc, argv); i = 0; while (i < first_ndx && list_scanner_scan_next(&scanner)) i++; while (i >= first_ndx && i < last_ndx && list_scanner_scan_next(&scanner)) { _append_comma(result); str_repr_encode_append(result, list_scanner_get_current_value(&scanner), -1, ","); i++; } list_scanner_deinit(&scanner); } static void _list_nth(gint argc, GString *argv[], GString *result, gint ndx) { ListScanner scanner; gint i; if (argc == 0) return; list_scanner_init(&scanner); list_scanner_input_gstring_array(&scanner, argc, argv); i = 0; while (i < ndx && list_scanner_scan_next(&scanner)) i++; if (i >= ndx && list_scanner_scan_next(&scanner)) { g_string_append(result, list_scanner_get_current_value(&scanner)); } list_scanner_deinit(&scanner); } /* * Take off the first item of the list, unencoded. */ static void tf_list_head(LogMessage *msg, gint argc, GString *argv[], GString *result) { _list_nth(argc, argv, result, 0); } TEMPLATE_FUNCTION_SIMPLE(tf_list_head); static void tf_list_nth(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint64 ndx = 0; const gchar *ndx_spec; if (argc < 1) return; ndx_spec = argv[0]->str; /* get start position from first argument */ if (!parse_number(ndx_spec, &ndx)) { msg_error("$(list-nth) parsing failed, index must be the first argument", evt_tag_str("ndx", ndx_spec)); return; } _list_nth(argc - 1, &argv[1], result, ndx); } TEMPLATE_FUNCTION_SIMPLE(tf_list_nth); static void tf_list_tail(LogMessage *msg, gint argc, GString *argv[], GString *result) { if (argc == 0) return; _list_slice(argc, argv, result, 1, INT_MAX); } TEMPLATE_FUNCTION_SIMPLE(tf_list_tail); static void tf_list_count(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint count = _list_count(argc, argv); format_uint32_padded(result, -1, ' ', 10, count); } TEMPLATE_FUNCTION_SIMPLE(tf_list_count); /* $(list-slice FIRST:LAST list ...) */ static void tf_list_slice(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint64 first_ndx = 0, last_ndx = INT_MAX; const gchar *slice_spec, *first_spec, *last_spec; gchar *colon; if (argc < 1) return; slice_spec = argv[0]->str; first_spec = slice_spec; colon = strchr(first_spec, ':'); if (colon) { last_spec = colon + 1; *colon = 0; } else last_spec = NULL; /* get start position from first argument */ if (first_spec && first_spec[0] && !parse_number(first_spec, &first_ndx)) { msg_error("$(list-slice) parsing failed, first could not be parsed", evt_tag_str("start", first_spec)); return; } /* get last position from second argument */ if (last_spec && last_spec[0] && !parse_number(last_spec, &last_ndx)) { msg_error("$(list-slice) parsing failed, last could not be parsed", evt_tag_str("last", last_spec)); return; } _list_slice(argc - 1, &argv[1], result, (gint) first_ndx, (gint) last_ndx); } TEMPLATE_FUNCTION_SIMPLE(tf_list_slice); syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/misc-funcs.c000066400000000000000000000023461321171025300234450ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ static void tf_env(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint i; for (i = 0; i < argc; i++) { char *val = getenv(argv[i]->str); if (!val) continue; g_string_append(result, val); if (i < argc - 1) g_string_append_c(result, ' '); } } TEMPLATE_FUNCTION_SIMPLE(tf_env); syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/numeric-funcs.c000066400000000000000000000220501321171025300241460ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ typedef gboolean (*AggregateFunc)(gpointer, gint64); static gboolean tf_num_parse(gint argc, GString *argv[], const gchar *func_name, gint64 *n, gint64 *m) { if (argc != 2) { msg_debug("Template function requires two arguments.", evt_tag_str("function", func_name)); return FALSE; } if (!parse_number_with_suffix(argv[0]->str, n)) { msg_debug("Parsing failed, template function's first argument is not a number", evt_tag_str("function", func_name), evt_tag_str("arg1", argv[0]->str)); return FALSE; } if (!parse_number_with_suffix(argv[1]->str, m)) { msg_debug("Parsing failed, template function's second argument is not a number", evt_tag_str("function", func_name), evt_tag_str("arg2", argv[1]->str)); return FALSE; } return TRUE; } static void tf_num_plus(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint64 n, m; if (!tf_num_parse(argc, argv, "+", &n, &m)) { g_string_append_len(result, "NaN", 3); return; } format_int64_padded(result, 0, ' ', 10, n + m); } TEMPLATE_FUNCTION_SIMPLE(tf_num_plus); static void tf_num_minus(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint64 n, m; if (!tf_num_parse(argc, argv, "-", &n, &m)) { g_string_append_len(result, "NaN", 3); return; } format_int64_padded(result, 0, ' ', 10, n - m); } TEMPLATE_FUNCTION_SIMPLE(tf_num_minus); static void tf_num_multi(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint64 n, m; if (!tf_num_parse(argc, argv, "*", &n, &m)) { g_string_append_len(result, "NaN", 3); return; } format_int64_padded(result, 0, ' ', 10, n * m); } TEMPLATE_FUNCTION_SIMPLE(tf_num_multi); static void tf_num_div(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint64 n, m; if (!tf_num_parse(argc, argv, "/", &n, &m) || !m) { g_string_append_len(result, "NaN", 3); return; } format_int64_padded(result, 0, ' ', 10, n / m); } TEMPLATE_FUNCTION_SIMPLE(tf_num_div); static void tf_num_mod(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint64 n, m; if (!tf_num_parse(argc, argv, "%", &n, &m) || !m) { g_string_append_len(result, "NaN", 3); return; } format_uint64_padded(result, 0, ' ', 10, n % m); } TEMPLATE_FUNCTION_SIMPLE(tf_num_mod); static GString * _get_gstring_scratch_buffer(const LogTemplateInvokeArgs *args, gsize initial_capacity) { if (args->bufs->len == 0) g_ptr_array_add(args->bufs, g_string_sized_new(initial_capacity)); return (GString *) g_ptr_array_index(args->bufs, 0); } static gboolean _tf_num_parse_arg_with_message(const TFSimpleFuncState *state, LogMessage *message, const LogTemplateInvokeArgs *args, gint64 *number) { GString *formatted_template = _get_gstring_scratch_buffer(args, 64); gint on_error = args->opts->on_error; log_template_format(state->argv[0], message, args->opts, args->tz, args->seq_num, args->context_id, formatted_template); if (!parse_number_with_suffix(formatted_template->str, number)) { if (!(on_error & ON_ERROR_SILENT)) msg_error("Parsing failed, template function's argument is not a number", evt_tag_str("arg", formatted_template->str)); return FALSE; } return TRUE; } static gboolean tf_num_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent, gint argc, gchar *argv[], GError **error) { g_return_val_if_fail(error == NULL || *error == NULL, FALSE); if (argc != 2) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "$(%s) requires only one argument", argv[0]); return FALSE; } return tf_simple_func_prepare(self, s, parent, argc, argv, error); } static gint _tf_num_filter_iterate(const TFSimpleFuncState *state, const LogTemplateInvokeArgs *args, gint message_index, AggregateFunc aggregate, gpointer accumulator) { for (; message_index < args->num_messages; message_index++) { LogMessage *message = args->messages[message_index]; gint64 number; if ((_tf_num_parse_arg_with_message(state, message, args, &number) && (!aggregate(accumulator, number)))) return message_index; } return -1; } static gboolean _tf_num_filter(const TFSimpleFuncState *state, const LogTemplateInvokeArgs *args, AggregateFunc start, AggregateFunc aggregate, gpointer accumulator) { gint first = _tf_num_filter_iterate(state, args, 0, start, accumulator); if (first < 0) return FALSE; _tf_num_filter_iterate(state, args, first + 1, aggregate, accumulator); return TRUE; } static gboolean _tf_num_store_first(gpointer accumulator, gint64 element) { gint64 *acc = (gint64 *)accumulator; *acc = element; return FALSE; } static void _tf_num_aggregation(TFSimpleFuncState *state, const LogTemplateInvokeArgs *args, AggregateFunc aggregate, GString *result) { gint64 accumulator; if (!_tf_num_filter(state, args, _tf_num_store_first, aggregate, &accumulator)) return; format_int64_padded(result, 0, ' ', 10, accumulator); } static gboolean _tf_num_sum(gpointer accumulator, gint64 element) { gint64 *acc = (gint64 *)accumulator; *acc += element; return TRUE; } static void tf_num_sum_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { _tf_num_aggregation((TFSimpleFuncState *) s, args, _tf_num_sum, result); } TEMPLATE_FUNCTION(TFSimpleFuncState, tf_num_sum, tf_num_prepare, NULL, tf_num_sum_call, tf_simple_func_free_state, NULL); static gboolean _tf_num_minimum(gpointer accumulator, gint64 element) { gint64 *acc = (gint64 *)accumulator; if (element < *acc) *acc = element; return TRUE; } static void tf_num_min_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { _tf_num_aggregation((TFSimpleFuncState *) s, args, _tf_num_minimum, result); } TEMPLATE_FUNCTION(TFSimpleFuncState, tf_num_min, tf_num_prepare, NULL, tf_num_min_call, tf_simple_func_free_state, NULL); static gboolean _tf_num_maximum(gpointer accumulator, gint64 element) { gint64 *acc = (gint64 *)accumulator; if (element > *acc) *acc = element; return TRUE; } static void tf_num_max_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { _tf_num_aggregation((TFSimpleFuncState *) s, args, _tf_num_maximum, result); } TEMPLATE_FUNCTION(TFSimpleFuncState, tf_num_max, tf_num_prepare, NULL, tf_num_max_call, tf_simple_func_free_state, NULL); typedef struct _AverageState { gint count; gint64 sum; } AverageState; static gboolean _tf_num_store_average_first(gpointer accumulator, gint64 element) { AverageState *state = (AverageState *) accumulator; state->count = 1; state->sum = element; return FALSE; } static gboolean _tf_num_average(gpointer accumulator, gint64 element) { AverageState *state = (AverageState *) accumulator; ++state->count; state->sum += element; return TRUE; } static void tf_num_average_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { TFSimpleFuncState *state = (TFSimpleFuncState *)s; AverageState accumulator = {0, 0}; if (!_tf_num_filter(state, args, _tf_num_store_average_first, _tf_num_average, &accumulator)) return; g_assert(accumulator.count > 0); gint64 mean = accumulator.sum / accumulator.count; format_int64_padded(result, 0, ' ', 10, mean); } TEMPLATE_FUNCTION(TFSimpleFuncState, tf_num_average, tf_num_prepare, NULL, tf_num_average_call, tf_simple_func_free_state, NULL); syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/str-funcs.c000066400000000000000000000326711321171025300233260ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * Copyright (c) 2014 Viktor Tusa * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include static void _append_args_with_separator(gint argc, GString *argv[], GString *result, gchar separator) { gint i; for (i = 0; i < argc; i++) { g_string_append_len(result, argv[i]->str, argv[i]->len); if (i < argc - 1) g_string_append_c(result, separator); } } static void tf_echo(LogMessage *msg, gint argc, GString *argv[], GString *result) { _append_args_with_separator(argc, argv, result, ' '); } TEMPLATE_FUNCTION_SIMPLE(tf_echo); static void tf_length(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint i; for (i = 0; i < argc; i++) { format_uint32_padded(result, 0, 0, 10, argv[i]->len); if (i < argc - 1) g_string_append_c(result, ' '); } } TEMPLATE_FUNCTION_SIMPLE(tf_length); /* * $(substr $arg START [LEN]) */ static void tf_substr(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint64 start, len; /* * We need to cast argv[0]->len, which is gsize (so unsigned) type, to a * signed type, so we can compare negative offsets/lengths with string * length. But if argv[0]->len is bigger than G_MAXLONG, this can lead to * completely wrong calculations, so we'll just return nothing (alternative * would be to return original string and perhaps print an error...) */ if (argv[0]->len >= G_MAXLONG) { msg_error("$(substr) error: string is too long"); return; } /* check number of arguments */ if (argc < 2 || argc > 3) return; /* get offset position from second argument */ if (!parse_number(argv[1]->str, &start)) { msg_error("$(substr) parsing failed, start could not be parsed", evt_tag_str("start", argv[1]->str)); return; } /* if we were called with >2 arguments, third was desired length */ if (argc > 2) { if (!parse_number(argv[2]->str, &len)) { msg_error("$(substr) parsing failed, length could not be parsed", evt_tag_str("length", argv[2]->str)); return; } } else len = (glong)argv[0]->len; /* * if requested substring length is negative and beyond string start, do nothing; * also if it is greater than string length, limit it to string length */ if (len < 0 && -(len) > (glong)argv[0]->len) return; else if (len > (glong)argv[0]->len) len = (glong)argv[0]->len; /* * if requested offset is beyond string length, do nothing; * also, if offset is negative and "before" string beginning, do nothing * (or should we perhaps align start with the beginning instead?) */ if (start >= (glong)argv[0]->len) return; else if (start < 0 && -(start) > (glong)argv[0]->len) return; /* with negative length, see if we don't end up with start > end */ if (len < 0 && ((start < 0 && start > len) || (start >= 0 && (len + ((glong)argv[0]->len) - start) < 0))) return; /* if requested offset is negative, move start it accordingly */ if (start < 0) { start = start + (glong)argv[0]->len; /* * this shouldn't actually happen, as earlier we tested for * (start < 0 && -start > argv0len), but better safe than sorry */ if (start < 0) start = 0; } /* * if requested length is negative, "resize" len to include exactly as many * characters as needed from the end of the string, given our start position. * (start is always non-negative here already) */ if (len < 0) { len = ((glong)argv[0]->len) - start + len; /* this also shouldn't happen, but - again - better safe than sorry */ if (len < 0) return; } /* if we're beyond string end, do nothing */ if (start >= (glong)argv[0]->len) return; /* if we want something beyond string end, do it only till the end */ if (start + len > (glong)argv[0]->len) len = ((glong)argv[0]->len) - start; /* skip g_string_append_len if we ended up having to extract 0 chars */ if (len == 0) return; g_string_append_len(result, argv[0]->str + start, len); } TEMPLATE_FUNCTION_SIMPLE(tf_substr); /* * $(strip $arg1 $arg2 ...) */ static void tf_strip(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint i; for (i = 0; i < argc; i++) { if (argv[i]->len == 0) continue; gint spaces_end = 0; while (isspace(argv[i]->str[argv[i]->len - spaces_end - 1]) && spaces_end < argv[i]->len) spaces_end++; if (argv[i]->len == spaces_end) continue; gint spaces_start = 0; while (isspace(argv[i]->str[spaces_start])) spaces_start++; if (result->len > 0) g_string_append_c(result, ' '); g_string_append_len(result, &argv[i]->str[spaces_start], argv[i]->len - spaces_end - spaces_start); } } TEMPLATE_FUNCTION_SIMPLE(tf_strip); /* * $(sanitize [opts] $arg1 $arg2 ...) * * Options: * --ctrl-chars or -c Filter control characters (default) * --no-ctrl-chars or -C Don't filter control characters * --invalid-chars or -i Set of characters to be translated, default "/" * --replacement or -r Single character replacement for invalid chars. */ typedef struct _TFSanitizeState { TFSimpleFuncState super; gint ctrl_chars:1, replacement:8; gchar *invalid_chars; } TFSanitizeState; static gboolean tf_sanitize_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent, gint argc, gchar *argv[], GError **error) { TFSanitizeState *state = (TFSanitizeState *) s; gboolean ctrl_chars = TRUE; gchar *invalid_chars = NULL; gchar *replacement = NULL; GOptionContext *ctx; GOptionEntry stize_options[] = { { "ctrl-chars", 'c', 0, G_OPTION_ARG_NONE, &ctrl_chars, NULL, NULL }, { "no-ctrl-chars", 'C', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &ctrl_chars, NULL, NULL }, { "invalid-chars", 'i', 0, G_OPTION_ARG_STRING, &invalid_chars, NULL, NULL }, { "replacement", 'r', 0, G_OPTION_ARG_STRING, &replacement, NULL, NULL }, { NULL } }; gboolean result = FALSE; ctx = g_option_context_new("sanitize-file"); g_option_context_add_main_entries(ctx, stize_options, NULL); if (!g_option_context_parse(ctx, &argc, &argv, error)) { g_option_context_free(ctx); goto exit; } g_option_context_free(ctx); invalid_chars = invalid_chars ? : g_strdup("/"); replacement = replacement ? : g_strdup("_"); if (!tf_simple_func_prepare(self, state, parent, argc, argv, error)) { goto exit; } state->ctrl_chars = ctrl_chars; state->invalid_chars = g_strdup(invalid_chars); state->replacement = replacement[0]; result = TRUE; exit: /* glib supplies us with duplicated strings that we are responsible for! */ g_free(invalid_chars); g_free(replacement); return result; } static void tf_sanitize_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { TFSanitizeState *state = (TFSanitizeState *) s; GString **argv; gint argc; gint i, pos; argv = (GString **) args->bufs->pdata; argc = args->bufs->len; for (i = 0; i < argc; i++) { for (pos = 0; pos < argv[i]->len; pos++) { guchar last_char = argv[i]->str[pos]; if ((state->ctrl_chars && last_char < 32) || (strchr(state->invalid_chars, (gchar) last_char) != NULL)) g_string_append_c(result, state->replacement); else g_string_append_c(result, last_char); } if (i < argc - 1) g_string_append_c(result, '/'); } } static void tf_sanitize_free_state(gpointer s) { TFSanitizeState *state = (TFSanitizeState *) s; g_free(state->invalid_chars); tf_simple_func_free_state(&state->super); } TEMPLATE_FUNCTION(TFSanitizeState, tf_sanitize, tf_sanitize_prepare, tf_simple_func_eval, tf_sanitize_call, tf_sanitize_free_state, NULL); void tf_indent_multi_line(LogMessage *msg, gint argc, GString *argv[], GString *text) { gchar *p, *new_line; /* append the message text(s) to the template string */ _append_args_with_separator(argc, argv, text, ' '); /* look up the \n-s and insert a \t after them */ p = text->str; new_line = memchr(p, '\n', text->len); while(new_line) { if (*(gchar *)(new_line + 1) != '\t') { g_string_insert_c(text, new_line - p + 1, '\t'); } new_line = memchr(new_line + 1, '\n', p + text->len - new_line); } } TEMPLATE_FUNCTION_SIMPLE(tf_indent_multi_line); void tf_lowercase(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint i; for (i = 0; i < argc; i++) { gchar *new = g_utf8_strdown(argv[i]->str, argv[i]->len); g_string_append(result, new); if (i < argc - 1) g_string_append_c(result, ' '); g_free(new); } } TEMPLATE_FUNCTION_SIMPLE(tf_lowercase); void tf_uppercase(LogMessage *msg, gint argc, GString *argv[], GString *result) { gint i; for (i = 0; i < argc; i++) { gchar *new = g_utf8_strup(argv[i]->str, argv[i]->len); g_string_append(result, new); if (i < argc - 1) g_string_append_c(result, ' '); g_free(new); } } TEMPLATE_FUNCTION_SIMPLE(tf_uppercase); void tf_replace_delimiter(LogMessage *msg, gint argc, GString *argv[], GString *result) { gchar *haystack, *delimiters, new_delimiter; if (argc != 3) { msg_error("$(replace-delimiter) parsing failed, wrong number of arguments"); return; } delimiters = argv[0]->str; new_delimiter = argv[1]->str[0]; haystack = g_strdup(argv[2]->str); g_string_append(result, g_strdelimit(haystack, delimiters, new_delimiter)); g_free(haystack); } TEMPLATE_FUNCTION_SIMPLE(tf_replace_delimiter); static void tf_string_padding(LogMessage *msg, gint argc, GString *argv[], GString *result) { GString *text = argv[0]; GString *padding; gint64 width, i; if (argc <= 1) { msg_debug("Not enough arguments for padding template function!"); return; } if (!parse_number_with_suffix(argv[1]->str, &width)) { msg_debug("Padding template function requires a number as second argument!"); return; } if (argc <= 2) padding = g_string_new(" "); else padding = argv[2]; if (text->len < width) { for (i = 0; i < width - text->len; i++) { g_string_append_c(result, *(padding->str + (i % padding->len))); } } g_string_append_len(result, text->str, text->len); if (argc <= 2) { g_string_free(padding, TRUE); } } TEMPLATE_FUNCTION_SIMPLE(tf_string_padding); typedef struct _TFBinaryState { TFSimpleFuncState super; GString *octets; } TFBinaryState; static void tf_binary_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { TFBinaryState *state = (TFBinaryState *) s; g_string_append_len(result, state->octets->str, state->octets->len); } static gboolean tf_binary_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent, gint argc, gchar *argv[], GError **error) { TFBinaryState *state = (TFBinaryState *) s; GString *octets = g_string_new(""); if (argc < 2) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "$(binary) Incorrect parameters, usage $(binary ...)"); goto error; } for (gint i = 1; i < argc; i++) { gint64 number; gchar *token = argv[i]; if (!parse_number(token, &number)) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "$(binary) template function requires list of dec/hex/oct numbers as arguments, unable to parse %s as a number", token); goto error; } if (number > 0xFF) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "$(binary) template function only supports 8 bit values as characters, %" G_GUINT64_FORMAT " is above 255", number); goto error; } g_string_append_c(octets, (gchar) number); } if (!tf_simple_func_prepare(self, state, parent, argc, argv, error)) { goto error; } state->octets = octets; return TRUE; error: g_string_free(octets, TRUE); return FALSE; } static void tf_binary_free_state(gpointer s) { TFBinaryState *state = (TFBinaryState *) s; g_string_free(state->octets, TRUE); tf_simple_func_free_state(&state->super); } TEMPLATE_FUNCTION(TFBinaryState, tf_binary, tf_binary_prepare, tf_simple_func_eval, tf_binary_call, tf_binary_free_state, NULL); syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/tests/000077500000000000000000000000001321171025300223675ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/tests/Makefile.am000066400000000000000000000005021321171025300244200ustar00rootroot00000000000000modules_basicfuncs_tests_TESTS = \ modules/basicfuncs/tests/test_basicfuncs check_PROGRAMS += ${modules_basicfuncs_tests_TESTS} modules_basicfuncs_tests_test_basicfuncs_CFLAGS = $(TEST_CFLAGS) modules_basicfuncs_tests_test_basicfuncs_LDADD = \ $(TEST_LDADD) \ $(PREOPEN_SYSLOGFORMAT) $(PREOPEN_BASICFUNCS) syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/tests/test_basicfuncs.c000066400000000000000000000405771321171025300257270ustar00rootroot00000000000000/* * Copyright (c) 2010-2015 Balabit * Copyright (c) 2010-2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "template_lib.h" #include "apphook.h" #include "plugin.h" #include "cfg.h" static void add_dummy_template_to_configuration(void) { LogTemplate *dummy = log_template_new(configuration, "dummy"); assert_true(log_template_compile(dummy, "dummy template expanded $HOST", NULL), "Unexpected error compiling dummy template"); cfg_tree_add_template(&configuration->tree, dummy); } static void _log_msg_free(gpointer data, gpointer user_data) { log_msg_unref((LogMessage *) data); } static GPtrArray * create_log_messages_with_values(const gchar *name, const gchar **values) { LogMessage *message; GPtrArray *messages = g_ptr_array_new(); const gchar **value; for (value = values; *value != NULL; ++value) { message = create_empty_message(); log_msg_set_value_by_name(message, name, *value, -1); g_ptr_array_add(messages, message); } return messages; } static void free_log_message_array(GPtrArray *messages) { g_ptr_array_foreach(messages, _log_msg_free, NULL); g_ptr_array_free(messages, TRUE); } void test_cond_funcs(void) { assert_template_format_with_context("$(grep 'facility(local3)' $PID)", "23323,23323"); assert_template_format_with_context("$(grep -m 1 'facility(local3)' $PID)", "23323"); assert_template_format_with_context("$(grep 'facility(local3)' $PID $PROGRAM)", "23323,syslog-ng,23323,syslog-ng"); assert_template_format_with_context("$(grep 'facility(local4)' $PID)", ""); assert_template_format_with_context("$(grep ('$FACILITY' eq 'local4') $PID)", ""); assert_template_format_with_context("$(grep ('$FACILITY(' eq 'local3(') $PID)", "23323,23323"); assert_template_format_with_context("$(grep ('$FACILITY(' eq 'local4)') $PID)", ""); assert_template_format_with_context("$(grep \\'$FACILITY\\'\\ eq\\ \\'local4\\' $PID)", ""); assert_template_format_with_context("$(if 'facility(local4)' alma korte)", "korte"); assert_template_format_with_context("$(if 'facility(local3)' alma korte)", "alma"); assert_template_format_with_context("$(if '\"$FACILITY\" lt \"local3\"' alma korte)", "korte"); assert_template_format_with_context("$(if '\"$FACILITY\" le \"local3\"' alma korte)", "alma"); assert_template_format_with_context("$(if '\"$FACILITY\" eq \"local3\"' alma korte)", "alma"); assert_template_format_with_context("$(if '\"$FACILITY\" ne \"local3\"' alma korte)", "korte"); assert_template_format_with_context("$(if '\"$FACILITY\" gt \"local3\"' alma korte)", "korte"); assert_template_format_with_context("$(if '\"$FACILITY\" ge \"local3\"' alma korte)", "alma"); assert_template_format_with_context("$(if '\"$FACILITY_NUM\" < \"19\"' alma korte)", "korte"); assert_template_format_with_context("$(if '\"$FACILITY_NUM\" <= \"19\"' alma korte)", "alma"); assert_template_format_with_context("$(if '\"$FACILITY_NUM\" == \"19\"' alma korte)", "alma"); assert_template_format_with_context("$(if '\"$FACILITY_NUM\" != \"19\"' alma korte)", "korte"); assert_template_format_with_context("$(if '\"$FACILITY_NUM\" > \"19\"' alma korte)", "korte"); assert_template_format_with_context("$(if '\"$FACILITY_NUM\" >= \"19\"' alma korte)", "alma"); assert_template_format_with_context("$(if '\"$FACILITY_NUM\" >= \"19\" and \"kicsi\" eq \"nagy\"' alma korte)", "korte"); assert_template_format_with_context("$(if '\"$FACILITY_NUM\" >= \"19\" or \"kicsi\" eq \"nagy\"' alma korte)", "alma"); assert_template_format_with_context("$(grep 'facility(local3)' $PID)@0", "23323"); assert_template_format_with_context("$(grep 'facility(local3)' $PID)@1", "23323"); assert_template_format_with_context("$(grep 'facility(local3)' $PID)@2", ""); assert_template_format_with_context("$(or 1 \"\" 2)", "1"); assert_template_format_with_context("$(or \"\" 2)", "2"); assert_template_format_with_context("$(or \"\" \"\")", ""); assert_template_format_with_context("$(or)", ""); } void test_str_funcs(void) { assert_template_format("$(ipv4-to-int $SOURCEIP)", "168496141"); assert_template_format("$(length $HOST $PID)", "5 5"); assert_template_format("$(length $HOST)", "5"); assert_template_format("$(length)", ""); assert_template_format("$(substr $HOST 1 3)", "zor"); assert_template_format("$(substr $HOST 1)", "zorp"); assert_template_format("$(substr $HOST -1)", "p"); assert_template_format("$(substr $HOST -2 1)", "r"); assert_template_format("$(strip ${APP.STRIP1})", "value"); assert_template_format("$(strip ${APP.STRIP2})", "value"); assert_template_format("$(strip ${APP.STRIP3})", "value"); assert_template_format("$(strip ${APP.STRIP4})", "value"); assert_template_format("$(strip ${APP.STRIP5})", ""); assert_template_format("$(strip ${APP.STRIP5} ${APP.STRIP1} ${APP.STRIP5})", "value"); assert_template_format("$(strip ${APP.STRIP1} ${APP.STRIP2} ${APP.STRIP3} ${APP.STRIP4} ${APP.STRIP5})", "value value value value"); assert_template_format("$(strip ŐRÜLT_ÍRÓ)", "ŐRÜLT_ÍRÓ"); /* Wide characters are accepted */ assert_template_format("$(strip ' \n\t\r a b \n\t\r ')", "a b"); assert_template_format("$(sanitize alma/bela)", "alma_bela"); assert_template_format("$(sanitize -r @ alma/bela)", "alma@bela"); assert_template_format("$(sanitize -i @ alma@bela)", "alma_bela"); assert_template_format("$(sanitize -i '@/l ' alma@/bela)", "a_ma__be_a"); assert_template_format("$(sanitize alma\x1b_bela)", "alma__bela"); assert_template_format("$(sanitize -C alma\x1b_bela)", "alma\x1b_bela"); assert_template_format("$(sanitize $HOST $PROGRAM)", "bzorp/syslog-ng"); assert_template_failure("$(sanitize ${missingbrace)", "Invalid macro, '}' is missing, error_pos='14'"); assert_template_format("$(indent-multi-line 'foo\nbar')", "foo\n\tbar"); assert_template_format("$(lowercase ŐRÜLT ÍRÓ)", "őrült író"); assert_template_format("$(uppercase őrült író)", "ŐRÜLT ÍRÓ"); assert_template_format("$(replace-delimiter \"\t\" \",\" \"hello\tworld\")", "hello,world"); assert_template_format("$(padding foo 10)", " foo"); assert_template_format("$(padding foo 10 x)", "xxxxxxxfoo"); assert_template_format("$(padding foo 10 abc)", "abcabcafoo"); assert_template_failure("$(binary)", "Incorrect parameters"); assert_template_failure("$(binary abc)", "unable to parse abc"); assert_template_failure("$(binary 256)", "256 is above 255"); assert_template_format("$(binary 1)", "\1"); assert_template_format("$(binary 1 0x1)", "\1\1"); assert_template_format("$(binary 0xFF 255 0377)", "\xFF\xFF\xFF"); assert_template_format_with_len("$(binary 0xFF 0x00 0x40)", "\xFF\000@", 3); } void test_numeric_funcs(void) { assert_template_format("$(+ $FACILITY_NUM 1)", "20"); assert_template_format("$(+ -1 -1)", "-2"); assert_template_format("$(- $FACILITY_NUM 1)", "18"); assert_template_format("$(- $FACILITY_NUM 20)", "-1"); assert_template_format("$(* $FACILITY_NUM 2)", "38"); assert_template_format("$(/ $FACILITY_NUM 2)", "9"); assert_template_format("$(% $FACILITY_NUM 3)", "1"); assert_template_format("$(/ $FACILITY_NUM 0)", "NaN"); assert_template_format("$(% $FACILITY_NUM 0)", "NaN"); assert_template_format("$(+ foo bar)", "NaN"); assert_template_format("$(/ 2147483648 1)", "2147483648"); assert_template_format("$(+ 5000000000 5000000000)", "10000000000"); assert_template_format("$(% 10000000000 5000000001)", "4999999999"); assert_template_format("$(* 5000000000 2)", "10000000000"); assert_template_format("$(- 10000000000 5000000000)", "5000000000"); } void test_fname_funcs(void) { assert_template_format("$(basename foo)", "foo"); assert_template_format("$(basename /foo/bar)", "bar"); assert_template_format("$(basename /foo/bar/baz)", "baz"); assert_template_format("$(dirname foo)", "."); assert_template_format("$(dirname /foo/bar)", "/foo"); assert_template_format("$(dirname /foo/bar/)", "/foo"); assert_template_format("$(dirname /foo/bar/baz)", "/foo/bar"); } typedef struct { const gchar *macro; const gchar *result; } MacroAndResult; static void _test_macros_with_context(const gchar *id, const gchar *numbers[], const MacroAndResult test_cases[]) { GPtrArray *messages = create_log_messages_with_values(id, numbers); for (const MacroAndResult *test_case = test_cases; test_case->macro; test_case++) assert_template_format_with_context_msgs( test_case->macro, test_case->result, (LogMessage **)messages->pdata, messages->len); free_log_message_array(messages); } void test_numeric_aggregate_simple(void) { _test_macros_with_context( "NUMBER", (const gchar *[]) { "1", "-1", "3", NULL }, (const MacroAndResult[]) { { "$(sum ${NUMBER})", "3" }, { "$(min ${NUMBER})", "-1" }, { "$(max ${NUMBER})", "3" }, { "$(average ${NUMBER})", "1" }, { } }); } void test_numeric_aggregate_invalid_values(void) { _test_macros_with_context( "NUMBER", (const gchar *[]) { "abc", "1", "c", "2", "", NULL }, (const MacroAndResult[]) { { "$(sum ${NUMBER})", "3" }, { "$(min ${NUMBER})", "1" }, { "$(max ${NUMBER})", "2" }, { "$(average ${NUMBER})", "1" }, { } }); } void test_numeric_aggregate_full_invalid_values(void) { _test_macros_with_context( "NUMBER", (const gchar *[]) { "abc", "184467440737095516160", "c", "", NULL }, (const MacroAndResult[]) { { "$(sum ${NUMBER})", "" }, { "$(min ${NUMBER})", "" }, { "$(max ${NUMBER})", "" }, { "$(average ${NUMBER})", "" }, { } }); } void test_numeric_aggregate_funcs(void) { test_numeric_aggregate_simple(); test_numeric_aggregate_invalid_values(); test_numeric_aggregate_full_invalid_values(); } void test_misc_funcs(void) { unsetenv("OHHELLO"); setenv("TEST_ENV", "test-env", 1); assert_template_format("$(env OHHELLO)", ""); assert_template_format("$(env TEST_ENV)", "test-env"); } static void test_tf_template(void) { assert_template_format("foo $(template dummy) bar", "foo dummy template expanded bzorp bar"); assert_template_failure("foo $(template unknown) bar", "Unknown template function or template \"unknown\""); } static void test_list_funcs(void) { assert_template_format("$(list-concat)", ""); assert_template_format("$(list-concat foo bar baz)", "foo,bar,baz"); assert_template_format("$(list-concat foo bar baz '')", "foo,bar,baz"); assert_template_format("$(list-concat foo $HOST $PROGRAM $PID bar)", "foo,bzorp,syslog-ng,23323,bar"); assert_template_format("$(list-concat foo $HOST,$PROGRAM,$PID bar)", "foo,bzorp,syslog-ng,23323,bar"); assert_template_format("$(list-concat foo '$HOST,$PROGRAM,$PID' bar)", "foo,bzorp,syslog-ng,23323,bar"); assert_template_format("$(list-concat foo '$HOST,$PROGRAM,$PID,' bar)", "foo,bzorp,syslog-ng,23323,bar"); assert_template_format("$(list-append)", ""); assert_template_format("$(list-append '' foo)", "foo"); assert_template_format("$(list-append '' foo bar)", "foo,bar"); assert_template_format("$(list-append '' foo bar baz)", "foo,bar,baz"); assert_template_format("$(list-append foo,bar,baz 'x')", "foo,bar,baz,x"); assert_template_format("$(list-append foo,bar,baz '')", "foo,bar,baz,\"\""); assert_template_format("$(list-append foo,bar,baz 'xxx,')", "foo,bar,baz,\"xxx,\""); assert_template_format("$(list-append foo,bar,baz 'a\tb')", "foo,bar,baz,\"a\\tb\""); assert_template_format("$(list-head)", ""); assert_template_format("$(list-head '')", ""); assert_template_format("$(list-head foo)", "foo"); assert_template_format("$(list-head foo,)", "foo"); assert_template_format("$(list-head foo,bar)", "foo"); assert_template_format("$(list-head foo,bar,baz)", "foo"); assert_template_format("$(list-head ,bar,baz)", "bar"); assert_template_format("$(list-head foo bar)", "foo"); assert_template_format("$(list-head foo bar baz)", "foo"); assert_template_format("$(list-head '' bar baz)", "bar"); assert_template_format("$(list-head '\"\\tfoo,\",bar,baz')", "\tfoo,"); assert_template_format("$(list-nth 1 '\"foo,\",\"bar\",\"baz\"')", "bar"); assert_template_format("$(list-nth 2 '\"foo,\",\"bar\",\"baz\"')", "baz"); assert_template_format("$(list-tail)", ""); assert_template_format("$(list-tail foo)", ""); assert_template_format("$(list-tail foo,bar)", "bar"); assert_template_format("$(list-tail foo,)", ""); assert_template_format("$(list-tail ,bar)", ""); assert_template_format("$(list-tail foo,bar,baz)", "bar,baz"); assert_template_format("$(list-tail foo bar baz)", "bar,baz"); assert_template_format("$(list-tail foo,bar baz bad)", "bar,baz,bad"); assert_template_format("$(list-tail foo,bar,xxx, baz bad)", "bar,xxx,baz,bad"); assert_template_format("$(list-slice 0:0 foo,bar,xxx,baz,bad)", ""); assert_template_format("$(list-slice 0:1 foo,bar,xxx,baz,bad)", "foo"); assert_template_format("$(list-slice 0:2 foo,bar,xxx,baz,bad)", "foo,bar"); assert_template_format("$(list-slice 0:3 foo,bar,xxx,baz,bad)", "foo,bar,xxx"); assert_template_format("$(list-slice 1:1 foo,bar,xxx,baz,bad)", ""); assert_template_format("$(list-slice 1:2 foo,bar,xxx,baz,bad)", "bar"); assert_template_format("$(list-slice : foo,bar,xxx,baz,bad)", "foo,bar,xxx,baz,bad"); assert_template_format("$(list-slice 0: foo,bar,xxx,baz,bad)", "foo,bar,xxx,baz,bad"); assert_template_format("$(list-slice 3: foo,bar,xxx,baz,bad)", "baz,bad"); assert_template_format("$(list-slice :1 foo,bar,xxx,baz,bad)", "foo"); assert_template_format("$(list-slice :2 foo,bar,xxx,baz,bad)", "foo,bar"); assert_template_format("$(list-slice :3 foo,bar,xxx,baz,bad)", "foo,bar,xxx"); assert_template_format("$(list-slice -1: foo,bar,xxx,baz,bad)", "bad"); assert_template_format("$(list-slice -2: foo,bar,xxx,baz,bad)", "baz,bad"); assert_template_format("$(list-slice -3: foo,bar,xxx,baz,bad)", "xxx,baz,bad"); assert_template_format("$(list-slice -5: foo,bar,xxx,baz,bad)", "foo,bar,xxx,baz,bad"); assert_template_format("$(list-slice -6: foo,bar,xxx,baz,bad)", "foo,bar,xxx,baz,bad"); assert_template_format("$(list-slice -100: foo,bar,xxx,baz,bad)", "foo,bar,xxx,baz,bad"); assert_template_format("$(list-slice :-1 foo,bar,xxx,baz,bad)", "foo,bar,xxx,baz"); assert_template_format("$(list-slice :-2 foo,bar,xxx,baz,bad)", "foo,bar,xxx"); assert_template_format("$(list-slice :-3 foo,bar,xxx,baz,bad)", "foo,bar"); assert_template_format("$(list-slice :-4 foo,bar,xxx,baz,bad)", "foo"); assert_template_format("$(list-slice :-5 foo,bar,xxx,baz,bad)", ""); assert_template_format("$(list-slice :-6 foo,bar,xxx,baz,bad)", ""); assert_template_format("$(list-count foo,bar,xxx, baz bad)", "5"); } void test_context_funcs(void) { assert_template_format_with_context("$(context-length)", "2"); assert_template_format_with_context("$(context-lookup 'facility(local3)' $PID)", "23323,23323"); assert_template_format_with_context("$(context-lookup 'facility(local3)' ${comma_value})", "\"value,with,a,comma\",\"value,with,a,comma\""); assert_template_format_with_context("$(context-values ${PID})", "23323,23323"); assert_template_format_with_context("$(context-values ${comma_value})", "\"value,with,a,comma\",\"value,with,a,comma\""); } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { app_startup(); init_template_tests(); add_dummy_template_to_configuration(); cfg_load_module(configuration, "basicfuncs"); test_cond_funcs(); test_str_funcs(); test_numeric_funcs(); test_numeric_aggregate_funcs(); test_misc_funcs(); test_tf_template(); test_list_funcs(); test_context_funcs(); deinit_template_tests(); app_shutdown(); } syslog-ng-syslog-ng-3.13.2/modules/basicfuncs/tf-template.c000066400000000000000000000062571321171025300236250ustar00rootroot00000000000000/* * Copyright (c) 2002-2014 Balabit * Copyright (c) 1998-2014 Balázs Scheidler * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg.h" typedef struct _TFTemplateState { LogTemplate *invoked_template; } TFTemplateState; static gboolean tf_template_lookup_invoked_template(TFTemplateState *state, GlobalConfig *cfg, const gchar *function_name, GError **error) { state->invoked_template = cfg_tree_lookup_template(&cfg->tree, function_name); if (!state->invoked_template) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "$(template) Unknown template function or template \"%s\"", function_name); return FALSE; } return TRUE; } static const gchar * tf_template_extract_invoked_template_name_from_args(gint argc, gchar *argv[]) { if (argc == 2 && strcmp(argv[0], "template") == 0) return argv[1]; return NULL; } static gboolean tf_template_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent, gint argc, gchar *argv[], GError **error) { TFTemplateState *state = (TFTemplateState *) s; const gchar *invoked_template_name; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); invoked_template_name = tf_template_extract_invoked_template_name_from_args(argc, argv); if (!invoked_template_name) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "$(template) requires one argument, that specifies the template name to be invoked"); return FALSE; } return tf_template_lookup_invoked_template(state, parent->cfg, invoked_template_name, error); } static void tf_template_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { TFTemplateState *state = (TFTemplateState *) s; log_template_append_format_with_context(state->invoked_template, args->messages, args->num_messages, args->opts, args->tz, args->seq_num, args->context_id, result); } static void tf_template_free_state(gpointer s) { TFTemplateState *state = (TFTemplateState *) s; log_template_unref(state->invoked_template); } TEMPLATE_FUNCTION(TFTemplateState, tf_template, tf_template_prepare, NULL, tf_template_call, tf_template_free_state, NULL); syslog-ng-syslog-ng-3.13.2/modules/cef/000077500000000000000000000000001321171025300176425ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/cef/CMakeLists.txt000066400000000000000000000005311321171025300224010ustar00rootroot00000000000000set(CEF_SOURCES format-cef-extension.c format-cef-extension.h cef-plugin.c ) include_directories (${CMAKE_CURRENT_BINARY_DIR}) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) add_library(cef MODULE ${CEF_SOURCES}) target_link_libraries(cef PRIVATE syslog-ng) install(TARGETS cef LIBRARY DESTINATION lib/syslog-ng/ COMPONENT cef) syslog-ng-syslog-ng-3.13.2/modules/cef/Makefile.am000066400000000000000000000011201321171025300216700ustar00rootroot00000000000000module_LTLIBRARIES += modules/cef/libcef.la modules_cef_libcef_la_SOURCES = \ modules/cef/format-cef-extension.c \ modules/cef/format-cef-extension.h \ modules/cef/cef-plugin.c modules_cef_libcef_la_CFLAGS = \ $(AM_CFLAGS) \ -I$(top_srcdir)/modules/cef \ -I$(top_builddir)/modules/cef modules_cef_libcef_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_cef_libcef_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_cef_libcef_la_DEPENDENCIES= \ $(MODULE_DEPS_LIBS) modules/cef modules/cef/ mod-cef: modules/cef/libcef.la .PHONY: modules/cef/ mod-cef include modules/cef/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/modules/cef/cef-plugin.c000066400000000000000000000027651321171025300220510ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "format-cef-extension.h" #include "plugin.h" #include "plugin-types.h" static Plugin cef_plugins[] = { TEMPLATE_FUNCTION_PLUGIN(tf_cef, "format-cef-extension"), }; gboolean cef_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, cef_plugins, G_N_ELEMENTS(cef_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "cef", .version = SYSLOG_NG_VERSION, .description = "The CEF module provides CEF formatting support for syslog-ng.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = cef_plugins, .plugins_len = G_N_ELEMENTS(cef_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/cef/format-cef-extension.c000066400000000000000000000125211321171025300240440ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "filter/filter-expr.h" #include "filter/filter-expr-parser.h" #include "cfg.h" #include "value-pairs/value-pairs.h" #include "value-pairs/cmdline.h" #include "syslog-ng.h" #include "str-utils.h" #include "format-cef-extension.h" typedef struct _TFCefState { TFSimpleFuncState super; ValuePairs *vp; } TFCefState; static gboolean tf_cef_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent, gint argc, gchar *argv[], GError **error) { TFCefState *state = (TFCefState *)s; state->vp = value_pairs_new_from_cmdline(parent->cfg, &argc, &argv, FALSE, error); if (!state->vp) return FALSE; return TRUE; } typedef struct { gboolean need_separator; GString *buffer; const LogTemplateOptions *template_options; } CefWalkerState; static gboolean tf_cef_is_valid_key(const gchar *str) { size_t end = strspn(str, "0123456789" "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); return str[end] == '\0'; } static inline void tf_cef_append_escaped(GString *escaped_string, const gchar *str, gsize str_len) { const gchar *char_ptr; gunichar uchar; while (str_len) { uchar = g_utf8_get_char_validated(str, str_len); switch (uchar) { case (gunichar) -1: case (gunichar) -2: g_string_append_printf(escaped_string, "\\x%02x", *(guint8 *) str++); str_len--; continue; break; case '=': g_string_append(escaped_string, "\\="); break; case '\n': g_string_append(escaped_string, "\\n"); break; case '\r': g_string_append(escaped_string, "\\r"); break; case '\\': g_string_append(escaped_string, "\\\\"); break; default: if (uchar < 32) g_string_append_printf(escaped_string, "\\u%04x", uchar); else g_string_append_unichar_optimized(escaped_string, uchar); break; } char_ptr = g_utf8_next_char(str); str_len -= char_ptr - str; str = char_ptr; } } static gboolean tf_cef_append_value(const gchar *name, const gchar *value, gsize value_len, CefWalkerState *state) { if (state->need_separator) g_string_append_c(state->buffer, ' '); g_string_append(state->buffer, name); g_string_append_c(state->buffer, '='); tf_cef_append_escaped(state->buffer, value, value_len); return TRUE; } static gint tf_cef_walk_cmp(const gchar *s1, const gchar *s2) { return strcmp(s1, s2); } static gboolean tf_cef_walker(const gchar *name, TypeHint type, const gchar *value, gsize value_len, gpointer user_data) { CefWalkerState *state = (CefWalkerState *)user_data; gint on_error = state->template_options->on_error; if (!tf_cef_is_valid_key(name)) { if (!(on_error & ON_ERROR_SILENT)) { msg_error("Invalid CEF key", evt_tag_str("key", name)); } return !!(on_error & ON_ERROR_DROP_MESSAGE); } tf_cef_append_value(name, value, value_len, state); state->need_separator = TRUE; return FALSE; } static gboolean tf_cef_append(GString *result, ValuePairs *vp, LogMessage *msg, const LogTemplateOptions *template_options, gint32 seq_num, gint time_zone_mode) { CefWalkerState state; state.need_separator = FALSE; state.buffer = result; state.template_options = template_options; return value_pairs_foreach_sorted(vp, tf_cef_walker, (GCompareFunc) tf_cef_walk_cmp, msg, seq_num, time_zone_mode, template_options, &state); } static void tf_cef_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { TFCefState *state = (TFCefState *)s; gint i; gboolean r = TRUE; gsize orig_size = result->len; for (i = 0; i < args->num_messages; i++) r &= tf_cef_append(result, state->vp, args->messages[i], args->opts, args->seq_num, args->tz); if (!r && (args->opts->on_error & ON_ERROR_DROP_MESSAGE)) g_string_set_size(result, orig_size); } static void tf_cef_free_state(gpointer s) { TFCefState *state = (TFCefState *)s; if (state->vp) value_pairs_unref(state->vp); tf_simple_func_free_state(&state->super); } TEMPLATE_FUNCTION(TFCefState, tf_cef, tf_cef_prepare, NULL, tf_cef_call, tf_cef_free_state, NULL); syslog-ng-syslog-ng-3.13.2/modules/cef/format-cef-extension.h000066400000000000000000000020761321171025300240550ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #ifndef FORMAT_CEF_EXTENSION_H_INCLUDED #define FORMAT_CEF_EXTENSION_H_INCLUDED #include "template/simple-function.h" #include "plugin.h" TEMPLATE_FUNCTION_DECLARE(tf_cef); #endif syslog-ng-syslog-ng-3.13.2/modules/cef/tests/000077500000000000000000000000001321171025300210045ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/cef/tests/Makefile.am000066400000000000000000000007571321171025300230510ustar00rootroot00000000000000modules_cef_tests_TESTS = \ modules/cef/tests/test-format-cef-extension check_PROGRAMS += ${modules_cef_tests_TESTS} modules_cef_tests_test_format_cef_extension_CFLAGS = $(TEST_CFLAGS) modules_cef_tests_test_format_cef_extension_LDADD = $(TEST_LDADD) modules_cef_tests_test_format_cef_extension_LDFLAGS = \ $(PREOPEN_SYSLOGFORMAT) \ -dlpreopen $(top_builddir)/modules/cef/libcef.la modules_cef_tests_test_format_cef_extension_DEPENDENCIES = \ $(top_builddir)/modules/cef/libcef.la syslog-ng-syslog-ng-3.13.2/modules/cef/tests/test-format-cef-extension.c000066400000000000000000000162031321171025300261640ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "template_lib.h" #include "apphook.h" #include "plugin.h" #include "cfg.h" #include #define _EXPECT_CEF_RESULT(...) _expect_cef_result_va(__VA_ARGS__, NULL) #define _EXPECT_DROP_MESSAGE(...) _expect_cef_result_va("", __VA_ARGS__, NULL) #define _EXPECT_SKIP_BAD_PROPERTY(...) _expect_skip_bad_property_va(__VA_ARGS__, NULL) #define _EXPECT_CEF_RESULT_FORMAT(X, ...) _expect_cef_result_format_va(X, __VA_ARGS__, NULL); static void _expect_cef_result_properties_list(const gchar *expected, va_list ap) { LogMessage *msg = message_from_list(ap); assert_template_format_msg("$(format-cef-extension --subkeys .cef.)", expected, msg); log_msg_unref(msg); } static void _expect_cef_result_va(const gchar *expected, ...) { va_list ap; configuration->template_options.on_error = ON_ERROR_DROP_MESSAGE | ON_ERROR_SILENT; va_start(ap, expected); _expect_cef_result_properties_list(expected, ap); va_end(ap); } static void _expect_skip_bad_property_va(const gchar *expected, ...) { va_list ap; configuration->template_options.on_error = ON_ERROR_DROP_PROPERTY | ON_ERROR_SILENT; va_start(ap, expected); _expect_cef_result_properties_list(expected, ap); va_end(ap); } static void _expect_cef_result_format_va(const gchar *format, const gchar *expected, ...) { va_list ap; va_start(ap, expected); LogMessage *msg = message_from_list(ap); va_end(ap); configuration->template_options.on_error = ON_ERROR_DROP_MESSAGE | ON_ERROR_SILENT; assert_template_format_msg(format, expected, msg); log_msg_unref(msg); } static void _test_null_in_value(void) { LogMessage *msg = create_empty_message(); configuration->template_options.on_error = ON_ERROR_DROP_MESSAGE | ON_ERROR_SILENT; log_msg_set_value_by_name(msg, ".cef.k", "a\0b", 3); assert_template_format_msg("$(format-cef-extension --subkeys .cef.)", "k=a\\u0000b", msg); log_msg_unref(msg); } static void _test_filter(void) { _EXPECT_CEF_RESULT("k=v", ".cef.k", "v", "x", "w"); } static void _test_multiple_properties_with_space(void) { _EXPECT_CEF_RESULT("act=c:/program files dst=10.0.0.1", ".cef.act", "c:/program files", ".cef.dst", "10.0.0.1"); } static void _test_multiple_properties(void) { _EXPECT_CEF_RESULT("k=v x=y", ".cef.k", "v", ".cef.x", "y"); } static void _test_drop_property(void) { _EXPECT_SKIP_BAD_PROPERTY("kkk=v", ".cef.a|b", "c", ".cef.kkk", "v", ".cef.x=y", "w"); } static void _test_drop_message(void) { _EXPECT_DROP_MESSAGE(".cef.a|b", "c", ".cef.kkk", "v", ".cef.x=y", "w"); } static void _test_empty(void) { _EXPECT_CEF_RESULT(""); } static void _test_inline(void) { _EXPECT_CEF_RESULT_FORMAT("$(format-cef-extension --subkeys .cef. .cef.k=v)", "k=v"); } static void _test_space(void) { _EXPECT_CEF_RESULT("act=blocked a ping", ".cef.act", "blocked a ping"); } static void _test_charset(void) { _EXPECT_DROP_MESSAGE(".cef.árvíztűrőtükörfúrógép", "v"); _EXPECT_CEF_RESULT("k=árvíztűrőtükörfúrógép", ".cef.k", "árvíztűrőtükörfúrógép"); _EXPECT_CEF_RESULT("k=\\xff", ".cef.k", "\xff"); _EXPECT_CEF_RESULT("k=\\xc3", ".cef.k", "\xc3"); _EXPECT_DROP_MESSAGE(".cef.k\xff", "v"); _EXPECT_DROP_MESSAGE(".cef.k\xc3", "v"); } static void _test_escaping(void) { _EXPECT_CEF_RESULT("act=\\\\", ".cef.act", "\\"); _EXPECT_CEF_RESULT("act=\\\\\\\\", ".cef.act", "\\\\"); _EXPECT_CEF_RESULT("act=\\=", ".cef.act", "="); _EXPECT_CEF_RESULT("act=|", ".cef.act", "|"); _EXPECT_CEF_RESULT("act=\\u0009", ".cef.act", "\t"); _EXPECT_CEF_RESULT("act=\\n", ".cef.act", "\n"); _EXPECT_CEF_RESULT("act=\\r", ".cef.act", "\r"); _EXPECT_CEF_RESULT("act=v\\n", ".cef.act", "v\n"); _EXPECT_CEF_RESULT("act=v\\r", ".cef.act", "v\r"); _EXPECT_CEF_RESULT("act=u\\nv", ".cef.act", "u\nv"); _EXPECT_CEF_RESULT("act=\\r\\n", ".cef.act", "\r\n"); _EXPECT_CEF_RESULT("act=\\n\\r", ".cef.act", "\n\r"); _EXPECT_CEF_RESULT("act=this is a long value \\= something", ".cef.act", "this is a long value = something"); _EXPECT_DROP_MESSAGE(".cef.k=w", "v"); _EXPECT_DROP_MESSAGE(".cef.k|w", "v"); _EXPECT_DROP_MESSAGE(".cef.k\\w", "v"); _EXPECT_DROP_MESSAGE(".cef.k\nw", "v"); _EXPECT_DROP_MESSAGE(".cef.k w", "v"); } static void _test_prefix(void) { configuration->template_options.on_error = ON_ERROR_DROP_MESSAGE | ON_ERROR_SILENT; _EXPECT_CEF_RESULT_FORMAT("$(format-cef-extension --subkeys ..)", "k=v", "..k", "v"); _EXPECT_CEF_RESULT_FORMAT("$(format-cef-extension --subkeys ,)", "k=v", ",k", "v"); _EXPECT_CEF_RESULT_FORMAT("$(format-cef-extension --subkeys .cef.)", "", "k", "v"); _EXPECT_CEF_RESULT_FORMAT("$(format-cef-extension --subkeys ' ')", "k=v", " k", "v"); _EXPECT_CEF_RESULT_FORMAT("$(format-cef-extension --subkeys \" \")", "k=v", " k", "v"); _EXPECT_CEF_RESULT_FORMAT("$(format-cef-extension x=y)", "x=y", "k", "v"); _EXPECT_CEF_RESULT_FORMAT("$(format-cef-extension)", "", "k", "v"); assert_template_failure("$(format-cef-extension --subkeys)", "Missing argument for --subkeys"); assert_template_failure("$(format-cef-extension --subkeys '')", "Error parsing value-pairs: --subkeys requires a non-empty argument"); assert_template_failure("$(format-cef-extension --subkeys \"\")", "Error parsing value-pairs: --subkeys requires a non-empty argument"); } static void _test_macro_parity(void) { _EXPECT_CEF_RESULT("", "k"); _EXPECT_CEF_RESULT_FORMAT("", ""); _EXPECT_CEF_RESULT_FORMAT("", "", "k"); _EXPECT_DROP_MESSAGE(""); _EXPECT_DROP_MESSAGE("", "k"); _EXPECT_SKIP_BAD_PROPERTY(""); _EXPECT_SKIP_BAD_PROPERTY("", "k"); } int main(int argc, char *argv[]) { app_startup(); putenv("TZ=UTC"); tzset(); init_template_tests(); cfg_load_module(configuration, "cef"); _test_filter(); _test_multiple_properties_with_space(); _test_multiple_properties(); _test_drop_property(); _test_drop_message(); _test_empty(); _test_inline(); _test_space(); _test_charset(); _test_escaping(); _test_prefix(); _test_macro_parity(); _test_null_in_value(); deinit_template_tests(); app_shutdown(); } syslog-ng-syslog-ng-3.13.2/modules/confgen/000077500000000000000000000000001321171025300205245ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/confgen/CMakeLists.txt000066400000000000000000000004631321171025300232670ustar00rootroot00000000000000set (CONFGEN_SOURCES confgen.h confgen-plugin.c ) add_library(confgen MODULE ${CONFGEN_SOURCES}) target_include_directories (confgen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(confgen PRIVATE syslog-ng) install(TARGETS confgen LIBRARY DESTINATION lib/syslog-ng/ COMPONENT confgen) syslog-ng-syslog-ng-3.13.2/modules/confgen/Makefile.am000066400000000000000000000010221321171025300225530ustar00rootroot00000000000000module_LTLIBRARIES += modules/confgen/libconfgen.la modules_confgen_libconfgen_la_SOURCES = \ modules/confgen/confgen.h \ modules/confgen/confgen-plugin.c modules_confgen_libconfgen_la_CPPFLAGS = \ $(AM_CPPFLAGS) modules_confgen_libconfgen_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_confgen_libconfgen_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_confgen_libconfgen_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) modules/confgen modules/confgen/ mod-confgen: modules/confgen/libconfgen.la .PHONY: modules/confgen/ mod-confgen syslog-ng-syslog-ng-3.13.2/modules/confgen/confgen-plugin.c000066400000000000000000000112671321171025300236120ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "confgen.h" #include "cfg.h" #include "cfg-block-generator.h" #include "messages.h" #include "plugin.h" #include #include #include static void confgen_set_args_as_env(gpointer k, gpointer v, gpointer user_data) { gchar buf[1024]; g_snprintf(buf, sizeof(buf), "confgen_%s", (gchar *)k); setenv(buf, (gchar *)v, 1); } static void confgen_unset_args_from_env(gpointer k, gpointer v, gpointer user_data) { gchar buf[1024]; g_snprintf(buf, sizeof(buf), "confgen_%s", (gchar *)k); unsetenv(buf); } typedef struct _ConfgenExec { CfgBlockGenerator super; gchar *exec; } ConfgenExec; gboolean confgen_exec_generate(CfgBlockGenerator *s, GlobalConfig *cfg, CfgArgs *args, GString *result) { ConfgenExec *self = (ConfgenExec *) s; FILE *out; gsize res; gchar buf[256]; g_snprintf(buf, sizeof(buf), "%s confgen %s", cfg_lexer_lookup_context_name_by_type(self->super.context), self->super.name); cfg_args_foreach(args, confgen_set_args_as_env, NULL); out = popen(self->exec, "r"); cfg_args_foreach(args, confgen_unset_args_from_env, NULL); if (!out) { msg_error("confgen: Error executing generator program", evt_tag_str("context", cfg_lexer_lookup_context_name_by_type(self->super.context)), evt_tag_str("block", self->super.name), evt_tag_str("exec", self->exec), evt_tag_errno("error", errno)); return FALSE; } g_string_set_size(result, 1024); while ((res = fread(result->str + result->len, 1, 1024, out)) > 0) { result->len += res; g_string_set_size(result, result->len + 1024); } res = pclose(out); if (res != 0) { msg_error("confgen: Generator program returned with non-zero exit code", evt_tag_str("context", cfg_lexer_lookup_context_name_by_type(self->super.context)), evt_tag_str("block", self->super.name), evt_tag_str("exec", self->exec), evt_tag_int("rc", res)); return FALSE; } msg_debug("confgen: output from the executed program to be included is", evt_tag_printf("block", "%.*s", (gint) result->len, result->str)); return TRUE; } static void confgen_exec_free(CfgBlockGenerator *s) { ConfgenExec *self = (ConfgenExec *) s; g_free(self->exec); cfg_block_generator_free_instance(s); } static CfgBlockGenerator * confgen_exec_new(gint context, const gchar *name, const gchar *exec) { ConfgenExec *self = g_new0(ConfgenExec, 1); cfg_block_generator_init_instance(&self->super, context, name); self->super.generate = confgen_exec_generate; self->super.free_fn = confgen_exec_free; self->exec = g_strdup(exec); return &self->super; } gboolean confgen_module_init(PluginContext *plugin_context, CfgArgs *args) { const gchar *name, *context, *exec; name = cfg_args_get(args, "name"); if (!name) { msg_error("confgen: name argument expected"); return FALSE; } context = cfg_args_get(args, "context"); if (!context) { msg_error("confgen: context argument expected"); return FALSE; } exec = cfg_args_get(args, "exec"); if (!exec) { msg_error("confgen: exec argument expected"); return FALSE; } cfg_lexer_register_generator_plugin(plugin_context, confgen_exec_new(cfg_lexer_lookup_context_type_by_name(context), name, exec)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "confgen", .version = SYSLOG_NG_VERSION, .description = "The confgen module provides support for dynamically generated configuration file snippets for syslog-ng, used for the SCL system() driver for example", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = NULL, .plugins_len = 0, }; syslog-ng-syslog-ng-3.13.2/modules/confgen/confgen.h000066400000000000000000000020221321171025300223100ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CONFGEN_H_INCLUDED #define CONFGEN_H_INCLUDED #include "syslog-ng.h" #endif syslog-ng-syslog-ng-3.13.2/modules/cryptofuncs/000077500000000000000000000000001321171025300214645ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/cryptofuncs/CMakeLists.txt000066400000000000000000000007511321171025300242270ustar00rootroot00000000000000set (CRYPTOFUNCS_SOURCES cryptofuncs.c ) find_package(OpenSSL) if (OPENSSL_FOUND) add_library(cryptofuncs MODULE ${CRYPTOFUNCS_SOURCES}) target_include_directories (cryptofuncs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories (cryptofuncs PRIVATE SYSTEM ${OPENSSL_INCLUDE_DIRS}) target_link_libraries(cryptofuncs PRIVATE syslog-ng ${OPENSSL_LIBRARIES}) install(TARGETS cryptofuncs LIBRARY DESTINATION lib/syslog-ng/ COMPONENT cryptofuncs) endif() syslog-ng-syslog-ng-3.13.2/modules/cryptofuncs/Makefile.am000066400000000000000000000011221321171025300235140ustar00rootroot00000000000000module_LTLIBRARIES += \ modules/cryptofuncs/libcryptofuncs.la modules_cryptofuncs_libcryptofuncs_la_SOURCES = \ modules/cryptofuncs/cryptofuncs.c modules_cryptofuncs_libcryptofuncs_la_LIBADD = \ $(MODULE_DEPS_LIBS) $(OPENSSL_LIBS) modules_cryptofuncs_libcryptofuncs_la_LDFLAGS = \ $(MODULE_LDFLAGS) $(OPENSSL_CFLAGS) modules_cryptofuncs_libcryptofuncs_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) modules/cryptofuncs modules/cryptofuncs/ mod-cryptofuncs: modules/cryptofuncs/libcryptofuncs.la .PHONY: modules/cryptofuncs/ mod-cryptofuncs include modules/cryptofuncs/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/modules/cryptofuncs/cryptofuncs.c000066400000000000000000000124611321171025300242130ustar00rootroot00000000000000/* * Copyright (c) 2012 Balabit * Copyright (c) 2012 Gergely Nagy * Copyright (c) 2012 Peter Gyongyosi * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. */ #include "plugin.h" #include "template/simple-function.h" #include "cfg.h" #include "uuid.h" #include "str-format.h" #include "plugin-types.h" #include "compat/openssl_support.h" #include static void tf_uuid(LogMessage *msg, gint argc, GString *argv[], GString *result) { char uuid_str[37]; uuid_gen_random(uuid_str, sizeof(uuid_str)); g_string_append (result, uuid_str); } TEMPLATE_FUNCTION_SIMPLE(tf_uuid); /* * $($hash_method [opts] $arg1 $arg2 $arg3...) * * Returns the hash of the argument, using the specified hashing * method. Note that the values of the arguments are simply concatenated * when calculating the hash. * * Options: * --length N, -l N Truncate the hash to the first N characters */ typedef struct _TFHashState { TFSimpleFuncState super; gint length; const EVP_MD *md; } TFHashState; static gboolean tf_hash_prepare(LogTemplateFunction *self, gpointer s, LogTemplate *parent, gint argc, gchar *argv[], GError **error) { TFHashState *state = (TFHashState *) s; GOptionContext *ctx; gint length = 0; const EVP_MD *md; GOptionEntry hash_options[] = { { "length", 'l', 0, G_OPTION_ARG_INT, &length, NULL, NULL }, { NULL } }; ctx = g_option_context_new("hash"); g_option_context_add_main_entries(ctx, hash_options, NULL); if (!g_option_context_parse(ctx, &argc, &argv, error)) { g_option_context_free(ctx); return FALSE; } g_option_context_free(ctx); if (argc < 2) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "$(hash) parsing failed, invalid number of arguments"); return FALSE; } if (!tf_simple_func_prepare(self, state, parent, argc, argv, error)) { return FALSE; } state->length = length; md = EVP_get_digestbyname(strcmp(argv[0], "hash") == 0 ? "sha256" : argv[0]); if (!md) { g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_COMPILE, "$(hash) parsing failed, unknown digest type"); return FALSE; } state->md = md; gint md_size = EVP_MD_size(md); if ((state->length == 0) || (state->length > md_size * 2)) state->length = md_size * 2; return TRUE; } static guint _hash(const EVP_MD *md, GString **argv, gint argc, guchar *hash, guint hash_size) { gint i; guint md_len; DECLARE_EVP_MD_CTX(mdctx); EVP_MD_CTX_init(mdctx); EVP_DigestInit_ex(mdctx, md, NULL); for (i = 0; i < argc; i++) { EVP_DigestUpdate(mdctx, argv[i]->str, argv[i]->len); } EVP_DigestFinal_ex(mdctx, hash, &md_len); EVP_MD_CTX_cleanup(mdctx); EVP_MD_CTX_destroy(mdctx); return md_len; } static void tf_hash_call(LogTemplateFunction *self, gpointer s, const LogTemplateInvokeArgs *args, GString *result) { TFHashState *state = (TFHashState *) s; GString **argv; gint argc; guchar hash[EVP_MAX_MD_SIZE]; gchar hash_str[EVP_MAX_MD_SIZE * 2 + 1]; guint md_len; argv = (GString **) args->bufs->pdata; argc = args->bufs->len; md_len = _hash(state->md, argv, argc, hash, sizeof(hash)); // we fetch the entire hash in a hex format otherwise we cannot truncate at // odd character numbers format_hex_string(hash, md_len, hash_str, sizeof(hash_str)); if (state->length == 0) { g_string_append(result, hash_str); } else { g_string_append_len(result, hash_str, MIN(sizeof(hash_str), state->length)); } } TEMPLATE_FUNCTION(TFHashState, tf_hash, tf_hash_prepare, tf_simple_func_eval, tf_hash_call, tf_simple_func_free_state, NULL); static Plugin cryptofuncs_plugins[] = { TEMPLATE_FUNCTION_PLUGIN(tf_uuid, "uuid"), TEMPLATE_FUNCTION_PLUGIN(tf_hash, "hash"), TEMPLATE_FUNCTION_PLUGIN(tf_hash, "sha1"), TEMPLATE_FUNCTION_PLUGIN(tf_hash, "sha256"), TEMPLATE_FUNCTION_PLUGIN(tf_hash, "sha512"), TEMPLATE_FUNCTION_PLUGIN(tf_hash, "md4"), TEMPLATE_FUNCTION_PLUGIN(tf_hash, "md5"), }; gboolean cryptofuncs_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, cryptofuncs_plugins, G_N_ELEMENTS(cryptofuncs_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "cryptofuncs", .version = SYSLOG_NG_VERSION, .description = "The cryptofuncs module provides cryptographic template functions.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = cryptofuncs_plugins, .plugins_len = G_N_ELEMENTS(cryptofuncs_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/cryptofuncs/tests/000077500000000000000000000000001321171025300226265ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/cryptofuncs/tests/Makefile.am000066400000000000000000000005441321171025300246650ustar00rootroot00000000000000modules_cryptofuncs_tests_TESTS = \ modules/cryptofuncs/tests/test_cryptofuncs check_PROGRAMS += \ ${modules_cryptofuncs_tests_TESTS} modules_cryptofuncs_tests_test_cryptofuncs_CFLAGS = \ $(TEST_CFLAGS) modules_cryptofuncs_tests_test_cryptofuncs_LDADD = \ $(TEST_LDADD) \ -dlpreopen ${top_builddir}/modules/cryptofuncs/libcryptofuncs.la syslog-ng-syslog-ng-3.13.2/modules/cryptofuncs/tests/test_cryptofuncs.c000066400000000000000000000057671321171025300264270ustar00rootroot00000000000000/* * Copyright (c) 2012-2015 Balabit * Copyright (c) 2012-2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "template_lib.h" #include "apphook.h" #include "cfg.h" void test_hash(void) { assert_template_format("$(sha1 foo)", "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"); assert_template_format("$(sha1 bar)", "62cdb7020ff920e5aa642c3d4066950dd1f01f4d"); assert_template_format("$(md5 foo)", "acbd18db4cc2f85cedef654fccc4a4d8"); assert_template_format("$(hash foo)", "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"); assert_template_format("$(md4 foo)", "0ac6700c491d70fb8650940b1ca1e4b2"); assert_template_format("$(sha256 foo)", "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"); assert_template_format("$(sha512 foo)", "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7"); assert_template_failure("$(sha1)", "$(hash) parsing failed, invalid number of arguments"); assert_template_format("$(sha1 --length 5 foo)", "0beec"); assert_template_format("$(sha1 -l 5 foo)", "0beec"); assert_template_failure("$(sha1 --length 5)", "$(hash) parsing failed, invalid number of arguments"); assert_template_failure("$(sha1 --length 5)", "$(hash) parsing failed, invalid number of arguments"); assert_template_failure("$(sha1 ${missingbrace)", "Invalid macro, '}' is missing, error_pos='14'"); assert_template_failure("$(sha1 --length invalid_length_specification foo)", "Cannot parse integer value"); assert_template_format("$(sha1 --length 99999 foo)", "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"); assert_template_format("$(sha1 foo bar)", "8843d7f92416211de9ebb963ff4ce28125932878"); assert_template_format("$(sha1 \"foo bar\")", "3773dea65156909838fa6c22825cafe090ff8030"); assert_template_format("$(md5 $(sha1 foo) bar)", "196894290a831b2d2755c8de22619a97"); } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { app_startup(); init_template_tests(); cfg_load_module(configuration, "cryptofuncs"); test_hash(); deinit_template_tests(); app_shutdown(); } syslog-ng-syslog-ng-3.13.2/modules/csvparser/000077500000000000000000000000001321171025300211155ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/csvparser/CMakeLists.txt000066400000000000000000000013451321171025300236600ustar00rootroot00000000000000set(CSVPARSER_SOURCES csvparser.c csvparser.h csvparser-parser.c csvparser-parser.h csvparser-plugin.c ${CMAKE_CURRENT_BINARY_DIR}/csvparser-grammar.h ${CMAKE_CURRENT_BINARY_DIR}/csvparser-grammar.c ) generate_y_from_ym(modules/csvparser/csvparser-grammar) bison_target(CSVParserGrammar ${CMAKE_CURRENT_BINARY_DIR}/csvparser-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/csvparser-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) include_directories (${CMAKE_CURRENT_BINARY_DIR}) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) add_library(csvparser MODULE ${CSVPARSER_SOURCES}) target_link_libraries(csvparser PRIVATE syslog-ng) install(TARGETS csvparser LIBRARY DESTINATION lib/syslog-ng/ COMPONENT csvparser) syslog-ng-syslog-ng-3.13.2/modules/csvparser/Makefile.am000066400000000000000000000022021321171025300231450ustar00rootroot00000000000000module_LTLIBRARIES += modules/csvparser/libcsvparser.la modules_csvparser_libcsvparser_la_SOURCES = \ modules/csvparser/csvparser.c \ modules/csvparser/csvparser.h \ modules/csvparser/csvparser-grammar.y \ modules/csvparser/csvparser-parser.c \ modules/csvparser/csvparser-parser.h \ modules/csvparser/csvparser-plugin.c modules_csvparser_libcsvparser_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/csvparser \ -I$(top_builddir)/modules/csvparser \ -I$(top_srcdir)/lib/scanner/csv-scanner \ -I$(top_builddir)/lib/scanner/csv-scanner modules_csvparser_libcsvparser_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_csvparser_libcsvparser_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_csvparser_libcsvparser_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) BUILT_SOURCES += \ modules/csvparser/csvparser-grammar.y \ modules/csvparser/csvparser-grammar.c \ modules/csvparser/csvparser-grammar.h EXTRA_DIST += \ modules/csvparser/csvparser-grammar.ym modules/csvparser modules/csvparser/ mod-csvparser: modules/csvparser/libcsvparser.la .PHONY: modules/csvparser/ mod-csvparser include modules/csvparser/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/modules/csvparser/csvparser-grammar.ym000066400000000000000000000110441321171025300251200ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code top { #include "csvparser-parser.h" } %code { #include "csvparser.h" #include "cfg-parser.h" #include "cfg-grammar.h" #include "csvparser-grammar.h" #include "syslog-names.h" #include "messages.h" } %name-prefix "csvparser_" /* this parameter is needed in order to instruct bison to use a complete * argument list for yylex/yyerror */ %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogParser **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_CSV_PARSER %token KW_DIALECT %token KW_PREFIX %token KW_COLUMNS %token KW_DELIMITERS %token KW_QUOTES %token KW_QUOTE_PAIRS %token KW_NULL %token KW_CHARS %token KW_STRINGS %type parser_expr_csv %type parser_csv_flags %type parser_csv_dialect %% start : LL_CONTEXT_PARSER parser_expr_csv { YYACCEPT; } ; parser_expr_csv : KW_CSV_PARSER '(' { last_parser = *instance = csv_parser_new(configuration); } parser_csv_opts ')' { $$ = last_parser; } ; parser_csv_opts : parser_csv_opt parser_csv_opts | ; parser_csv_opt /* CSVParser related options */ : KW_FLAGS '(' parser_csv_flags ')' { CHECK_ERROR(csv_parser_set_flags(last_parser, $3), @3, "only one escape style can be used in the flags argument"); } | KW_PREFIX '(' string ')' { csv_parser_set_prefix(last_parser, $3); free($3); } /* CSVScanner related options */ | KW_DIALECT '(' parser_csv_dialect ')' { csv_scanner_options_set_dialect(csv_parser_get_scanner_options(last_parser), $3); } | KW_DELIMITERS '(' parser_csv_delimiters ')' | KW_QUOTES '(' string ')' { csv_scanner_options_set_quotes(csv_parser_get_scanner_options(last_parser), $3); free($3); } | KW_QUOTE_PAIRS '(' string ')' { csv_scanner_options_set_quote_pairs(csv_parser_get_scanner_options(last_parser), $3); free($3); } | KW_NULL '(' string ')' { csv_scanner_options_set_null_value(csv_parser_get_scanner_options(last_parser), $3); free($3); } | KW_COLUMNS '(' string_list ')' { csv_scanner_options_set_columns(csv_parser_get_scanner_options(last_parser), $3); } | parser_opt ; parser_csv_delimiters : string { csv_scanner_options_set_delimiters(csv_parser_get_scanner_options(last_parser), $1); free($1); } | parser_csv_delimiters_opts ; parser_csv_delimiters_opts : parser_csv_delimiters_opt parser_csv_delimiters_opts | ; parser_csv_delimiters_opt : KW_CHARS '(' string ')' { csv_scanner_options_set_delimiters(csv_parser_get_scanner_options(last_parser), $3); free($3); } | KW_STRINGS '(' string_list ')' { csv_scanner_options_set_string_delimiters(csv_parser_get_scanner_options(last_parser), $3); } ; parser_csv_flags : string parser_csv_flags { guint32 flag = csv_parser_lookup_flag($1); CHECK_ERROR(flag != 0, @1, "unknown csv-parser() flag %s", $1); $$ = flag | $2; free($1); } | { $$ = 0; } ; parser_csv_dialect : string { gint mode = csv_parser_lookup_dialect($1); CHECK_ERROR(mode >= 0, @1, "unknown dialect() argument for csv-parser()"); free($1); } /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/csvparser/csvparser-parser.c000066400000000000000000000035251321171025300245700ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "csvparser.h" #include "cfg-parser.h" #include "csvparser-grammar.h" extern int csvparser_debug; int csvparser_parse(CfgLexer *lexer, LogParser **instance, gpointer arg); static CfgLexerKeyword csvparser_keywords[] = { { "csv_parser", KW_CSV_PARSER }, { "dialect", KW_DIALECT }, { "prefix", KW_PREFIX }, { "columns", KW_COLUMNS }, { "delimiters", KW_DELIMITERS }, { "quotes", KW_QUOTES }, { "quote_pairs", KW_QUOTE_PAIRS }, { "chars", KW_CHARS}, { "strings", KW_STRINGS}, { "null", KW_NULL }, { NULL } }; CfgParser csvparser_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &csvparser_debug, #endif .name = "csvparser", .keywords = csvparser_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer)) csvparser_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(csvparser_, LogParser **) syslog-ng-syslog-ng-3.13.2/modules/csvparser/csvparser-parser.h000066400000000000000000000022451321171025300245730ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CSVPARSER_PARSER_H_INCLUDED #define CSVPARSER_PARSER_H_INCLUDED #include "cfg-parser.h" #include "parser/parser-expr.h" extern CfgParser csvparser_parser; CFG_PARSER_DECLARE_LEXER_BINDING(csvparser_, LogParser **) #endif syslog-ng-syslog-ng-3.13.2/modules/csvparser/csvparser-plugin.c000066400000000000000000000033251321171025300245700ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "csvparser.h" #include "plugin.h" #include "plugin-types.h" extern CfgParser csvparser_parser; static Plugin csvparser_plugins[] = { { .type = LL_CONTEXT_PARSER, .name = "csv-parser", .parser = &csvparser_parser, }, }; gboolean csvparser_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, csvparser_plugins, G_N_ELEMENTS(csvparser_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "csvparser", .version = SYSLOG_NG_VERSION, .description = "The csvparser module provides parsing support for CSV and other separated value formats for syslog-ng.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = csvparser_plugins, .plugins_len = G_N_ELEMENTS(csvparser_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/csvparser/csvparser.c000066400000000000000000000142011321171025300232670ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "csvparser.h" #include "scanner/csv-scanner/csv-scanner.h" #include "parser/parser-expr.h" #include "scratch-buffers.h" #include typedef struct _CSVParser { LogParser super; CSVScannerOptions options; gchar *prefix; gint prefix_len; } CSVParser; #define _ESCAPE_MODE_SHIFT 16 #define _ESCAPE_MODE_MASK 0xFFFF0000 #define _ESCAPE_MODE_NONE (1 << _ESCAPE_MODE_SHIFT) #define _ESCAPE_MODE_BACKSLASH (2 << _ESCAPE_MODE_SHIFT) #define _ESCAPE_MODE_DOUBLE_CHAR (4 << _ESCAPE_MODE_SHIFT) CSVScannerOptions * csv_parser_get_scanner_options(LogParser *s) { CSVParser *self = (CSVParser *) s; return &self->options; } gboolean csv_parser_set_flags(LogParser *s, guint32 flags) { CSVParser *self = (CSVParser *) s; guint32 dialect = (flags & _ESCAPE_MODE_MASK); guint32 scanner_flags = flags & 0xFFFF; csv_scanner_options_set_flags(&self->options, scanner_flags); switch (dialect) { case 0: break; case _ESCAPE_MODE_NONE: csv_scanner_options_set_dialect(&self->options, CSV_SCANNER_ESCAPE_NONE); break; case _ESCAPE_MODE_BACKSLASH: csv_scanner_options_set_dialect(&self->options, CSV_SCANNER_ESCAPE_BACKSLASH); break; case _ESCAPE_MODE_DOUBLE_CHAR: csv_scanner_options_set_dialect(&self->options, CSV_SCANNER_ESCAPE_DOUBLE_CHAR); break; default: return FALSE; } return TRUE; } void csv_parser_set_prefix(LogParser *s, const gchar *prefix) { CSVParser *self = (CSVParser *) s; g_free(self->prefix); if (prefix) { self->prefix = g_strdup(prefix); self->prefix_len = strlen(prefix); } else { self->prefix = NULL; self->prefix_len = 0; } } static const gchar * _format_key_for_prefix(GString *scratch, const gchar *key, const gint prefix_len) { g_string_truncate(scratch, prefix_len); g_string_append(scratch, key); return scratch->str; } static const gchar * _return_key(GString *scratch, const gchar *key, const gint prefix_len) { return key; } typedef const gchar *(*key_formatter_t)(GString *scratch, const gchar *key, const gint prefix_len); static key_formatter_t dispatch_key_formatter(gchar *prefix) { return prefix ? _format_key_for_prefix : _return_key; } static gboolean csv_parser_process(LogParser *s, LogMessage **pmsg, const LogPathOptions *path_options, const gchar *input, gsize input_len) { CSVParser *self = (CSVParser *) s; LogMessage *msg = log_msg_make_writable(pmsg, path_options); CSVScanner scanner; csv_scanner_init(&scanner, &self->options, input); GString *key_scratch = scratch_buffers_alloc(); if (self->prefix) g_string_assign(key_scratch, self->prefix); key_formatter_t _key_formatter = dispatch_key_formatter(self->prefix); while (csv_scanner_scan_next(&scanner)) { log_msg_set_value_by_name(msg, _key_formatter(key_scratch, csv_scanner_get_current_name(&scanner), self->prefix_len), csv_scanner_get_current_value(&scanner), csv_scanner_get_current_value_len(&scanner)); } csv_scanner_deinit(&scanner); return csv_scanner_is_scan_finished(&scanner); } static LogPipe * csv_parser_clone(LogPipe *s) { CSVParser *self = (CSVParser *) s; CSVParser *cloned; cloned = (CSVParser *) csv_parser_new(s->cfg); csv_scanner_options_copy(&cloned->options, &self->options); cloned->super.template = log_template_ref(self->super.template); csv_parser_set_prefix(&cloned->super, self->prefix); return &cloned->super.super; } static void csv_parser_free(LogPipe *s) { CSVParser *self = (CSVParser *) s; csv_scanner_options_clean(&self->options); g_free(self->prefix); log_parser_free_method(s); } /* * Parse comma-separated values from a log message. */ LogParser * csv_parser_new(GlobalConfig *cfg) { CSVParser *self = g_new0(CSVParser, 1); log_parser_init_instance(&self->super, cfg); self->super.super.free_fn = csv_parser_free; self->super.super.clone = csv_parser_clone; self->super.process = csv_parser_process; csv_scanner_options_set_delimiters(&self->options, " "); csv_scanner_options_set_quote_pairs(&self->options, "\"\"''"); csv_scanner_options_set_flags(&self->options, CSV_SCANNER_STRIP_WHITESPACE); csv_scanner_options_set_dialect(&self->options, CSV_SCANNER_ESCAPE_NONE); return &self->super; } guint32 csv_parser_lookup_flag(const gchar *flag) { if (strcmp(flag, "escape-none") == 0) return _ESCAPE_MODE_NONE; else if (strcmp(flag, "escape-backslash") == 0) return _ESCAPE_MODE_BACKSLASH; else if (strcmp(flag, "escape-double-char") == 0) return _ESCAPE_MODE_DOUBLE_CHAR; else if (strcmp(flag, "strip-whitespace") == 0) return CSV_SCANNER_STRIP_WHITESPACE; else if (strcmp(flag, "greedy") == 0) return CSV_SCANNER_GREEDY; else if (strcmp(flag, "drop-invalid") == 0) return CSV_SCANNER_DROP_INVALID; return 0; } gint csv_parser_lookup_dialect(const gchar *flag) { if (strcmp(flag, "escape-none") == 0) return CSV_SCANNER_ESCAPE_NONE; else if (strcmp(flag, "escape-backslash") == 0) return CSV_SCANNER_ESCAPE_BACKSLASH; else if (strcmp(flag, "escape-double-char") == 0) return CSV_SCANNER_ESCAPE_DOUBLE_CHAR; return -1; } syslog-ng-syslog-ng-3.13.2/modules/csvparser/csvparser.h000066400000000000000000000026371321171025300233060ustar00rootroot00000000000000/* * Copyright (c) 2002-2015 Balabit * Copyright (c) 1998-2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef CSVPARSER_H_INCLUDED #define CSVPARSER_H_INCLUDED #include "parser/parser-expr.h" #include "scanner/csv-scanner/csv-scanner.h" CSVScannerOptions *csv_parser_get_scanner_options(LogParser *s); gboolean csv_parser_set_flags(LogParser *s, guint32 flags); void csv_parser_set_prefix(LogParser *s, const gchar *prefix); LogParser *csv_parser_new(GlobalConfig *cfg); guint32 csv_parser_lookup_flag(const gchar *flag); gint csv_parser_lookup_dialect(const gchar *flag); #endif syslog-ng-syslog-ng-3.13.2/modules/csvparser/tests/000077500000000000000000000000001321171025300222575ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/csvparser/tests/Makefile.am000066400000000000000000000023621321171025300243160ustar00rootroot00000000000000modules_csvparser_tests_TESTS = \ modules/csvparser/tests/test_csvparser \ modules/csvparser/tests/test_csvparser_perf check_PROGRAMS += \ ${modules_csvparser_tests_TESTS} modules_csvparser_tests_test_csvparser_CFLAGS = \ $(TEST_CFLAGS) -I$(top_srcdir)/modules/csvparser modules_csvparser_tests_test_csvparser_LDADD = \ $(TEST_LDADD) modules_csvparser_tests_test_csvparser_LDFLAGS = \ $(PREOPEN_SYSLOGFORMAT) \ -dlpreopen $(top_builddir)/modules/csvparser/libcsvparser.la modules_csvparser_tests_test_csvparser_perf_CFLAGS = \ $(TEST_CFLAGS) -I$(top_srcdir)/modules/csvparser modules_csvparser_tests_test_csvparser_perf_LDADD = \ $(TEST_LDADD) modules_csvparser_tests_test_csvparser_perf_LDFLAGS = \ $(PREOPEN_SYSLOGFORMAT) \ -dlpreopen $(top_builddir)/modules/csvparser/libcsvparser.la if ENABLE_CRITERION modules_csvparser_tests_TESTS += modules/csvparser/tests/test_csvparser_statistics modules_csvparser_tests_test_csvparser_statistics_CFLAGS = \ $(TEST_CFLAGS) -I$(top_srcdir)/modules/csvparser modules_csvparser_tests_test_csvparser_statistics_LDADD = \ $(TEST_LDADD) modules_csvparser_tests_test_csvparser_statistics_LDFLAGS = \ $(PREOPEN_SYSLOGFORMAT) \ -dlpreopen $(top_builddir)/modules/csvparser/libcsvparser.la endif syslog-ng-syslog-ng-3.13.2/modules/csvparser/tests/test_csvparser.c000066400000000000000000000445461321171025300255070ustar00rootroot00000000000000/* * Copyright (c) 2008-2015 Balabit * Copyright (c) 2008-2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "csvparser.h" #include "syslog-ng.h" #include "logmsg/logmsg.h" #include "apphook.h" #include "string-list.h" #include "cfg.h" #include "plugin.h" #include #include #include #include #define TEST_ASSERT(x, desc) \ do \ { \ if (!(x)) \ { \ fprintf(stderr, "Testcase failed: %s; msg='%s', cond='%s', value='%s', expected_value='%s'\n", desc, msg, #x, value, expected_value); \ exit(1); \ } \ } \ while (0) MsgFormatOptions parse_options; int testcase(gchar *msg, guint parse_flags, gint max_columns, gint dialect, guint32 flags, gchar *delimiters, gchar *quotes, gchar *null_value, const gchar *string_delims[], gchar *first_value, ...) { LogMessage *logmsg; LogParser *p, *pclone; gchar *expected_value; gint i; va_list va; NVTable *nvtable; const gchar *column_array[] = { "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10", "C11", "C12", "C13", "C14", "C15", "C16", "C17", "C18", "C19", "C20", "C21", "C22", "C23", "C24", "C25", "C26", "C27", "C28", "C29", "C30", NULL }; gboolean success; if (max_columns != -1) { g_assert(max_columns < (sizeof(column_array) / sizeof(column_array[0]))); column_array[max_columns] = NULL; } parse_options.flags = parse_flags; logmsg = log_msg_new(msg, strlen(msg), NULL, &parse_options); p = csv_parser_new(NULL); csv_scanner_options_set_flags(csv_parser_get_scanner_options(p), flags); csv_scanner_options_set_dialect(csv_parser_get_scanner_options(p), dialect); csv_scanner_options_set_columns(csv_parser_get_scanner_options(p), string_array_to_list(column_array)); if (delimiters) csv_scanner_options_set_delimiters(csv_parser_get_scanner_options(p), delimiters); if (quotes) csv_scanner_options_set_quote_pairs(csv_parser_get_scanner_options(p), quotes); if (null_value) csv_scanner_options_set_null_value(csv_parser_get_scanner_options(p), null_value); if (string_delims) csv_scanner_options_set_string_delimiters(csv_parser_get_scanner_options(p), string_array_to_list(string_delims)); pclone = (LogParser *) log_pipe_clone(&p->super); log_pipe_unref(&p->super); nvtable = nv_table_ref(logmsg->payload); success = log_parser_process(pclone, &logmsg, NULL, log_msg_get_value(logmsg, LM_V_MESSAGE, NULL), -1); nv_table_unref(nvtable); if (success && !first_value) { fprintf(stderr, "unexpected match; msg=%s\n", msg); exit(1); } if (!success && first_value) { fprintf(stderr, "unexpected non-match; msg=%s\n", msg); exit(1); } log_pipe_unref(&pclone->super); va_start(va, first_value); expected_value = first_value; i = 0; while (expected_value && column_array[i]) { const gchar *value; gssize value_len; value = log_msg_get_value_by_name(logmsg, column_array[i], &value_len); if (expected_value && expected_value[0]) { TEST_ASSERT(value && value[0], "expected value set, but no actual value"); TEST_ASSERT(strlen(expected_value) == value_len, "value length doesn't match actual length"); TEST_ASSERT(strncmp(value, expected_value, value_len) == 0, "value does not match expected value"); } else { TEST_ASSERT(!(value && value[0]), "expected unset, but actual value present"); } expected_value = va_arg(va, char *); i++; } log_msg_unref(logmsg); return 1; } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { app_startup(); putenv("TZ=MET-1METDST"); tzset(); configuration = cfg_new_snippet(); cfg_load_module(configuration, "syslogformat"); msg_format_options_defaults(&parse_options); msg_format_options_init(&parse_options, configuration); // string delim & single char & a char benne van a stringben is const char *string_delims[] = {" :", NULL}; testcase("<15> openvpn[2499]: PTHREAD support :initialized", 0, -1, CSV_SCANNER_ESCAPE_NONE, 0, " ", NULL, NULL, string_delims, "PTHREAD", "support", "initialized", NULL); // string delim & single char & a char nincs benne a stringben testcase("<15> openvpn[2499]: PTHREAD,support :initialized", 0, -1, CSV_SCANNER_ESCAPE_NONE, 0, ",", NULL, NULL, string_delims, "PTHREAD", "support", "initialized", NULL); // string delim & multi char & a char benne van a stringben is testcase("<15> openvpn[2499]: PTHREAD support :initialized", 0, -1, CSV_SCANNER_ESCAPE_NONE, 0, " :", NULL, NULL, string_delims, "PTHREAD", "support", "initialized", NULL); // string delim & multi char & a char nincs benne a stringben testcase("<15> openvpn[2499]: PTHREAD,support :initialized", 0, -1, CSV_SCANNER_ESCAPE_NONE, 0, ";,", NULL, NULL, string_delims, "PTHREAD", "support", "initialized", NULL); // quote + string delim & multi char & a char benne van a stringben is testcase("<15> openvpn[2499]: 'PTHREAD' 'support' :'initialized'", 0, -1, CSV_SCANNER_ESCAPE_NONE, 0, " :", "''", NULL, string_delims, "PTHREAD", "support", "initialized", NULL); // quote + string delim & multi char & a char nincs benne a stringben testcase("<15> openvpn[2499]: 'PTHREAD','support' :'initialized'", 0, -1, CSV_SCANNER_ESCAPE_NONE, 0, ";,", "''", NULL, string_delims, "PTHREAD", "support", "initialized", NULL); // BE + quote + string delim & multi char & a char benne van a stringben is testcase("<15> openvpn[2499]: 'PTHRE\\\'AD' 'support' :'initialized'", 0, -1, CSV_SCANNER_ESCAPE_BACKSLASH, 0, " :", "''", NULL, string_delims, "PTHRE'AD", "support", "initialized", NULL); // DCE + quote + string delim & multi char & a char nincs benne a stringben testcase("<15> openvpn[2499]: 'PTHREAD','sup''port' :'initialized'", 0, -1, CSV_SCANNER_ESCAPE_DOUBLE_CHAR, 0, ";,", "''", NULL, string_delims, "PTHREAD", "sup'port", "initialized", NULL); testcase("<15> openvpn[2499]: PTHREAD support initialized", 0, 3, CSV_SCANNER_ESCAPE_NONE, 0, " ", NULL, NULL, NULL, "PTHREAD", "support", "initialized", NULL); testcase("<15> openvpn[2499]: PTHREAD support initialized", 0, 2, CSV_SCANNER_ESCAPE_NONE, CSV_SCANNER_DROP_INVALID, " ", NULL, NULL, NULL, NULL); testcase("<15> openvpn[2499]: PTHREAD support initialized", 0, 2, CSV_SCANNER_ESCAPE_NONE, CSV_SCANNER_GREEDY, " ", NULL, NULL, NULL, "PTHREAD", "support initialized", NULL); testcase("<15> openvpn[2499]: PTHREAD support initialized", 0, -1, CSV_SCANNER_ESCAPE_NONE, 0, " ,;", NULL, NULL, NULL, "PTHREAD", "support", "initialized", NULL); testcase("<15> openvpn[2499]: PTHREAD support initialized", 0, -1, CSV_SCANNER_ESCAPE_NONE, 0, " ,;", NULL, "support", NULL, "PTHREAD", "", "initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD\" \"support\" \"initialized\"", 0, -1, CSV_SCANNER_ESCAPE_NONE, 0, " ", NULL, NULL, NULL, "PTHREAD", "support", "initialized", NULL); // testcase("<15> openvpn[2499]: \"PTHREAD\"+\"support\" \"initialized\"", 0, -1, CSV_SCANNER_ESCAPE_NONE, " ", NULL, NULL, NULL, // "PTHREAD\"+\"support", "initialized", NULL); testcase("<15> openvpn[2499]: \" PTHREAD \" \" support\" \"initialized \"", 0, -1, CSV_SCANNER_ESCAPE_NONE, CSV_SCANNER_STRIP_WHITESPACE, " ", NULL, NULL, NULL, "PTHREAD", "support", "initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD support\" \"initialized\"", 0, -1, CSV_SCANNER_ESCAPE_NONE, 0, " ", NULL, NULL, NULL, "PTHREAD support", "initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD support initialized\"", 0, -1, CSV_SCANNER_ESCAPE_NONE, 0, " ", NULL, NULL, NULL, "PTHREAD support initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD support initialized", 0, -1, CSV_SCANNER_ESCAPE_NONE, 0, " ", NULL, NULL, NULL, "PTHREAD support initialized", NULL); testcase("<15> openvpn[2499]: PTHREAD support initialized", 0, -1, CSV_SCANNER_ESCAPE_BACKSLASH, 0, " ", NULL, NULL, NULL, "PTHREAD", "support", "initialized", NULL); testcase("<15> openvpn[2499]: PTHREAD support initialized", 0, 2, CSV_SCANNER_ESCAPE_BACKSLASH, CSV_SCANNER_GREEDY, " ", NULL, NULL, NULL, "PTHREAD", "support initialized", NULL); testcase("<15> openvpn[2499]: PTHREAD support initialized", 0, -1, CSV_SCANNER_ESCAPE_BACKSLASH, 0, " ;,", NULL, NULL, NULL, "PTHREAD", "support", "initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD\" \"support\" \"initialized\"", 0, -1, CSV_SCANNER_ESCAPE_BACKSLASH, 0, " ", NULL, NULL, NULL, "PTHREAD", "support", "initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD\" \"support\" \"initialized\"", 0, 2, CSV_SCANNER_ESCAPE_BACKSLASH, CSV_SCANNER_GREEDY, " ", NULL, NULL, NULL, "PTHREAD", "\"support\" \"initialized\"", NULL); testcase("<15> openvpn[2499]: \" PTHREAD \" \" support\" \"initialized \"", 0, -1, CSV_SCANNER_ESCAPE_BACKSLASH, CSV_SCANNER_STRIP_WHITESPACE, " ", NULL, NULL, NULL, "PTHREAD", "support", "initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD support\" \"initialized\"", 0, -1, CSV_SCANNER_ESCAPE_BACKSLASH, 0, " ", NULL, NULL, NULL, "PTHREAD support", "initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD \\\"support initialized\"", 0, -1, CSV_SCANNER_ESCAPE_BACKSLASH, 0, " ", NULL, NULL, NULL, "PTHREAD \"support initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD support initialized", 0, -1, CSV_SCANNER_ESCAPE_BACKSLASH, 0, " ", NULL, NULL, NULL, "PTHREAD support initialized", NULL); testcase("<15> openvpn[2499]: PTHREAD support initialized", 0, -1, CSV_SCANNER_ESCAPE_DOUBLE_CHAR, 0, " ", NULL, NULL, NULL, "PTHREAD", "support", "initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD\" \"support\" \"initialized\"", 0, -1, CSV_SCANNER_ESCAPE_DOUBLE_CHAR, 0, " ", NULL, NULL, NULL, "PTHREAD", "support", "initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD\" \"support\" \"initialized\"", 0, 2, CSV_SCANNER_ESCAPE_DOUBLE_CHAR, CSV_SCANNER_GREEDY, " ", NULL, NULL, NULL, "PTHREAD", "\"support\" \"initialized\"", NULL); testcase("<15> openvpn[2499]: \" PTHREAD \" \" support\" \"initialized \"", 0, -1, CSV_SCANNER_ESCAPE_DOUBLE_CHAR, CSV_SCANNER_STRIP_WHITESPACE, " ", NULL, NULL, NULL, "PTHREAD", "support", "initialized", NULL); testcase("<15> openvpn[2499]: \" PTHREAD \" \" support\" \"initialized \"", 0, 2, CSV_SCANNER_ESCAPE_DOUBLE_CHAR, CSV_SCANNER_GREEDY + CSV_SCANNER_STRIP_WHITESPACE, " ", NULL, NULL, NULL, "PTHREAD", "\" support\" \"initialized \"", NULL); testcase("<15> openvpn[2499]: \"PTHREAD support\" \"initialized\"", 0, -1, CSV_SCANNER_ESCAPE_DOUBLE_CHAR, 0, " ", NULL, NULL, NULL, "PTHREAD support", "initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD \"\"support initialized\"", 0, -1, CSV_SCANNER_ESCAPE_DOUBLE_CHAR, 0, " ", NULL, NULL, NULL, "PTHREAD \"support initialized", NULL); testcase("<15> openvpn[2499]: \"PTHREAD support initialized", 0, -1, CSV_SCANNER_ESCAPE_DOUBLE_CHAR, 0, " ", NULL, NULL, NULL, "PTHREAD support initialized", NULL); testcase("postfix/smtpd", LP_NOPARSE, 2, CSV_SCANNER_ESCAPE_NONE, CSV_SCANNER_GREEDY | CSV_SCANNER_DROP_INVALID, "/", NULL, NULL, NULL, "postfix", "smtpd", NULL); testcase("postfix", LP_NOPARSE, 3, CSV_SCANNER_ESCAPE_NONE, CSV_SCANNER_GREEDY | CSV_SCANNER_DROP_INVALID, "/", NULL, NULL, NULL, NULL); testcase("postfix/smtpd/ququ", LP_NOPARSE, 2, CSV_SCANNER_ESCAPE_NONE, CSV_SCANNER_GREEDY | CSV_SCANNER_DROP_INVALID, "/", NULL, NULL, NULL, "postfix", "smtpd/ququ", NULL); testcase("Jul 27 19:55:33 myhost zabbix: ZabbixConnector.log : 19:55:32,782 INFO [Thread-2834] - [ZabbixEventSyncCommand] Processing message ", LP_EXPECT_HOSTNAME, 2, CSV_SCANNER_ESCAPE_NONE, CSV_SCANNER_GREEDY, " ", NULL, NULL, NULL, "ZabbixConnector.log", ": 19:55:32,782 INFO [Thread-2834] - [ZabbixEventSyncCommand] Processing message ", NULL); testcase("10.100.20.1 - - [31/Dec/2007:00:17:10 +0100] \"GET /cgi-bin/bugzilla/buglist.cgi?keywords_type=allwords&keywords=public&format=simple HTTP/1.1\" 200 2708 \"-\" \"curl/7.15.5 (i4 86-pc-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8c zlib/1.2.3 libidn/0.6.5\" 2 bugzilla.balabit", LP_NOPARSE, -1, CSV_SCANNER_ESCAPE_BACKSLASH, 0, " ", "\"\"[]", "-", NULL, "10.100.20.1", "", "", "31/Dec/2007:00:17:10 +0100", "GET /cgi-bin/bugzilla/buglist.cgi?keywords_type=allwords&keywords=public&format=simple HTTP/1.1", "200", "2708", "", "curl/7.15.5 (i4 86-pc-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8c zlib/1.2.3 libidn/0.6.5", "2", "bugzilla.balabit", NULL); testcase("10.100.20.1 - - [31/Dec/2007:00:17:10 +0100] \"GET /cgi-bin/bugzilla/buglist.cgi?keywords_type=allwords&keywords=public&format=simple HTTP/1.1\" 200 2708 \"-\" \"curl/7.15.5 (i4 86-pc-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8c zlib/1.2.3 libidn/0.6.5\" 2 bugzilla.balabit", LP_NOPARSE, 11, CSV_SCANNER_ESCAPE_BACKSLASH, 0, " ", "\"\"[]", "-", NULL, "10.100.20.1", "", "", "31/Dec/2007:00:17:10 +0100", "GET /cgi-bin/bugzilla/buglist.cgi?keywords_type=allwords&keywords=public&format=simple HTTP/1.1", "200", "2708", "", "curl/7.15.5 (i4 86-pc-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8c zlib/1.2.3 libidn/0.6.5", "2", "bugzilla.balabit", NULL); testcase("10.100.20.1 - - [31/Dec/2007:00:17:10 +0100] \"GET /cgi-bin/bugzilla/buglist.cgi?keywords_type=allwords&keywords=public&format=simple HTTP/1.1\" 200 2708 \"-\" \"curl/7.15.5 (i4 86-pc-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8c zlib/1.2.3 libidn/0.6.5\" 2 bugzilla.balabit", LP_NOPARSE, 10, CSV_SCANNER_ESCAPE_BACKSLASH, 0, " ", "\"\"[]", "-", NULL, "10.100.20.1", "", "", "31/Dec/2007:00:17:10 +0100", "GET /cgi-bin/bugzilla/buglist.cgi?keywords_type=allwords&keywords=public&format=simple HTTP/1.1", "200", "2708", "", "curl/7.15.5 (i4 86-pc-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8c zlib/1.2.3 libidn/0.6.5", "2", NULL); testcase("10.100.20.1 - - [31/Dec/2007:00:17:10 +0100] \"GET /cgi-bin/bugzilla/buglist.cgi?keywords_type=allwords&keywords=public&format=simple HTTP/1.1\" 200 2708 \"-\" \"curl/7.15.5 (i4 86-pc-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8c zlib/1.2.3 libidn/0.6.5\" 2 bugzilla.balabit", LP_NOPARSE, 12, CSV_SCANNER_ESCAPE_BACKSLASH, 0, " ", "\"\"[]", "-", NULL, "10.100.20.1", "", "", "31/Dec/2007:00:17:10 +0100", "GET /cgi-bin/bugzilla/buglist.cgi?keywords_type=allwords&keywords=public&format=simple HTTP/1.1", "200", "2708", "", "curl/7.15.5 (i4 86-pc-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8c zlib/1.2.3 libidn/0.6.5", "2", "bugzilla.balabit", "", NULL); testcase("10.100.20.1 - - [31/Dec/2007:00:17:10 +0100] \"GET /cgi-bin/bugzilla/buglist.cgi?keywords_type=allwords&keywords=public&format=simple HTTP/1.1\" 200 2708 \"-\" \"curl/7.15.5 (i4 86-pc-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8c zlib/1.2.3 libidn/0.6.5\" 2 bugzilla.balabit almafa", LP_NOPARSE, 11, CSV_SCANNER_ESCAPE_BACKSLASH, CSV_SCANNER_DROP_INVALID, " ", "\"\"[]", "-", NULL, NULL); testcase("random.vhost 10.0.0.1 - \"GET /index.html HTTP/1.1\" 200", LP_NOPARSE, 5, CSV_SCANNER_ESCAPE_NONE, CSV_SCANNER_DROP_INVALID, " ", "\"\"", "-", NULL, "random.vhost", "10.0.0.1", "", "GET /index.html HTTP/1.1", "200", NULL); testcase("random.vhost 10.0.0.1 - \"GET /index.html HTTP/1.1\" 200", LP_NOPARSE, 5, CSV_SCANNER_ESCAPE_BACKSLASH, CSV_SCANNER_DROP_INVALID, " ", "\"\"", "-", NULL, "random.vhost", "10.0.0.1", "", "GET /index.html HTTP/1.1", "200", NULL); /* greedy column can be empty */ testcase("random.vhost 10.0.0.1 - \"GET /index.html HTTP/1.1\" 200", LP_NOPARSE, 6, CSV_SCANNER_ESCAPE_NONE, CSV_SCANNER_GREEDY | CSV_SCANNER_DROP_INVALID, " ", "\"\"", "-", NULL, "random.vhost", "10.0.0.1", "", "GET /index.html HTTP/1.1", "200", "", NULL); testcase("random.vhost 10.0.0.1 - \"GET /index.html HTTP/1.1\" 200", LP_NOPARSE, 6, CSV_SCANNER_ESCAPE_BACKSLASH, CSV_SCANNER_GREEDY | CSV_SCANNER_DROP_INVALID, " ", "\"\"", "-", NULL, "random.vhost", "10.0.0.1", "", "GET /index.html HTTP/1.1", "200", "", NULL); testcase("random.vhost\t10.0.0.1\t-\t\"GET /index.html HTTP/1.1\"\t200", LP_NOPARSE, 6, CSV_SCANNER_ESCAPE_BACKSLASH, 0, "\t", "\"\"", "-", NULL, "random.vhost", "10.0.0.1", "", "GET /index.html HTTP/1.1", "200", "", NULL); testcase("random.vhost\t10.0.0.1\t-\t\"GET /index.html HTTP/1.1\"\t\t200", LP_NOPARSE, 7, CSV_SCANNER_ESCAPE_BACKSLASH, 0, "\t", "\"\"", "-", NULL, "random.vhost", "10.0.0.1", "", "GET /index.html HTTP/1.1", "", "200", "", NULL); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/modules/csvparser/tests/test_csvparser_perf.c000066400000000000000000000101611321171025300265050ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "csvparser.h" #include "logmsg/logmsg.h" #include "string-list.h" #include "scratch-buffers.h" LogParser * _construct_parser(gint max_columns, gint dialect, gchar *delimiters, gchar *quotes, gchar *null_value, const gchar *string_delims[]) { LogParser *p; const gchar *column_array[] = { "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10", "C11", "C12", "C13", "C14", "C15", "C16", "C17", "C18", "C19", "C20", "C21", "C22", "C23", "C24", "C25", "C26", "C27", "C28", "C29", "C30", NULL }; if (max_columns != -1) { g_assert(max_columns < (sizeof(column_array) / sizeof(column_array[0]))); column_array[max_columns] = NULL; } p = csv_parser_new(NULL); csv_scanner_options_set_dialect(csv_parser_get_scanner_options(p), dialect); csv_scanner_options_set_columns(csv_parser_get_scanner_options(p), string_array_to_list(column_array)); if (delimiters) csv_scanner_options_set_delimiters(csv_parser_get_scanner_options(p), delimiters); if (quotes) csv_scanner_options_set_quote_pairs(csv_parser_get_scanner_options(p), quotes); if (null_value) csv_scanner_options_set_null_value(csv_parser_get_scanner_options(p), null_value); if (string_delims) csv_scanner_options_set_string_delimiters(csv_parser_get_scanner_options(p), string_array_to_list(string_delims)); return p; } static LogMessage * _construct_msg(const gchar *msg) { LogMessage *logmsg; logmsg = log_msg_new_empty(); log_msg_set_value_by_name(logmsg, "MESSAGE", msg, -1); return logmsg; } static void iterate_pattern(LogParser *p, const gchar *input) { LogMessage *msg; GTimeVal start, end; gint i; msg = _construct_msg(input); g_get_current_time(&start); for (i = 0; i < 100000; i++) { log_parser_process(p, &msg, NULL, log_msg_get_value(msg, LM_V_MESSAGE, NULL), -1); } log_msg_unref(msg); g_get_current_time(&end); printf(" %-90.*s speed: %12.3f msg/sec\n", (int) strlen(input), input, i * 1e6 / g_time_val_diff(&end, &start)); } static void perftest_parser(LogParser *p, const gchar *input) { iterate_pattern(p, input); log_pipe_unref(&p->super); } static void test_escaped_parsers(void) { perftest_parser(_construct_parser(3, CSV_SCANNER_ESCAPE_NONE, " ", NULL, "", NULL), "foo bar baz"); perftest_parser(_construct_parser(-1, CSV_SCANNER_ESCAPE_NONE, " ", NULL, NULL, NULL), "PROXY TCP4 198.51.100.22 203.0.113.7 35646 80"); perftest_parser(_construct_parser(-1, CSV_SCANNER_ESCAPE_BACKSLASH, " ", "\"\"[]", "-", NULL), "10.100.20.1 - - [31/Dec/2007:00:17:10 +0100] \"GET /cgi-bin/bugzilla/buglist.cgi?keywords_type=allwords&keywords=public&format=simple HTTP/1.1\" 200 2708 \"-\" \"curl/7.15.5 (i486-pc-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8c zlib/1.2.3 libidn/0.6.5\" 2 bugzilla.balabit"); } int main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED) { stats_init(); scratch_buffers_allocator_init(); log_msg_global_init(); test_escaped_parsers(); log_msg_global_deinit(); stats_destroy(); return 0; } syslog-ng-syslog-ng-3.13.2/modules/csvparser/tests/test_csvparser_statistics.c000066400000000000000000000064021321171025300277460ustar00rootroot00000000000000/* * Copyright (c) 2008-2017 Balabit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "csvparser.h" #include "syslog-ng.h" #include "logmsg/logmsg.h" #include "plugin.h" #include "string-list.h" #include "apphook.h" #include "cfg.h" #include MsgFormatOptions parse_options; LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; static LogParser * _create_parser(GlobalConfig *cfg) { LogParser *p = csv_parser_new(cfg); const gchar *column_array[] = { "header1", NULL }; stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_PARSER, p->name, NULL ); stats_register_counter(1, &sc_key, SC_TYPE_DISCARDED, &p->super.discarded_messages); stats_unlock(); csv_scanner_options_set_delimiters(csv_parser_get_scanner_options(p), ","); csv_scanner_options_set_flags(csv_parser_get_scanner_options(p), CSV_SCANNER_DROP_INVALID); csv_scanner_options_set_columns(csv_parser_get_scanner_options(p), string_array_to_list(column_array)); return p; } static void _unregister_statistics(LogParser *p) { stats_lock(); StatsClusterKey sc_key; stats_cluster_logpipe_key_set(&sc_key, SCS_PARSER, p->name, NULL ); stats_unregister_counter(&sc_key, SC_TYPE_DISCARDED, &p->super.discarded_messages); stats_unlock(); } static void _parse_msg(LogParser *self, gchar *msg) { LogMessage *logmsg = log_msg_new(msg, strlen(msg), NULL, &parse_options); log_parser_process_message(self, &logmsg, &path_options); log_msg_unref(logmsg); } Test(test_filters_statistics, filter_stastistics) { app_startup(); configuration = cfg_new_snippet(); configuration->stats_options.level = 1; cr_assert(cfg_init(configuration)); cfg_load_module(configuration, "syslogformat"); msg_format_options_defaults(&parse_options); msg_format_options_init(&parse_options, configuration); LogParser *parser = _create_parser(configuration); cr_assert_eq(stats_counter_get(parser->super.discarded_messages), 0); _parse_msg(parser, "column1, column2, column3, column4"); cr_assert_eq(stats_counter_get(parser->super.discarded_messages), 1); _parse_msg(parser, "column1, column2, column3"); cr_assert_eq(stats_counter_get(parser->super.discarded_messages), 2); _parse_msg(parser, "column1, column2"); cr_assert_eq(stats_counter_get(parser->super.discarded_messages), 2); _unregister_statistics(parser); log_parser_free_method((LogPipe *)parser); cfg_deinit(configuration); cfg_free(configuration); app_shutdown(); } syslog-ng-syslog-ng-3.13.2/modules/date/000077500000000000000000000000001321171025300200225ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/date/CMakeLists.txt000066400000000000000000000013371321171025300225660ustar00rootroot00000000000000set(DATE_PARSER_SOURCES date-plugin.c date-parser.c date-parser.h date-parser-parser.c date-parser-parser.h strptime-tz.c strptime-tz.h ${CMAKE_CURRENT_BINARY_DIR}/date-grammar.c ${CMAKE_CURRENT_BINARY_DIR}/date-grammar.h ) generate_y_from_ym(modules/date/date-grammar) bison_target(DateParserGrammar ${CMAKE_CURRENT_BINARY_DIR}/date-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/date-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) include_directories (${CMAKE_CURRENT_BINARY_DIR}) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) add_library(date MODULE ${DATE_PARSER_SOURCES}) target_link_libraries(date PRIVATE syslog-ng) install(TARGETS date LIBRARY DESTINATION lib/syslog-ng/ COMPONENT date) syslog-ng-syslog-ng-3.13.2/modules/date/Makefile.am000066400000000000000000000017041321171025300220600ustar00rootroot00000000000000module_LTLIBRARIES += modules/date/libdate.la modules_date_libdate_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/date \ -I$(top_builddir)/modules/date modules_date_libdate_la_SOURCES = \ modules/date/date-grammar.y \ modules/date/date-plugin.c \ modules/date/date-parser.c \ modules/date/date-parser.h \ modules/date/date-parser-parser.c \ modules/date/date-parser-parser.h \ modules/date/strptime-tz.c \ modules/date/strptime-tz.h modules_date_libdate_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_date_libdate_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_date_libdate_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) BUILT_SOURCES += \ modules/date/date-grammar.y \ modules/date/date-grammar.c \ modules/date/date-grammar.h include modules/date/tests/Makefile.am modules/date mod-date: modules/date/libdate.la EXTRA_DIST += \ modules/date/date-grammar.ym .PHONY: modules/date mod-date syslog-ng-syslog-ng-3.13.2/modules/date/README.md000066400000000000000000000023041321171025300213000ustar00rootroot00000000000000date parser =========== The date parser can extract dates from non-syslog messages. It operates by default on `$MSG` but any template can be provided. The date will be stored as the sender date and the remaining of the message (if any) is discarded. Therefore, the result can be accessed using any of the `S_` macros (`${S_DATE}`, `${S_ISODATE}`, `${S_MONTH}`, …). Example config: ``` source s_apache { channel { source { file("/var/log/apache/access.log" flags(no-parse)); }; parser(p_apache_parser); }; }; }; parser p_apache_parser { csv-parser(columns("APACHE.CLIENT_IP", "APACHE.IDENT_NAME", "APACHE.USER_NAME", "APACHE.TIMESTAMP", "APACHE.REQUEST_URL", "APACHE.REQUEST_STATUS", "APACHE.CONTENT_LENGTH", "APACHE.REFERER", "APACHE.USER_AGENT", "APACHE.PROCESS_TIME", "APACHE.SERVER_NAME") flags(escape-double-char,strip-whitespace) delimiters(" ") quote-pairs('""[]')); date-parser( format("%d/%b/%Y:%H:%M:%S %Z") template("${APACHE.TIMESTAMP}")); }; destination d_file { file("/var/log/messages"); }; log { source(s_apache); destination(d_file); }; ``` syslog-ng-syslog-ng-3.13.2/modules/date/date-grammar.ym000066400000000000000000000044311321171025300227340ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Vincent Bernat * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code requires { #include "date-parser-parser.h" } %code { #include "cfg-grammar.h" #include "cfg-parser.h" #include "plugin.h" #include "parser/parser-expr.h" #include "date-parser.h" } %name-prefix "date_" %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogParser **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_DATE_PARSER %token KW_TIME_STAMP %type date_parser_stamp %% start : LL_CONTEXT_PARSER date_parser { YYACCEPT; } ; date_parser : KW_DATE_PARSER '(' { last_parser = *instance = date_parser_new (configuration); } date_parser_options ')' ; date_parser_options : date_parser_option date_parser_options | ; date_parser_option : KW_FORMAT '(' string ')' { date_parser_set_format(last_parser, $3); free($3); } | KW_TIME_ZONE '(' string ')' { date_parser_set_timezone(last_parser, $3); free($3); } | KW_TIME_STAMP '(' date_parser_stamp ')' { date_parser_set_time_stamp(last_parser, $3); } | parser_opt ; date_parser_stamp : string { $$ = log_msg_lookup_time_stamp_name($1); CHECK_ERROR($$ != -1, @1, "unknown time stamp name %s", $1); free($1); } /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/date/date-parser-parser.c000066400000000000000000000031171321171025300236710ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Vincent Bernat * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "date-parser.h" #include "cfg-parser.h" #include "date-grammar.h" #include "date-parser-parser.h" extern int date_debug; int date_parse(CfgLexer *lexer, LogParser **instance, gpointer arg); static CfgLexerKeyword date_keywords[] = { { "date_parser", KW_DATE_PARSER }, { "time_stamp", KW_TIME_STAMP }, { NULL } }; CfgParser date_parser = { #if ENABLE_DEBUG .debug_flag = &date_debug, #endif .name = "date-parser", .keywords = date_keywords, .parse = (int (*)(CfgLexer *, gpointer *, gpointer)) date_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(date_, LogParser **); syslog-ng-syslog-ng-3.13.2/modules/date/date-parser-parser.h000066400000000000000000000022501321171025300236730ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Vincent Bernat * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DATE_PARSER_PARSER_H_INCLUDED #define DATE_PARSER_PARSER_H_INCLUDED #include "date-parser.h" #include "cfg-parser.h" extern CfgParser date_parser; CFG_PARSER_DECLARE_LEXER_BINDING(date_, LogParser **) #endif syslog-ng-syslog-ng-3.13.2/modules/date/date-parser.c000066400000000000000000000155341321171025300224050ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Vincent Bernat * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "date-parser.h" #include "strptime-tz.h" #include "str-utils.h" typedef struct _DateParser { LogParser super; gchar *date_format; gchar *date_tz; LogMessageTimeStamp time_stamp; TimeZoneInfo *date_tz_info; } DateParser; void date_parser_set_format(LogParser *s, gchar *format) { DateParser *self = (DateParser *) s; g_free(self->date_format); self->date_format = g_strdup(format); } void date_parser_set_timezone(LogParser *s, gchar *tz) { DateParser *self = (DateParser *) s; g_free(self->date_tz); self->date_tz = g_strdup(tz); } void date_parser_set_time_stamp(LogParser *s, LogMessageTimeStamp time_stamp) { DateParser *self = (DateParser *) s; self->time_stamp = time_stamp; } static gboolean date_parser_init(LogPipe *s) { DateParser *self = (DateParser *) s; if (self->date_tz_info) time_zone_info_free(self->date_tz_info); self->date_tz_info = self->date_tz ? time_zone_info_new(self->date_tz) : NULL; return log_parser_init_method(s); } /* NOTE: tm is initialized with the current time and date */ static gboolean _parse_timestamp_and_deduce_missing_parts(DateParser *self, struct tm *tm, glong *tm_zone_offset, const gchar *input) { gint current_year; struct tm nowtm = *tm; long tm_gmtoff; const gchar *tm_zone = NULL; const gchar *remainder; current_year = tm->tm_year; tm->tm_year = 0; tm_gmtoff = -1; remainder = strptime_with_tz(input, self->date_format, tm, &tm_gmtoff, &tm_zone); if (!remainder || remainder[0]) return FALSE; /* hopefully _parse_timestamp will fill the year information, if * not, we are going to need the received year to find it out * heuristically */ if (tm->tm_year == 0) { /* no year information in the timestamp, deduce it from the current year */ tm->tm_year = current_year; tm->tm_year = determine_year_for_month(tm->tm_mon, &nowtm); } if (tm_gmtoff != -1) *tm_zone_offset = tm_gmtoff; else *tm_zone_offset = -1; return TRUE; } static void _adjust_tvsec_to_move_it_into_given_timezone(LogStamp *timestamp, gint normalized_hour, gint unnormalized_hour) { timestamp->tv_sec = timestamp->tv_sec + get_local_timezone_ofs(timestamp->tv_sec) - (normalized_hour - unnormalized_hour) * 3600 - timestamp->zone_offset; } static glong _get_target_zone_offset(DateParser *self, glong tm_zone_offset, time_t now) { if (tm_zone_offset != -1) return tm_zone_offset; else if (self->date_tz_info) return time_zone_info_get_offset(self->date_tz_info, now); else return get_local_timezone_ofs(now); } static gboolean _convert_struct_tm_to_logstamp(DateParser *self, time_t now, struct tm *tm, glong tm_zone_offset, LogStamp *target) { gint unnormalized_hour; target->zone_offset = _get_target_zone_offset(self, tm_zone_offset, now); /* NOTE: mktime changes struct tm in the call below! For instance it * changes the hour value. (in daylight saving changes, and when it * is out of range). * * We save the hour prior to this conversion, as it is needed when * converting the timestamp from our local timezone to the specified * one. */ /* FIRST: We convert the timestamp as it was in our local time zone. */ unnormalized_hour = tm->tm_hour; target->tv_sec = cached_mktime(tm); /* we can't parse USEC value, as strptime() does not support that */ target->tv_usec = 0; /* SECOND: adjust tv_sec as if we converted it according to our timezone. */ _adjust_tvsec_to_move_it_into_given_timezone(target, tm->tm_hour, unnormalized_hour); return TRUE; } static gboolean _convert_timestamp_to_logstamp(DateParser *self, time_t now, LogStamp *target, const gchar *input) { struct tm tm; glong tm_zone_offset; /* initialize tm with current date, this fills in dst and other * fields (even non-standard ones) */ cached_localtime(&now, &tm); if (!_parse_timestamp_and_deduce_missing_parts(self, &tm, &tm_zone_offset, input)) return FALSE; if (!_convert_struct_tm_to_logstamp(self, now, &tm, tm_zone_offset, target)) return FALSE; return TRUE; } static gboolean date_parser_process(LogParser *s, LogMessage **pmsg, const LogPathOptions *path_options, const gchar *input, gsize input_len) { DateParser *self = (DateParser *) s; LogMessage *msg = log_msg_make_writable(pmsg, path_options); /* this macro ensures zero termination by copying input to a * g_alloca()-d buffer if necessary. In most cases it's not though. */ APPEND_ZERO(input, input, input_len); return _convert_timestamp_to_logstamp(self, msg->timestamps[LM_TS_RECVD].tv_sec, &msg->timestamps[self->time_stamp], input); } static LogPipe * date_parser_clone(LogPipe *s) { DateParser *self = (DateParser *) s; LogParser *cloned; cloned = date_parser_new(log_pipe_get_config(&self->super.super)); date_parser_set_format(cloned, self->date_format); date_parser_set_timezone(cloned, self->date_tz); date_parser_set_time_stamp(cloned, self->time_stamp); log_parser_set_template(cloned, log_template_ref(self->super.template)); return &cloned->super; } static void date_parser_free(LogPipe *s) { DateParser *self = (DateParser *)s; g_free(self->date_format); g_free(self->date_tz); if (self->date_tz_info) time_zone_info_free(self->date_tz_info); log_parser_free_method(s); } LogParser * date_parser_new(GlobalConfig *cfg) { DateParser *self = g_new0(DateParser, 1); log_parser_init_instance(&self->super, cfg); self->super.super.init = date_parser_init; self->super.process = date_parser_process; self->super.super.clone = date_parser_clone; self->super.super.free_fn = date_parser_free; self->time_stamp = LM_TS_STAMP; date_parser_set_format(&self->super, "%FT%T%z"); return &self->super; } syslog-ng-syslog-ng-3.13.2/modules/date/date-parser.h000066400000000000000000000025371321171025300224110ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Vincent Bernat * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DATE_PARSER_H_INCLUDED #define DATE_PARSER_H_INCLUDED #include "parser/parser-expr.h" LogParser *date_parser_new(GlobalConfig *cfg); void date_parser_set_offset(LogParser *s, goffset offset); void date_parser_set_format(LogParser *s, gchar *format); void date_parser_set_timezone(LogParser *s, gchar *tz); void date_parser_set_time_stamp(LogParser *s, LogMessageTimeStamp timestamp); #endif syslog-ng-syslog-ng-3.13.2/modules/date/date-plugin.c000066400000000000000000000031471321171025300224040ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Vincent Bernat * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "date-parser.h" #include "date-parser-parser.h" #include "plugin.h" #include "plugin-types.h" extern CfgParser date_parser; static Plugin date_plugin = { .type = LL_CONTEXT_PARSER, .name = "date-parser", .parser = &date_parser, }; gboolean date_module_init(PluginContext *context, CfgArgs *args G_GNUC_UNUSED) { plugin_register(context, &date_plugin, 1); return TRUE; } const ModuleInfo module_info = { .canonical_name = "date", .version = SYSLOG_NG_VERSION, .description = "The date module provides parsing support for dates in syslog-ng.", .core_revision = VERSION_CURRENT_VER_ONLY, .plugins = &date_plugin, .plugins_len = 1, }; syslog-ng-syslog-ng-3.13.2/modules/date/strptime-tz.c000066400000000000000000000541551321171025300225020ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balazs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ /* $NetBSD: strptime.c,v 1.49 2015/10/09 17:21:45 christos Exp $ */ /*- * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc. * All rights reserved. * * This code was contributed to The NetBSD Foundation by Klaus Klein. * Heavily optimised by David Laight * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (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 "strptime-tz.h" #include "timeutils.h" #include #include #include #include typedef unsigned char _u_char; typedef unsigned int _uint; #define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) #define TM_YEAR_BASE 1900 #define TM_SUNDAY 0 #define TM_MONDAY 1 #define TM_TUESDAY 2 #define TM_WEDNESDAY 3 #define TM_THURSDAY 4 #define TM_FRIDAY 5 #define TM_SATURDAY 6 #define TM_JANUARY 0 #define TM_FEBRUARY 1 #define TM_MARCH 2 #define TM_APRIL 3 #define TM_MAY 4 #define TM_JUNE 5 #define TM_JULY 6 #define TM_AUGUST 7 #define TM_SEPTEMBER 8 #define TM_OCTOBER 9 #define TM_NOVEMBER 10 #define TM_DECEMBER 11 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) #define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) typedef struct { const char *abday[7]; const char *day[7]; const char *abmon[12]; const char *mon[12]; const char *am_pm[2]; const char *d_t_fmt; const char *d_fmt; const char *t_fmt; const char *t_fmt_ampm; } _TimeLocale; static const _TimeLocale _DefaultTimeLocale = { /* abbreviated day */ { "Sun","Mon","Tue","Wed","Thu","Fri","Sat", }, /* days */ { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }, /* abbreviated month */ { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }, /* month */ { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }, /* ampm */ { "AM", "PM" }, "%a %b %e %H:%M:%S %Y", "%m/%d/%y", "%H:%M:%S", "%I:%M:%S %p" }; #define _TIME_LOCALE(loc) \ (&_DefaultTimeLocale) static const _u_char *conv_num(const unsigned char *, int *, _uint, _uint); static const _u_char *find_string(const _u_char *, int *, const char *const *, const char *const *, int); /* * We do not implement alternate representations. However, we always * check whether a given modifier is allowed for a certain conversion. */ #define ALT_E 0x01 #define ALT_O 0x02 #define LEGAL_ALT(x) { if (alt_format & ~(x)) return NULL; } #define S_YEAR (1 << 0) #define S_MON (1 << 1) #define S_YDAY (1 << 2) #define S_MDAY (1 << 3) #define S_WDAY (1 << 4) #define S_HOUR (1 << 5) #define HAVE_MDAY(s) (s & S_MDAY) #define HAVE_MON(s) (s & S_MON) #define HAVE_WDAY(s) (s & S_WDAY) #define HAVE_YDAY(s) (s & S_YDAY) #define HAVE_YEAR(s) (s & S_YEAR) #define HAVE_HOUR(s) (s & S_HOUR) static char gmt[] = { "GMT" }; static char utc[] = { "UTC" }; /* RFC-822/RFC-2822 */ static const char *const nast[5] = { "EST", "CST", "MST", "PST", "\0\0\0" }; static const char *const nadt[5] = { "EDT", "CDT", "MDT", "PDT", "\0\0\0" }; /* * Table to determine the ordinal date for the start of a month. * Ref: http://en.wikipedia.org/wiki/ISO_week_date */ static const int start_of_month[2][13] = { /* non-leap year */ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, /* leap year */ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } }; /* * Calculate the week day of the first day of a year. Valid for * the Gregorian calendar, which began Sept 14, 1752 in the UK * and its colonies. Ref: * http://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week */ static int first_wday_of(int yr) { return ((2 * (3 - (yr / 100) % 4)) + (yr % 100) + ((yr % 100) / 4) + (isleap(yr) ? 6 : 0) + 1) % 7; } /* standard strptime() doesn't support %z / %Z properly on all * platforms, especially those that don't have tm_gmtoff/tm_zone in * their struct tm. This is a slightly modified NetBSD strptime() with * some modifications and explicit zone related parameters. */ char * strptime_with_tz(const char *buf, const char *fmt, struct tm *tm, long *tm_gmtoff, const char **tm_zone) { unsigned char c; const unsigned char *bp, *ep; int alt_format, i, split_year = 0, neg = 0, state = 0, day_offset = -1, week_offset = 0, offs; const char *new_fmt; bp = (const _u_char *)buf; while (bp != NULL && (c = *fmt++) != '\0') { /* Clear `alternate' modifier prior to new conversion. */ alt_format = 0; i = 0; /* Eat up white-space. */ if (isspace(c)) { while (isspace(*bp)) bp++; continue; } if (c != '%') goto literal; again: switch (c = *fmt++) { case '%': /* "%%" is converted to "%". */ literal: if (c != *bp++) return NULL; LEGAL_ALT(0); continue; /* * "Alternative" modifiers. Just set the appropriate flag * and start over again. */ case 'E': /* "%E?" alternative conversion modifier. */ LEGAL_ALT(0); alt_format |= ALT_E; goto again; case 'O': /* "%O?" alternative conversion modifier. */ LEGAL_ALT(0); alt_format |= ALT_O; goto again; /* * "Complex" conversion rules, implemented through recursion. */ case 'c': /* Date and time, using the locale's format. */ new_fmt = _TIME_LOCALE(loc)->d_t_fmt; state |= S_WDAY | S_MON | S_MDAY | S_YEAR; goto recurse; case 'D': /* The date as "%m/%d/%y". */ new_fmt = "%m/%d/%y"; LEGAL_ALT(0); state |= S_MON | S_MDAY | S_YEAR; goto recurse; case 'F': /* The date as "%Y-%m-%d". */ new_fmt = "%Y-%m-%d"; LEGAL_ALT(0); state |= S_MON | S_MDAY | S_YEAR; goto recurse; case 'R': /* The time as "%H:%M". */ new_fmt = "%H:%M"; LEGAL_ALT(0); goto recurse; case 'r': /* The time in 12-hour clock representation. */ new_fmt = _TIME_LOCALE(loc)->t_fmt_ampm; LEGAL_ALT(0); goto recurse; case 'T': /* The time as "%H:%M:%S". */ new_fmt = "%H:%M:%S"; LEGAL_ALT(0); goto recurse; case 'X': /* The time, using the locale's format. */ new_fmt = _TIME_LOCALE(loc)->t_fmt; goto recurse; case 'x': /* The date, using the locale's format. */ new_fmt = _TIME_LOCALE(loc)->d_fmt; state |= S_MON | S_MDAY | S_YEAR; recurse: bp = (const _u_char *)strptime_with_tz((const char *)bp, new_fmt, tm, tm_gmtoff, tm_zone); LEGAL_ALT(ALT_E); continue; /* * "Elementary" conversion rules. */ case 'A': /* The day of week, using the locale's form. */ case 'a': bp = find_string(bp, &tm->tm_wday, _TIME_LOCALE(loc)->day, _TIME_LOCALE(loc)->abday, 7); LEGAL_ALT(0); state |= S_WDAY; continue; case 'B': /* The month, using the locale's form. */ case 'b': case 'h': bp = find_string(bp, &tm->tm_mon, _TIME_LOCALE(loc)->mon, _TIME_LOCALE(loc)->abmon, 12); LEGAL_ALT(0); state |= S_MON; continue; case 'C': /* The century number. */ i = 20; bp = conv_num(bp, &i, 0, 99); i = i * 100 - TM_YEAR_BASE; if (split_year) i += tm->tm_year % 100; split_year = 1; tm->tm_year = i; LEGAL_ALT(ALT_E); state |= S_YEAR; continue; case 'd': /* The day of month. */ case 'e': bp = conv_num(bp, &tm->tm_mday, 1, 31); LEGAL_ALT(ALT_O); state |= S_MDAY; continue; case 'k': /* The hour (24-hour clock representation). */ LEGAL_ALT(0); /* FALLTHROUGH */ case 'H': bp = conv_num(bp, &tm->tm_hour, 0, 23); LEGAL_ALT(ALT_O); state |= S_HOUR; continue; case 'l': /* The hour (12-hour clock representation). */ LEGAL_ALT(0); /* FALLTHROUGH */ case 'I': bp = conv_num(bp, &tm->tm_hour, 1, 12); if (tm->tm_hour == 12) tm->tm_hour = 0; LEGAL_ALT(ALT_O); state |= S_HOUR; continue; case 'j': /* The day of year. */ i = 1; bp = conv_num(bp, &i, 1, 366); tm->tm_yday = i - 1; LEGAL_ALT(0); state |= S_YDAY; continue; case 'M': /* The minute. */ bp = conv_num(bp, &tm->tm_min, 0, 59); LEGAL_ALT(ALT_O); continue; case 'm': /* The month. */ i = 1; bp = conv_num(bp, &i, 1, 12); tm->tm_mon = i - 1; LEGAL_ALT(ALT_O); state |= S_MON; continue; case 'p': /* The locale's equivalent of AM/PM. */ bp = find_string(bp, &i, _TIME_LOCALE(loc)->am_pm, NULL, 2); if (HAVE_HOUR(state) && tm->tm_hour > 11) return NULL; tm->tm_hour += i * 12; LEGAL_ALT(0); continue; case 'S': /* The seconds. */ bp = conv_num(bp, &tm->tm_sec, 0, 61); LEGAL_ALT(ALT_O); continue; #ifndef TIME_MAX #define TIME_MAX INT64_MAX #endif case 's': /* seconds since the epoch */ { time_t sse = 0; uint64_t rulim = TIME_MAX; if (*bp < '0' || *bp > '9') { bp = NULL; continue; } do { sse *= 10; sse += *bp++ - '0'; rulim /= 10; } while ((sse * 10 <= TIME_MAX) && rulim && *bp >= '0' && *bp <= '9'); if (sse < 0 || (uint64_t)sse > TIME_MAX) { bp = NULL; continue; } cached_localtime(&sse, tm); state |= S_YDAY | S_WDAY | S_MON | S_MDAY | S_YEAR; } continue; case 'U': /* The week of year, beginning on sunday. */ case 'W': /* The week of year, beginning on monday. */ /* * XXX This is bogus, as we can not assume any valid * information present in the tm structure at this * point to calculate a real value, so just check the * range for now. */ bp = conv_num(bp, &i, 0, 53); LEGAL_ALT(ALT_O); if (c == 'U') day_offset = TM_SUNDAY; else day_offset = TM_MONDAY; week_offset = i; continue; case 'w': /* The day of week, beginning on sunday. */ bp = conv_num(bp, &tm->tm_wday, 0, 6); LEGAL_ALT(ALT_O); state |= S_WDAY; continue; case 'u': /* The day of week, monday = 1. */ bp = conv_num(bp, &i, 1, 7); tm->tm_wday = i % 7; LEGAL_ALT(ALT_O); state |= S_WDAY; continue; case 'g': /* The year corresponding to the ISO week * number but without the century. */ bp = conv_num(bp, &i, 0, 99); continue; case 'G': /* The year corresponding to the ISO week * number with century. */ do bp++; while (isdigit(*bp)); continue; case 'V': /* The ISO 8601:1988 week number as decimal */ bp = conv_num(bp, &i, 0, 53); continue; case 'Y': /* The year. */ i = TM_YEAR_BASE; /* just for data sanity... */ bp = conv_num(bp, &i, 0, 9999); tm->tm_year = i - TM_YEAR_BASE; LEGAL_ALT(ALT_E); state |= S_YEAR; continue; case 'y': /* The year within 100 years of the epoch. */ /* LEGAL_ALT(ALT_E | ALT_O); */ bp = conv_num(bp, &i, 0, 99); if (split_year) /* preserve century */ i += (tm->tm_year / 100) * 100; else { split_year = 1; if (i <= 68) i = i + 2000 - TM_YEAR_BASE; else i = i + 1900 - TM_YEAR_BASE; } tm->tm_year = i; state |= S_YEAR; continue; case 'Z': tzset(); if (strncmp((const char *)bp, gmt, 3) == 0 || strncmp((const char *)bp, utc, 3) == 0) { tm->tm_isdst = 0; *tm_gmtoff = 0; *tm_zone = gmt; bp += 3; } else { ep = find_string(bp, &i, (const char *const *)tzname, NULL, 2); if (ep != NULL) { tm->tm_isdst = i; #ifdef SYSLOG_NG_HAVE_TIMEZONE *tm_gmtoff = -(timezone); #endif *tm_zone = tzname[i]; } bp = ep; } continue; case 'z': /* * We recognize all ISO 8601 formats: * Z = Zulu time/UTC * [+-]hhmm * [+-]hh:mm * [+-]hh * We recognize all RFC-822/RFC-2822 formats: * UT|GMT * North American : UTC offsets * E[DS]T = Eastern : -4 | -5 * C[DS]T = Central : -5 | -6 * M[DS]T = Mountain: -6 | -7 * P[DS]T = Pacific : -7 | -8 * Military * [A-IL-M] = -1 ... -9 (J not used) * [N-Y] = +1 ... +12 */ while (isspace(*bp)) bp++; switch (*bp++) { case 'G': if (*bp++ != 'M') return NULL; /*FALLTHROUGH*/ case 'U': if (*bp++ != 'T') return NULL; /*FALLTHROUGH*/ case 'Z': tm->tm_isdst = 0; *tm_gmtoff = 0; *tm_zone = utc; continue; case '+': neg = 0; break; case '-': neg = 1; break; default: --bp; ep = find_string(bp, &i, nast, NULL, 4); if (ep != NULL) { *tm_gmtoff = (-5 - i) * 3600; *tm_zone = __UNCONST(nast[i]); bp = ep; continue; } ep = find_string(bp, &i, nadt, NULL, 4); if (ep != NULL) { tm->tm_isdst = 1; *tm_gmtoff = (-4 - i) * 3600; *tm_zone = __UNCONST(nadt[i]); bp = ep; continue; } if ((*bp >= 'A' && *bp <= 'I') || (*bp >= 'L' && *bp <= 'Y')) { /* Argh! No 'J'! */ if (*bp >= 'A' && *bp <= 'I') *tm_gmtoff = (('A' - 1) - (int)*bp) * 3600; else if (*bp >= 'L' && *bp <= 'M') *tm_gmtoff = ('A' - (int)*bp) * 3600; else if (*bp >= 'N' && *bp <= 'Y') *tm_gmtoff = ((int)*bp - 'M') * 3600; *tm_zone = utc; /* XXX */ bp++; continue; } return NULL; } offs = 0; for (i = 0; i < 4; ) { if (isdigit(*bp)) { offs = offs * 10 + (*bp++ - '0'); i++; continue; } if (i == 2 && *bp == ':') { bp++; continue; } break; } switch (i) { case 2: offs *= 100; break; case 4: i = offs % 100; if (i >= 60) return NULL; /* Convert minutes into decimal */ offs = (offs / 100) * 100 + (i * 50) / 30; break; default: return NULL; } if (neg) offs = -offs; tm->tm_isdst = 0; /* XXX */ *tm_gmtoff = (offs * 3600) / 100; *tm_zone = utc; /* XXX */ continue; /* * Miscellaneous conversions. */ case 'n': /* Any kind of white-space. */ case 't': while (isspace(*bp)) bp++; LEGAL_ALT(0); continue; default: /* Unknown/unsupported conversion. */ return NULL; } } if (!HAVE_YDAY(state) && HAVE_YEAR(state)) { if (HAVE_MON(state) && HAVE_MDAY(state)) { /* calculate day of year (ordinal date) */ tm->tm_yday = start_of_month[isleap_sum(tm->tm_year, TM_YEAR_BASE)][tm->tm_mon] + (tm->tm_mday - 1); state |= S_YDAY; } else if (day_offset != -1) { /* * Set the date to the first Sunday (or Monday) * of the specified week of the year. */ if (!HAVE_WDAY(state)) { tm->tm_wday = day_offset; state |= S_WDAY; } tm->tm_yday = (7 - first_wday_of(tm->tm_year + TM_YEAR_BASE) + day_offset) % 7 + (week_offset - 1) * 7 + tm->tm_wday - day_offset; state |= S_YDAY; } } if (HAVE_YDAY(state) && HAVE_YEAR(state)) { int isleap; if (!HAVE_MON(state)) { /* calculate month of day of year */ i = 0; isleap = isleap_sum(tm->tm_year, TM_YEAR_BASE); while (tm->tm_yday >= start_of_month[isleap][i]) i++; if (i > 12) { i = 1; tm->tm_yday -= start_of_month[isleap][12]; tm->tm_year++; } tm->tm_mon = i - 1; state |= S_MON; } if (!HAVE_MDAY(state)) { /* calculate day of month */ isleap = isleap_sum(tm->tm_year, TM_YEAR_BASE); tm->tm_mday = tm->tm_yday - start_of_month[isleap][tm->tm_mon] + 1; state |= S_MDAY; } if (!HAVE_WDAY(state)) { /* calculate day of week */ i = 0; week_offset = first_wday_of(tm->tm_year); while (i++ <= tm->tm_yday) { if (week_offset++ >= 6) week_offset = 0; } tm->tm_wday = week_offset; state |= S_WDAY; } } return __UNCONST(bp); } static const _u_char * conv_num(const unsigned char *buf, int *dest, _uint llim, _uint ulim) { _uint result = 0; unsigned char ch; /* The limit also determines the number of valid digits. */ _uint rulim = ulim; ch = *buf; if (ch < '0' || ch > '9') return NULL; do { result *= 10; result += ch - '0'; rulim /= 10; ch = *++buf; } while ((result * 10 <= ulim) && rulim && ch >= '0' && ch <= '9'); if (result < llim || result > ulim) return NULL; *dest = result; return buf; } static const _u_char * find_string(const _u_char *bp, int *tgt, const char *const *n1, const char *const *n2, int c) { int i; size_t len; /* check full name - then abbreviated ones */ for (; n1 != NULL; n1 = n2, n2 = NULL) { for (i = 0; i < c; i++, n1++) { len = strlen(*n1); if (strncasecmp(*n1, (const char *)bp, len) == 0) { *tgt = i; return bp + len; } } } /* Nothing matched */ return NULL; } syslog-ng-syslog-ng-3.13.2/modules/date/strptime-tz.h000066400000000000000000000022451321171025300225000ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Balazs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DATE_STRPTIME_TZ_H_INCLUDED #define DATE_STRPTIME_TZ_H_INCLUDED 1 #include char *strptime_with_tz(const char *buf, const char *fmt, struct tm *tm, long *tm_gmtoff, const char **tm_zone); #endif syslog-ng-syslog-ng-3.13.2/modules/date/tests/000077500000000000000000000000001321171025300211645ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/date/tests/Makefile.am000066400000000000000000000007001321171025300232150ustar00rootroot00000000000000if ENABLE_CRITERION modules_date_tests_TESTS = \ modules/date/tests/test_date check_PROGRAMS += \ ${modules_date_tests_TESTS} modules_date_tests_test_date_CFLAGS = $(TEST_CFLAGS) -I$(top_srcdir)/modules/date modules_date_tests_test_date_LDADD = $(TEST_LDADD) modules_date_tests_test_date_LDFLAGS = \ -dlpreopen $(top_builddir)/modules/date/libdate.la modules_date_tests_test_date_DEPENDENCIES = $(top_builddir)/modules/date/libdate.la endif syslog-ng-syslog-ng-3.13.2/modules/date/tests/test_date.c000066400000000000000000000142711321171025300233110ustar00rootroot00000000000000/* * Copyright (c) 2015 Balabit * Copyright (c) 2015 Vincent Bernat * Copyright (c) 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include #include #include "date-parser.h" #include "apphook.h" #include #include struct date_params { gchar *msg; gchar *timezone_; gchar *format; gint time_stamp; gchar *expected; }; static LogParser * _construct_parser(gchar *timezone_, gchar *format, gint time_stamp) { LogParser *parser; parser = date_parser_new (configuration); if (format != NULL) date_parser_set_format(parser, format); if (timezone_ != NULL) date_parser_set_timezone(parser, timezone_); date_parser_set_time_stamp(parser, time_stamp); log_pipe_init(&parser->super); return parser; } static LogMessage * _construct_logmsg(const gchar *msg) { LogMessage *logmsg; logmsg = log_msg_new_empty(); logmsg->timestamps[LM_TS_RECVD].tv_sec = 1451473200; /* Dec 30 2015 */ log_msg_set_value(logmsg, LM_V_MESSAGE, msg, -1); return logmsg; } void setup(void) { app_startup(); setlocale (LC_ALL, "C"); putenv("TZ=CET-1"); tzset(); configuration = cfg_new_snippet(); } void teardown(void) { app_shutdown(); } TestSuite(date, .init = setup, .fini = teardown); ParameterizedTestParameters(date, test_date_parser) { static struct date_params params[] = { { "2015-01-26T16:14:49+03:00", NULL, NULL, LM_TS_RECVD, "2015-01-26T16:14:49+03:00" }, /* Various ISO8601 formats */ { "2015-01-26T16:14:49+0300", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49+03:00" }, { "2015-01-26T16:14:49+0330", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49+03:30" }, { "2015-01-26T16:14:49+0200", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49+02:00" }, { "2015-01-26T16:14:49+03:00", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49+03:00" }, { "2015-01-26T16:14:49+03:30", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49+03:30" }, { "2015-01-26T16:14:49+02:00", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49+02:00" }, { "2015-01-26T16:14:49Z", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49+00:00" }, { "2015-01-26T16:14:49A", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49-01:00" }, { "2015-01-26T16:14:49B", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49-02:00" }, { "2015-01-26T16:14:49N", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49+01:00" }, { "2015-01-26T16:14:49O", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49+02:00" }, { "2015-01-26T16:14:49GMT", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49+00:00" }, { "2015-01-26T16:14:49PDT", NULL, NULL, LM_TS_STAMP, "2015-01-26T16:14:49-07:00" }, /* RFC 2822 */ { "Tue, 27 Jan 2015 11:48:46 +0200", NULL, "%a, %d %b %Y %T %z", LM_TS_STAMP, "2015-01-27T11:48:46+02:00" }, /* Apache-like */ { "21/Jan/2015:14:40:07 +0500", NULL, "%d/%b/%Y:%T %z", LM_TS_STAMP, "2015-01-21T14:40:07+05:00" }, /* Dates without timezones. America/Phoenix has no DST */ { "Tue, 27 Jan 2015 11:48:46", NULL, "%a, %d %b %Y %T", LM_TS_STAMP, "2015-01-27T11:48:46+01:00" }, { "Tue, 27 Jan 2015 11:48:46", "America/Phoenix", "%a, %d %b %Y %T", LM_TS_STAMP, "2015-01-27T11:48:46-07:00" }, { "Tue, 27 Jan 2015 11:48:46", "+05:00", "%a, %d %b %Y %T", LM_TS_STAMP, "2015-01-27T11:48:46+05:00" }, /* Try without the year. */ { "01/Jan:00:40:07 +0500", NULL, "%d/%b:%T %z", LM_TS_STAMP, "2016-01-01T00:40:07+05:00" }, { "01/Aug:00:40:07 +0500", NULL, "%d/%b:%T %z", LM_TS_STAMP, "2015-08-01T00:40:07+05:00" }, { "01/Sep:00:40:07 +0500", NULL, "%d/%b:%T %z", LM_TS_STAMP, "2015-09-01T00:40:07+05:00" }, { "01/Oct:00:40:07 +0500", NULL, "%d/%b:%T %z", LM_TS_STAMP, "2015-10-01T00:40:07+05:00" }, { "01/Nov:00:40:07 +0500", NULL, "%d/%b:%T %z", LM_TS_STAMP, "2015-11-01T00:40:07+05:00" }, { "1446128356 +01:00", NULL, "%s %z", LM_TS_STAMP, "2015-10-29T15:19:16+01:00" }, { "1446128356", "Europe/Budapest", "%s", LM_TS_STAMP, "2015-10-29T15:19:16+01:00" }, }; return cr_make_param_array(struct date_params, params, sizeof(params) / sizeof(struct date_params)); } ParameterizedTest(struct date_params *params, date, test_date_parser) { LogMessage *logmsg; LogParser *parser = _construct_parser(params->timezone_, params->format, params->time_stamp); gboolean success; GString *res = g_string_sized_new(128); logmsg = _construct_logmsg(params->msg); success = log_parser_process(parser, &logmsg, NULL, log_msg_get_value(logmsg, LM_V_MESSAGE, NULL), -1); cr_assert(success, "unable to parse format=%s msg=%s", params->format, params->msg); log_stamp_append_format(&logmsg->timestamps[params->time_stamp], res, TS_FMT_ISO, -1, 0); cr_assert_str_eq(res->str, params->expected, "incorrect date parsed msg=%s format=%s", params->msg, params->format); g_string_free(res, TRUE); log_pipe_unref(&parser->super); log_msg_unref(logmsg); } Test(date, test_date_with_additional_text_at_the_end) { const gchar *msg = "2015-01-26T16:14:49+0300 Disappointing log file"; LogParser *parser = _construct_parser(NULL, NULL, LM_TS_STAMP); LogMessage *logmsg = _construct_logmsg(msg); gboolean success = log_parser_process(parser, &logmsg, NULL, log_msg_get_value(logmsg, LM_V_MESSAGE, NULL), -1); cr_assert_not(success, "successfully parsed but expected failure, msg=%s", msg); log_pipe_unref(&parser->super); log_msg_unref(logmsg); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/000077500000000000000000000000001321171025300207075ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/dbparser/CMakeLists.txt000066400000000000000000000041251321171025300234510ustar00rootroot00000000000000set(PATTERNDB_SOURCES radix.c radix.h patterndb.c patterndb.h pdb-load.c pdb-load.h pdb-rule.c pdb-rule.h pdb-file.c pdb-file.h pdb-error.c pdb-error.h pdb-action.c pdb-action.h pdb-program.c pdb-program.h pdb-example.c pdb-example.h pdb-ruleset.c pdb-ruleset.h pdb-context.c pdb-context.h pdb-ratelimit.c pdb-ratelimit.h pdb-lookup-params.h correllation.c correllation.h correllation-key.c correllation-key.h correllation-context.c correllation-context.h synthetic-message.c synthetic-message.h synthetic-context.c synthetic-context.h timerwheel.c timerwheel.h patternize.c patternize.h ) add_library(patterndb ${PATTERNDB_SOURCES}) # The radix tree uses unsigned char internally but passes these values to # string.h functions, which trigger a lot of harmless warnings. Of course # these could be fixed by adding a lot of casts to the code, but I # considered these to be less readable, than simply adding -Wno-pointer-sign # warning option. # set_target_properties(patterndb PROPERTIES COMPILE_FLAGS "-fPIC -Wno-pointer-sign") target_link_libraries(patterndb PUBLIC syslog-ng) set(DBPARSER_SOURCES stateful-parser.c stateful-parser.h dbparser.c dbparser.h dbparser-parser.c dbparser-parser.h dbparser-plugin.c groupingby.c groupingby.h ${CMAKE_CURRENT_BINARY_DIR}/dbparser-grammar.c ${CMAKE_CURRENT_BINARY_DIR}/dbparser-grammar.h ) generate_y_from_ym(modules/dbparser/dbparser-grammar) bison_target(DBParserGrammar ${CMAKE_CURRENT_BINARY_DIR}/dbparser-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/dbparser-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) add_library(dbparser MODULE ${DBPARSER_SOURCES}) target_link_libraries(dbparser PRIVATE patterndb) target_include_directories(dbparser PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(dbparser PRIVATE syslog-ng) install(TARGETS dbparser LIBRARY DESTINATION lib/syslog-ng/ COMPONENT dbparser) add_subdirectory(pdbtool) syslog-ng-syslog-ng-3.13.2/modules/dbparser/Makefile.am000066400000000000000000000067001321171025300227460ustar00rootroot00000000000000noinst_LTLIBRARIES += modules/dbparser/libsyslog-ng-patterndb.la modules_dbparser_libsyslog_ng_patterndb_la_SOURCES = \ modules/dbparser/radix.c \ modules/dbparser/radix.h \ modules/dbparser/patterndb.c \ modules/dbparser/patterndb.h \ modules/dbparser/pdb-error.c \ modules/dbparser/pdb-error.h \ modules/dbparser/pdb-file.c \ modules/dbparser/pdb-file.h \ modules/dbparser/pdb-load.c \ modules/dbparser/pdb-load.h \ modules/dbparser/pdb-rule.c \ modules/dbparser/pdb-rule.h \ modules/dbparser/pdb-action.c \ modules/dbparser/pdb-action.h \ modules/dbparser/pdb-program.c \ modules/dbparser/pdb-program.h \ modules/dbparser/pdb-example.c \ modules/dbparser/pdb-example.h \ modules/dbparser/pdb-ruleset.c \ modules/dbparser/pdb-ruleset.h \ modules/dbparser/pdb-context.c \ modules/dbparser/pdb-context.h \ modules/dbparser/pdb-ratelimit.c \ modules/dbparser/pdb-ratelimit.h \ modules/dbparser/pdb-lookup-params.h \ modules/dbparser/correllation.c \ modules/dbparser/correllation.h \ modules/dbparser/correllation-key.c \ modules/dbparser/correllation-key.h \ modules/dbparser/correllation-context.c \ modules/dbparser/correllation-context.h \ modules/dbparser/synthetic-message.c \ modules/dbparser/synthetic-message.h \ modules/dbparser/synthetic-context.c \ modules/dbparser/synthetic-context.h \ modules/dbparser/timerwheel.c \ modules/dbparser/timerwheel.h \ modules/dbparser/patternize.c \ modules/dbparser/patternize.h # The radix tree uses unsigned char internally but passes these values to # string.h functions, which trigger a lot of harmless warnings. Of course # these could be fixed by adding a lot of casts to the code, but I # considered these to be less readable, than simply adding -Wno-pointer-sign # warning option. # modules_dbparser_libsyslog_ng_patterndb_la_CFLAGS = \ $(AM_CFLAGS) -fPIC @CFLAGS_NOWARN_POINTER_SIGN@ modules_dbparser_libsyslog_ng_patterndb_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_dbparser_libsyslog_ng_patterndb_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) module_LTLIBRARIES += modules/dbparser/libdbparser.la modules_dbparser_libdbparser_la_SOURCES = \ modules/dbparser/stateful-parser.c \ modules/dbparser/stateful-parser.h \ modules/dbparser/dbparser.c \ modules/dbparser/dbparser.h \ modules/dbparser/dbparser-grammar.y \ modules/dbparser/dbparser-parser.c \ modules/dbparser/dbparser-parser.h \ modules/dbparser/dbparser-plugin.c \ modules/dbparser/groupingby.c \ modules/dbparser/groupingby.h \ $(modules_dbparser_libsyslog_ng_patterndb_la_SOURCES) modules_dbparser_libdbparser_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/dbparser \ -I$(top_builddir)/modules/dbparser \ @CFLAGS_NOWARN_POINTER_SIGN@ modules_dbparser_libdbparser_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_dbparser_libdbparser_la_LDFLAGS = \ $(MODULE_LDFLAGS) modules_dbparser_libdbparser_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) BUILT_SOURCES += \ modules/dbparser/dbparser-grammar.y \ modules/dbparser/dbparser-grammar.c \ modules/dbparser/dbparser-grammar.h EXTRA_DIST += \ modules/dbparser/dbparser-grammar.ym modules/dbparser modules/dbparser/ mod-dbparser: modules/dbparser/libdbparser.la \ modules/dbparser/pdbtool/pdbtool .PHONY: modules/dbparser/ mod-dbparser include modules/dbparser/pdbtool/Makefile.am include modules/dbparser/tests/Makefile.am syslog-ng-syslog-ng-3.13.2/modules/dbparser/correllation-context.c000066400000000000000000000046401321171025300252360ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "correllation-context.h" #include "logmsg/logmsg.h" #include void correllation_context_init(CorrellationContext *self, const CorrellationKey *key) { self->messages = g_ptr_array_new(); memcpy(&self->key, key, sizeof(self->key)); if (self->key.pid) self->key.pid = g_strdup(self->key.pid); if (self->key.program) self->key.program = g_strdup(self->key.program); if (self->key.host) self->key.host = g_strdup(self->key.host); self->ref_cnt = 1; self->free_fn = correllation_context_free_method; } void correllation_context_free_method(CorrellationContext *self) { gint i; for (i = 0; i < self->messages->len; i++) { log_msg_unref((LogMessage *) g_ptr_array_index(self->messages, i)); } g_ptr_array_free(self->messages, TRUE); if (self->key.host) g_free((gchar *) self->key.host); if (self->key.program) g_free((gchar *) self->key.program); if (self->key.pid) g_free((gchar *) self->key.pid); g_free(self->key.session_id); } CorrellationContext * correllation_context_new(CorrellationKey *key) { CorrellationContext *self = g_new0(CorrellationContext, 1); correllation_context_init(self, key); return self; } CorrellationContext * correllation_context_ref(CorrellationContext *self) { self->ref_cnt++; return self; } void correllation_context_unref(CorrellationContext *self) { if (--self->ref_cnt == 0) { if (self->free_fn) self->free_fn(self); g_free(self); } } syslog-ng-syslog-ng-3.13.2/modules/dbparser/correllation-context.h000066400000000000000000000040631321171025300252420ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_CORRELLATION_CONTEXT_H_INCLUDED #define PATTERNDB_CORRELLATION_CONTEXT_H_INCLUDED #include "syslog-ng.h" #include "correllation-key.h" #include "timerwheel.h" /* This class encapsulates a correllation context, keyed by CorrellationKey, type == PSK_RULE. */ typedef struct _CorrellationContext CorrellationContext; struct _CorrellationContext { /* key in the hashtable. */ CorrellationKey key; /* timeout timer */ TWEntry *timer; /* messages belonging to this context */ GPtrArray *messages; gint ref_cnt; void (*free_fn)(CorrellationContext *s); }; static inline LogMessage * correllation_context_get_last_message(CorrellationContext *self) { return (LogMessage *) g_ptr_array_index(self->messages, self->messages->len - 1); } void correllation_context_init(CorrellationContext *self, const CorrellationKey *key); void correllation_context_free_method(CorrellationContext *self); CorrellationContext *correllation_context_new(CorrellationKey *key); CorrellationContext *correllation_context_ref(CorrellationContext *self); void correllation_context_unref(CorrellationContext *self); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/correllation-key.c000066400000000000000000000066251321171025300243470ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "correllation-key.h" #include "logmsg/logmsg.h" #include /********************************************************* * CorrellationKey, is the key in the state hash table *********************************************************/ guint correllation_key_hash(gconstpointer k) { CorrellationKey *key = (CorrellationKey *) k; guint hash; hash = (key->scope << 30); switch (key->scope) { case RCS_PROCESS: hash += g_str_hash(key->pid); case RCS_PROGRAM: hash += g_str_hash(key->program); case RCS_HOST: hash += g_str_hash(key->host); case RCS_GLOBAL: break; default: g_assert_not_reached(); break; } return hash + g_str_hash(key->session_id); } gboolean correllation_key_equal(gconstpointer k1, gconstpointer k2) { CorrellationKey *key1 = (CorrellationKey *) k1; CorrellationKey *key2 = (CorrellationKey *) k2; if (key1->scope != key2->scope) return FALSE; switch (key1->scope) { case RCS_PROCESS: if (strcmp(key1->pid, key2->pid) != 0) return FALSE; case RCS_PROGRAM: if (strcmp(key1->program, key2->program) != 0) return FALSE; case RCS_HOST: if (strcmp(key1->host, key2->host) != 0) return FALSE; case RCS_GLOBAL: break; default: g_assert_not_reached(); break; } if (strcmp(key1->session_id, key2->session_id) != 0) return FALSE; return TRUE; } /* fills a CorrellationKey structure with borrowed values */ void correllation_key_setup(CorrellationKey *self, CorrellationScope scope, LogMessage *msg, gchar *session_id) { memset(self, 0, sizeof(*self)); self->scope = scope; self->session_id = session_id; /* NVTable ensures that builtin name-value pairs are always NUL terminated */ switch (scope) { case RCS_PROCESS: self->pid = log_msg_get_value(msg, LM_V_PID, NULL); case RCS_PROGRAM: self->program = log_msg_get_value(msg, LM_V_PROGRAM, NULL); case RCS_HOST: self->host = log_msg_get_value(msg, LM_V_HOST, NULL); case RCS_GLOBAL: break; default: g_assert_not_reached(); break; } } gint correllation_key_lookup_scope(const gchar *scope) { if (strcasecmp(scope, "global") == 0) return RCS_GLOBAL; else if (strcasecmp(scope, "host") == 0) return RCS_HOST; else if (strcasecmp(scope, "program") == 0) return RCS_PROGRAM; else if (strcasecmp(scope, "process") == 0) return RCS_PROCESS; return -1; } syslog-ng-syslog-ng-3.13.2/modules/dbparser/correllation-key.h000066400000000000000000000045101321171025300243430ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_CORRELLATION_KEY_H_INCLUDED #define PATTERNDB_CORRELLATION_KEY_H_INCLUDED #include "syslog-ng.h" /* rule context scope */ typedef enum { /* correllation happens globally, e.g. log messages even on different hosts are considered */ RCS_GLOBAL, /* correllation happens inside the same host only, e.g. messages from other hosts are not considered */ RCS_HOST, /* correllation happens for the same program only, e.g. messages from other programs are not considered */ RCS_PROGRAM, /* correllation happens for the same process only, e.g. messages from a different program/pid are not considered */ RCS_PROCESS, } CorrellationScope; gint correllation_key_lookup_scope(const gchar *scope); /* Our state hash contains a mixed set of values, they are either * correllation contexts or the state entry required by rate limiting. */ typedef struct _CorrellationKey { const gchar *host; const gchar *program; const gchar *pid; gchar *session_id; /* we use guint8 to limit the size of this structure, we can have 10s of * thousands of this structure present in memory */ guint8 /* CorrellationScope */ scope; } CorrellationKey; guint correllation_key_hash(gconstpointer k); gboolean correllation_key_equal(gconstpointer k1, gconstpointer k2); void correllation_key_setup(CorrellationKey *self, CorrellationScope scope, LogMessage *msg, gchar *session_id); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/correllation.c000066400000000000000000000032651321171025300235560ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "correllation.h" #include "correllation-key.h" #include "correllation-context.h" void correllation_state_init_instance(CorrellationState *self) { self->state = g_hash_table_new_full(correllation_key_hash, correllation_key_equal, NULL, (GDestroyNotify) correllation_context_unref); } void correllation_state_deinit_instance(CorrellationState *self) { if (self->state) g_hash_table_destroy(self->state); } CorrellationState * correllation_state_new(void) { CorrellationState *self = g_new0(CorrellationState, 1); correllation_state_init_instance(self); return self; } void correllation_state_free(CorrellationState *self) { correllation_state_deinit_instance(self); g_free(self); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/correllation.h000066400000000000000000000026231321171025300235600ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_CORRELLATION_H_INCLUDED #define PATTERNDB_CORRELLATION_H_INCLUDED #include "syslog-ng.h" #include "correllation-key.h" typedef struct _CorrellationState { GHashTable *state; } CorrellationState; void correllation_state_init_instance(CorrellationState *self); void correllation_state_deinit_instance(CorrellationState *self); CorrellationState *correllation_state_new(void); void correllation_state_free(CorrellationState *self); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/dbparser-grammar.ym000066400000000000000000000132401321171025300245040ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code top { #include "dbparser-parser.h" } %code { #include "dbparser.h" #include "cfg-grammar.h" #include "groupingby.h" #include "cfg-parser.h" #include "dbparser-grammar.h" #include "syslog-names.h" #include "messages.h" #include "filter/filter-expr.h" #include SyntheticMessage *last_message; } %name-prefix "dbparser_" /* this parameter is needed in order to instruct bison to use a complete * argument list for yylex/yyerror */ %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogParser **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_DB_PARSER %token KW_GROUPING_BY %token KW_INJECT_MODE %token KW_KEY %token KW_SCOPE %token KW_INHERIT_MODE %token KW_TIMEOUT %token KW_TRIGGER %token KW_WHERE %token KW_HAVING %token KW_AGGREGATE %token KW_VALUE %token KW_DROP_UNMATCHED %type stateful_parser_inject_mode %type synthetic_message %type inherit_mode %type context_scope %% start : LL_CONTEXT_PARSER parser_expr_db { YYACCEPT; } ; parser_expr_db : KW_DB_PARSER '(' { last_parser = *instance = (LogParser *) log_db_parser_new(configuration); } parser_db_opts ')' | KW_GROUPING_BY '(' { last_parser = *instance = grouping_by_new(configuration); } grouping_by_opts ')' ; parser_db_opts : parser_db_opt parser_db_opts | ; /* NOTE: we don't support parser_opt as we don't want the user to specify a template */ parser_db_opt : KW_FILE '(' string ')' { log_db_parser_set_db_file(((LogDBParser *) last_parser), $3); free($3); } | KW_DROP_UNMATCHED '(' yesno ')' { log_db_parser_set_drop_unmatched(((LogDBParser *) last_parser), $3); }; | stateful_parser_opt ; stateful_parser_opt : KW_INJECT_MODE '(' stateful_parser_inject_mode ')' { stateful_parser_set_inject_mode(((StatefulParser *) last_parser), $3); } | parser_opt ; stateful_parser_inject_mode : string { $$ = stateful_parser_lookup_inject_mode($1); CHECK_ERROR($$ != -1, @1, "Unknown inject-mode %s", $1); free($1); } | KW_INTERNAL { $$ = stateful_parser_lookup_inject_mode("internal"); } ; grouping_by_opts : grouping_by_opt grouping_by_opts | ; grouping_by_opt : KW_KEY '(' template_content ')' { grouping_by_set_key_template(last_parser, $3); log_template_unref($3); } | KW_SCOPE '(' context_scope ')' { grouping_by_set_scope(last_parser, $3); } | KW_WHERE '(' { FilterExprNode *filter_expr; CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&filter_expr_parser, lexer, (gpointer *) &filter_expr, NULL), @1); grouping_by_set_where_condition(last_parser, filter_expr); } ')' | KW_HAVING '(' { FilterExprNode *filter_expr; CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&filter_expr_parser, lexer, (gpointer *) &filter_expr, NULL), @1); grouping_by_set_having_condition(last_parser, filter_expr); } ')' | KW_TIMEOUT '(' nonnegative_integer ')' { CHECK_ERROR($3 >= 1, @1, "timeout() needs to be greater than 1 second"); grouping_by_set_timeout(last_parser, $3); } | KW_AGGREGATE '(' synthetic_message ')' { grouping_by_set_synthetic_message(last_parser, $3); } | KW_TRIGGER '(' { FilterExprNode *filter_expr; CHECK_ERROR_WITHOUT_MESSAGE(cfg_parser_parse(&filter_expr_parser, lexer, (gpointer *) &filter_expr, NULL), @1); grouping_by_set_trigger_condition(last_parser, filter_expr); } ')' | stateful_parser_opt ; synthetic_message : { last_message = synthetic_message_new(); } synthetic_message_opts { $$ = last_message; } ; synthetic_message_opts : synthetic_message_opt synthetic_message_opts | ; synthetic_message_opt : KW_INHERIT_MODE '(' inherit_mode ')' { synthetic_message_set_inherit_mode(last_message, $3); } | KW_VALUE '(' string template_content ')' { synthetic_message_add_value_template(last_message, $3, $4); free($3); log_template_unref($4); } | KW_TAGS '(' string ')' { synthetic_message_add_tag(last_message, $3); free($3); } ; inherit_mode : string { $$ = synthetic_message_lookup_inherit_mode($1); free($1); CHECK_ERROR($$ >= 0, @1, "unknown inherit-mode()"); } ; context_scope : string { $$ = correllation_key_lookup_scope($1); free($1); CHECK_ERROR($$ >= 0, @1, "unknown context-scope()"); } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/dbparser/dbparser-parser.c000066400000000000000000000040601321171025300241470ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "dbparser.h" #include "cfg-parser.h" #include "dbparser-grammar.h" extern int dbparser_debug; int dbparser_parse(CfgLexer *lexer, LogParser **instance, gpointer arg); static CfgLexerKeyword dbparser_keywords[] = { { "db_parser", KW_DB_PARSER }, { "grouping_by", KW_GROUPING_BY }, /* correllate options */ { "inject_mode", KW_INJECT_MODE }, { "drop_unmatched", KW_DROP_UNMATCHED }, { "key", KW_KEY }, { "scope", KW_SCOPE }, { "timeout", KW_TIMEOUT }, { "aggregate", KW_AGGREGATE }, { "inherit_mode", KW_INHERIT_MODE }, { "where", KW_WHERE }, { "having", KW_HAVING }, { "trigger", KW_TRIGGER }, { "value", KW_VALUE }, { NULL } }; CfgParser dbparser_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &dbparser_debug, #endif .name = "dbparser", .keywords = dbparser_keywords, .parse = (gint (*)(CfgLexer *, gpointer *, gpointer)) dbparser_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(dbparser_, LogParser **) syslog-ng-syslog-ng-3.13.2/modules/dbparser/dbparser-parser.h000066400000000000000000000022411321171025300241530ustar00rootroot00000000000000/* * Copyright (c) 2002-2010 Balabit * Copyright (c) 1998-2010 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DBPARSER_PARSER_H_INCLUDED #define DBPARSER_PARSER_H_INCLUDED #include "cfg-parser.h" #include "parser/parser-expr.h" extern CfgParser dbparser_parser; CFG_PARSER_DECLARE_LEXER_BINDING(dbparser_, LogParser **) #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/dbparser-plugin.c000066400000000000000000000035461321171025300241610ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "dbparser.h" #include "groupingby.h" #include "plugin.h" #include "plugin-types.h" extern CfgParser dbparser_parser; static Plugin dbparser_plugins[] = { { .type = LL_CONTEXT_PARSER, .name = "db-parser", .parser = &dbparser_parser, }, { .type = LL_CONTEXT_PARSER, .name = "grouping-by", .parser = &dbparser_parser, }, }; gboolean dbparser_module_init(PluginContext *context, CfgArgs *args) { pattern_db_global_init(); grouping_by_global_init(); plugin_register(context, dbparser_plugins, G_N_ELEMENTS(dbparser_plugins)); return TRUE; } const ModuleInfo module_info = { .canonical_name = "dbparser", .version = SYSLOG_NG_VERSION, .description = "The db-parser() module implements sample database based parsing for syslog-ng.", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = dbparser_plugins, .plugins_len = G_N_ELEMENTS(dbparser_plugins), }; syslog-ng-syslog-ng-3.13.2/modules/dbparser/dbparser.c000066400000000000000000000204671321171025300226660ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "dbparser.h" #include "patterndb.h" #include "radix.h" #include "apphook.h" #include "reloc.h" #include "stateful-parser.h" #include #include #include struct _LogDBParser { StatefulParser super; GStaticMutex lock; struct iv_timer tick; PatternDB *db; gchar *db_file; time_t db_file_last_check; ino_t db_file_inode; time_t db_file_mtime; gboolean db_file_reloading; gboolean drop_unmatched; }; static void log_db_parser_emit(LogMessage *msg, gboolean synthetic, gpointer user_data) { LogDBParser *self = (LogDBParser *) user_data; if (synthetic) { stateful_parser_emit_synthetic(&self->super, msg); msg_debug("db-parser: emitting synthetic message", evt_tag_str("msg", log_msg_get_value(msg, LM_V_MESSAGE, NULL))); } } static void log_db_parser_reload_database(LogDBParser *self) { struct stat st; GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super); if (stat(self->db_file, &st) < 0) { msg_error("Error stating pattern database file, no automatic reload will be performed", evt_tag_str("error", g_strerror(errno))); return; } if ((self->db_file_inode == st.st_ino && self->db_file_mtime == st.st_mtime)) { return; } self->db_file_inode = st.st_ino; self->db_file_mtime = st.st_mtime; if (!pattern_db_reload_ruleset(self->db, cfg, self->db_file)) { msg_error("Error reloading pattern database, no automatic reload will be performed"); } else { /* free the old database if the new was loaded successfully */ msg_notice("Log pattern database reloaded", evt_tag_str("file", self->db_file), evt_tag_str("version", pattern_db_get_ruleset_version(self->db)), evt_tag_str("pub_date", pattern_db_get_ruleset_pub_date(self->db))); } } static void log_db_parser_timer_tick(gpointer s) { LogDBParser *self = (LogDBParser *) s; pattern_db_timer_tick(self->db); iv_validate_now(); self->tick.expires = iv_now; self->tick.expires.tv_sec++; iv_timer_register(&self->tick); } static gchar * log_db_parser_format_persist_name(LogDBParser *self) { static gchar persist_name[512]; g_snprintf(persist_name, sizeof(persist_name), "db-parser(%s)", self->db_file); return persist_name; } static gboolean log_db_parser_init(LogPipe *s) { LogDBParser *self = (LogDBParser *) s; GlobalConfig *cfg = log_pipe_get_config(s); self->db = cfg_persist_config_fetch(cfg, log_db_parser_format_persist_name(self)); if (self->db) { struct stat st; if (stat(self->db_file, &st) < 0) { msg_error("Error stating pattern database file, no automatic reload will be performed", evt_tag_str("error", g_strerror(errno))); } else if (self->db_file_inode != st.st_ino || self->db_file_mtime != st.st_mtime) { log_db_parser_reload_database(self); self->db_file_inode = st.st_ino; self->db_file_mtime = st.st_mtime; } } else { self->db = pattern_db_new(); log_db_parser_reload_database(self); } if (self->db) pattern_db_set_emit_func(self->db, log_db_parser_emit, self); iv_validate_now(); IV_TIMER_INIT(&self->tick); self->tick.cookie = self; self->tick.handler = log_db_parser_timer_tick; self->tick.expires = iv_now; self->tick.expires.tv_sec++; self->tick.expires.tv_nsec = 0; iv_timer_register(&self->tick); if (!self->db) return FALSE; return stateful_parser_init_method(s); } static gboolean log_db_parser_deinit(LogPipe *s) { LogDBParser *self = (LogDBParser *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (iv_timer_registered(&self->tick)) { iv_timer_unregister(&self->tick); } cfg_persist_config_add(cfg, log_db_parser_format_persist_name(self), self->db, (GDestroyNotify) pattern_db_free, FALSE); self->db = NULL; return stateful_parser_deinit_method(s); } static gboolean log_db_parser_process(LogParser *s, LogMessage **pmsg, const LogPathOptions *path_options, const char *input, gsize input_len) { LogDBParser *self = (LogDBParser *) s; gboolean matched = FALSE; if (G_UNLIKELY(!self->db_file_reloading && (self->db_file_last_check == 0 || self->db_file_last_check < (*pmsg)->timestamps[LM_TS_RECVD].tv_sec - 5))) { /* first check if we need to reload without doing a lock, then grab * the lock, recheck the condition to rule out parallel database * reloads. This avoids a lock in the fast path. */ g_static_mutex_lock(&self->lock); if (!self->db_file_reloading && (self->db_file_last_check == 0 || self->db_file_last_check < (*pmsg)->timestamps[LM_TS_RECVD].tv_sec - 5)) { self->db_file_last_check = (*pmsg)->timestamps[LM_TS_RECVD].tv_sec; self->db_file_reloading = TRUE; g_static_mutex_unlock(&self->lock); /* only one thread may come here, the others may continue to use self->db, until we update it here. */ log_db_parser_reload_database(self); g_static_mutex_lock(&self->lock); self->db_file_reloading = FALSE; } g_static_mutex_unlock(&self->lock); } if (self->db) { log_msg_make_writable(pmsg, path_options); if (G_UNLIKELY(self->super.super.template)) matched = pattern_db_process_with_custom_message(self->db, *pmsg, input, input_len); else matched = pattern_db_process(self->db, *pmsg); } if (!self->drop_unmatched) matched = TRUE; return matched; } void log_db_parser_set_db_file(LogDBParser *self, const gchar *db_file) { if (self->db_file) g_free(self->db_file); self->db_file = g_strdup(db_file); } void log_db_parser_set_drop_unmatched(LogDBParser *self, gboolean setting) { self->drop_unmatched = setting; } /* * NOTE: we could be smarter than this by sharing the radix tree in this case. */ static LogPipe * log_db_parser_clone(LogPipe *s) { LogDBParser *cloned; LogDBParser *self = (LogDBParser *) s; cloned = (LogDBParser *) log_db_parser_new(s->cfg); log_db_parser_set_db_file(cloned, self->db_file); return &cloned->super.super.super; } static void log_db_parser_free(LogPipe *s) { LogDBParser *self = (LogDBParser *) s; g_static_mutex_free(&self->lock); if (self->db) pattern_db_free(self->db); if (self->db_file) g_free(self->db_file); stateful_parser_free_method(s); } LogParser * log_db_parser_new(GlobalConfig *cfg) { LogDBParser *self = g_new0(LogDBParser, 1); stateful_parser_init_instance(&self->super, cfg); self->super.super.super.free_fn = log_db_parser_free; self->super.super.super.init = log_db_parser_init; self->super.super.super.deinit = log_db_parser_deinit; self->super.super.super.clone = log_db_parser_clone; self->super.super.process = log_db_parser_process; self->db_file = g_strdup(get_installation_path_for(PATH_PATTERNDB_FILE)); g_static_mutex_init(&self->lock); if (cfg_is_config_version_older(cfg, 0x0303)) { msg_warning_once("WARNING: The default behaviour for injecting messages in db-parser() has changed in " VERSION_3_3 " from internal to pass-through, use an explicit inject-mode(internal) option for old behaviour"); self->super.inject_mode = LDBP_IM_INTERNAL; } return &self->super.super; } syslog-ng-syslog-ng-3.13.2/modules/dbparser/dbparser.h000066400000000000000000000026301321171025300226630ustar00rootroot00000000000000/* * Copyright (c) 2002-2011 Balabit * Copyright (c) 1998-2011 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DBPARSER_H_INCLUDED #define DBPARSER_H_INCLUDED #include "stateful-parser.h" #include "patterndb.h" #define PATH_PATTERNDB_FILE SYSLOG_NG_PATH_LOCALSTATEDIR "/patterndb.xml" typedef struct _LogDBParser LogDBParser; void log_db_parser_set_drop_unmatched(LogDBParser *self, gboolean setting); void log_db_parser_set_db_file(LogDBParser *self, const gchar *db_file); LogParser *log_db_parser_new(GlobalConfig *cfg); void log_pattern_database_init(void); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/groupingby.c000066400000000000000000000361241321171025300232460ustar00rootroot00000000000000/* * Copyright (c) 2015 BalaBit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "groupingby.h" #include "correllation.h" #include "correllation-context.h" #include "synthetic-message.h" #include "messages.h" #include "str-utils.h" #include "filter/filter-expr.h" #include typedef struct _GroupingBy { StatefulParser super; GStaticMutex lock; struct iv_timer tick; TimerWheel *timer_wheel; GTimeVal last_tick; CorrellationState *correllation; LogTemplate *key_template; gint timeout; CorrellationScope scope; SyntheticMessage *synthetic_message; FilterExprNode *trigger_condition_expr; FilterExprNode *where_condition_expr; FilterExprNode *having_condition_expr; } GroupingBy; static NVHandle context_id_handle = 0; void grouping_by_set_key_template(LogParser *s, LogTemplate *key_template) { GroupingBy *self = (GroupingBy *) s; log_template_unref(self->key_template); self->key_template = log_template_ref(key_template); } void grouping_by_set_scope(LogParser *s, CorrellationScope scope) { GroupingBy *self = (GroupingBy *) s; self->scope = scope; } void grouping_by_set_timeout(LogParser *s, gint timeout) { GroupingBy *self = (GroupingBy *) s; self->timeout = timeout; } void grouping_by_set_trigger_condition(LogParser *s, FilterExprNode *filter_expr) { GroupingBy *self = (GroupingBy *) s; self->trigger_condition_expr = filter_expr; } void grouping_by_set_where_condition(LogParser *s, FilterExprNode *filter_expr) { GroupingBy *self = (GroupingBy *) s; self->where_condition_expr = filter_expr; } void grouping_by_set_having_condition(LogParser *s, FilterExprNode *filter_expr) { GroupingBy *self = (GroupingBy *) s; self->having_condition_expr = filter_expr; } void grouping_by_set_synthetic_message(LogParser *s, SyntheticMessage *message) { GroupingBy *self = (GroupingBy *) s; if (self->synthetic_message) synthetic_message_free(self->synthetic_message); self->synthetic_message = message; } /* NOTE: lock should be acquired for writing before calling this function. */ void grouping_by_set_time(GroupingBy *self, const LogStamp *ls) { GTimeVal now; gchar buf[256]; /* clamp the current time between the timestamp of the current message * (low limit) and the current system time (high limit). This ensures * that incorrect clocks do not skew the current time know by the * correllation engine too much. */ cached_g_current_time(&now); self->last_tick = now; if (ls->tv_sec < now.tv_sec) now.tv_sec = ls->tv_sec; timer_wheel_set_time(self->timer_wheel, now.tv_sec); msg_debug("Advancing grouping-by() current time because of an incoming message", evt_tag_long("utc", timer_wheel_get_time(self->timer_wheel)), evt_tag_str("location", log_expr_node_format_location(self->super.super.super.expr_node, buf, sizeof(buf)))); } /* * This function can be called any time when pattern-db is not processing * messages, but we expect the correllation timer to move forward. It * doesn't need to be called absolutely regularly as it'll use the current * system time to determine how much time has passed since the last * invocation. See the timing comment at pattern_db_process() for more * information. */ void _grouping_by_timer_tick(GroupingBy *self) { GTimeVal now; glong diff; gchar buf[256]; g_static_mutex_lock(&self->lock); cached_g_current_time(&now); diff = g_time_val_diff(&now, &self->last_tick); if (diff > 1e6) { glong diff_sec = diff / 1e6; timer_wheel_set_time(self->timer_wheel, timer_wheel_get_time(self->timer_wheel) + diff_sec); msg_debug("Advancing grouping-by() current time because of timer tick", evt_tag_long("utc", timer_wheel_get_time(self->timer_wheel)), evt_tag_str("location", log_expr_node_format_location(self->super.super.super.expr_node, buf, sizeof(buf)))); /* update last_tick, take the fraction of the seconds not calculated into this update into account */ self->last_tick = now; g_time_val_add(&self->last_tick, -(diff - diff_sec * 1e6)); } else if (diff < 0) { /* time moving backwards, this can only happen if the computer's time * is changed. We don't update patterndb's idea of the time now, wait * another tick instead to update that instead. */ self->last_tick = now; } g_static_mutex_unlock(&self->lock); } static void grouping_by_timer_tick(gpointer s) { GroupingBy *self = (GroupingBy *) s; _grouping_by_timer_tick(self); iv_validate_now(); self->tick.expires = iv_now; self->tick.expires.tv_sec++; iv_timer_register(&self->tick); } static gboolean _evaluate_filter(FilterExprNode *expr, CorrellationContext *context) { return filter_expr_eval_with_context(expr, (LogMessage **) context->messages->pdata, context->messages->len); } static gboolean _evaluate_having(GroupingBy *self, CorrellationContext *context) { if (!self->having_condition_expr) return TRUE; return _evaluate_filter(self->having_condition_expr, context); } static gboolean _evaluate_trigger(GroupingBy *self, CorrellationContext *context) { if (!self->trigger_condition_expr) return FALSE; return _evaluate_filter(self->trigger_condition_expr, context); } static void grouping_by_emit_synthetic(GroupingBy *self, CorrellationContext *context) { LogMessage *msg; if (_evaluate_having(self, context)) { GString *buffer = g_string_sized_new(256); msg = synthetic_message_generate_with_context(self->synthetic_message, context, buffer); stateful_parser_emit_synthetic(&self->super, msg); log_msg_unref(msg); g_string_free(buffer, TRUE); } else { gchar buf[256]; msg_debug("groupingby() dropping context, because having() is FALSE", evt_tag_str("key", context->key.session_id), evt_tag_str("location", log_expr_node_format_location(self->super.super.super.expr_node, buf, sizeof(buf)))); } } static void grouping_by_expire_entry(TimerWheel *wheel, guint64 now, gpointer user_data) { CorrellationContext *context = user_data; GroupingBy *self = (GroupingBy *) timer_wheel_get_associated_data(wheel); gchar buf[256]; msg_debug("Expiring grouping-by() correllation context", evt_tag_long("utc", timer_wheel_get_time(wheel)), evt_tag_str("context-id", context->key.session_id), evt_tag_str("location", log_expr_node_format_location(self->super.super.super.expr_node, buf, sizeof(buf)))); grouping_by_emit_synthetic(self, context); g_hash_table_remove(self->correllation->state, &context->key); /* correllation_context_free is automatically called when returning from this function by the timerwheel code as a destroy notify callback. */ } static gchar * grouping_by_format_persist_name(GroupingBy *self) { static gchar persist_name[512]; g_snprintf(persist_name, sizeof(persist_name), "grouping-by()"); return persist_name; } static gboolean _perform_groupby(GroupingBy *self, LogMessage *msg) { GString *buffer = g_string_sized_new(32); CorrellationContext *context = NULL; gchar buf[256]; g_static_mutex_lock(&self->lock); grouping_by_set_time(self, &msg->timestamps[LM_TS_STAMP]); if (self->key_template) { CorrellationKey key; log_template_format(self->key_template, msg, NULL, LTZ_LOCAL, 0, NULL, buffer); log_msg_set_value(msg, context_id_handle, buffer->str, -1); correllation_key_setup(&key, self->scope, msg, buffer->str); context = g_hash_table_lookup(self->correllation->state, &key); if (!context) { msg_debug("Correllation context lookup failure, starting a new context", evt_tag_str("key", buffer->str), evt_tag_int("timeout", self->timeout), evt_tag_int("expiration", timer_wheel_get_time(self->timer_wheel) + self->timeout), evt_tag_str("location", log_expr_node_format_location(self->super.super.super.expr_node, buf, sizeof(buf)))); context = correllation_context_new(&key); g_hash_table_insert(self->correllation->state, &context->key, context); g_string_steal(buffer); } else { msg_debug("Correllation context lookup successful", evt_tag_str("key", buffer->str), evt_tag_int("timeout", self->timeout), evt_tag_int("expiration", timer_wheel_get_time(self->timer_wheel) + self->timeout), evt_tag_int("num_messages", context->messages->len), evt_tag_str("location", log_expr_node_format_location(self->super.super.super.expr_node, buf, sizeof(buf)))); } g_ptr_array_add(context->messages, log_msg_ref(msg)); if (_evaluate_trigger(self, context)) { msg_verbose("Correllation trigger() met, closing state", evt_tag_str("key", context->key.session_id), evt_tag_int("timeout", self->timeout), evt_tag_int("num_messages", context->messages->len), evt_tag_str("location", log_expr_node_format_location(self->super.super.super.expr_node, buf, sizeof(buf)))); /* close down state */ if (context->timer) timer_wheel_del_timer(self->timer_wheel, context->timer); grouping_by_expire_entry(self->timer_wheel, timer_wheel_get_time(self->timer_wheel), context); } else { if (context->timer) { timer_wheel_mod_timer(self->timer_wheel, context->timer, self->timeout); } else { context->timer = timer_wheel_add_timer(self->timer_wheel, self->timeout, grouping_by_expire_entry, correllation_context_ref(context), (GDestroyNotify) correllation_context_unref); } } } else { context = NULL; } g_static_mutex_unlock(&self->lock); if (context) log_msg_write_protect(msg); g_string_free(buffer, TRUE); return TRUE; } static gboolean _evaluate_where(GroupingBy *self, LogMessage **pmsg, const LogPathOptions *path_options) { if (!self->where_condition_expr) return TRUE; return filter_expr_eval_root(self->where_condition_expr, pmsg, path_options); } static gboolean grouping_by_process(LogParser *s, LogMessage **pmsg, const LogPathOptions *path_options, const char *input, gsize input_len) { GroupingBy *self = (GroupingBy *) s; if (_evaluate_where(self, pmsg, path_options)) return _perform_groupby(self, log_msg_make_writable(pmsg, path_options)); return TRUE; } static gboolean grouping_by_init(LogPipe *s) { GroupingBy *self = (GroupingBy *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (!self->synthetic_message) { msg_error("The aggregate() option for grouping-by() is mandatory", log_pipe_location_tag(s)); return FALSE; } if (self->timeout < 1) { msg_error("timeout() needs to be specified explicitly and must be greater than 0 in the grouping-by() parser", log_pipe_location_tag(s)); return FALSE; } if (!self->key_template) { msg_error("The key() option is mandatory for the grouping-by() parser", log_pipe_location_tag(s)); return FALSE; } self->correllation = cfg_persist_config_fetch(cfg, grouping_by_format_persist_name(self)); if (!self->correllation) { self->correllation = correllation_state_new(); } iv_validate_now(); IV_TIMER_INIT(&self->tick); self->tick.cookie = self; self->tick.handler = grouping_by_timer_tick; self->tick.expires = iv_now; self->tick.expires.tv_sec++; self->tick.expires.tv_nsec = 0; iv_timer_register(&self->tick); return stateful_parser_init_method(s); } static gboolean grouping_by_deinit(LogPipe *s) { GroupingBy *self = (GroupingBy *) s; GlobalConfig *cfg = log_pipe_get_config(s); if (iv_timer_registered(&self->tick)) { iv_timer_unregister(&self->tick); } cfg_persist_config_add(cfg, grouping_by_format_persist_name(self), self->correllation, (GDestroyNotify) correllation_state_free, FALSE); self->correllation = NULL; return stateful_parser_deinit_method(s); } static LogPipe * grouping_by_clone(LogPipe *s) { LogParser *cloned; GroupingBy *self = (GroupingBy *) s; /* FIXME: share state between clones! */ cloned = grouping_by_new(s->cfg); grouping_by_set_key_template(cloned, self->key_template); grouping_by_set_timeout(cloned, self->timeout); return &cloned->super; } static void grouping_by_free(LogPipe *s) { GroupingBy *self = (GroupingBy *) s; g_static_mutex_free(&self->lock); log_template_unref(self->key_template); if (self->synthetic_message) synthetic_message_free(self->synthetic_message); timer_wheel_free(self->timer_wheel); stateful_parser_free_method(s); } LogParser * grouping_by_new(GlobalConfig *cfg) { GroupingBy *self = g_new0(GroupingBy, 1); stateful_parser_init_instance(&self->super, cfg); self->super.super.super.free_fn = grouping_by_free; self->super.super.super.init = grouping_by_init; self->super.super.super.deinit = grouping_by_deinit; self->super.super.super.clone = grouping_by_clone; self->super.super.process = grouping_by_process; g_static_mutex_init(&self->lock); self->scope = RCS_GLOBAL; self->timer_wheel = timer_wheel_new(); timer_wheel_set_associated_data(self->timer_wheel, self, NULL); cached_g_current_time(&self->last_tick); self->timeout = -1; return &self->super.super; } void grouping_by_global_init(void) { context_id_handle = log_msg_get_value_handle(".classifier.context_id"); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/groupingby.h000066400000000000000000000032601321171025300232460ustar00rootroot00000000000000/* * Copyright (c) 2015 BalaBit * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_GROUPING_BY_PARSER_H_INCLUDED #define PATTERNDB_GROUPING_BY_PARSER_H_INCLUDED #include "stateful-parser.h" #include "synthetic-message.h" #include "filter/filter-expr.h" void grouping_by_set_key_template(LogParser *s, LogTemplate *context_id); void grouping_by_set_timeout(LogParser *s, gint timeout); void grouping_by_set_scope(LogParser *s, CorrellationScope scope); void grouping_by_set_synthetic_message(LogParser *s, SyntheticMessage *message); void grouping_by_set_trigger_condition(LogParser *s, FilterExprNode *filter_expr); void grouping_by_set_where_condition(LogParser *s, FilterExprNode *filter_expr); void grouping_by_set_having_condition(LogParser *s, FilterExprNode *filter_expr); LogParser *grouping_by_new(GlobalConfig *cfg); void grouping_by_global_init(void); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/patterndb.c000066400000000000000000000630421321171025300230430ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "patterndb.h" #include "pdb-action.h" #include "pdb-rule.h" #include "pdb-program.h" #include "pdb-ruleset.h" #include "pdb-load.h" #include "pdb-context.h" #include "pdb-ratelimit.h" #include "pdb-lookup-params.h" #include "correllation.h" #include "logmsg/logmsg.h" #include "template/templates.h" #include "str-utils.h" #include "filter/filter-expr-parser.h" #include "logpipe.h" #include #include #include #include static NVHandle context_id_handle = 0; #define EXPECTED_NUMBER_OF_MESSAGES_EMITTED 32 typedef struct _PDBProcessParams { PDBRule *rule; PDBAction *action; PDBContext *context; LogMessage *msg; GString *buffer; gpointer emitted_messages[EXPECTED_NUMBER_OF_MESSAGES_EMITTED]; GPtrArray *emitted_messages_overflow; gint num_emitted_messages; } PDBProcessParams; struct _PatternDB { GStaticRWLock lock; PDBRuleSet *ruleset; CorrellationState correllation; GHashTable *rate_limits; TimerWheel *timer_wheel; GTimeVal last_tick; /* process_params used by the timer expiration callback. Should only be * set with the write lock held and only during the duration of * timer_wheel_set_time() */ PDBProcessParams *timer_process_params; PatternDBEmitFunc emit; gpointer emit_data; }; static inline gpointer _piggy_back_log_message_pointer_with_synthetic_value(LogMessage *msg, gboolean synthetic) { /* we piggy back the "synthetic" value as the LSB in the pointer value * (which is always zero anyway). This avoids creating a struct that * holds two values */ return (gpointer) ((guintptr) msg | (!!synthetic)); } static inline void _extract_log_message_pointer_and_synthetic_value(gpointer value, LogMessage **pmsg, gboolean *synthetic) { *synthetic = (gboolean) ((guintptr) value & 1); *pmsg = (LogMessage *) ((guintptr) value & ~1); } /* This function is called to populate the emitted_messages array in * process_params. It only manipulates per-thread data structure so it does * not require locks but does not mind them being locked either. */ static void _emit_message(PatternDB *self, PDBProcessParams *process_params, gboolean synthetic, LogMessage *msg) { if (!self->emit) return; if (process_params->num_emitted_messages < EXPECTED_NUMBER_OF_MESSAGES_EMITTED) { process_params->emitted_messages[process_params->num_emitted_messages++] = _piggy_back_log_message_pointer_with_synthetic_value(msg, synthetic); } else { if (!process_params->emitted_messages_overflow) process_params->emitted_messages_overflow = g_ptr_array_new(); g_ptr_array_add(process_params->emitted_messages_overflow, _piggy_back_log_message_pointer_with_synthetic_value(msg, synthetic)); } log_msg_ref(msg); } static void _send_emitted_message_array(PatternDB *self, gpointer *values, gsize len) { /* if emit is NULL, we don't store any entries in the arrays, so no need * to check it here. */ for (gint i = 0; i < len; i++) { gpointer *value = values[i]; LogMessage *msg; gboolean synthetic; _extract_log_message_pointer_and_synthetic_value(value, &msg, &synthetic); self->emit(msg, synthetic, self->emit_data); log_msg_unref(msg); } } /* This function is called to flush the accumulated list of messages that * are generated during rule evaluation. We must not hold any locks within * PatternDB when doing this, as it will cause log_pipe_queue() calls to * subsequent elements in the message pipeline, which in turn may recurse * into PatternDB. This works as process_params itself is per-thread * (actually an auto variable on the stack), and this is called without * locks held at the end of a pattern_db_process() invocation. */ static void _flush_emitted_messages(PatternDB *self, PDBProcessParams *process_params) { /* send inline elements */ _send_emitted_message_array(self, process_params->emitted_messages, process_params->num_emitted_messages); process_params->num_emitted_messages = 0; if (process_params->emitted_messages_overflow) { /* send overflow area */ _send_emitted_message_array(self, process_params->emitted_messages_overflow->pdata, process_params->emitted_messages_overflow->len); g_ptr_array_free(process_params->emitted_messages_overflow, TRUE); process_params->emitted_messages_overflow = NULL; } } /* * Timing * ====== * * The time tries to follow the message stream, e.g. it is independent from * the current system time. Whenever a message comes in, its timestamp * moves the current time forward, which means it is quite easy to process * logs from the past, correllation timeouts will be measured in "message * time". There's one exception to this rule: when the patterndb is idle * (e.g. no messages are coming in), the current system time is used to * measure as real time passes, and that will also increase the time of the * correllation engine. This is based on the following assumptions: * * 1) dbparser can only be idle in case on-line logs are processed * (otherwise messages are read from the disk much faster) * * 2) if on-line processing is done, it is expected that messages have * roughly correct timestamps, e.g. if 1 second passes in current * system time, further incoming messages will have a timestamp close * to this. * * Thus whenever the patterndb is idle, a timer tick callback arrives, which * checks the real elapsed time between the last message (or last tick) and * increments the current known time with this value. * * This behaviour makes it possible to properly work in these use-cases: * * 1) process a log file stored on disk, containing messages in the past * 2) process an incoming message stream on-line, expiring correllation * states even if there are no incoming messages * */ /********************************************* * Rule evaluation *********************************************/ static gboolean _is_action_within_rate_limit(PatternDB *db, PDBProcessParams *process_params) { PDBRule *rule = process_params->rule; PDBAction *action = process_params->action; LogMessage *msg = process_params->msg; GString *buffer = process_params->buffer; CorrellationKey key; PDBRateLimit *rl; guint64 now; if (action->rate == 0) return TRUE; g_string_printf(buffer, "%s:%d", rule->rule_id, action->id); correllation_key_setup(&key, rule->context.scope, msg, buffer->str); rl = g_hash_table_lookup(db->rate_limits, &key); if (!rl) { rl = pdb_rate_limit_new(&key); g_hash_table_insert(db->rate_limits, &rl->key, rl); g_string_steal(buffer); } now = timer_wheel_get_time(db->timer_wheel); if (rl->last_check == 0) { rl->last_check = now; rl->buckets = action->rate; } else { /* quick and dirty fixed point arithmetic, 8 bit fraction part */ gint new_credits = (((glong) (now - rl->last_check)) << 8) / ((((glong) action->rate_quantum) << 8) / action->rate); if (new_credits) { /* ok, enough time has passed to increase the current credit. * Deposit the new credits in bucket but make sure we don't permit * more than the maximum rate. */ rl->buckets = MIN(rl->buckets + new_credits, action->rate); rl->last_check = now; } } if (rl->buckets) { rl->buckets--; return TRUE; } return FALSE; } static gboolean _is_action_triggered(PatternDB *db, PDBProcessParams *process_params, PDBActionTrigger trigger) { PDBAction *action = process_params->action; PDBContext *context = process_params->context; LogMessage *msg = process_params->msg; if (action->trigger != trigger) return FALSE; if (action->condition) { if (context && !filter_expr_eval_with_context(action->condition, (LogMessage **) context->super.messages->pdata, context->super.messages->len)) return FALSE; if (!context && !filter_expr_eval(action->condition, msg)) return FALSE; } if (!_is_action_within_rate_limit(db, process_params)) return FALSE; return TRUE; } static LogMessage * _generate_synthetic_message(PDBProcessParams *process_params) { PDBAction *action = process_params->action; PDBContext *context = process_params->context; LogMessage *msg = process_params->msg; GString *buffer = process_params->buffer; if (context) return synthetic_message_generate_with_context(&action->content.message, &context->super, buffer); else return synthetic_message_generate_without_context(&action->content.message, msg, buffer); } static void _execute_action_message(PatternDB *db, PDBProcessParams *process_params) { LogMessage *genmsg; genmsg = _generate_synthetic_message(process_params); _emit_message(db, process_params, TRUE, genmsg); log_msg_unref(genmsg); } static void pattern_db_expire_entry(TimerWheel *wheel, guint64 now, gpointer user_data); static void _execute_action_create_context(PatternDB *db, PDBProcessParams *process_params) { CorrellationKey key; PDBAction *action = process_params->action; PDBRule *rule = process_params->rule; PDBContext *triggering_context = process_params->context; LogMessage *triggering_msg = process_params->msg; GString *buffer = process_params->buffer; PDBContext *new_context; LogMessage *context_msg; SyntheticContext *syn_context; SyntheticMessage *syn_message; syn_context = &action->content.create_context.context; syn_message = &action->content.create_context.message; if (triggering_context) { context_msg = synthetic_message_generate_with_context(syn_message, &triggering_context->super, buffer); log_template_format_with_context(syn_context->id_template, (LogMessage **) triggering_context->super.messages->pdata, triggering_context->super.messages->len, NULL, LTZ_LOCAL, 0, NULL, buffer); } else { context_msg = synthetic_message_generate_without_context(syn_message, triggering_msg, buffer); log_template_format(syn_context->id_template, triggering_msg, NULL, LTZ_LOCAL, 0, NULL, buffer); } msg_debug("Explicit create-context action, starting a new context", evt_tag_str("rule", rule->rule_id), evt_tag_str("context", buffer->str), evt_tag_int("context_timeout", syn_context->timeout), evt_tag_int("context_expiration", timer_wheel_get_time(db->timer_wheel) + syn_context->timeout)); correllation_key_setup(&key, syn_context->scope, context_msg, buffer->str); new_context = pdb_context_new(&key); g_hash_table_insert(db->correllation.state, &new_context->super.key, new_context); g_string_steal(buffer); g_ptr_array_add(new_context->super.messages, context_msg); new_context->super.timer = timer_wheel_add_timer(db->timer_wheel, rule->context.timeout, pattern_db_expire_entry, correllation_context_ref(&new_context->super), (GDestroyNotify) correllation_context_unref); new_context->rule = pdb_rule_ref(rule); } static void _execute_action(PatternDB *db, PDBProcessParams *process_params) { PDBAction *action = process_params->action; switch (action->content_type) { case RAC_NONE: break; case RAC_MESSAGE: _execute_action_message(db, process_params); break; case RAC_CREATE_CONTEXT: _execute_action_create_context(db, process_params); break; default: g_assert_not_reached(); break; } } static void _execute_action_if_triggered(PatternDB *db, PDBProcessParams *process_params, PDBActionTrigger trigger) { if (_is_action_triggered(db, process_params, trigger)) _execute_action(db, process_params); } static void _execute_rule_actions(PatternDB *db, PDBProcessParams *process_params, PDBActionTrigger trigger) { gint i; PDBRule *rule = process_params->rule; if (!rule->actions) return; for (i = 0; i < rule->actions->len; i++) { process_params->action = (PDBAction *) g_ptr_array_index(rule->actions, i); _execute_action_if_triggered(db, process_params, trigger); } } /********************************************************* * PatternDB *********************************************************/ /* NOTE: this function requires PatternDB reader/writer lock to be * write-locked. * * Currently, it is, as timer_wheel_set_time() is only called with that * precondition, and timer-wheel callbacks are only called from within * timer_wheel_set_time(). */ static void pattern_db_expire_entry(TimerWheel *wheel, guint64 now, gpointer user_data) { PDBContext *context = user_data; PatternDB *pdb = (PatternDB *) timer_wheel_get_associated_data(wheel); GString *buffer = g_string_sized_new(256); LogMessage *msg = correllation_context_get_last_message(&context->super); PDBProcessParams *process_params = pdb->timer_process_params; msg_debug("Expiring patterndb correllation context", evt_tag_str("last_rule", context->rule->rule_id), evt_tag_long("utc", timer_wheel_get_time(pdb->timer_wheel))); process_params->context = context; process_params->rule = context->rule; process_params->msg = msg; process_params->buffer = buffer; _execute_rule_actions(pdb, process_params, RAT_TIMEOUT); g_hash_table_remove(pdb->correllation.state, &context->super.key); g_string_free(buffer, TRUE); /* pdb_context_free is automatically called when returning from this function by the timerwheel code as a destroy notify callback. */ } /* * This function can be called any time when pattern-db is not processing * messages, but we expect the correllation timer to move forward. It * doesn't need to be called absolutely regularly as it'll use the current * system time to determine how much time has passed since the last * invocation. See the timing comment at pattern_db_process() for more * information. */ void pattern_db_timer_tick(PatternDB *self) { GTimeVal now; glong diff; PDBProcessParams process_params_p = {0}; PDBProcessParams *process_params = &process_params_p; g_static_rw_lock_writer_lock(&self->lock); self->timer_process_params = process_params; cached_g_current_time(&now); diff = g_time_val_diff(&now, &self->last_tick); if (diff > 1e6) { glong diff_sec = diff / 1e6; timer_wheel_set_time(self->timer_wheel, timer_wheel_get_time(self->timer_wheel) + diff_sec); msg_debug("Advancing patterndb current time because of timer tick", evt_tag_long("utc", timer_wheel_get_time(self->timer_wheel))); /* update last_tick, take the fraction of the seconds not calculated into this update into account */ self->last_tick = now; g_time_val_add(&self->last_tick, -(diff - diff_sec * 1e6)); } else if (diff < 0) { /* time moving backwards, this can only happen if the computer's time * is changed. We don't update patterndb's idea of the time now, wait * another tick instead to update that instead. */ self->last_tick = now; } self->timer_process_params = NULL; g_static_rw_lock_writer_unlock(&self->lock); _flush_emitted_messages(self, process_params); } /* NOTE: lock should be acquired for writing before calling this function. */ static void _advance_time_based_on_message(PatternDB *self, PDBProcessParams *process_params, const LogStamp *ls) { GTimeVal now; /* clamp the current time between the timestamp of the current message * (low limit) and the current system time (high limit). This ensures * that incorrect clocks do not skew the current time know by the * correllation engine too much. */ cached_g_current_time(&now); self->last_tick = now; if (ls->tv_sec < now.tv_sec) now.tv_sec = ls->tv_sec; /* the expire callback uses this pointer to find the process_params it * needs to emit messages. ProcessParams itself is a per-thread value, * however the timer callback is executing with the writer lock held. * There's no other mechanism to pass this pointer to the timer callback, * so we add it to PatternDB, but make sure it is properly protected by * locks. * */ self->timer_process_params = process_params; timer_wheel_set_time(self->timer_wheel, now.tv_sec); self->timer_process_params = NULL; msg_debug("Advancing patterndb current time because of an incoming message", evt_tag_long("utc", timer_wheel_get_time(self->timer_wheel))); } void pattern_db_advance_time(PatternDB *self, gint timeout) { PDBProcessParams process_params_p = {0}; PDBProcessParams *process_params = &process_params_p; time_t new_time; g_static_rw_lock_writer_lock(&self->lock); new_time = timer_wheel_get_time(self->timer_wheel) + timeout; self->timer_process_params = process_params; timer_wheel_set_time(self->timer_wheel, new_time); self->timer_process_params = NULL; g_static_rw_lock_writer_unlock(&self->lock); _flush_emitted_messages(self, process_params); } gboolean pattern_db_reload_ruleset(PatternDB *self, GlobalConfig *cfg, const gchar *pdb_file) { PDBRuleSet *new_ruleset; new_ruleset = pdb_rule_set_new(); if (!pdb_rule_set_load(new_ruleset, cfg, pdb_file, NULL)) { pdb_rule_set_free(new_ruleset); return FALSE; } else { g_static_rw_lock_writer_lock(&self->lock); if (self->ruleset) pdb_rule_set_free(self->ruleset); self->ruleset = new_ruleset; g_static_rw_lock_writer_unlock(&self->lock); return TRUE; } } void pattern_db_set_emit_func(PatternDB *self, PatternDBEmitFunc emit, gpointer emit_data) { self->emit = emit; self->emit_data = emit_data; } const gchar * pattern_db_get_ruleset_pub_date(PatternDB *self) { return self->ruleset->pub_date; } const gchar * pattern_db_get_ruleset_version(PatternDB *self) { return self->ruleset->version; } PDBRuleSet * pattern_db_get_ruleset(PatternDB *self) { return self->ruleset; } static gboolean _pattern_db_is_empty(PatternDB *self) { return (G_UNLIKELY(!self->ruleset) || self->ruleset->is_empty); } static void _pattern_db_process_matching_rule(PatternDB *self, PDBProcessParams *process_params) { PDBContext *context = NULL; PDBRule *rule = process_params->rule; LogMessage *msg = process_params->msg; GString *buffer = g_string_sized_new(32); g_static_rw_lock_writer_lock(&self->lock); _advance_time_based_on_message(self, process_params, &msg->timestamps[LM_TS_STAMP]); if (rule->context.id_template) { CorrellationKey key; log_template_format(rule->context.id_template, msg, NULL, LTZ_LOCAL, 0, NULL, buffer); log_msg_set_value(msg, context_id_handle, buffer->str, -1); correllation_key_setup(&key, rule->context.scope, msg, buffer->str); context = g_hash_table_lookup(self->correllation.state, &key); if (!context) { msg_debug("Correllation context lookup failure, starting a new context", evt_tag_str("rule", rule->rule_id), evt_tag_str("context", buffer->str), evt_tag_int("context_timeout", rule->context.timeout), evt_tag_int("context_expiration", timer_wheel_get_time(self->timer_wheel) + rule->context.timeout)); context = pdb_context_new(&key); g_hash_table_insert(self->correllation.state, &context->super.key, context); g_string_steal(buffer); } else { msg_debug("Correllation context lookup successful", evt_tag_str("rule", rule->rule_id), evt_tag_str("context", buffer->str), evt_tag_int("context_timeout", rule->context.timeout), evt_tag_int("context_expiration", timer_wheel_get_time(self->timer_wheel) + rule->context.timeout), evt_tag_int("num_messages", context->super.messages->len)); } g_ptr_array_add(context->super.messages, log_msg_ref(msg)); if (context->super.timer) { timer_wheel_mod_timer(self->timer_wheel, context->super.timer, rule->context.timeout); } else { context->super.timer = timer_wheel_add_timer(self->timer_wheel, rule->context.timeout, pattern_db_expire_entry, correllation_context_ref(&context->super), (GDestroyNotify) correllation_context_unref); } if (context->rule != rule) { if (context->rule) pdb_rule_unref(context->rule); context->rule = pdb_rule_ref(rule); } } else { context = NULL; } process_params->context = context; process_params->buffer = buffer; synthetic_message_apply(&rule->msg, &context->super, msg, buffer); _emit_message(self, process_params, FALSE, msg); _execute_rule_actions(self, process_params, RAT_MATCH); pdb_rule_unref(rule); g_static_rw_lock_writer_unlock(&self->lock); if (context) log_msg_write_protect(msg); g_string_free(buffer, TRUE); } static void _pattern_db_process_unmatching_rule(PatternDB *self, PDBProcessParams *process_params) { LogMessage *msg = process_params->msg; g_static_rw_lock_writer_lock(&self->lock); _advance_time_based_on_message(self, process_params, &msg->timestamps[LM_TS_STAMP]); _emit_message(self, process_params, FALSE, msg); g_static_rw_lock_writer_unlock(&self->lock); } static gboolean _pattern_db_process(PatternDB *self, PDBLookupParams *lookup, GArray *dbg_list) { LogMessage *msg = lookup->msg; PDBProcessParams process_params_p = {0}; PDBProcessParams *process_params = &process_params_p; g_static_rw_lock_reader_lock(&self->lock); if (_pattern_db_is_empty(self)) { g_static_rw_lock_reader_unlock(&self->lock); return FALSE; } process_params->rule = pdb_ruleset_lookup(self->ruleset, lookup, dbg_list); process_params->msg = msg; g_static_rw_lock_reader_unlock(&self->lock); if (process_params->rule) _pattern_db_process_matching_rule(self, process_params); else _pattern_db_process_unmatching_rule(self, process_params); _flush_emitted_messages(self, process_params); return process_params->rule != NULL; } gboolean pattern_db_process(PatternDB *self, LogMessage *msg) { PDBLookupParams lookup; pdb_lookup_params_init(&lookup, msg); return _pattern_db_process(self, &lookup, NULL); } gboolean pattern_db_process_with_custom_message(PatternDB *self, LogMessage *msg, const gchar *message, gssize message_len) { PDBLookupParams lookup; pdb_lookup_params_init(&lookup, msg); lookup.message_handle = LM_V_NONE; lookup.message_string = message; lookup.message_len = message_len; return _pattern_db_process(self, &lookup, NULL); } void pattern_db_debug_ruleset(PatternDB *self, LogMessage *msg, GArray *dbg_list) { PDBLookupParams lookup; pdb_lookup_params_init(&lookup, msg); _pattern_db_process(self, &lookup, dbg_list); } void pattern_db_expire_state(PatternDB *self) { PDBProcessParams process_params_p = {0}; PDBProcessParams *process_params = &process_params_p; g_static_rw_lock_writer_lock(&self->lock); self->timer_process_params = process_params; timer_wheel_expire_all(self->timer_wheel); self->timer_process_params = NULL; g_static_rw_lock_writer_unlock(&self->lock); _flush_emitted_messages(self, process_params); } static void _init_state(PatternDB *self) { self->rate_limits = g_hash_table_new_full(correllation_key_hash, correllation_key_equal, NULL, (GDestroyNotify) pdb_rate_limit_free); correllation_state_init_instance(&self->correllation); self->timer_wheel = timer_wheel_new(); timer_wheel_set_associated_data(self->timer_wheel, self, NULL); } static void _destroy_state(PatternDB *self) { if (self->timer_wheel) timer_wheel_free(self->timer_wheel); g_hash_table_destroy(self->rate_limits); correllation_state_deinit_instance(&self->correllation); } void pattern_db_forget_state(PatternDB *self) { g_static_rw_lock_writer_lock(&self->lock); _destroy_state(self); _init_state(self); g_static_rw_lock_writer_unlock(&self->lock); } PatternDB * pattern_db_new(void) { PatternDB *self = g_new0(PatternDB, 1); self->ruleset = pdb_rule_set_new(); _init_state(self); cached_g_current_time(&self->last_tick); g_static_rw_lock_init(&self->lock); return self; } void pattern_db_free(PatternDB *self) { if (self->ruleset) pdb_rule_set_free(self->ruleset); _destroy_state(self); g_static_rw_lock_free(&self->lock); g_free(self); } void pattern_db_global_init(void) { context_id_handle = log_msg_get_value_handle(".classifier.context_id"); pdb_rule_set_global_init(); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/patterndb.h000066400000000000000000000042021321171025300230410ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_H_INCLUDED #define PATTERNDB_H_INCLUDED #include "syslog-ng.h" #include "pdb-ruleset.h" #include "timerwheel.h" typedef struct _PatternDB PatternDB; typedef void (*PatternDBEmitFunc)(LogMessage *msg, gboolean synthetic, gpointer user_data); void pattern_db_set_emit_func(PatternDB *self, PatternDBEmitFunc emit_func, gpointer emit_data); PDBRuleSet *pattern_db_get_ruleset(PatternDB *self); const gchar *pattern_db_get_ruleset_version(PatternDB *self); const gchar *pattern_db_get_ruleset_pub_date(PatternDB *self); gboolean pattern_db_reload_ruleset(PatternDB *self, GlobalConfig *cfg, const gchar *pdb_file); void pattern_db_advance_time(PatternDB *self, gint timeout); void pattern_db_timer_tick(PatternDB *self); gboolean pattern_db_process(PatternDB *self, LogMessage *msg); gboolean pattern_db_process_with_custom_message(PatternDB *self, LogMessage *msg, const gchar *message, gssize message_len); void pattern_db_debug_ruleset(PatternDB *self, LogMessage *msg, GArray *dbg_list); void pattern_db_expire_state(PatternDB *self); void pattern_db_forget_state(PatternDB *self); PatternDB *pattern_db_new(void); void pattern_db_free(PatternDB *self); void pattern_db_global_init(void); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/patternize.c000066400000000000000000000447021321171025300232470ustar00rootroot00000000000000/* * Copyright (c) 2010-2012 Balabit * Copyright (c) 2009-2011 Péter Gyöngyösi * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "patternize.h" #include "logmsg/logmsg.h" #include "messages.h" #include "uuid.h" #include #include /* * NOTE: most of the algorithms come from SLCT and LogHound, written by Risto Vaarandi */ /* * Constants */ #define PTZ_MAXLINELEN 10240 #define PTZ_MAXWORDS 512 /* maximum number of words in one line */ #define PTZ_LOGTABLE_ALLOC_BASE 3000 #define PTZ_WORDLIST_CACHE 3 /* FIXME: make this a commandline parameter? */ static LogTagId cluster_tag_id; #if 0 static void _ptz_debug_print_word(gpointer key, gpointer value, gpointer dummy) { fprintf(stderr, "%d: %s\n", *((guint *) value), (gchar *) key); } static void _ptz_debug_print_cluster(gpointer key, gpointer value, gpointer dummy) { fprintf(stderr, "%s: %s\n", (gchar *) key, ((Cluster *) value)->words[0]); } #endif guint ptz_str2hash(gchar *string, guint modulo, guint seed) { int i; /* fast string hashing algorithm by M.V.Ramakrishna and Justin Zobel */ for (i = 0; string[i] != 0; ++i) { seed = seed ^ ((seed << 5) + (seed >> 2) + string[i]); } return seed % modulo; } gchar * ptz_find_delimiters(gchar *str, gchar *delimdef) { gchar *remainder; GString *delimiters = g_string_sized_new(32); remainder = str; while (remainder[0] != 0) { remainder += strcspn(remainder, delimdef); if (remainder[0] != 0) { g_string_append_c(delimiters, remainder[0]); remainder++; } } return g_string_free(delimiters, FALSE); } gboolean ptz_find_frequent_words_remove_key_predicate(gpointer key, gpointer value, gpointer support) { return (*((guint *) value) < GPOINTER_TO_UINT(support)); } GHashTable * ptz_find_frequent_words(GPtrArray *logs, guint support, gchar *delimiters, gboolean two_pass) { int i, j, pass; guint *curr_count; LogMessage *msg; gchar *msgstr; gssize msglen; gchar **words; GHashTable *wordlist; int *wordlist_cache = NULL; guint cachesize = 0, cacheseed = 0, cacheindex = 0; gchar *hash_key; wordlist = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); for (pass = (two_pass ? 1 : 2); pass <= 2; ++pass) { if (pass == 1) { msg_progress("Finding frequent words", evt_tag_str("phase", "caching")); srand(time(NULL)); cachesize = (guint) ((logs->len * PTZ_WORDLIST_CACHE)); cacheseed = rand(); wordlist_cache = g_new0(int, cachesize); } else { msg_progress("Finding frequent words", evt_tag_str("phase", "searching")); } for (i = 0; i < logs->len; ++i) { msg = (LogMessage *) g_ptr_array_index(logs, i); msgstr = (gchar *) log_msg_get_value(msg, LM_V_MESSAGE, &msglen); words = g_strsplit_set(msgstr, delimiters, PTZ_MAXWORDS); for (j = 0; words[j]; ++j) { /* NOTE: to calculate the key for the hash, we prefix a word with * its position in the row and a space -- as we always split at * spaces, this should not create confusion */ hash_key = g_strdup_printf("%d %s", j, words[j]); if (two_pass) cacheindex = ptz_str2hash(hash_key, cachesize, cacheseed); if (pass == 1) { wordlist_cache[cacheindex]++; } else if (pass == 2) { if (!two_pass || wordlist_cache[cacheindex] >= support) { curr_count = (guint *) g_hash_table_lookup(wordlist, hash_key); if (!curr_count) { guint *currcount_ref = g_new(guint, 1); (*currcount_ref) = 1; g_hash_table_insert(wordlist, g_strdup(hash_key), currcount_ref); } else { (*curr_count)++; } } } g_free(hash_key); } g_strfreev(words); } /* g_hash_table_foreach(wordlist, _ptz_debug_print_word, NULL); */ g_hash_table_foreach_remove(wordlist, ptz_find_frequent_words_remove_key_predicate, GUINT_TO_POINTER(support)); } if (wordlist_cache) g_free(wordlist_cache); return wordlist; } gboolean ptz_find_clusters_remove_cluster_predicate(gpointer key, gpointer value, gpointer data) { Cluster *val = (Cluster *) value; gboolean ret; LogMessage *msg; guint support; int i; support = GPOINTER_TO_UINT(data); ret = (val->loglines->len < support); if (ret) { /* remove cluster reference from the relevant logs */ for (i = 0; i < val->loglines->len; ++i) { msg = (LogMessage *) g_ptr_array_index(val->loglines, i); log_msg_clear_tag_by_id(msg, cluster_tag_id); } } return ret; } static void cluster_free(Cluster *cluster) { gint i; if (cluster->samples) { for (i = 0; i < cluster->samples->len; i++) g_free(g_ptr_array_index(cluster->samples, i)); g_ptr_array_free(cluster->samples, TRUE); } g_ptr_array_free(cluster->loglines, TRUE); g_strfreev(cluster->words); g_free(cluster); } GHashTable * ptz_find_clusters_slct(GPtrArray *logs, guint support, gchar *delimiters, guint num_of_samples) { GHashTable *wordlist; GHashTable *clusters; int i, j; LogMessage *msg; gchar *msgstr; gssize msglen; gchar **words; gchar *hash_key; gboolean is_candidate; Cluster *cluster; GString *cluster_key; gchar *msgdelimiters; /* get the frequent word list */ wordlist = ptz_find_frequent_words(logs, support, delimiters, TRUE); /* g_hash_table_foreach(wordlist, _ptz_debug_print_word, NULL); */ /* find the cluster candidates */ clusters = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) cluster_free); cluster_key = g_string_sized_new(0); for (i = 0; i < logs->len; ++i) { msg = (LogMessage *) g_ptr_array_index(logs, i); msgstr = (gchar *) log_msg_get_value(msg, LM_V_MESSAGE, &msglen); g_string_truncate(cluster_key, 0); words = g_strsplit_set(msgstr, delimiters, PTZ_MAXWORDS); msgdelimiters = ptz_find_delimiters(msgstr, delimiters); is_candidate = FALSE; for (j = 0; words[j]; ++j) { hash_key = g_strdup_printf("%d %s", j, words[j]); if (g_hash_table_lookup(wordlist, hash_key)) { is_candidate = TRUE; g_string_append(cluster_key, hash_key); g_string_append_c(cluster_key, PTZ_SEPARATOR_CHAR); } else { g_string_append_printf(cluster_key, "%d %c%c", j, PTZ_PARSER_MARKER_CHAR, PTZ_SEPARATOR_CHAR); } g_free(hash_key); } /* append the delimiters of the message to the cluster key to assure unicity * otherwise the same words with different delimiters would still show as the * same cluster */ g_string_append_printf(cluster_key, "%s%c", msgdelimiters, PTZ_SEPARATOR_CHAR); g_free(msgdelimiters); if (is_candidate) { cluster = (Cluster *) g_hash_table_lookup(clusters, cluster_key->str); if (!cluster) { cluster = g_new0(Cluster, 1); if (num_of_samples > 0) { cluster->samples = g_ptr_array_sized_new(5); g_ptr_array_add(cluster->samples, g_strdup(msgstr)); } cluster->loglines = g_ptr_array_sized_new(64); g_ptr_array_add(cluster->loglines, (gpointer) msg); cluster->words = g_strdupv(words); g_hash_table_insert(clusters, g_strdup(cluster_key->str), (gpointer) cluster); } else { g_ptr_array_add(cluster->loglines, (gpointer) msg); if (cluster->samples && cluster->samples->len < num_of_samples) { g_ptr_array_add(cluster->samples, g_strdup(msgstr)); } } log_msg_set_tag_by_id(msg, cluster_tag_id); } g_strfreev(words); } g_hash_table_foreach_remove(clusters, ptz_find_clusters_remove_cluster_predicate, GUINT_TO_POINTER(support)); /* g_hash_table_foreach(clusters, _ptz_debug_print_cluster, NULL); */ g_hash_table_unref(wordlist); g_string_free(cluster_key, TRUE); return clusters; } /* callback function for g_hash_table_foreach_steal to migrate elements from one hash to the other */ static gboolean ptz_merge_clusterlists(gpointer _key, gpointer _value, gpointer _target) { gchar *key = _key; Cluster *cluster = _value; GHashTable *target = _target; g_hash_table_insert(target, key, cluster); return TRUE; } GHashTable * ptz_find_clusters_step(Patternizer *self, GPtrArray *logs, guint support, guint num_of_samples) { msg_progress("Searching clusters", evt_tag_int("input lines", logs->len)); if (self->algo == PTZ_ALGO_SLCT) return ptz_find_clusters_slct(logs, support, self->delimiters, num_of_samples); else { msg_error("Unknown clustering algorithm", evt_tag_int("algo_id", self->algo)); return NULL; } } GHashTable * ptz_find_clusters(Patternizer *self) { /* FIXME: maybe we should dup everything... this way * we give out a clusters hash that contains references * to our internal logs array... */ GHashTable *curr_clusters; GHashTable *ret_clusters; GPtrArray *prev_logs, *curr_logs; guint curr_support; LogMessage *msg; int i; prev_logs = NULL; if (self->iterate == PTZ_ITERATE_NONE) return ptz_find_clusters_step(self, self->logs, self->support, self->num_of_samples); if (self->iterate == PTZ_ITERATE_OUTLIERS) { ret_clusters = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) cluster_free); curr_logs = self->logs; curr_support = self->support; while (TRUE) { curr_clusters = ptz_find_clusters_step(self, curr_logs, curr_support, self->num_of_samples); if (g_hash_table_size(curr_clusters) == 0) { g_hash_table_destroy(curr_clusters); break; } g_hash_table_foreach_steal(curr_clusters, ptz_merge_clusterlists, ret_clusters); g_hash_table_destroy(curr_clusters); prev_logs = curr_logs; curr_logs = g_ptr_array_sized_new(g_hash_table_size(curr_clusters)); for (i = 0; i < prev_logs->len; ++i) { msg = (LogMessage *) g_ptr_array_index(prev_logs, i); if (!log_msg_is_tag_by_id(msg, cluster_tag_id)) { /* it's an outlier, include it in the next iteration */ g_ptr_array_add(curr_logs, msg); } } curr_support = curr_logs->len * (self->support_treshold / 100.0); if (prev_logs != self->logs) { g_ptr_array_free(prev_logs, TRUE); prev_logs = NULL; } } if (prev_logs && prev_logs != self->logs) g_ptr_array_free(prev_logs, TRUE); if (curr_logs != self->logs) g_ptr_array_free(curr_logs, TRUE); return ret_clusters; } msg_error("Invalid iteration type", evt_tag_int("iteration_type", self->iterate)); return NULL; } void ptz_print_patterndb_rule(gpointer key, gpointer value, gpointer user_data) { char uuid_string[37]; gchar **words; gchar *skey; gchar *splitstr; gchar *escapedstr; gchar **escapedparts; gchar *samplestr, *samplestr_escaped; gboolean named_parsers = *((gboolean *) user_data); guint parser_counts[PTZ_NUM_OF_PARSERS]; int i; Cluster *cluster; GString *pattern = g_string_new(""); guint wordcount; gchar *delimiters; cluster = (Cluster *) value; if (named_parsers) { for (i = 0; i < PTZ_NUM_OF_PARSERS; ++i) parser_counts[i] = 0; } uuid_gen_random(uuid_string, sizeof(uuid_string)); printf(" \n", uuid_string); printf(" \n", cluster->loglines->len); printf(" \n"); printf(" "); /* we have to help strsplit a bit here so that we * won't get junk as the last word */ skey = g_strdup((gchar *) key); if (skey[strlen(skey) -1] == PTZ_SEPARATOR_CHAR) skey[strlen(skey) -1] = 0; splitstr = g_strdup_printf("%c", PTZ_SEPARATOR_CHAR); words = g_strsplit(skey, splitstr, 0); g_free(splitstr); /* pop the delimiters from the cluster key */ wordcount = g_strv_length(words); delimiters = words[wordcount-1]; words[wordcount-1] = 0; for (i = 0; words[i]; ++i) { g_string_truncate(pattern, 0); gchar **word_parts; word_parts = g_strsplit(words[i], " ", 2); if (word_parts[1][0] == PTZ_PARSER_MARKER_CHAR) { /* NOTE: nasty workaround: do not display last ESTRING as syslog-ng won't handle that well... */ /* FIXME: enter a simple @STRING@ here instead... */ if (words[i + 1]) { g_string_append(pattern, "@ESTRING:"); if (named_parsers) { /* TODO: do not hardcode ESTRING here... */ g_string_append_printf(pattern, ".dict.string%d", parser_counts[PTZ_PARSER_ESTRING]++); } g_string_append_printf(pattern, ":%c@", delimiters[i]); escapedstr = g_markup_escape_text(pattern->str, -1); printf("%s", escapedstr); g_free(escapedstr); } } else { g_string_append(pattern, word_parts[1]); if (words[i + 1]) g_string_append_printf(pattern, "%c", delimiters[i]); escapedstr = g_markup_escape_text(pattern->str, -1); if (g_strrstr(escapedstr, "@")) { escapedparts = g_strsplit(escapedstr, "@", -1); g_free(escapedstr); escapedstr = g_strjoinv("@@", escapedparts); g_strfreev(escapedparts); } printf("%s", escapedstr); g_free(escapedstr); } g_strfreev(word_parts); } g_free(skey); g_free(delimiters); g_strfreev(words); g_string_free(pattern, TRUE); printf("\n"); printf(" \n"); if (cluster->samples->len > 0) { printf(" \n"); for (i = 0; i < cluster->samples->len; ++i) { samplestr = (gchar *) g_ptr_array_index(cluster->samples, i); samplestr_escaped = g_markup_escape_text(samplestr, strlen(samplestr)); printf(" \n"); printf(" %s\n", samplestr_escaped); printf(" \n"); g_free(samplestr_escaped); } printf(" \n"); printf(" \n"); } } void ptz_print_patterndb(GHashTable *clusters, gchar *delimiters, gboolean named_parsers) { char date[12], uuid_string[37]; time_t currtime; /* print the header */ time(&currtime); strftime(date, 12, "%Y-%m-%d", localtime(&currtime)); printf("\n", date); uuid_gen_random(uuid_string, sizeof(uuid_string)); printf(" \n", uuid_string); printf(" \n"); g_hash_table_foreach(clusters, ptz_print_patterndb_rule, (gpointer *) &named_parsers); printf(" \n"); printf(" \n"); printf("\n"); } gboolean ptz_load_file(Patternizer *self, gchar *input_file, gboolean no_parse, GError **error) { FILE *file; int len; MsgFormatOptions parse_options; gchar line[PTZ_MAXLINELEN]; LogMessage *msg; if (!input_file) { g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_IO, "No input file specified"); return FALSE; } if (strcmp(input_file, "-") != 0) { if (!(file = fopen(input_file, "r"))) { g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_IO, "Error opening input file %s", input_file); return FALSE; } } else { file = stdin; } memset(&parse_options, 0, sizeof(parse_options)); msg_format_options_defaults(&parse_options); if (no_parse) parse_options.flags |= LP_NOPARSE; else parse_options.flags |= LP_SYSLOG_PROTOCOL; msg_format_options_init(&parse_options, configuration); while (fgets(line, PTZ_MAXLINELEN, file)) { len = strlen(line); if (line[len-1] == '\n') line[len-1] = 0; msg = log_msg_new(line, len, NULL, &parse_options); g_ptr_array_add(self->logs, msg); } self->support = (self->logs->len * (self->support_treshold / 100.0)); msg_format_options_destroy(&parse_options); return TRUE; } Patternizer * ptz_new(gdouble support_treshold, guint algo, guint iterate, guint num_of_samples, gchar *delimiters) { Patternizer *self = g_new0(Patternizer, 1); self->algo = algo; self->iterate = iterate; self->support_treshold = support_treshold; self->num_of_samples = num_of_samples; self->delimiters = delimiters; self->logs = g_ptr_array_sized_new(PTZ_LOGTABLE_ALLOC_BASE); cluster_tag_id = log_tags_get_by_name(".in_patternize_cluster"); return self; } void ptz_free(Patternizer *self) { int i; for (i = 0; i < self->logs->len; ++i) log_msg_unref((LogMessage *) (LogMessage *) g_ptr_array_index(self->logs, i)); g_ptr_array_free(self->logs, TRUE); g_free(self); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/patternize.h000066400000000000000000000045651321171025300232570ustar00rootroot00000000000000/* * Copyright (c) 2010-2012 Balabit * Copyright (c) 2009-2011 Péter Gyöngyösi * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNIZE_H_INCLUDED #define PATTERNIZE_H_INCLUDED #define PTZ_ALGO_SLCT 1 #define PTZ_ALGO_LOGHOUND 2 #define PTZ_ITERATE_NONE 0 #define PTZ_ITERATE_OUTLIERS 1 #define PTZ_ITERATE_HIEARARCH 2 #define PTZ_SEPARATOR_CHAR 0x1E #define PTZ_PARSER_MARKER_CHAR 0x1A #define PTZ_NUM_OF_PARSERS 1 #define PTZ_PARSER_ESTRING 0 #include "syslog-ng.h" typedef struct _Patternizer { guint algo; guint iterate; guint support; guint num_of_samples; gdouble support_treshold; gchar *delimiters; // NOTE: for now, we store all logs read in in the memory. // This brings in some obvious constraints and should be solved // in a more optimized way later. GPtrArray *logs; } Patternizer; typedef struct _Cluster { GPtrArray *loglines; char **words; GPtrArray *samples; } Cluster; /* only declared for the test program */ GHashTable *ptz_find_frequent_words(GPtrArray *logs, guint support, gchar *delimiters, gboolean two_pass); GHashTable *ptz_find_clusters_slct(GPtrArray *logs, guint support, gchar *delimiters, guint num_of_samples); GHashTable *ptz_find_clusters(Patternizer *self); void ptz_print_patterndb(GHashTable *clusters, gchar *delimiters, gboolean named_parsers); gboolean ptz_load_file(Patternizer *self, gchar *input_file, gboolean no_parse, GError **error); Patternizer *ptz_new(gdouble support_treshold, guint algo, guint iterate, guint num_of_samples, gchar *delimiters); void ptz_free(Patternizer *self); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-action.c000066400000000000000000000055331321171025300231010ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "pdb-action.h" #include "pdb-error.h" #include "filter/filter-expr-parser.h" #include void pdb_action_set_condition(PDBAction *self, GlobalConfig *cfg, const gchar *filter_string, GError **error) { CfgLexer *lexer; lexer = cfg_lexer_new_buffer(cfg, filter_string, strlen(filter_string)); if (!cfg_run_parser(cfg, lexer, &filter_expr_parser, (gpointer *) &self->condition, NULL)) { g_set_error(error, PDB_ERROR, PDB_ERROR_FAILED, "Error compiling conditional expression"); self->condition = NULL; return; } } void pdb_action_set_rate(PDBAction *self, const gchar *rate_) { gchar *slash; gchar *rate; rate = g_strdup(rate_); slash = strchr(rate, '/'); if (!slash) { self->rate = atoi(rate); self->rate_quantum = 1; } else { *slash = 0; self->rate = atoi(rate); self->rate_quantum = atoi(slash + 1); *slash = '/'; } if (self->rate_quantum == 0) self->rate_quantum = 1; g_free(rate); } void pdb_action_set_trigger(PDBAction *self, const gchar *trigger, GError **error) { if (strcmp(trigger, "match") == 0) self->trigger = RAT_MATCH; else if (strcmp(trigger, "timeout") == 0) self->trigger = RAT_TIMEOUT; else g_set_error(error, PDB_ERROR, PDB_ERROR_FAILED, "Unknown trigger type: %s", trigger); } PDBAction * pdb_action_new(gint id) { PDBAction *self; self = g_new0(PDBAction, 1); self->trigger = RAT_MATCH; self->content_type = RAC_NONE; self->id = id; return self; } void pdb_action_free(PDBAction *self) { if (self->condition) filter_expr_unref(self->condition); switch (self->content_type) { case RAC_MESSAGE: synthetic_message_deinit(&self->content.message); break; case RAC_CREATE_CONTEXT: synthetic_context_deinit(&self->content.create_context.context); break; default: g_assert_not_reached(); } g_free(self); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-action.h000066400000000000000000000041061321171025300231010ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DBPARSER_PDB_ACTION_H_INCLUDED #define DBPARSER_PDB_ACTION_H_INCLUDED #include "syslog-ng.h" #include "synthetic-message.h" #include "synthetic-context.h" #include "filter/filter-expr.h" /* rule action triggers */ typedef enum { RAT_MATCH = 1, RAT_TIMEOUT } PDBActionTrigger; /* action content*/ typedef enum { RAC_NONE, RAC_MESSAGE, RAC_CREATE_CONTEXT, } PDBActionContentType; /* a rule may contain one or more actions to be performed */ typedef struct _PDBAction { FilterExprNode *condition; PDBActionTrigger trigger; PDBActionContentType content_type; guint32 rate_quantum; guint16 rate; guint8 id; union { SyntheticMessage message; struct { SyntheticMessage message; SyntheticContext context; } create_context; } content; } PDBAction; void pdb_action_set_condition(PDBAction *self, GlobalConfig *cfg, const gchar *filter_string, GError **error); void pdb_action_set_rate(PDBAction *self, const gchar *rate_); void pdb_action_set_trigger(PDBAction *self, const gchar *trigger, GError **error); PDBAction *pdb_action_new(gint id); void pdb_action_free(PDBAction *self); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-context.c000066400000000000000000000025351321171025300233070ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "pdb-context.h" static void pdb_context_free(CorrellationContext *s) { PDBContext *self = (PDBContext *) s; if (self->rule) pdb_rule_unref(self->rule); correllation_context_free_method(s); } PDBContext * pdb_context_new(CorrellationKey *key) { PDBContext *self = g_new0(PDBContext, 1); correllation_context_init(&self->super, key); self->super.free_fn = pdb_context_free; return self; } syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-context.h000066400000000000000000000031611321171025300233100ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_PDB_CONTEXT_H_INCLUDED #define PATTERNDB_PDB_CONTEXT_H_INCLUDED #include "pdb-rule.h" /************************************************************************** * PDBContext, represents a correllation state in the state hash table, is * marked with PSK_CONTEXT in the hash table key **************************************************************************/ /* This class encapsulates a correllation context, keyed by CorrellationKey, type == PSK_RULE. */ typedef struct _PDBContext { CorrellationContext super; /* back reference to the last rule touching this context */ PDBRule *rule; } PDBContext; PDBContext *pdb_context_new(CorrellationKey *key); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-error.c000066400000000000000000000020501321171025300227440ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * Copyright (c) 2016 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "pdb-error.h" GQuark pdb_error_quark(void) { return g_quark_from_static_string("syslog-ng-error-quark"); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-error.h000066400000000000000000000021771321171025300227630ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * Copyright (c) 2016 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PDB_ERROR_H_INCLUDED #define PDB_ERROR_H_INCLUDED #include "syslog-ng.h" #define PDB_ERROR pdb_error_quark() GQuark pdb_error_quark(void); typedef enum { PDB_ERROR_FAILED, } PDBError; #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-example.c000066400000000000000000000027211321171025300232530ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "pdb-example.h" void pdb_example_free(PDBExample *self) { gint i; if (self->rule) pdb_rule_unref(self->rule); if (self->message) g_free(self->message); if (self->program) g_free(self->program); if (self->values) { for (i = 0; i < self->values->len; i++) { gchar **nv = g_ptr_array_index(self->values, i); g_free(nv[0]); g_free(nv[1]); g_free(nv); } g_ptr_array_free(self->values, TRUE); } g_free(self); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-example.h000066400000000000000000000027201321171025300232570ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_PDB_EXAMPLE_H_INCLUDED #define PATTERNDB_PDB_EXAMPLE_H_INCLUDED #include "syslog-ng.h" #include "pdb-rule.h" /* this class encapsulates an example message in the pattern database * used for testing rules and patterns. It contains the message with the * program field and the expected rule_id with the expected name/value * pairs. */ typedef struct _PDBExample { PDBRule *rule; gchar *message; gchar *program; GPtrArray *values; } PDBExample; void pdb_example_free(PDBExample *s); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-file.c000066400000000000000000000110131321171025300225310ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 1998-2016 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "pdb-file.h" #include "pdb-error.h" #include "reloc.h" #include "pathutils.h" #include #include #include #include #include gint pdb_file_detect_version(const gchar *pdbfile, GError **error) { FILE *pdb; gchar line[1024]; gint result = 0; pdb = fopen(pdbfile, "r"); if (!pdb) { g_set_error(error, PDB_ERROR, PDB_ERROR_FAILED, "Error opening file %s (%s)", pdbfile, g_strerror(errno)); return 0; } while (fgets(line, sizeof(line), pdb)) { gchar *patterndb_tag; patterndb_tag = strstr(line, " version attribute not found or is not on its own line"); } return result; } static const gchar * _get_xsddir_in_build(void) { static gchar path[256]; g_snprintf(path, sizeof(path), "%s/doc/xsd", SYSLOG_NG_PATH_TOPSRC_DIR); return path; } static const gchar * _get_xsddir_in_production(void) { return get_installation_path_for(SYSLOG_NG_PATH_XSDDIR); } typedef const gchar *(*PdbGetXsdDirFunc) (void); static gchar * _get_xsd_file(gint version, PdbGetXsdDirFunc get_xsd_dir) { return g_strdup_printf("%s/patterndb-%d.xsd", get_xsd_dir(), version); } static gboolean _pdb_file_validate(const gchar *filename, GError **error, PdbGetXsdDirFunc get_xsd_dir) { gchar *xmllint_cmdline; gint version; gint exit_status; gchar *stderr_content = NULL; gchar *xsd_file; g_return_val_if_fail(error == NULL || *error == NULL, FALSE); version = pdb_file_detect_version(filename, error); if (!version) return FALSE; xsd_file = _get_xsd_file(version, get_xsd_dir); if (!is_file_regular(xsd_file)) { g_set_error(error, PDB_ERROR, PDB_ERROR_FAILED, "XSD file is not available at %s", xsd_file); g_free(xsd_file); return FALSE; } xmllint_cmdline = g_strdup_printf("xmllint --noout --nonet --schema '%s' '%s'", xsd_file, filename); g_free(xsd_file); if (!g_spawn_command_line_sync(xmllint_cmdline, NULL, &stderr_content, &exit_status, error)) { g_free(xmllint_cmdline); g_free(stderr_content); return FALSE; } if (exit_status != 0) { g_set_error(error, PDB_ERROR, PDB_ERROR_FAILED, "Non-zero exit code from xmllint while validating PDB file, " "schema version %d, rc=%d, error: %s, command line %s", version, WEXITSTATUS(exit_status), stderr_content, xmllint_cmdline); g_free(stderr_content); g_free(xmllint_cmdline); return FALSE; } g_free(xmllint_cmdline); g_free(stderr_content); return TRUE; } gboolean pdb_file_validate(const gchar *filename, GError **error) { return _pdb_file_validate(filename, error, _get_xsddir_in_production); } gboolean pdb_file_validate_in_tests(const gchar *filename, GError **error) { return _pdb_file_validate(filename, error, _get_xsddir_in_build); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-file.h000066400000000000000000000023741321171025300225500ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 1998-2016 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DBPARSER_PDB_FILE_H_INCLUDED #define DBPARSER_PDB_FILE_H_INCLUDED 1 #include "syslog-ng.h" gint pdb_file_detect_version(const gchar *pdbfile, GError **error); gboolean pdb_file_validate(const gchar *filename, GError **error); gboolean pdb_file_validate_in_tests(const gchar *filename, GError **error); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-load.c000066400000000000000000001075271321171025300225510ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "patterndb.h" #include "pdb-rule.h" #include "pdb-program.h" #include "pdb-action.h" #include "pdb-example.h" #include "pdb-ruleset.h" #include "pdb-error.h" #include #include #include #include enum PDBLoaderState { PDBL_INITIAL = 0, PDBL_PATTERNDB, PDBL_RULESET, PDBL_RULESET_URL, PDBL_RULESET_DESCRIPTION, PDBL_RULESET_PATTERN, PDBL_RULES, PDBL_RULE, PDBL_RULE_URL, PDBL_RULE_DESCRIPTION, PDBL_RULE_PATTERN, PDBL_RULE_EXAMPLES, PDBL_RULE_EXAMPLE, PDBL_RULE_EXAMPLE_TEST_MESSAGE, PDBL_RULE_EXAMPLE_TEST_VALUES, PDBL_RULE_EXAMPLE_TEST_VALUE, PDBL_RULE_ACTIONS, PDBL_RULE_ACTION, PDBL_RULE_ACTION_CREATE_CONTEXT, /* generic states, reused by multiple paths in the XML */ PDBL_VALUE, PDBL_TAG, PDBL_MESSAGE, }; #define PDB_STATE_STACK_MAX_DEPTH 12 typedef struct _PDBStateStack { gint stack[PDB_STATE_STACK_MAX_DEPTH]; gint top; } PDBStateStack; /* arguments passed to the markup parser functions */ typedef struct _PDBLoader { const gchar *filename; GMarkupParseContext *context; PDBRuleSet *ruleset; PDBProgram *root_program; PDBProgram *current_program; PDBRule *current_rule; PDBAction *current_action; PDBExample *current_example; SyntheticMessage *current_message; enum PDBLoaderState current_state; PDBStateStack state_stack; gboolean first_program; gboolean load_examples; GList *examples; gchar *value_name; gchar *test_value_name; GlobalConfig *cfg; gint action_id; GHashTable *ruleset_patterns; GArray *program_patterns; } PDBLoader; typedef struct _PDBProgramPattern { gchar *pattern; PDBRule *rule; } PDBProgramPattern; static void _pdb_state_stack_push(PDBStateStack *self, gint state) { g_assert(self->top < PDB_STATE_STACK_MAX_DEPTH - 1); self->stack[self->top] = state; self->top++; } static gint _pdb_state_stack_pop(PDBStateStack *self) { g_assert(self->top > 0); self->top--; return self->stack[self->top]; } static void pdb_loader_set_error(PDBLoader *state, GError **error, const gchar *format, ...) { gchar *error_text; gchar *error_location; gint line_number, col_number; va_list va; va_start(va, format); error_text = g_strdup_vprintf(format, va); va_end(va); g_markup_parse_context_get_position(state->context, &line_number, &col_number); error_location = g_strdup_printf("%s:%d:%d", state->filename, line_number, col_number); g_set_error(error, PDB_ERROR, PDB_ERROR_FAILED, "%s: %s", error_location, error_text); g_free(error_text); g_free(error_location); } static void _push_state(PDBLoader *state, gint new_state) { _pdb_state_stack_push(&state->state_stack, state->current_state); state->current_state = new_state; } static void _pop_state(PDBLoader *state) { state->current_state = _pdb_state_stack_pop(&state->state_stack); } static gboolean _pop_state_for_closing_tag_with_alternatives(PDBLoader *state, const gchar *element_name, const gchar *expected_element, const gchar *alternatives, GError **error) { if (strcmp(element_name, expected_element) != 0) { pdb_loader_set_error(state, error, "Unexpected tag, expected %s%s", element_name, expected_element, alternatives ? ", " : "", alternatives); return FALSE; } _pop_state(state); return TRUE; } static gboolean _pop_state_for_closing_tag(PDBLoader *state, const gchar *element_name, const gchar *expected_element, GError **error) { return _pop_state_for_closing_tag_with_alternatives(state, element_name, expected_element, NULL, error); } static gboolean _is_whitespace_only(const gchar *text, gsize text_len) { gint i; for (i = 0; i < text_len; i++) { if (!g_ascii_isspace(text[i])) return FALSE; } return TRUE; } static void _process_value_element(PDBLoader *state, const gchar **attribute_names, const gchar **attribute_values, GError **error) { if (attribute_names[0] && g_str_equal(attribute_names[0], "name")) state->value_name = g_strdup(attribute_values[0]); else { pdb_loader_set_error(state, error, " misses name attribute in rule %s", state->current_rule->rule_id); return; } _push_state(state, PDBL_VALUE); } static void _process_tag_element(PDBLoader *state, const gchar **attribute_names, const gchar **attribute_values, GError **error) { _push_state(state, PDBL_TAG); } static void _process_message_element(PDBLoader *state, const gchar **attribute_names, const gchar **attribute_values, SyntheticMessage *target, GError **error) { gint i; for (i = 0; attribute_names[i]; i++) { if (strcmp(attribute_names[i], "inherit-properties") == 0) synthetic_message_set_inherit_properties_string(target, attribute_values[i], error); else if (strcmp(attribute_names[i], "inherit-mode") == 0) synthetic_message_set_inherit_mode_string(target, attribute_values[i], error); } state->current_message = target; _push_state(state, PDBL_MESSAGE); } static void _process_create_context_element(PDBLoader *state, const gchar **attribute_names, const gchar **attribute_values, SyntheticContext *target, GError **error) { gint i; for (i = 0; attribute_names[i]; i++) { if (strcmp(attribute_names[i], "context-id") == 0) { LogTemplate *template; GError *local_error = NULL; template = log_template_new(state->cfg, NULL); if (!log_template_compile(template, attribute_values[i], &local_error)) { log_template_unref(template); pdb_loader_set_error(state, error, "Error compiling create-context context-id, rule=%s, context-id=%s, error=%s", state->current_rule->rule_id, attribute_values[i], local_error->message); g_clear_error(&local_error); return; } else synthetic_context_set_context_id_template(target, template); } else if (strcmp(attribute_names[i], "context-timeout") == 0) synthetic_context_set_context_timeout(target, strtol(attribute_values[i], NULL, 0)); else if (strcmp(attribute_names[i], "context-scope") == 0) synthetic_context_set_context_scope(target, attribute_values[i], error); } if (!target->id_template) { pdb_loader_set_error(state, error, "context-id attribute is missing from , rule=%s", state->current_rule->rule_id); return; } _push_state(state, PDBL_RULE_ACTION_CREATE_CONTEXT); } /* PDBL_INITIAL */ static void _pdbl_initial_start(PDBLoader *state, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, GError **error) { gint i; if (strcmp(element_name, "patterndb") == 0) { for (i = 0; attribute_names[i]; i++) { if (strcmp(attribute_names[i], "version") == 0) state->ruleset->version = g_strdup(attribute_values[i]); else if (strcmp(attribute_names[i], "pub_date") == 0) state->ruleset->pub_date = g_strdup(attribute_values[i]); } if (!state->ruleset->version) { msg_warning("patterndb version is unspecified, assuming v4 format"); state->ruleset->version = g_strdup("4"); } else if (state->ruleset->version && atoi(state->ruleset->version) < 2) { pdb_loader_set_error(state, error, "patterndb version too old, this version of syslog-ng only supports v3 and v4 formatted patterndb files, please upgrade it using pdbtool"); return; } else if (state->ruleset->version && atoi(state->ruleset->version) > 5) { pdb_loader_set_error(state, error, "patterndb version too new, this version of syslog-ng supports v3, v4 & v5 formatted patterndb files."); return; } _push_state(state, PDBL_PATTERNDB); } else { pdb_loader_set_error(state, error, "Unexpected <%s> tag, expected a ", element_name); } } /* PDBL_PATTERNDB */ static void _pdbl_patterndb_start(PDBLoader *state, const gchar *element_name, GError **error) { if (strcmp(element_name, "ruleset") == 0) { state->ruleset->is_empty = FALSE; state->first_program = TRUE; state->program_patterns = g_array_new(0, 0, sizeof(PDBProgramPattern)); _push_state(state, PDBL_RULESET); } else { pdb_loader_set_error(state, error, "Unexpected <%s> tag, expected a ", element_name); } } static void _populate_ruleset_radix(gpointer key, gpointer value, gpointer user_data) { PDBLoader *state = (PDBLoader *) user_data; gchar *pattern = key; PDBProgram *program = (PDBProgram *) value; r_insert_node(state->ruleset->programs, pattern, pdb_program_ref(program), NULL); } static void _pdbl_patterndb_end(PDBLoader *state, const gchar *element_name, GError **error) { if (_pop_state_for_closing_tag(state, element_name, "patterndb", error)) { g_hash_table_foreach(state->ruleset_patterns, _populate_ruleset_radix, state); g_hash_table_remove_all(state->ruleset_patterns); } } /* PDBL_RULESET */ static void _pdbl_ruleset_start(PDBLoader *state, const gchar *element_name, GError **error) { if (strcmp(element_name, "rules") == 0) { _push_state(state, PDBL_RULES); } else if (strcmp(element_name, "patterns") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "urls") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "url") == 0) { _push_state(state, PDBL_RULESET_URL); } else if (strcmp(element_name, "pattern") == 0) { _push_state(state, PDBL_RULESET_PATTERN); } else if (strcmp(element_name, "description") == 0) { _push_state(state, PDBL_RULESET_DESCRIPTION); } else { pdb_loader_set_error(state, error, "Unexpected <%s> tag, expected a , , , , or ", element_name); } } static void _pdbl_ruleset_end(PDBLoader *state, const gchar *element_name, GError **error) { gint i; PDBProgramPattern *program_pattern; PDBProgram *program; if (strcmp(element_name, "patterns") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "urls") == 0) { /* valid, but we don't do anything */ } else if (_pop_state_for_closing_tag_with_alternatives(state, element_name, "ruleset", " or ", error)) { program = (state->current_program ? state->current_program : state->root_program); /* Copy stored rules into current program */ for (i = 0; i < state->program_patterns->len; i++) { program_pattern = &g_array_index(state->program_patterns, PDBProgramPattern, i); r_insert_node(program->rules, program_pattern->pattern, program_pattern->rule, (RNodeGetValueFunc) pdb_rule_get_name); g_free(program_pattern->pattern); } state->current_program = NULL; g_array_free(state->program_patterns, TRUE); state->program_patterns = NULL; } } /* PDBL_RULESET_PATTERN */ static gboolean _pdbl_ruleset_pattern_text(PDBLoader *state, const gchar *text, gsize text_len, GError **error) { if (state->first_program) { state->current_program = g_hash_table_lookup(state->ruleset_patterns, text); if (state->current_program == NULL) { /* create new program specific radix */ state->current_program = pdb_program_new(); g_hash_table_insert(state->ruleset_patterns, g_strdup(text), state->current_program); } state->first_program = FALSE; } else if (state->current_program) { /* secondary program names should point to the same MSG radix */ PDBProgram *program = g_hash_table_lookup(state->ruleset_patterns, text); if (!program) { g_hash_table_insert(state->ruleset_patterns, g_strdup(text), pdb_program_ref(state->current_program)); } else if (program != state->current_program) { pdb_loader_set_error(state, error, "Joining rulesets with mismatching program name sets, program=%s", text); return FALSE; } } return TRUE; } /* PDBL_RULES */ static void _pdbl_rules_start(PDBLoader *state, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, GError **error) { gint i; if (strcmp(element_name, "rule") == 0) { state->current_rule = pdb_rule_new(); for (i = 0; attribute_names[i]; i++) { if (strcmp(attribute_names[i], "class") == 0) pdb_rule_set_class(state->current_rule, attribute_values[i]); else if (strcmp(attribute_names[i], "id") == 0) pdb_rule_set_rule_id(state->current_rule, attribute_values[i]); else if (strcmp(attribute_names[i], "context-id") == 0) { LogTemplate *template; GError *local_error = NULL; template = log_template_new(state->cfg, NULL); if (!log_template_compile(template, attribute_values[i], &local_error)) { log_template_unref(template); pdb_loader_set_error(state, error, "Error compiling context-id template, rule=%s, context-id=%s, error=%s", state->current_rule->rule_id, attribute_values[i], local_error->message); g_clear_error(&local_error); return; } else synthetic_context_set_context_id_template(&state->current_rule->context, template); } else if (strcmp(attribute_names[i], "context-timeout") == 0) synthetic_context_set_context_timeout(&state->current_rule->context, strtol(attribute_values[i], NULL, 0)); else if (strcmp(attribute_names[i], "context-scope") == 0) synthetic_context_set_context_scope(&state->current_rule->context, attribute_values[i], error); } if (!state->current_rule->rule_id) { pdb_loader_set_error(state, error, "No id attribute for rule element"); pdb_rule_unref(state->current_rule); state->current_rule = NULL; return; } state->current_message = &state->current_rule->msg; state->action_id = 0; _push_state(state, PDBL_RULE); } else { pdb_loader_set_error(state, error, "Unexpected <%s> tag, expected a ", element_name); } } /* PDBL_RULE */ static void _pdbl_rule_start(PDBLoader *state, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, GError **error) { if (strcmp(element_name, "patterns") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "pattern") == 0) { _push_state(state, PDBL_RULE_PATTERN); } else if (strcmp(element_name, "tags") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "tag") == 0) { _process_tag_element(state, attribute_names, attribute_values, error); } else if (strcmp(element_name, "values") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "urls") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "description") == 0) { _push_state(state, PDBL_RULE_DESCRIPTION); } else if (strcmp(element_name, "url") == 0) { _push_state(state, PDBL_RULE_URL); } else if (strcmp(element_name, "value") == 0) { _process_value_element(state, attribute_names, attribute_values, error); } else if (strcmp(element_name, "actions") == 0) { _push_state(state, PDBL_RULE_ACTIONS); } else if (strcmp(element_name, "examples") == 0) { _push_state(state, PDBL_RULE_EXAMPLES); } else { pdb_loader_set_error(state, error, "Unexpected <%s> tag, expected a , , , or ", element_name); } } static void _pdbl_rule_end(PDBLoader *state, const gchar *element_name, GError **error) { if (strcmp(element_name, "patterns") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "description") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "tags") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "urls") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "values") == 0) { /* valid, but we don't do anything */ } else if (_pop_state_for_closing_tag_with_alternatives(state, element_name, "rule", ", , , , ", error) == 0) { if (state->current_rule) { pdb_rule_unref(state->current_rule); state->current_rule = NULL; } state->current_message = NULL; } } /* PDBL_RULE_EXAMPLES */ static void _pdbl_rule_examples_start(PDBLoader *state, const gchar *element_name, GError **error) { if (strcmp(element_name, "example") == 0) { state->current_example = g_new0(PDBExample, 1); state->current_example->rule = pdb_rule_ref(state->current_rule); _push_state(state, PDBL_RULE_EXAMPLE); } else { pdb_loader_set_error(state, error, "Unexpected <%s> tag, expected a ", element_name); } } /* PDBL_RULE_EXAMPLE */ static void _pdbl_rule_example_start(PDBLoader *state, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, GError **error) { gint i; if (strcmp(element_name, "test_message") == 0) { for (i = 0; attribute_names[i]; i++) { if (strcmp(attribute_names[i], "program") == 0) state->current_example->program = g_strdup(attribute_values[i]); } _push_state(state, PDBL_RULE_EXAMPLE_TEST_MESSAGE); } else if (strcmp(element_name, "test_values") == 0) { _push_state(state, PDBL_RULE_EXAMPLE_TEST_VALUES); } else { pdb_loader_set_error(state, error, "Unexpected <%s> tag, expected a , ", element_name); } } static void _pdbl_rule_example_end(PDBLoader *state, const gchar *element_name, GError **error) { if (_pop_state_for_closing_tag(state, element_name, "example", error)) { if (state->load_examples) state->examples = g_list_prepend(state->examples, state->current_example); else pdb_example_free(state->current_example); state->current_example = NULL; } } /* PDBL_RULE_EXAMPLE_TEST_MESSAGE */ static gboolean _pdbl_rule_example_test_message_text(PDBLoader *state, const gchar *text, gsize text_len, GError **error) { state->current_example->message = g_strdup(text); return TRUE; } /* PDBL_RULE_EXAMPLE_TEST_VALUES */ static void _pdbl_rule_example_test_values_start(PDBLoader *state, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, GError **error) { if (strcmp(element_name, "test_value") == 0) { if (attribute_names[0] && g_str_equal(attribute_names[0], "name")) state->test_value_name = g_strdup(attribute_values[0]); else { msg_error("No name is specified for test_value", evt_tag_str("rule_id", state->current_rule->rule_id)); pdb_loader_set_error(state, error, " misses name attribute"); return; } _push_state(state, PDBL_RULE_EXAMPLE_TEST_VALUE); } else { pdb_loader_set_error(state, error, "Unexpected <%s> tag, expected ", element_name); } } /* PDBL_RULE_EXAMPLE_TEST_VALUE */ static void _pdbl_rule_example_test_value_end(PDBLoader *state, const gchar *element_name, GError **error) { if (_pop_state_for_closing_tag(state, element_name, "test_value", error)) { if (state->test_value_name) g_free(state->test_value_name); state->test_value_name = NULL; } } static gboolean _pdbl_rule_example_test_value_text(PDBLoader *state, const gchar *text, gsize text_len, GError **error) { gchar **nv; if (!state->current_example->values) state->current_example->values = g_ptr_array_new(); nv = g_new(gchar *, 2); nv[0] = state->test_value_name; state->test_value_name = NULL; nv[1] = g_strdup(text); g_ptr_array_add(state->current_example->values, nv); return TRUE; } /* PDBL_RULE_ACTIONS */ static void _pdbl_rule_actions_start(PDBLoader *state, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, GError **error) { gint i; if (strcmp(element_name, "action") == 0) { if (!state->current_rule) { pdb_loader_set_error(state, error, "Unexpected element, it must be inside a rule"); return; } state->current_action = pdb_action_new(state->action_id++); for (i = 0; attribute_names[i]; i++) { if (strcmp(attribute_names[i], "trigger") == 0) pdb_action_set_trigger(state->current_action, attribute_values[i], error); else if (strcmp(attribute_names[i], "condition") == 0) pdb_action_set_condition(state->current_action, state->cfg, attribute_values[i], error); else if (strcmp(attribute_names[i], "rate") == 0) pdb_action_set_rate(state->current_action, attribute_values[i]); } _push_state(state, PDBL_RULE_ACTION); } else { pdb_loader_set_error(state, error, "Unexpected <%s> tag, expected a ", element_name); } } /* PDBL_RULE_ACTION */ static void _pdbl_rule_action_start(PDBLoader *state, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, GError **error) { if (strcmp(element_name, "message") == 0) { state->current_action->content_type = RAC_MESSAGE; _process_message_element(state, attribute_names, attribute_values, &state->current_action->content.message, error); } else if (strcmp(element_name, "create-context") == 0) { state->current_action->content_type = RAC_CREATE_CONTEXT; _process_create_context_element(state, attribute_names, attribute_values, &state->current_action->content.create_context.context, error); } else { pdb_loader_set_error(state, error, "Unexpected <%s> tag, expected or ", element_name); } } /* PDBL_RULE_ACTION_CREATE_CONTEXT */ static void _pdbl_rule_action_create_context_start(PDBLoader *state, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, GError **error) { if (strcmp(element_name, "message") == 0) { _process_message_element(state, attribute_names, attribute_values, &state->current_action->content.create_context.message, error); } else { pdb_loader_set_error(state, error, "Unexpected <%s> tag, expected ", element_name); } } /* PDBL_MESSAGE */ static void _pdbl_message_start(PDBLoader *state, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, GError **error) { if (strcmp(element_name, "values") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "value") == 0) { _process_value_element(state, attribute_names, attribute_values, error); } else if (strcmp(element_name, "tags") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "tag") == 0) { _process_tag_element(state, attribute_names, attribute_values, error); } else { pdb_loader_set_error(state, error, "Unexpected <%s> tag, expected a , , or ", element_name); } } /* PDBL_RULE_PATTERN */ static gboolean _pdbl_rule_pattern_text(PDBLoader *state, const gchar *text, gsize text_len, GError **error) { PDBProgramPattern program_pattern; program_pattern.pattern = g_strdup(text); program_pattern.rule = pdb_rule_ref(state->current_rule); g_array_append_val(state->program_patterns, program_pattern); return TRUE; } /* PDBL_RULE_ACTION */ static void _pdbl_rule_action_end(PDBLoader *state, const gchar *element_name, GError **error) { if (_pop_state_for_closing_tag(state, element_name, "action", error)) { pdb_rule_add_action(state->current_rule, state->current_action); state->current_action = NULL; } } /* PDBL_MESSAGE */ static void _pdbl_message_end(PDBLoader *state, const gchar *element_name, GError **error) { if (strcmp(element_name, "values") == 0) { /* valid, but we don't do anything */ } else if (strcmp(element_name, "tags") == 0) { /* valid, but we don't do anything */ } else if (_pop_state_for_closing_tag_with_alternatives(state, element_name, "message", ", ", error)) { state->current_message = &state->current_rule->msg; } } /* PDBL_VALUE */ static void _pdbl_value_end(PDBLoader *state, const gchar *element_name, GError **error) { if (_pop_state_for_closing_tag(state, element_name, "value", error)) { if (state->value_name) g_free(state->value_name); state->value_name = NULL; } } static gboolean _pdbl_value_text(PDBLoader *state, const gchar *text, gsize text_len, GError **error) { GError *err = NULL; g_assert(state->value_name != NULL); if (!synthetic_message_add_value_template_string(state->current_message, state->cfg, state->value_name, text, &err)) { pdb_loader_set_error(state, error, "Error compiling value template, rule=%s, name=%s, value=%s, error=%s", state->current_rule->rule_id, state->value_name, text, err->message); return FALSE; } return TRUE; } /* PDBL_TAG */ static gboolean _pdbl_tag_text(PDBLoader *state, const gchar *text, gsize text_len, GError **error) { synthetic_message_add_tag(state->current_message, text); return TRUE; } /* element start callback */ void pdb_loader_start_element(GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, GError **error) { PDBLoader *state = (PDBLoader *) user_data; switch (state->current_state) { case PDBL_INITIAL: _pdbl_initial_start(state, element_name, attribute_names, attribute_values, error); break; case PDBL_PATTERNDB: _pdbl_patterndb_start(state, element_name, error); break; case PDBL_RULESET: _pdbl_ruleset_start(state, element_name, error); break; case PDBL_RULES: _pdbl_rules_start(state, element_name, attribute_names, attribute_values, error); break; case PDBL_RULE: _pdbl_rule_start(state, element_name, attribute_names, attribute_values, error); break; case PDBL_RULE_EXAMPLES: _pdbl_rule_examples_start(state, element_name, error); break; case PDBL_RULE_EXAMPLE: _pdbl_rule_example_start(state, element_name, attribute_names, attribute_values, error); break; case PDBL_RULE_EXAMPLE_TEST_VALUES: _pdbl_rule_example_test_values_start(state, element_name, attribute_names, attribute_values, error); break; case PDBL_RULE_ACTIONS: _pdbl_rule_actions_start(state, element_name, attribute_names, attribute_values, error); break; case PDBL_RULE_ACTION: _pdbl_rule_action_start(state, element_name, attribute_names, attribute_values, error); break; case PDBL_RULE_ACTION_CREATE_CONTEXT: _pdbl_rule_action_create_context_start(state, element_name, attribute_names, attribute_values, error); break; /* generic states reused by multiple locations in the grammar */ case PDBL_MESSAGE: _pdbl_message_start(state, element_name, attribute_names, attribute_values, error); break; default: pdb_loader_set_error(state, error, "Unexpected state %d, tag <%s>", state->current_state, element_name); break; } } void pdb_loader_end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error) { PDBLoader *state = (PDBLoader *) user_data; switch (state->current_state) { case PDBL_PATTERNDB: _pdbl_patterndb_end(state, element_name, error); break; case PDBL_RULESET: _pdbl_ruleset_end(state, element_name, error); break; case PDBL_RULESET_URL: _pop_state_for_closing_tag(state, element_name, "url", error); break; case PDBL_RULESET_PATTERN: _pop_state_for_closing_tag(state, element_name, "pattern", error); break; case PDBL_RULESET_DESCRIPTION: _pop_state_for_closing_tag(state, element_name, "description", error); break; case PDBL_RULES: _pop_state_for_closing_tag(state, element_name, "rules", error); break; case PDBL_RULE: _pdbl_rule_end(state, element_name, error); break; case PDBL_RULE_DESCRIPTION: _pop_state_for_closing_tag(state, element_name, "description", error); break; case PDBL_RULE_URL: _pop_state_for_closing_tag(state, element_name, "url", error); break; case PDBL_RULE_PATTERN: _pop_state_for_closing_tag(state, element_name, "pattern", error); break; case PDBL_RULE_EXAMPLES: _pop_state_for_closing_tag(state, element_name, "examples", error); break; case PDBL_RULE_EXAMPLE: _pdbl_rule_example_end(state, element_name, error); break; case PDBL_RULE_EXAMPLE_TEST_VALUES: _pop_state_for_closing_tag(state, element_name, "test_values", error); break; case PDBL_RULE_EXAMPLE_TEST_VALUE: _pdbl_rule_example_test_value_end(state, element_name, error); break; case PDBL_RULE_EXAMPLE_TEST_MESSAGE: _pop_state_for_closing_tag(state, element_name, "test_message", error); break; case PDBL_RULE_ACTIONS: _pop_state_for_closing_tag(state, element_name, "actions", error); break; case PDBL_RULE_ACTION: _pdbl_rule_action_end(state, element_name, error); break; case PDBL_RULE_ACTION_CREATE_CONTEXT: _pop_state_for_closing_tag(state, element_name, "create-context", error); break; /* generic states reused by multiple locations in the grammar */ case PDBL_MESSAGE: _pdbl_message_end(state, element_name, error); break; case PDBL_VALUE: _pdbl_value_end(state, element_name, error); break; case PDBL_TAG: _pop_state_for_closing_tag(state, element_name, "tag", error); break; default: pdb_loader_set_error(state, error, "Unexpected state %d, tag ", state->current_state, element_name); break; } } void pdb_loader_text(GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error) { PDBLoader *state = (PDBLoader *) user_data; switch (state->current_state) { case PDBL_RULESET_DESCRIPTION: break; case PDBL_RULESET_PATTERN: if (!_pdbl_ruleset_pattern_text(state, text, text_len, error)) return; break; case PDBL_RULESET_URL: break; case PDBL_RULE_PATTERN: if (!_pdbl_rule_pattern_text(state, text, text_len, error)) return; break; case PDBL_RULE_EXAMPLE: break; case PDBL_RULE_URL: break; case PDBL_RULE_DESCRIPTION: break; case PDBL_RULE_EXAMPLE_TEST_MESSAGE: if (!_pdbl_rule_example_test_message_text(state, text, text_len, error)) return; break; case PDBL_RULE_EXAMPLE_TEST_VALUE: if (!_pdbl_rule_example_test_value_text(state, text, text_len, error)) return; break; /* generic states reused by multiple locations in the grammar */ case PDBL_VALUE: if (!_pdbl_value_text(state, text, text_len, error)) return; break; case PDBL_TAG: if (!_pdbl_tag_text(state, text, text_len, error)) return; break; default: if (!_is_whitespace_only(text, text_len)) pdb_loader_set_error(state, error, "Unexpected text node in state %d, text=[[%s]]", state->current_state, text); break; } } static GMarkupParser db_parser = { .start_element = pdb_loader_start_element, .end_element = pdb_loader_end_element, .text = pdb_loader_text, .passthrough = NULL, .error = NULL }; gboolean pdb_rule_set_load(PDBRuleSet *self, GlobalConfig *cfg, const gchar *config, GList **examples) { PDBLoader state; GMarkupParseContext *parse_ctx = NULL; GError *error = NULL; FILE *dbfile = NULL; gint bytes_read; gchar buff[4096]; gboolean success = FALSE; if ((dbfile = fopen(config, "r")) == NULL) { msg_error("Error opening classifier configuration file", evt_tag_str(EVT_TAG_FILENAME, config), evt_tag_errno(EVT_TAG_OSERROR, errno)); return FALSE; } memset(&state, 0x0, sizeof(state)); state.ruleset = self; state.root_program = pdb_program_new(); state.load_examples = !!examples; state.ruleset_patterns = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) pdb_program_unref); state.cfg = cfg; state.filename = config; state.context = parse_ctx = g_markup_parse_context_new(&db_parser, 0, &state, NULL); self->programs = r_new_node("", state.root_program); while ((bytes_read = fread(buff, sizeof(gchar), 4096, dbfile)) != 0) { if (!g_markup_parse_context_parse(parse_ctx, buff, bytes_read, &error)) { msg_error("Error parsing pattern database file", evt_tag_str(EVT_TAG_FILENAME, config), evt_tag_str("error", error ? error->message : "unknown")); goto error; } } fclose(dbfile); dbfile = NULL; if (!g_markup_parse_context_end_parse(parse_ctx, &error)) { msg_error("Error parsing pattern database file", evt_tag_str(EVT_TAG_FILENAME, config), evt_tag_str("error", error ? error->message : "unknown")); goto error; } if (state.load_examples) *examples = state.examples; success = TRUE; error: if (dbfile) fclose(dbfile); if (parse_ctx) g_markup_parse_context_free(parse_ctx); g_hash_table_unref(state.ruleset_patterns); return success; } syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-load.h000066400000000000000000000023061321171025300225430ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_PDB_LOAD_H_INCLUDED #define PATTERNDB_PDB_LOAD_H_INCLUDED #include "syslog-ng.h" #include "pdb-ruleset.h" #include "cfg.h" gboolean pdb_rule_set_load(PDBRuleSet *self, GlobalConfig *cfg, const gchar *config, GList **examples); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-lookup-params.h000066400000000000000000000027121321171025300244170ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_PDB_LOOKUP_PARAMS_H_INCLUDED #define PATTERNDB_PDB_LOOKUP_PARAMS_H_INCLUDED typedef struct _PDBLookupParams PDBLookupParams; struct _PDBLookupParams { LogMessage *msg; NVHandle program_handle; NVHandle message_handle; const gchar *message_string; gssize message_len; }; static inline void pdb_lookup_params_init(PDBLookupParams *lookup, LogMessage *msg) { lookup->msg = msg; lookup->program_handle = LM_V_PROGRAM; lookup->message_handle = LM_V_MESSAGE; lookup->message_len = 0; } #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-program.c000066400000000000000000000031651321171025300232720ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "pdb-program.h" #include "pdb-rule.h" /* * Database based parser. The patterns are stored in an XML database. * Data structure is: * - Parser -> programs -> rules -> patterns */ PDBProgram * pdb_program_new(void) { PDBProgram *self = g_new0(PDBProgram, 1); self->rules = r_new_node((guint8 *) "", NULL); self->ref_cnt = 1; return self; } PDBProgram * pdb_program_ref(PDBProgram *self) { self->ref_cnt++; return self; } void pdb_program_unref(PDBProgram *s) { PDBProgram *self = (PDBProgram *) s; if (--self->ref_cnt == 0) { if (self->rules) r_free_node(self->rules, (void (*)(void *)) pdb_rule_unref); g_free(self); } } syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-program.h000066400000000000000000000027741321171025300233040ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_PDB_PROGRAM_H_INCLUDED #define PATTERNDB_PDB_PROGRAM_H_INCLUDED #include "syslog-ng.h" #include "radix.h" /* * This class encapsulates a set of program related rules in the * pattern database. Its instances are stored as "value" in the * program name RADIX tree. It basically contains another RADIX for * the per-program patterns. */ typedef struct _PDBProgram { guint ref_cnt; RNode *rules; } PDBProgram; PDBProgram *pdb_program_new(void); PDBProgram *pdb_program_ref(PDBProgram *self); void pdb_program_unref(PDBProgram *s); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-ratelimit.c000066400000000000000000000034531321171025300236150ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "pdb-ratelimit.h" #include /*************************************************************************** * PDBRateLimit ***************************************************************************/ PDBRateLimit * pdb_rate_limit_new(CorrellationKey *key) { PDBRateLimit *self = g_new0(PDBRateLimit, 1); memcpy(&self->key, key, sizeof(*key)); if (self->key.pid) self->key.pid = g_strdup(self->key.pid); if (self->key.program) self->key.program = g_strdup(self->key.program); if (self->key.host) self->key.host = g_strdup(self->key.host); return self; } void pdb_rate_limit_free(PDBRateLimit *self) { if (self->key.host) g_free((gchar *) self->key.host); if (self->key.program) g_free((gchar *) self->key.program); if (self->key.pid) g_free((gchar *) self->key.pid); g_free(self->key.session_id); g_free(self); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-ratelimit.h000066400000000000000000000027351321171025300236240ustar00rootroot00000000000000/* * Copyright (c) 2002-2017 Balabit * Copyright (c) 1998-2017 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_PDB_RATELIMIT_H_INCLUDED #define PATTERNDB_PDB_RATELIMIT_H_INCLUDED #include "correllation-key.h" /* This class encapsulates a rate-limit state stored in db->state. */ typedef struct _PDBRateLimit { /* key in the hashtable. NOTE: host/program/pid/session_id are allocated, thus they need to be freed when the structure is freed. */ CorrellationKey key; gint buckets; guint64 last_check; } PDBRateLimit; PDBRateLimit *pdb_rate_limit_new(CorrellationKey *key); void pdb_rate_limit_free(PDBRateLimit *self); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-rule.c000066400000000000000000000050641321171025300225720ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "pdb-rule.h" #include "pdb-error.h" void pdb_rule_set_class(PDBRule *self, const gchar *class) { gchar class_tag_text[32]; if (self->class) { g_free(self->class); } else { g_snprintf(class_tag_text, sizeof(class_tag_text), ".classifier.%s", class); synthetic_message_add_tag(&self->msg, class_tag_text); } self->class = class ? g_strdup(class) : NULL; } void pdb_rule_set_rule_id(PDBRule *self, const gchar *rule_id) { if (self->rule_id) g_free(self->rule_id); self->rule_id = g_strdup(rule_id); } void pdb_rule_add_action(PDBRule *self, PDBAction *action) { if (!self->actions) self->actions = g_ptr_array_new(); g_ptr_array_add(self->actions, action); } gchar * pdb_rule_get_name(PDBRule *self) { if (self) return self->rule_id; else return NULL; } PDBRule * pdb_rule_new(void) { PDBRule *self = g_new0(PDBRule, 1); g_atomic_counter_set(&self->ref_cnt, 1); synthetic_context_init(&self->context); synthetic_message_init(&self->msg); return self; } PDBRule * pdb_rule_ref(PDBRule *self) { g_atomic_counter_inc(&self->ref_cnt); return self; } void pdb_rule_unref(PDBRule *self) { if (g_atomic_counter_dec_and_test(&self->ref_cnt)) { if (self->actions) { g_ptr_array_foreach(self->actions, (GFunc) pdb_action_free, NULL); g_ptr_array_free(self->actions, TRUE); } if (self->rule_id) g_free(self->rule_id); if (self->class) g_free(self->class); synthetic_context_deinit(&self->context); synthetic_message_deinit(&self->msg); g_free(self); } } syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-rule.h000066400000000000000000000034511321171025300225750ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_PDB_RULE_H_INCLUDED #define PATTERNDB_PDB_RULE_H_INCLUDED #include "syslog-ng.h" #include "pdb-action.h" /* this class encapsulates a the verdict of a rule in the pattern * database and is stored as the "value" member in the RADIX tree * node. It contains a reference the the original rule in the rule * database. */ typedef struct _PDBRule PDBRule; struct _PDBRule { GAtomicCounter ref_cnt; gchar *class; gchar *rule_id; SyntheticMessage msg; SyntheticContext context; GPtrArray *actions; }; void pdb_rule_set_class(PDBRule *self, const gchar *class); void pdb_rule_set_rule_id(PDBRule *self, const gchar *rule_id); void pdb_rule_add_action(PDBRule *self, PDBAction *action); gchar *pdb_rule_get_name(PDBRule *self); PDBRule *pdb_rule_new(void); PDBRule *pdb_rule_ref(PDBRule *self); void pdb_rule_unref(PDBRule *self); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-ruleset.c000066400000000000000000000135771321171025300233160ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "pdb-ruleset.h" #include "pdb-program.h" #include "pdb-lookup-params.h" static NVHandle class_handle = 0; static NVHandle rule_id_handle = 0; static LogTagId system_tag; static LogTagId unknown_tag; /** * _add_matches_to_message: * * Adds the values from the given GArray of RParserMatch entries to the NVTable * of the passed LogMessage. * * @msg: the LogMessage to add the matches to * @matches: an array of RParserMatch entries * @ref_handle: if the matches are indirect matches, they are referenced based on this handle (eg. LM_V_MESSAGE) **/ static void _add_matches_to_message(LogMessage *msg, GArray *matches, NVHandle ref_handle, const gchar *input_string) { gint i; for (i = 0; i < matches->len; i++) { RParserMatch *match = &g_array_index(matches, RParserMatch, i); if (match->match) { log_msg_set_value(msg, match->handle, match->match, match->len); g_free(match->match); } else if (ref_handle != LM_V_NONE && log_msg_is_handle_settable_with_an_indirect_value(match->handle)) { log_msg_set_value_indirect(msg, match->handle, ref_handle, match->type, match->ofs, match->len); } else { log_msg_set_value(msg, match->handle, input_string + match->ofs, match->len); } } } /* * Looks up a matching rule in the ruleset. * * NOTE: it also modifies @msg to store the name-value pairs found during lookup, so */ PDBRule * pdb_ruleset_lookup(PDBRuleSet *rule_set, PDBLookupParams *lookup, GArray *dbg_list) { RNode *node; LogMessage *msg = lookup->msg; GArray *prg_matches, *matches; const gchar *program_value; gssize program_len; if (G_UNLIKELY(!rule_set->programs)) return FALSE; program_value = log_msg_get_value(msg, lookup->program_handle, &program_len); prg_matches = g_array_new(FALSE, TRUE, sizeof(RParserMatch)); node = r_find_node(rule_set->programs, (guint8 *) program_value, program_len, prg_matches); if (node) { _add_matches_to_message(msg, prg_matches, lookup->program_handle, program_value); g_array_free(prg_matches, TRUE); PDBProgram *program = (PDBProgram *) node->value; if (program->rules) { RNode *msg_node; const gchar *message; gssize message_len; /* NOTE: We're not using g_array_sized_new as that does not * correctly zero-initialize the new items even if clear_ is TRUE */ matches = g_array_new(FALSE, TRUE, sizeof(RParserMatch)); g_array_set_size(matches, 1); if (lookup->message_handle) { message = log_msg_get_value(msg, lookup->message_handle, &message_len); } else { message = lookup->message_string; message_len = lookup->message_len; } if (G_UNLIKELY(dbg_list)) msg_node = r_find_node_dbg(program->rules, (guint8 *) message, message_len, matches, dbg_list); else msg_node = r_find_node(program->rules, (guint8 *) message, message_len, matches); if (msg_node) { PDBRule *rule = (PDBRule *) msg_node->value; GString *buffer = g_string_sized_new(32); msg_debug("patterndb rule matches", evt_tag_str("rule_id", rule->rule_id)); log_msg_set_value(msg, class_handle, rule->class ? rule->class : "system", -1); log_msg_set_value(msg, rule_id_handle, rule->rule_id, -1); _add_matches_to_message(msg, matches, lookup->message_handle, message); g_array_free(matches, TRUE); if (!rule->class) { log_msg_set_tag_by_id(msg, system_tag); } log_msg_clear_tag_by_id(msg, unknown_tag); g_string_free(buffer, TRUE); pdb_rule_ref(rule); return rule; } else { log_msg_set_value(msg, class_handle, "unknown", 7); log_msg_set_tag_by_id(msg, unknown_tag); } g_array_free(matches, TRUE); } } else { g_array_free(prg_matches, TRUE); } return NULL; } PDBRuleSet * pdb_rule_set_new(void) { PDBRuleSet *self = g_new0(PDBRuleSet, 1); self->is_empty = TRUE; return self; } void pdb_rule_set_free(PDBRuleSet *self) { if (self->programs) r_free_node(self->programs, (GDestroyNotify) pdb_program_unref); if (self->version) g_free(self->version); if (self->pub_date) g_free(self->pub_date); self->programs = NULL; self->version = NULL; self->pub_date = NULL; g_free(self); } void pdb_rule_set_global_init(void) { class_handle = log_msg_get_value_handle(".classifier.class"); rule_id_handle = log_msg_get_value_handle(".classifier.rule_id"); system_tag = log_tags_get_by_name(".classifier.system"); unknown_tag = log_tags_get_by_name(".classifier.unknown"); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdb-ruleset.h000066400000000000000000000027611321171025300233140ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_PDB_RULESET_H_INCLUDED #define PATTERNDB_PDB_RULESET_H_INCLUDED #include "syslog-ng.h" #include "radix.h" #include "pdb-lookup-params.h" #include "pdb-rule.h" /* rules loaded from a pdb file */ typedef struct _PDBRuleSet { RNode *programs; gchar *version; gchar *pub_date; gboolean is_empty; } PDBRuleSet; PDBRule *pdb_ruleset_lookup(PDBRuleSet *rule_set, PDBLookupParams *lookup, GArray *dbg_list); PDBRuleSet *pdb_rule_set_new(void); void pdb_rule_set_free(PDBRuleSet *self); void pdb_rule_set_global_init(void); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdbtool/000077500000000000000000000000001321171025300223525ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdbtool/CMakeLists.txt000066400000000000000000000005731321171025300251170ustar00rootroot00000000000000set(PDBTOOL_SOURCES pdbtool.c) add_executable(pdbtool ${PDBTOOL_SOURCES}) target_link_libraries(pdbtool patterndb) set_target_properties(pdbtool PROPERTIES COMPILE_FLAGS "-Wno-pointer-sign") target_include_directories(pdbtool PRIVATE ${PROJECT_SOURCE_DIR}/modules/dbparser ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) install(TARGETS pdbtool RUNTIME DESTINATION bin) syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdbtool/Makefile.am000066400000000000000000000007221321171025300244070ustar00rootroot00000000000000bin_PROGRAMS += modules/dbparser/pdbtool/pdbtool modules_dbparser_pdbtool_pdbtool_SOURCES = \ modules/dbparser/pdbtool/pdbtool.c modules_dbparser_pdbtool_pdbtool_CPPFLAGS= \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/dbparser \ -I$(top_builddir)/modules/dbparser \ @CFLAGS_NOWARN_POINTER_SIGN@ modules_dbparser_pdbtool_pdbtool_LDADD = \ $(top_builddir)/lib/libsyslog-ng.la \ $(top_builddir)/modules/dbparser/libsyslog-ng-patterndb.la \ @TOOL_DEPS_LIBS@ syslog-ng-syslog-ng-3.13.2/modules/dbparser/pdbtool/pdbtool.c000066400000000000000000001103741321171025300241670ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "syslog-ng.h" #include "messages.h" #include "template/templates.h" #include "patterndb.h" #include "dbparser.h" #include "radix.h" #include "stats/stats-registry.h" #include "plugin.h" #include "filter/filter-expr-parser.h" #include "patternize.h" #include "pdb-example.h" #include "pdb-program.h" #include "pdb-load.h" #include "pdb-file.h" #include "apphook.h" #include "transport/transport-file.h" #include "logproto/logproto-text-server.h" #include "reloc.h" #include "pathutils.h" #include "resolved-configurable-paths.h" #include "crypto.h" #include "compat/openssl_support.h" #include "scratch-buffers.h" #include #include #include #include #include #include #include #define BOOL(x) ((x) ? "TRUE" : "FALSE") static gchar *full_colors[] = { "\33[01;34m", /* blue */ "\33[0;33m", /* brown */ "\33[01;32m", /* green */ "\33[01;31m" /* red */ }; static gchar *empty_colors[] = { "", "", "", "" }; #define COLOR_TRAILING_JUNK 0 #define COLOR_PARSER 1 #define COLOR_LITERAL 2 #define COLOR_PARTIAL 3 static gchar *no_color = "\33[01;0m"; static gchar **colors = empty_colors; static gchar *patterndb_file = PATH_PATTERNDB_FILE; static gboolean color_out = FALSE; typedef struct _PdbToolMergeState { GString *merged; gint version; gboolean in_rule; } PdbToolMergeState; void pdbtool_merge_start_element(GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, GError **error) { PdbToolMergeState *state = (PdbToolMergeState *) user_data; gchar *buff; gint i; if (g_str_equal(element_name, "patterndb")) { for (i = 0; attribute_names[i]; i++) { if (g_str_equal(attribute_names[i], "version")) state->version = strtol(attribute_values[i], NULL, 10); } return; } else if (g_str_equal(element_name, "rule")) state->in_rule = TRUE; if (g_str_equal(element_name, "program")) g_string_append(state->merged, "version == 1 && state->in_rule && g_str_equal(element_name, "pattern")) g_string_append_printf(state->merged, "\n<%s", element_name); else if (state->version == 1 && state->in_rule && g_str_equal(element_name, "url")) g_string_append_printf(state->merged, "\n<%s", element_name); else g_string_append_printf(state->merged, "<%s", element_name); for (i = 0; attribute_names[i]; i++) { buff = g_markup_printf_escaped(" %s='%s'", attribute_names[i], attribute_values[i]); g_string_append_printf(state->merged, "%s", buff); g_free(buff); } g_string_append(state->merged, ">"); } void pdbtool_merge_end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error) { PdbToolMergeState *state = (PdbToolMergeState *) user_data; if (g_str_equal(element_name, "patterndb")) return; else if (g_str_equal(element_name, "rule")) state->in_rule = FALSE; if (g_str_equal(element_name, "program")) g_string_append(state->merged, ""); else if (state->version == 1 && state->in_rule && g_str_equal(element_name, "pattern")) g_string_append_printf(state->merged, "\n", element_name); else if (state->version == 1 && state->in_rule && g_str_equal(element_name, "url")) g_string_append_printf(state->merged, "\n", element_name); else g_string_append_printf(state->merged, "", element_name); } void pdbtool_merge_text(GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error) { PdbToolMergeState *state = (PdbToolMergeState *) user_data; gchar *buff = g_markup_printf_escaped("%s", text); g_string_append(state->merged, buff); g_free(buff); } GMarkupParser pdbtool_merge_parser = { .start_element = pdbtool_merge_start_element, .end_element = pdbtool_merge_end_element, .text = pdbtool_merge_text, .passthrough = NULL, .error = NULL }; static gboolean pdbtool_merge_file(const gchar *filename, GString *merged) { GMarkupParseContext *parse_ctx = NULL; PdbToolMergeState state; GError *error = NULL; gboolean success = TRUE; gchar *buff = NULL; gsize buff_len; if (!g_file_get_contents(filename, &buff, &buff_len, &error)) { fprintf(stderr, "Error reading pattern database file; filename='%s', error='%s'\n", filename, error ? error->message : "Unknown error"); success = FALSE; goto error; } state.version = 0; state.merged = merged; state.in_rule = FALSE; parse_ctx = g_markup_parse_context_new(&pdbtool_merge_parser, 0, &state, NULL); if (!g_markup_parse_context_parse(parse_ctx, buff, buff_len, &error)) { fprintf(stderr, "Error parsing pattern database file; filename='%s', error='%s'\n", filename, error ? error->message : "Unknown error"); success = FALSE; goto error; } if (!g_markup_parse_context_end_parse(parse_ctx, &error)) { fprintf(stderr, "Error parsing pattern database file; filename='%s', error='%s'\n", filename, error ? error->message : "Unknown error"); success = FALSE; goto error; } error: if (buff) g_free(buff); if (parse_ctx) g_markup_parse_context_free(parse_ctx); return success; } static gchar *merge_dir = NULL; static gchar *merge_glob = NULL; static gboolean merge_recursive = FALSE; static gboolean pdbtool_merge_dir(const gchar *dir, gboolean recursive, GString *merged) { GDir *pdb_dir; gboolean ok = TRUE; GError *error = NULL; const gchar *filename; if ((pdb_dir = g_dir_open(dir, 0, &error)) == NULL) { fprintf(stderr, "Error opening directory %s, error='%s'\n", merge_dir, error ? error->message : "Unknown error"); g_clear_error(&error); return FALSE; } while ((filename = g_dir_read_name(pdb_dir)) != NULL && ok) { gchar *full_name = g_build_filename(dir, filename, NULL); if (recursive && is_file_directory(full_name)) { ok = pdbtool_merge_dir(full_name, recursive, merged); } else if (is_file_regular(full_name) && (!merge_glob || g_pattern_match_simple(merge_glob, filename))) { ok = pdbtool_merge_file(full_name, merged); } g_free(full_name); } g_dir_close(pdb_dir); return TRUE; } static gint pdbtool_merge(int argc, char *argv[]) { GDate date; GError *error = NULL; GString *merged = NULL; gchar *buff; gboolean ok; if (!merge_dir) { fprintf(stderr, "No directory is specified to merge from\n"); return 1; } if (!patterndb_file) { fprintf(stderr, "No patterndb file is specified to merge to\n"); return 1; } merged = g_string_sized_new(4096); g_date_clear(&date, 1); g_date_set_time_t(&date, time (NULL)); buff = g_markup_printf_escaped("\n", g_date_get_year(&date), g_date_get_month(&date), g_date_get_day(&date)); g_string_append(merged, buff); g_free(buff); ok = pdbtool_merge_dir(merge_dir, merge_recursive, merged); g_string_append(merged, "\n"); if (ok && !g_file_set_contents(patterndb_file, merged->str, merged->len, &error)) { fprintf(stderr, "Error storing patterndb; filename='%s', errror='%s'\n", patterndb_file, error ? error->message : "Unknown error"); ok = FALSE; } g_string_free(merged, TRUE); return ok ? 0 : 1; } static GOptionEntry merge_options[] = { { "pdb", 'p', 0, G_OPTION_ARG_STRING, &patterndb_file, "Name of the patterndb output file", "" }, { "recursive", 'r', 0, G_OPTION_ARG_NONE, &merge_recursive, "Recurse into subdirectories", NULL }, { "glob", 'G', 0, G_OPTION_ARG_STRING, &merge_glob, "Filenames to consider for merging", "" }, { "directory", 'D', 0, G_OPTION_ARG_STRING, &merge_dir, "Directory from merge pattern databases", "" }, { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL } }; static gchar *match_program = NULL; static gchar *match_message = NULL; static gchar *match_file = NULL; static gchar *template_string = NULL; static gchar *filter_string = NULL; static gboolean debug_pattern = FALSE; static gboolean debug_pattern_parse = FALSE; gboolean pdbtool_match_values(NVHandle handle, const gchar *name, const gchar *value, gssize length, gpointer user_data) { gint *ret = user_data; printf("%s=%.*s\n", name, (gint) length, value); if (g_str_equal(name, ".classifier.rule_id") && ret) *ret = 0; if (ret && (g_str_equal(name, ".classifier.class") && g_str_equal(value, "unknown"))) *ret = 1; return FALSE; } static void pdbtool_pdb_emit(LogMessage *msg, gboolean synthetic, gpointer user_data) { gpointer *args = (gpointer *) user_data; FilterExprNode *filter = (FilterExprNode *) args[0]; LogTemplate *template = (LogTemplate *) args[1]; gint *ret = (gint *) args[2]; GString *output = (GString *) args[3]; gboolean matched; matched = !filter || filter_expr_eval(filter, msg); if (matched) { if (G_UNLIKELY(!template)) { if (debug_pattern && !debug_pattern_parse) printf("\nValues:\n"); nv_table_foreach(msg->payload, logmsg_registry, pdbtool_match_values, ret); g_string_truncate(output, 0); log_msg_print_tags(msg, output); printf("TAGS=%s\n", output->str); printf("\n"); } else { log_template_format(template, msg, NULL, LTZ_LOCAL, 0, NULL, output); printf("%s", output->str); } } } static gint pdbtool_match(int argc, char *argv[]) { PatternDB *patterndb; GArray *dbg_list = NULL; RDebugInfo *dbg_info; gint i = 0, pos = 0; gint ret = 0; const gchar *name = NULL; gssize name_len = 0; MsgFormatOptions parse_options; gboolean eof = FALSE; const guchar *buf = NULL; gsize buflen; LogMessage *msg = NULL; LogTemplate *template = NULL; GString *output = NULL; FilterExprNode *filter = NULL; LogProtoServer *proto = NULL; LogProtoServerOptions proto_options; gboolean may_read = TRUE; gpointer args[4]; memset(&parse_options, 0, sizeof(parse_options)); if (!match_message && !match_file) { fprintf(stderr, "Either -M or -f is required to specify which message to match\n"); return ret; } if (template_string) { gchar *t; t = g_strcompress(template_string); template = log_template_new(configuration, NULL); log_template_compile(template, t, NULL); g_free(t); } output = g_string_sized_new(512); if (filter_string) { CfgLexer *lexer; lexer = cfg_lexer_new_buffer(configuration, filter_string, strlen(filter_string)); if (!cfg_run_parser(configuration, lexer, &filter_expr_parser, (gpointer *) &filter, NULL)) { fprintf(stderr, "Error parsing filter expression\n"); return 1; } } msg_format_options_defaults(&parse_options); /* the syslog protocol parser automatically falls back to RFC3164 format */ parse_options.flags |= LP_SYSLOG_PROTOCOL | LP_EXPECT_HOSTNAME; msg_format_options_init(&parse_options, configuration); log_proto_server_options_defaults(&proto_options); proto_options.max_msg_size = 65536; log_proto_server_options_init(&proto_options, configuration); patterndb = pattern_db_new(); if (!pattern_db_reload_ruleset(patterndb, configuration, patterndb_file)) { goto error; } msg = log_msg_new_empty(); if (!match_file) { log_msg_set_value(msg, LM_V_MESSAGE, match_message, strlen(match_message)); if (match_program && match_program[0]) log_msg_set_value(msg, LM_V_PROGRAM, match_program, strlen(match_program)); } else { LogTransport *transport; gint fd; if (strcmp(match_file, "-") == 0) { fd = 0; } else { fd = open(match_file, O_RDONLY); if (fd < 0) { fprintf(stderr, "Error opening file to be processed: %s\n", g_strerror(errno)); goto error; } } transport = log_transport_file_new(fd); proto = log_proto_text_server_new(transport, &proto_options); eof = log_proto_server_fetch(proto, &buf, &buflen, &may_read, NULL, NULL) != LPS_SUCCESS; } if (!debug_pattern) { args[0] = filter; args[1] = template; args[2] = &ret; args[3] = output; pattern_db_set_emit_func(patterndb, pdbtool_pdb_emit, args); } else { dbg_list = g_array_new(FALSE, FALSE, sizeof(RDebugInfo)); } while (!eof && (buf || match_message)) { invalidate_cached_time(); if (G_LIKELY(proto)) { log_msg_unref(msg); msg = log_msg_new_empty(); parse_options.format_handler->parse(&parse_options, buf, buflen, msg); } if (G_UNLIKELY(debug_pattern)) { const gchar *msg_string; pattern_db_debug_ruleset(patterndb, msg, dbg_list); msg_string = log_msg_get_value(msg, LM_V_MESSAGE, NULL); pos = 0; if (!debug_pattern_parse) { printf("Pattern matching part:\n"); for (i = 0; i < dbg_list->len; i++) { dbg_info = &g_array_index(dbg_list, RDebugInfo, i); pos += dbg_info->i; if (dbg_info->pnode) { name = nv_registry_get_handle_name(logmsg_registry, dbg_info->pnode->handle, &name_len); printf("%s@%s:%s=%.*s@%s", colors[COLOR_PARSER], r_parser_type_name(dbg_info->pnode->type), name_len ? name : "", name_len ? dbg_info->match_len : 0, name_len ? msg_string + dbg_info->match_off : "", no_color ); } else if (dbg_info->i == dbg_info->node->keylen) { printf("%s%s%s", colors[COLOR_LITERAL], dbg_info->node->key, no_color); } else { printf("%s%.*s%s", colors[COLOR_PARTIAL], dbg_info->node->key ? dbg_info->i : 0, dbg_info->node->key ? (gchar *) dbg_info->node->key : "", no_color); } } printf("%s%s%s", colors[COLOR_TRAILING_JUNK], msg_string + pos, no_color); printf("\nMatching part:\n"); } if (debug_pattern_parse) printf("PDBTOOL_HEADER=i:len:key;keylen:match_off;match_len:parser_type:parser_name\n"); pos = 0; for (i = 0; i < dbg_list->len; i++) { /* NOTE: if i is smaller than node->keylen than we did not match the full node * so matching failed on this node, we need to highlight it somehow */ dbg_info = &g_array_index(dbg_list, RDebugInfo, i); if (debug_pattern_parse) { if (dbg_info->pnode) name = nv_registry_get_handle_name(logmsg_registry, dbg_info->pnode->handle, &name_len); printf("PDBTOOL_DEBUG=%d:%d:%d:%d:%d:%s:%s\n", i, dbg_info->i, dbg_info->node->keylen, dbg_info->match_off, dbg_info->match_len, dbg_info->pnode ? r_parser_type_name(dbg_info->pnode->type) : "", dbg_info->pnode && name_len ? name : "" ); } else { if (dbg_info->i == dbg_info->node->keylen || dbg_info->pnode) printf("%s%.*s%s", dbg_info->pnode ? colors[COLOR_PARSER] : colors[COLOR_LITERAL], dbg_info->i, msg_string + pos, no_color); else printf("%s%.*s%s", colors[COLOR_PARTIAL], dbg_info->i, msg_string + pos, no_color); pos += dbg_info->i; } } g_array_set_size(dbg_list, 0); dbg_info = NULL; { gpointer nulls[] = { NULL, NULL, &ret, output }; pdbtool_pdb_emit(msg, FALSE, nulls); } } else { pattern_db_process(patterndb, msg); } if (G_LIKELY(proto)) { buf = NULL; eof = log_proto_server_fetch(proto, &buf, &buflen, &may_read, NULL, NULL) != LPS_SUCCESS; } else { eof = TRUE; } } pattern_db_expire_state(patterndb); error: if (proto) log_proto_server_free(proto); if (template) log_template_unref(template); if (output) g_string_free(output, TRUE); pattern_db_free(patterndb); if (msg) log_msg_unref(msg); msg_format_options_destroy(&parse_options); return ret; } static GOptionEntry match_options[] = { { "pdb", 'p', 0, G_OPTION_ARG_STRING, &patterndb_file, "Name of the patterndb file", "" }, { "program", 'P', 0, G_OPTION_ARG_STRING, &match_program, "Program name to match as $PROGRAM", "" }, { "message", 'M', 0, G_OPTION_ARG_STRING, &match_message, "Message to match as $MSG", "" }, { "debug-pattern", 'D', 0, G_OPTION_ARG_NONE, &debug_pattern, "Print debuging information on pattern matching", NULL }, { "debug-csv", 'C', 0, G_OPTION_ARG_NONE, &debug_pattern_parse, "Output debuging information in parseable format", NULL }, { "color-out", 'c', 0, G_OPTION_ARG_NONE, &color_out, "Color terminal output", NULL }, { "template", 'T', 0, G_OPTION_ARG_STRING, &template_string, "Template string to be used to format the output", "template" }, { "file", 'f', 0, G_OPTION_ARG_STRING, &match_file, "Read the messages from the file specified", NULL }, { "filter", 'F', 0, G_OPTION_ARG_STRING, &filter_string, "Only print messages matching the specified syslog-ng filter", "expr" }, { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL } }; static gboolean test_validate = FALSE; static gchar *test_ruleid = NULL; static gboolean pdbtool_test_value(LogMessage *msg, const gchar *name, const gchar *test_value) { const gchar *value; gssize value_len; gboolean ret = TRUE; value = log_msg_get_value_by_name(msg, name, &value_len); if (!(value && strncmp(value, test_value, value_len) == 0 && value_len == strlen(test_value))) { if (value) printf(" Wrong match name='%s', value='%.*s', expected='%s'\n", name, (gint) value_len, value, test_value); else printf(" No value to match name='%s', expected='%s'\n", name, test_value); ret = FALSE; } else if (verbose_flag) printf(" Match name='%s', value='%.*s', expected='%s'\n", name, (gint) value_len, value, test_value); return ret; } static void pdbtool_test_find_conflicts(PatternDB *patterndb, LogMessage *msg) { const gchar *program; const gchar *message; RNode *node; program = log_msg_get_value(msg, LM_V_PROGRAM, NULL); message = log_msg_get_value(msg, LM_V_MESSAGE, NULL); node = r_find_node(pattern_db_get_ruleset(patterndb)->programs, (gchar *) program, strlen(program), NULL); if (node) { PDBProgram *program_rules = (PDBProgram *) node->value; gchar **matching_ids; gint matching_ids_len; matching_ids = r_find_all_applicable_nodes(program_rules->rules, (guint8 *) message, strlen(message), (RNodeGetValueFunc) pdb_rule_get_name); matching_ids_len = g_strv_length(matching_ids); if (matching_ids_len > 1) { gint i; printf(" Rule conflict! Multiple rules match this message, list of IDs follow\n"); for (i = 0; matching_ids[i]; i++) { printf(" %s\n", matching_ids[i]); } } g_strfreev(matching_ids); } } static gint pdbtool_test(int argc, char *argv[]) { PatternDB *patterndb; PDBExample *example; LogMessage *msg; GList *examples = NULL; gint i, arg_pos; gboolean failed_to_load = FALSE; gboolean failed_to_match = FALSE; gboolean failed_to_validate = FALSE; gboolean failed_to_find_id = TRUE; for (arg_pos = 1; arg_pos < argc; arg_pos++) { if (access(argv[arg_pos], R_OK) == -1) { fprintf(stderr, "%s: Unable to access the patterndb file\n", argv[arg_pos]); failed_to_validate = TRUE; continue; } if (test_validate) { GError *error = NULL; if (!pdb_file_validate(argv[arg_pos], &error)) { fprintf(stderr, "%s: error validating pdb file: %s\n", argv[arg_pos], error->message); g_clear_error(&error); failed_to_validate = TRUE; continue; } } patterndb = pattern_db_new(); if (!pdb_rule_set_load(pattern_db_get_ruleset(patterndb), configuration, argv[arg_pos], &examples)) { failed_to_load = TRUE; continue; } while (examples) { example = examples->data; if (example->message && example->program) { if (test_ruleid) { if (strcmp(example->rule->rule_id, test_ruleid) != 0) { pdb_example_free(example); examples = g_list_delete_link(examples, examples); continue; } else failed_to_find_id = FALSE; } msg = log_msg_new_empty(); log_msg_set_value(msg, LM_V_MESSAGE, example->message, strlen(example->message)); if (example->program && example->program[0]) log_msg_set_value(msg, LM_V_PROGRAM, example->program, strlen(example->program)); printf("Testing message: program='%s' message='%s'\n", example->program, example->message); pdbtool_test_find_conflicts(patterndb, msg); pattern_db_process(patterndb, msg); if (!pdbtool_test_value(msg, ".classifier.rule_id", example->rule->rule_id)) { failed_to_match = TRUE; if (debug_pattern) { match_message = example->message; match_program = example->program; patterndb_file = argv[arg_pos]; pdbtool_match(0, NULL); } } for (i = 0; example->values && i < example->values->len; i++) { gchar **nv = g_ptr_array_index(example->values, i); if (!pdbtool_test_value(msg, nv[0], nv[1])) failed_to_match = TRUE; } log_msg_unref(msg); } else if (!example->program && example->message) { printf("NOT Testing message as program is unset: message='%s'\n", example->message); } else if (example->program && !example->message) { printf("NOT Testing message as message is unset: program='%s'\n", example->program); } pdb_example_free(example); examples = g_list_delete_link(examples, examples); } pattern_db_free(patterndb); } if (failed_to_load || failed_to_validate) return 1; if (failed_to_match) return 2; if (failed_to_find_id && test_ruleid) { printf("Could not find the specified ID, or the defined rule doesn't have an example message.\n"); return 3; } return 0; } static GOptionEntry test_options[] = { { "validate", 0, 0, G_OPTION_ARG_NONE, &test_validate, "Validate the pdb file against the xsd (requires xmllint from libxml2)", NULL }, { "rule-id", 'r', 0, G_OPTION_ARG_STRING, &test_ruleid, "Rule ID of the patterndb rule to be tested against its example", NULL }, { "debug", 'D', 0, G_OPTION_ARG_NONE, &debug_pattern, "Print debuging information on non-matching patterns", NULL }, { "color-out", 'c', 0, G_OPTION_ARG_NONE, &color_out, "Color terminal output", NULL }, { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL } }; static gboolean dump_program_tree = FALSE; void pdbtool_walk_tree(RNode *root, gint level, gboolean program) { gint i; for (i = 0; i < level; i++) printf(" "); if (root->parser) printf("@%s:%s@ ", r_parser_type_name(root->parser->type), log_msg_get_value_name(root->parser->handle, NULL)); printf("'%s' ", root->key ? (gchar *) root->key : ""); if (root->value) { if (!program) printf("rule_id='%s'", ((PDBRule *) root->value)->rule_id); else printf("RULES"); } printf("\n"); for (i = 0; i < root->num_children; i++) pdbtool_walk_tree(root->children[i], level + 1, program); for (i = 0; i < root->num_pchildren; i++) pdbtool_walk_tree(root->pchildren[i], level + 1, program); } static gint pdbtool_dump(int argc, char *argv[]) { PatternDB *patterndb; patterndb = pattern_db_new(); if (!pattern_db_reload_ruleset(patterndb, configuration, patterndb_file)) return 1; if (dump_program_tree) pdbtool_walk_tree(pattern_db_get_ruleset(patterndb)->programs, 0, TRUE); else if (match_program) { RNode *ruleset = r_find_node(pattern_db_get_ruleset(patterndb)->programs, match_program, strlen(match_program), NULL); if (ruleset && ruleset->value) { RNode *root = ((PDBProgram *) ruleset->value)->rules; if (root) pdbtool_walk_tree(root, 0, FALSE); } } else { fprintf(stderr, "Neither --program-tree nor --program was specified, doing nothing\n"); } pattern_db_free(patterndb); return 0; } static GOptionEntry dump_options[] = { { "pdb", 'p', 0, G_OPTION_ARG_STRING, &patterndb_file, "Name of the patterndb file", "" }, { "program", 'P', 0, G_OPTION_ARG_STRING, &match_program, "Program name ($PROGRAM) to dump", "" }, { "program-tree", 'T', 0, G_OPTION_ARG_NONE, &dump_program_tree, "Dump the program ($PROGRAM) tree", NULL }, { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL } }; static gboolean dictionary_tags = FALSE; static void pdbtool_dictionary_walk(RNode *root, const gchar *progname) { gint i; if (root->parser && root->parser->handle && !dictionary_tags) printf("%s\n", log_msg_get_value_name(root->parser->handle, NULL)); if (root->value) { if (!progname) { pdbtool_dictionary_walk(((PDBProgram *)root->value)->rules, (gchar *)root->key); } else { PDBRule *rule = (PDBRule *)root->value; LogTemplate *template; guint tag_id; if (!dictionary_tags && rule->msg.values) { for (i = 0; i < rule->msg.values->len; i++) { template = (LogTemplate *)g_ptr_array_index(rule->msg.values, i); printf("%s\n", template->name); } } if (dictionary_tags && rule->msg.tags) { for (i = 0; i < rule->msg.tags->len; i++) { tag_id = g_array_index(rule->msg.tags, guint, i); printf("%s\n", log_tags_get_by_id(tag_id)); } } } } for (i = 0; i < root->num_children; i++) pdbtool_dictionary_walk(root->children[i], progname); for (i = 0; i < root->num_pchildren; i++) pdbtool_dictionary_walk(root->pchildren[i], progname); } static GOptionEntry dictionary_options[] = { { "pdb", 'p', 0, G_OPTION_ARG_STRING, &patterndb_file, "Name of the patterndb file", "" }, { "program", 'P', 0, G_OPTION_ARG_STRING, &match_program, "Program name ($PROGRAM) to dump", "" }, { "dump-tags", 'T', 0, G_OPTION_ARG_NONE, &dictionary_tags, "Dump the tags in the rules instead of the value names", NULL }, { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL } }; static gint pdbtool_dictionary(int argc, char *argv[]) { PDBRuleSet rule_set; memset(&rule_set, 0x0, sizeof(PDBRuleSet)); if (!pdb_rule_set_load(&rule_set, configuration, patterndb_file, NULL)) return 1; if (match_program) { RNode *ruleset = r_find_node(rule_set.programs, match_program, strlen(match_program), NULL); if (ruleset && ruleset->value) pdbtool_dictionary_walk(((PDBProgram *)ruleset->value)->rules, (gchar *)ruleset->key); } else pdbtool_dictionary_walk(rule_set.programs, NULL); return 0; } static gboolean pdbtool_load_module(const gchar *option_name, const gchar *value, gpointer data, GError **error) { return cfg_load_module(configuration, value); } static gchar *input_logfile = NULL; static gboolean no_parse = FALSE; static gdouble support_treshold = 4.0; static gboolean iterate_outliers = FALSE; static gboolean named_parsers = FALSE; static gint num_of_samples = 1; static gchar *delimiters = " :&~?![]=,;()'\""; static gint pdbtool_patternize(int argc, char *argv[]) { Patternizer *ptz; GHashTable *clusters; guint iterate = PTZ_ITERATE_NONE; gint i; GError *error = NULL; GString *delimcheck = g_string_new(" "); /* delims should always include a space */ if (iterate_outliers) iterate = PTZ_ITERATE_OUTLIERS; /* make sure that every character is unique in the delimiter list */ for (i = 0; delimiters[i]; i++) { if (strchr(delimcheck->str, delimiters[i]) == NULL) g_string_append_c(delimcheck, delimiters[i]); } delimiters = g_strdup(delimcheck->str); g_string_free(delimcheck, TRUE); if (!(ptz = ptz_new(support_treshold, PTZ_ALGO_SLCT, iterate, num_of_samples, delimiters))) { return 1; } argv[0] = input_logfile; for (i = 0; i < argc; i++) { if (argv[i] && !ptz_load_file(ptz, argv[i], no_parse, &error)) { fprintf(stderr, "Error adding log file as patternize input: %s\n", error->message); g_clear_error(&error); goto exit; } } clusters = ptz_find_clusters(ptz); ptz_print_patterndb(clusters, delimiters, named_parsers); g_hash_table_destroy(clusters); exit: ptz_free(ptz); return 0; } static GOptionEntry patternize_options[] = { { "file", 'f', 0, G_OPTION_ARG_STRING, &input_logfile, "Logfile to create pattern database from, use '-' for stdin", "" }, { "no-parse", 'p', 0, G_OPTION_ARG_NONE, &no_parse, "Do try to parse the input file, consider the whole lines as the message part of the log", NULL }, { "support", 'S', 0, G_OPTION_ARG_DOUBLE, &support_treshold, "Percentage of lines that have to support a pattern (default: 4.0)", "" }, { "iterate-outliers", 'o', 0, G_OPTION_ARG_NONE, &iterate_outliers, "Recursively iterate on the log lines that do not make it into a cluster in the previous step", NULL }, { "named-parsers", 'n', 0, G_OPTION_ARG_NONE, &named_parsers, "Give the parsers a name in the patterns, eg.: .dict.string1, .dict.string2... (default: no)", NULL }, { "delimiters", 'd', 0, G_OPTION_ARG_STRING, &delimiters, "Set of characters based on which the log messages are tokenized, defaults to :&~?![]=,;()'\"", "" }, { "samples", 0, 0, G_OPTION_ARG_INT, &num_of_samples, "Number of example lines to add for the patterns (default: 1)", "" }, { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL } }; const gchar * pdbtool_mode(int *argc, char **argv[]) { gint i; const gchar *mode; for (i = 1; i < (*argc); i++) { if ((*argv)[i][0] != '-') { mode = (*argv)[i]; memmove(&(*argv)[i], &(*argv)[i+1], ((*argc) - i) * sizeof(gchar *)); (*argc)--; return mode; } } return NULL; } static GOptionEntry pdbtool_options[] = { { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug_flag, "Enable debug/diagnostic messages on stderr", NULL }, { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose_flag, "Enable verbose messages on stderr", NULL }, { "module", 0, 0, G_OPTION_ARG_CALLBACK, pdbtool_load_module, "Load the module specified as parameter", "" }, { "module-path", 0, 0, G_OPTION_ARG_STRING, &resolvedConfigurablePaths.initial_module_path, "Set the list of colon separated directories to search for modules, default=" SYSLOG_NG_MODULE_PATH, "" }, { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL } }; static struct { const gchar *mode; const GOptionEntry *options; const gchar *description; gint (*main)(gint argc, gchar *argv[]); } modes[] = { { "match", match_options, "Match a message against the pattern database", pdbtool_match }, { "dump", dump_options, "Dump pattern datebase tree", pdbtool_dump }, { "merge", merge_options, "Merge pattern databases", pdbtool_merge }, { "test", test_options, "Test pattern databases", pdbtool_test }, { "patternize", patternize_options, "Create a pattern database from logs", pdbtool_patternize }, { "dictionary", dictionary_options, "Dump pattern dictionary", pdbtool_dictionary }, { NULL, NULL }, }; void usage(void) { gint mode; fprintf(stderr, "Syntax: pdbtool [options]\nPossible commands are:\n"); for (mode = 0; modes[mode].mode; mode++) { fprintf(stderr, " %-12s %s\n", modes[mode].mode, modes[mode].description); } exit(1); } int main(int argc, char *argv[]) { const gchar *mode_string; GOptionContext *ctx; gint mode, ret = 0; GError *error = NULL; mode_string = pdbtool_mode(&argc, &argv); if (!mode_string) { usage(); } ctx = NULL; for (mode = 0; modes[mode].mode; mode++) { if (strcmp(modes[mode].mode, mode_string) == 0) { ctx = g_option_context_new(mode_string); g_option_context_set_summary(ctx, modes[mode].description); g_option_context_add_main_entries(ctx, modes[mode].options, NULL); g_option_context_add_main_entries(ctx, pdbtool_options, NULL); msg_add_option_group(ctx); break; } } if (!ctx) { fprintf(stderr, "Unknown command\n"); usage(); } setlocale(LC_ALL, ""); msg_init(TRUE); resolved_configurable_paths_init(&resolvedConfigurablePaths); stats_init(); scratch_buffers_global_init(); scratch_buffers_allocator_init(); log_msg_global_init(); log_template_global_init(); log_tags_global_init(); pattern_db_global_init(); crypto_init(); configuration = cfg_new_snippet(); if (!g_option_context_parse(ctx, &argc, &argv, &error)) { fprintf(stderr, "Error parsing command line arguments: %s\n", error ? error->message : "Invalid arguments"); g_clear_error(&error); g_option_context_free(ctx); return 1; } g_option_context_free(ctx); cfg_load_module(configuration, "syslogformat"); cfg_load_module(configuration, "basicfuncs"); if (color_out) colors = full_colors; ret = modes[mode].main(argc, argv); scratch_buffers_allocator_deinit(); scratch_buffers_global_deinit(); stats_destroy(); log_tags_global_deinit(); log_msg_global_deinit(); cfg_free(configuration); configuration = NULL; crypto_deinit(); msg_deinit(); return ret; } syslog-ng-syslog-ng-3.13.2/modules/dbparser/radix.c000066400000000000000000001145551321171025300221750ustar00rootroot00000000000000/* * Copyright (c) 2002-2013 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "radix.h" #include #include #include /************************************************************** * Parsing nodes. **************************************************************/ /* FIXME: maybe we should return gchar with the result */ gboolean r_parser_string(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { *len = 0; while (str[*len] && (g_ascii_isalnum(str[*len]) || (param && strchr(param, str[*len])))) (*len)++; if (*len > 0) { return TRUE; } return FALSE; } gboolean r_parser_qstring(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { guint8 *end; if ((end = strchr(str + 1, ((gchar *)&state)[0])) != NULL) { *len = (end - str) + 1; if (match) { /* skip starting and ending quote */ match->ofs = 1; match->len = -2; } return TRUE; } else return FALSE; } gboolean r_parser_estring_c(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { guint8 *end; if (!param) return FALSE; if ((end = strchr(str, param[0])) != NULL) { *len = (end - str) + 1; if (match) match->len = -1; return TRUE; } else return FALSE; } gboolean r_parser_nlstring(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { guint8 *end; if ((end = strchr(str, '\n')) != NULL) { /* drop CR before to LF */ if (end - str >= 1 && *(end - 1) == '\r') end--; *len = (end - str); return TRUE; } else return FALSE; } gboolean r_parser_estring(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { guint8 *end; if (!param) return FALSE; if ((end = strstr(str, param)) != NULL) { *len = (end - str) + GPOINTER_TO_INT(state); if (match) match->len = -GPOINTER_TO_INT(state); return TRUE; } else return FALSE; } typedef struct _RParserPCREState { pcre *re; pcre_extra *extra; } RParserPCREState; gboolean r_parser_pcre(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { RParserPCREState *self = (RParserPCREState *) state; gint rc; gint matches[2]; rc = pcre_exec(self->re, self->extra, str, strlen(str), 0, 0, matches, 2); if (rc <= 0) return FALSE; *len = matches[1] - matches[0]; return TRUE; } gpointer r_parser_pcre_compile_state(const gchar *expr) { RParserPCREState *self = g_new0(RParserPCREState, 1); const gchar *errptr; gint erroffset; gint rc; self->re = pcre_compile2(expr, PCRE_ANCHORED, &rc, &errptr, &erroffset, NULL); if (!self->re) { msg_error("Error while compiling regular expression", evt_tag_str("regular_expression", expr), evt_tag_str("error_at", &expr[erroffset]), evt_tag_int("error_offset", erroffset), evt_tag_str("error_message", errptr), evt_tag_int("error_code", rc)); g_free(self); return NULL; } self->extra = pcre_study(self->re, 0, &errptr); if (errptr) { msg_error("Error while optimizing regular expression", evt_tag_str("regular_expression", expr), evt_tag_str("error_message", errptr)); pcre_free(self->re); if (self->extra) pcre_free(self->extra); g_free(self); return NULL; } return (gpointer) self; } static void r_parser_pcre_free_state(gpointer s) { RParserPCREState *self = (RParserPCREState *) s; if (self->re) pcre_free(self->re); if (self->extra) pcre_free(self->extra); g_free(self); } gboolean r_parser_anystring(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { *len = strlen(str); return TRUE; } gboolean r_parser_set(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { *len = 0; if (!param) return FALSE; while (strchr(param, str[*len])) (*len)++; if (*len > 0) { return TRUE; } return FALSE; } gboolean r_parser_email(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { gint end; int count = 0; gchar *email = "!#$%&'*+-/=?^_`{|}~."; *len = 0; if (param) while (strchr(param, str[*len])) (*len)++; if (match) match->ofs = *len; /* first character of e-mail can not be a period */ if (str[*len] == '.') return FALSE; while (g_ascii_isalnum(str[*len]) || (strchr(email, str[*len]))) (*len)++; /* last character of e-mail can not be a period */ if (str[*len-1] == '.') return FALSE; if (str[*len] == '@' ) (*len)++; else return FALSE; /* Be accepting of any hostnames - if they are in the logs, they probably were in the DNS */ while (g_ascii_isalnum(str[*len]) || (str[*len] == '-' )) { (*len)++; count++; while (g_ascii_isalnum(str[*len]) || (str[*len] == '-' )) (*len)++; if (str[*len] == '.') (*len)++; } if (count < 2) return FALSE; end = *len; if (param) while (strchr(param, str[*len])) (*len)++; if (match) match->len = end - *len - match->ofs; if (*len > 0) return TRUE; return FALSE; } gboolean r_parser_hostname(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { int count = 0; *len = 0; while (g_ascii_isalnum(str[*len]) || (str[*len] == '-' )) { (*len)++; count++; while (g_ascii_isalnum(str[*len]) || (str[*len] == '-' )) (*len)++; if (str[*len] == '.') (*len)++; } if (count < 2) return FALSE; return TRUE; } static gboolean _r_parser_lladdr(guint8 *str, gint *len, gint count, gint parts, gpointer state, RParserMatch *match) { gint i; *len = 0; for (i = 1; i <= parts; i++) { if (!g_ascii_isxdigit(str[*len]) || !g_ascii_isxdigit(str[*len + 1])) { if ( i > 1 ) { (*len) -= 1; break; } else return FALSE; } if (i == parts) (*len) += 2; else { if (str[*len + 2] != ':') { (*len) += 2; break; } else (*len) += 3; } } if (G_UNLIKELY(*len > count)) return FALSE; return TRUE; } gboolean r_parser_lladdr(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { gint count, parts; /* get the maximum octet count from the parameter */ if (param) { *len = 0; parts = 0; while (g_ascii_isdigit(param[*len])) { parts = parts * 10 + g_ascii_digit_value(param[*len]); (*len)++; } } else parts = 20; count = (parts * 3) - 1; return _r_parser_lladdr(str, len, count, parts, state, match); } gboolean r_parser_macaddr(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { return _r_parser_lladdr(str, len, 17, 6, state, match); } gboolean r_parser_ipv4(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { gint dots = 0; gint octet = -1; *len = 0; while (1) { if (str[*len] == '.') { if (octet > 255 || octet == -1) return FALSE; if (G_UNLIKELY(dots == 3)) break; dots++; octet = -1; } else if (g_ascii_isdigit(str[*len])) { if (octet == -1) octet = 0; else octet *= 10; octet += g_ascii_digit_value(str[*len]); } else break; (*len)++; } if (dots != 3 || octet > 255 || octet == -1) return FALSE; return TRUE; } gboolean r_parser_ipv6(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { gint colons = 0; gint dots = 0; gint octet = 0; gint digit = 16; gboolean shortened = FALSE; *len = 0; while (1) { if (str[*len] == ':') { if (G_UNLIKELY(octet > 0xffff || (octet == -1 && shortened))) return FALSE; if (G_UNLIKELY(colons == 7 || dots == 3)) break; if (G_UNLIKELY(digit == 10)) return FALSE; if (octet == -1) shortened = TRUE; colons++; octet = -1; } else if (g_ascii_isxdigit(str[*len])) { if (octet == -1) octet = 0; else octet *= digit; octet += g_ascii_xdigit_value(str[*len]); } else if (str[*len] == '.') { if (G_UNLIKELY((digit == 10 && octet > 255))) return FALSE; if (G_UNLIKELY((digit == 16 && octet > 597) || octet == -1 || colons == 7 || dots == 3)) break; dots++; octet = -1; digit = 10; } else break; (*len)++; } if (G_UNLIKELY(str[*len - 1] == '.')) { (*len)--; dots--; } else if (G_UNLIKELY(str[*len - 1] == ':' && str[*len - 2] != ':')) { (*len)--; colons--; } if (colons < 2 || colons > 7 || (digit == 10 && octet > 255) || (digit == 16 && octet > 0xffff) || !(dots == 0 || dots == 3) || (!shortened && colons < 7 && dots == 0)) return FALSE; return TRUE; } gboolean r_parser_ip(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { return r_parser_ipv4(str, len, param, state, match) || r_parser_ipv6(str, len, param, state, match); } gboolean r_parser_float(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { gboolean dot = FALSE; *len = 0; if (str[*len] == '-') (*len)++; while (g_ascii_isdigit(str[*len]) || (!dot && str[*len] == '.' && (dot = TRUE))) (*len)++; if (*len > 0 && (str[*len] == 'e' || str[*len] == 'E')) { (*len)++; if (str[*len] == '-') (*len)++; while (g_ascii_isdigit(str[*len])) (*len)++; } if (*len) return TRUE; return FALSE; } gboolean r_parser_number(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match) { gint min_len = 1; if (g_str_has_prefix(str, "0x") || g_str_has_prefix(str, "0X")) { *len = 2; min_len += 2; while (g_ascii_isxdigit(str[*len])) (*len)++; } else { *len = 0; if (str[*len] == '-') { (*len)++; min_len++; } while (g_ascii_isdigit(str[*len])) (*len)++; } if (*len >= min_len) { return TRUE; } return FALSE; } /** * r_new_pnode: * * Create a new parsing node. **/ static RParserNode * r_new_pnode(guint8 *key) { RParserNode *parser_node = g_new0(RParserNode, 1); gchar **params = g_strsplit(key, ":", 3); guint params_len = g_strv_length(params); parser_node->first = 0; parser_node->last = 255; if (strcmp(params[0], "IPv4") == 0) { parser_node->parse = r_parser_ipv4; parser_node->type = RPT_IPV4; parser_node->first = '0'; parser_node->last = '9'; } else if (strcmp(params[0], "IPv6") == 0) { parser_node->parse = r_parser_ipv6; parser_node->type = RPT_IPV6; } else if (strcmp(params[0], "IPvANY") == 0) { parser_node->parse = r_parser_ip; parser_node->type = RPT_IP; } else if (strcmp(params[0], "MACADDR") == 0) { parser_node->parse = r_parser_macaddr; parser_node->type = RPT_MACADDR; } else if (strcmp(params[0], "NUMBER") == 0) { parser_node->parse = r_parser_number; parser_node->type = RPT_NUMBER; parser_node->first = '-'; parser_node->last = '9'; } else if (strcmp(params[0], "FLOAT") == 0 || strcmp(params[0], "DOUBLE") == 0) { /* DOUBLE is a deprecated alias for FLOAT */ parser_node->parse = r_parser_float; parser_node->type = RPT_FLOAT; parser_node->first = '-'; parser_node->last = '9'; } else if (strcmp(params[0], "STRING") == 0) { parser_node->parse = r_parser_string; parser_node->type = RPT_STRING; } else if (strcmp(params[0], "ESTRING") == 0) { if (params_len == 3) { parser_node->parse = r_parser_estring_c; parser_node->type = RPT_ESTRING; if (params[2] && (strlen(params[2]) > 1)) { gint len = strlen(params[2]); parser_node->state = GINT_TO_POINTER(len); parser_node->parse = r_parser_estring; } } else { g_free(parser_node); msg_error("Missing ESTRING parser parameters", evt_tag_str("type", params[0])); parser_node = NULL; } } else if (strcmp(params[0], "NLSTRING") == 0) { if (params_len <= 2) { parser_node->parse = r_parser_nlstring; parser_node->type = RPT_NLSTRING; } else { g_free(parser_node); msg_error("Too many arguments to NLSTRING, no 3rd parameter supported"); parser_node = NULL; } } else if (strcmp(params[0], "PCRE") == 0) { parser_node->parse = r_parser_pcre; parser_node->type = RPT_PCRE; if (params[2]) { parser_node->free_state = r_parser_pcre_free_state; parser_node->state = r_parser_pcre_compile_state(params[2]); } else { g_free(parser_node); msg_error("Missing regular expression as 3rd argument", evt_tag_str("type", params[0])); parser_node = NULL; } } else if (strcmp(params[0], "ANYSTRING") == 0) { parser_node->parse = r_parser_anystring; parser_node->type = RPT_ANYSTRING; } else if (strcmp(params[0], "SET") == 0) { if (params_len == 3) { parser_node->parse = r_parser_set; parser_node->type = RPT_SET; } else { g_free(parser_node); msg_error("Missing SET parser parameters", evt_tag_str("type", params[0])); parser_node = NULL; } } else if (strcmp(params[0], "EMAIL") == 0) { parser_node->parse = r_parser_email; parser_node->type = RPT_EMAIL; } else if (strcmp(params[0], "HOSTNAME") == 0) { parser_node->parse = r_parser_hostname; parser_node->type = RPT_HOSTNAME; } else if (strcmp(params[0], "LLADDR") == 0) { parser_node->parse = r_parser_lladdr; parser_node->type = RPT_LLADDR; } else if (g_str_has_prefix(params[0], "QSTRING")) { if (params_len == 3) { gchar *state = (gchar *) &(parser_node->state); parser_node->parse = r_parser_qstring; parser_node->type = RPT_QSTRING; parser_node->first = params[2][0]; parser_node->last = params[2][0]; if (params_len >= 2 && params[2] && strlen(params[2]) == 2) state[0] = params[2][1]; else state[0] = params[2][0]; } else { g_free(parser_node); msg_error("Missing QSTRING parser parameters", evt_tag_str("type", params[0])); parser_node = NULL; } } else { g_free(parser_node); msg_error("Unknown parser type specified", evt_tag_str("type", params[0])); parser_node = NULL; } if (parser_node && params[1]) { if (params[1][0]) parser_node->handle = log_msg_get_value_handle(params[1]); if (params[2]) parser_node->param = g_strdup(params[2]); } g_strfreev(params); return parser_node; } void r_free_pnode_only(RParserNode *parser) { if (parser->param) g_free(parser->param); if (parser->state && parser->free_state) parser->free_state(parser->state); g_free(parser); } void r_free_pnode(RNode *node, void (*free_fn)(gpointer data)) { r_free_pnode_only(node->parser); node->key = NULL; r_free_node(node, free_fn); } /************************************************************** * Literal string nodes. **************************************************************/ gint r_node_cmp(const void *ap, const void *bp) { RNode *a = *(RNode * const *) ap; RNode *b = *(RNode * const *) bp; if (a->key[0] < b->key[0]) return -1; else if (a->key[0] > b->key[0]) return 1; return 0; } void r_add_child(RNode *parent, RNode *child) { parent->children = g_realloc(parent->children, (sizeof(RNode *) * (parent->num_children + 1))); //FIXME: we could do a simple sorted insert without resorting always parent->children[(parent->num_children)++] = child; qsort(&(parent->children[0]), parent->num_children, sizeof(RNode *), r_node_cmp); } static inline void r_add_child_check(RNode *root, guint8 *key, gpointer value, RNodeGetValueFunc value_func) { guint8 *at; if (((at = strchr(key, '@')) != NULL)) { /* there is an @ somewhere in the string */ if ((at - key) > 0) { /* there are some literal characters before @ so add a new child till @ */ *at = '\0'; RNode *child = r_new_node(key, NULL); r_add_child(root, child); /* and insert the rest begining from @ under the newly created literal node */ *at = '@'; r_insert_node(child, at, value, value_func); } else { /* @ is the first so let's insert it simply and let insert_node handle @ */ r_insert_node(root, key, value, value_func); } } else { /* either we don't care about parser or no @ in the text, so insert everything as * a simple literal node */ RNode *child = r_new_node(key, value); r_add_child(root, child); } } void r_add_pchild(RNode *parent, RNode *child) { parent->pchildren = realloc(parent->pchildren, (sizeof(RNode *) * (parent->num_pchildren + 1))); parent->pchildren[(parent->num_pchildren)++] = child; } gboolean r_equal_pnode(RParserNode *a, RParserNode *b) { return ((a->parse == b->parse) && (a->handle == b->handle) && ((a->param == NULL && b->param == NULL) || (a->param != NULL && b->param != NULL && g_str_equal(a->param, b->param))) ); } RNode * r_find_pchild(RNode *parent, RParserNode *parser_node) { RNode *node = NULL; gint i; for (i = 0; i < parent->num_pchildren; i++) { if (r_equal_pnode(parent->pchildren[i]->parser, parser_node)) { node = parent->pchildren[i]; break; } } return node; } RNode * r_find_child_by_first_character(RNode *root, char key) { register gint l, u, idx; register char k = key; l = 0; u = root->num_children; while (l < u) { idx = (l + u) / 2; if (root->children[idx]->key[0] > k) u = idx; else if (root->children[idx]->key[0] < k) l = idx + 1; else return root->children[idx]; } return NULL; } void r_insert_node(RNode *root, guint8 *key, gpointer value, RNodeGetValueFunc value_func) { RNode *node; gint keylen = strlen(key); gint nodelen = root->keylen; gint i = 0; if (key[0] == '@') { guint8 *end; if (keylen >= 2 && key[1] == '@') { /* we found and escape, so check if we already have a child with '@', or add a child like that */ node = r_find_child_by_first_character(root, key[1]); if (!node) { /* no child so we create one * if we are at the end of the key than use value, otherwise it is just a gap node */ node = r_new_node("@", (keylen == 2 ? value : NULL)); r_add_child(root, node); } else if (keylen == 2) { /* if we are at the end of the key set the value if it is not already exists, * otherwise it is duplicate node */ if (!node->value) node->value = value; else msg_error("Duplicate key in parser radix tree", evt_tag_str("key", "@"), evt_tag_str("value", value_func ? value_func(value) : "unknown"), evt_tag_str("other-value", value_func ? value_func(node->value) : "unknown")); } /* go down building the tree if there is key left */ if (keylen > 2) r_insert_node(node, key + 2, value, value_func); } else if ((keylen >= 2) && (end = strchr((const gchar *)key + 1, '@')) != NULL) { /* we are a parser node */ *end = '\0'; RParserNode *parser_node = r_new_pnode(key + 1); if (parser_node) { node = r_find_pchild(root, parser_node); if (!node) { node = r_new_node(NULL, NULL); node->parser = parser_node; r_add_pchild(root, node); } else { r_free_pnode_only(parser_node); } if ((end - key) < (keylen - 1)) { /* the key is not over so go on building the tree */ r_insert_node(node, end + 1, value, value_func); } else { /* the key is over so set value if it is not yet set */ if (!node->value) { node->value = value; } else { /* FIXME: print parser type in string format */ msg_error("Duplicate parser node in radix tree", evt_tag_int("type", node->parser->type), evt_tag_str("name", log_msg_get_value_name(node->parser->handle, NULL)), evt_tag_str("value", value_func ? value_func(value) : "unknown"), evt_tag_str("other-value", value_func ? value_func(node->value) : "unknown")); } } } } else msg_error("Key contains '@' without escaping", evt_tag_str("key", key), evt_tag_str("value", value_func ? value_func(value) : "unknown")); } else { /* we are not starting with @ sign or we are not interested in @ at all */ while (i < keylen && i < nodelen) { /* check if key is the same, or if it is a parser */ if ((key[i] != root->key[i]) || (key[i] == '@')) break; i++; } if (nodelen == 0 || i == 0 || (i < keylen && i >= nodelen)) { /*either at the root or we need to go down the tree on the right child */ node = r_find_child_by_first_character(root, key[i]); if (node) { /* @ is always a singel node, and we also have an @ so insert us under root */ if (key[i] == '@') r_insert_node(root, key + i, value, value_func); else r_insert_node(node, key + i, value, value_func); } else { r_add_child_check(root, key + i, value, value_func); } } else if (i == keylen && i == nodelen) { /* exact match */ if (!root->value) root->value = value; else msg_error("Duplicate key in radix tree", evt_tag_str("key", key), evt_tag_str("value", value_func ? value_func(value) : "unknown")); } else if (i > 0 && i < nodelen) { RNode *old_tree; guint8 *new_key; /* we need to split the current node */ old_tree = r_new_node(root->key + i, root->value); if (root->num_children) { old_tree->children = root->children; old_tree->num_children = root->num_children; root->children = NULL; root->num_children = 0; } if (root->num_pchildren) { old_tree->pchildren = root->pchildren; old_tree->num_pchildren = root->num_pchildren; root->pchildren = NULL; root->num_pchildren = 0; } root->value = NULL; new_key = g_strndup(root->key, i); g_free(root->key); root->key = new_key; root->keylen = i; r_add_child(root, old_tree); if (i < keylen) { /* we add a new sub tree */ r_add_child_check(root, key + i, value, value_func); } else { /* the split is us */ root->value = value; } } else { /* simply a new children */ r_add_child_check(root, key + i, value, value_func); } } } typedef struct _RFindNodeState { gboolean require_complete_match; gboolean partial_match_found; guint8 *whole_key; GArray *stored_matches; GArray *dbg_list; GPtrArray *applicable_nodes; } RFindNodeState; static RNode *_find_node_recursively(RFindNodeState *state, RNode *root, guint8 *key, gint keylen); static void _add_debug_info(RFindNodeState *state, RNode *node, RParserNode *pnode, gint i, gint match_off, gint match_len) { RDebugInfo dbg_info; if (state->dbg_list) { dbg_info.node = node; dbg_info.pnode = pnode; dbg_info.i = i; dbg_info.match_off = match_off; dbg_info.match_len = match_len; g_array_append_val(state->dbg_list, dbg_info); } } static void _add_literal_match_to_debug_info(RFindNodeState *state, RNode *node, gint literal_prefix) { _add_debug_info(state, node, NULL, literal_prefix, 0, 0); } static void _add_parser_match_debug_info(RFindNodeState *state, RNode *root, RParserNode *parser_node, guint8 *remaining_key, gint extracted_match_len, RParserMatch *match_slot) { if (state->dbg_list && match_slot) _add_debug_info(state, root, parser_node, extracted_match_len, ((gint16) match_slot->ofs) + remaining_key - state->whole_key, ((gint16) match_slot->len) + extracted_match_len); } static void _truncate_debug_info(RFindNodeState *state, gint truncated_size) { if (state->dbg_list) g_array_set_size(state->dbg_list, truncated_size); } static void _find_matching_literal_prefix(RNode *root, guint8 *key, gint keylen, gint *literal_prefix_inputlen, gint *literal_prefix_radixlen) { gint current_node_key_length = root->keylen; gint input_length; gint radix_length; if (current_node_key_length < 1) radix_length = input_length = 0; else { /* this is a prefix match algorithm, we are interested how long the * common part between key and root->key is. Currently this uses a * byte-by-byte comparison, using a 64/32/16 bit units would be * better. We had a PoC code to do that, and the performance * difference wasn't big enough to offset the complexity so it was * removed. We might want to rerun perf tests and see if we could * speed things up, but db-parser() seems fast enough as it is. */ input_length = radix_length = 0; while (input_length < keylen && radix_length < current_node_key_length) { if (key[input_length] == '\r' && root->key[radix_length] == '\n') { /* skip CR from input if the radix contains a newline */ input_length++; } if (key[input_length] != root->key[radix_length]) break; input_length++; radix_length++; } } *literal_prefix_inputlen = input_length; *literal_prefix_radixlen = radix_length; } static RNode * _find_child_by_remaining_key(RFindNodeState *state, RNode *root, guint8 *remaining_key, gint remaining_keylen) { RNode *candidate; if (remaining_keylen >= 2 && remaining_key[0] == '\r' && remaining_key[1] == '\n') { remaining_key++; remaining_keylen--; } candidate = r_find_child_by_first_character(root, remaining_key[0]); if (candidate) return _find_node_recursively(state, candidate, remaining_key, remaining_keylen); return NULL; } static gint _alloc_slot_in_matches(RFindNodeState *state) { gint matches_base = 0; if (state->stored_matches) { matches_base = state->stored_matches->len; g_array_set_size(state->stored_matches, matches_base + 1); } return matches_base; } static RParserMatch * _get_match_slot(RFindNodeState *state, gint matches_base) { if (state->stored_matches) return &g_array_index(state->stored_matches, RParserMatch, matches_base); return NULL; } static RParserMatch * _clear_match_slot(RFindNodeState *state, gint matches_base) { RParserMatch *match = NULL; if (state->stored_matches) { match = _get_match_slot(state, matches_base); memset(match, 0, sizeof(*match)); } return match; } static void _reset_matches_to_original_state(RFindNodeState *state, gint matches_base) { if (state->stored_matches) g_array_set_size(state->stored_matches, matches_base); } static gboolean _is_pnode_matching_initial_character(RParserNode *parser_node, guint8 *key) { return (parser_node->first <= key[0]) && (key[0] <= parser_node->last); } static gboolean _pnode_try_parse(RParserNode *parser_node, guint8 *key, gint *extracted_match_len, RParserMatch *match) { if (!_is_pnode_matching_initial_character(parser_node, key)) return FALSE; if (!parser_node->parse(key, extracted_match_len, parser_node->param, parser_node->state, match)) return FALSE; return TRUE; } static void _fixup_match_offsets(RFindNodeState *state, RParserNode *parser_node, gint extracted_match_len, guint8 *remaining_key, RParserMatch *match) { if (!(match->match)) { /* NOTE: we allow the parser to return relative * offset & length to the field parsed, this way * quote characters can still be returned as * REF_MATCH and we only need to duplicate the * result if the string is indeed modified */ match->type = parser_node->type; match->ofs = match->ofs + remaining_key - state->whole_key; match->len = (gint16) match->len + extracted_match_len; match->handle = parser_node->handle; } } static void _clear_match_content(RParserMatch *match) { if (match->match) { /* free the stored match, if this was a dead-end */ g_free(match->match); match->match = NULL; } } static RNode * _try_parse_with_a_given_child(RFindNodeState *state, RNode *root, gint parser_ndx, gint matches_slot_index, guint8 *remaining_key, gint remaining_keylen) { RNode *child_node = root->pchildren[parser_ndx]; RParserNode *parser_node = child_node->parser; RParserMatch *match_slot = NULL; gint extracted_match_len; RNode *ret = NULL; match_slot = _clear_match_slot(state, matches_slot_index); if (_pnode_try_parse(parser_node, remaining_key, &extracted_match_len, match_slot)) { /* FIXME: we don't try to find the longest match in case * the radix tree is split on a parser node. The correct * approach would be to try all parsers and select the * best match, however it is quite expensive and difficult * to implement and we don't really expect this to be a * realistic case. A log message is printed if such a * collision occurs, so there's a slight chance we'll * recognize if this happens in real life. */ _add_parser_match_debug_info(state, root, parser_node, remaining_key, extracted_match_len, match_slot); ret = _find_node_recursively(state, root->pchildren[parser_ndx], remaining_key + extracted_match_len, remaining_keylen - extracted_match_len); /* we have to look up "match_slot" again as the GArray may have * moved the data in case r_find_node() expanded it above */ match_slot = _get_match_slot(state, matches_slot_index); if (match_slot) { if (ret) _fixup_match_offsets(state, parser_node, extracted_match_len, remaining_key, match_slot); else _clear_match_content(match_slot); } } return ret; } static RNode * _find_child_by_parser(RFindNodeState *state, RNode *root, guint8 *remaining_key, gint remaining_keylen) { gint dbg_list_base = state->dbg_list ? state->dbg_list->len : 0; gint matches_slot_index = 0; gint parser_ndx; RNode *ret = NULL; matches_slot_index = _alloc_slot_in_matches(state); for (parser_ndx = 0; !ret && parser_ndx < root->num_pchildren; parser_ndx++) { _truncate_debug_info(state, dbg_list_base); ret = _try_parse_with_a_given_child(state, root, parser_ndx, matches_slot_index, remaining_key, remaining_keylen); } if (!ret && state->stored_matches) { /* the values in the stored_matches array has already been freed if we come here */ _reset_matches_to_original_state(state, matches_slot_index); } return ret; } static RNode * _find_node_recursively(RFindNodeState *state, RNode *root, guint8 *key, gint keylen) { gint literal_prefix_inputlen, literal_prefix_radixlen; _find_matching_literal_prefix(root, key, keylen, &literal_prefix_inputlen, &literal_prefix_radixlen); _add_literal_match_to_debug_info(state, root, literal_prefix_inputlen); msg_trace("Looking up node in the radix tree", evt_tag_int("literal_prefix_inputlen", literal_prefix_inputlen), evt_tag_int("literal_prefix_radixlen", literal_prefix_radixlen), evt_tag_int("root->keylen", root->keylen), evt_tag_int("keylen", keylen), evt_tag_str("root_key", root->key), evt_tag_str("key", key)); if (literal_prefix_inputlen == keylen && (literal_prefix_radixlen == root->keylen || root->keylen == -1)) { /* key completely consumed by the literal */ if (state->applicable_nodes) { /* collect all matching nodes */ g_ptr_array_add(state->applicable_nodes, root); return NULL; } if (root->value) return root; } else if ((root->keylen < 1) || (literal_prefix_inputlen < keylen && literal_prefix_radixlen >= root->keylen)) { /* we matched the key partially, go on with child nodes */ RNode *ret; guint8 *remaining_key = key + literal_prefix_inputlen; gint remaining_keylen = keylen - literal_prefix_inputlen; /* prefer a literal match over parsers */ ret = _find_child_by_remaining_key(state, root, remaining_key, remaining_keylen); /* then try parsers in order */ if (!ret) ret = _find_child_by_parser(state, root, remaining_key, remaining_keylen); if (!ret && root->value) { if (!state->require_complete_match) return root; state->partial_match_found = TRUE; } return ret; } return NULL; } static RNode * _find_node_with_state(RFindNodeState *state, RNode *root, guint8 *key, gint keylen) { RNode *ret; state->require_complete_match = TRUE; state->partial_match_found = FALSE; ret = _find_node_recursively(state, root, key, keylen); if (!ret && state->partial_match_found) { state->require_complete_match = FALSE; ret = _find_node_recursively(state, root, key, keylen); } return ret; } RNode * r_find_node(RNode *root, guint8 *key, gint keylen, GArray *stored_matches) { RFindNodeState state = { .whole_key = key, .stored_matches = stored_matches, }; return _find_node_with_state(&state, root, key, keylen); } RNode * r_find_node_dbg(RNode *root, guint8 *key, gint keylen, GArray *stored_matches, GArray *dbg_list) { RFindNodeState state = { .whole_key = key, .stored_matches = stored_matches, .dbg_list = dbg_list, }; return _find_node_with_state(&state, root, key, keylen); } gchar ** r_find_all_applicable_nodes(RNode *root, guint8 *key, gint keylen, RNodeGetValueFunc value_func) { RFindNodeState state = { .whole_key = key, }; gint i; GPtrArray *result; state.applicable_nodes = g_ptr_array_new(); state.require_complete_match = TRUE; _find_node_recursively(&state, root, key, keylen); result = g_ptr_array_new(); for (i = 0; i < state.applicable_nodes->len; i++) { RNode *node = (RNode *) g_ptr_array_index(state.applicable_nodes, i); g_ptr_array_add(result, g_strdup(value_func(node->value))); } g_ptr_array_add(result, NULL); g_ptr_array_free(state.applicable_nodes, TRUE); return (gchar **) g_ptr_array_free(result, FALSE); } /** * r_new_node: */ RNode * r_new_node(guint8 *key, gpointer value) { RNode *node = g_malloc(sizeof(RNode)); node->key = g_strdup(key); node->keylen = (key ? strlen(key) : -1); node->parser = NULL; node->value = value; node->num_children = 0; node->children = NULL; node->num_pchildren = 0; node->pchildren = NULL; return node; } void r_free_node(RNode *node, void (*free_fn)(gpointer data)) { gint i; for (i = 0; i < node->num_children; i++) r_free_node(node->children[i], free_fn); if (node->children) g_free(node->children); for (i = 0; i < node->num_pchildren; i++) r_free_pnode(node->pchildren[i], free_fn); if (node->pchildren) g_free(node->pchildren); if (node->key) g_free(node->key); if (node->value && free_fn) free_fn(node->value); g_free(node); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/radix.h000066400000000000000000000075141321171025300221760ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef RADIX_H_INCLUDED #define RADIX_H_INCLUDED #include "logmsg/logmsg.h" #include "messages.h" /* parser types, these are saved in the serialized log message along with * the match information thus they have to remain the same in order to keep * compatibility, thus add new stuff at the end */ enum { RPT_STRING, RPT_QSTRING, RPT_ESTRING, RPT_IPV4, RPT_NUMBER, RPT_ANYSTRING, RPT_IPV6, RPT_IP, RPT_FLOAT, RPT_SET, RPT_MACADDR, RPT_PCRE, RPT_EMAIL, RPT_HOSTNAME, RPT_LLADDR, RPT_NLSTRING, }; typedef struct _RParserMatch { /* if this pointer is non-NULL, it means that we've transformed the * original message to something else, and thus we couldn't get a * reference from the original payload */ gchar *match; /* the value in which to store this match */ NVHandle handle; guint16 len; guint16 ofs; guint8 type; } RParserMatch; typedef struct _RParserNode { /* user supplied parameters */ /* user supplied parameters */ gchar *param; /* internal state of the parser node */ gpointer state; guint8 first; guint8 last; guint8 type; NVHandle handle; gboolean (*parse)(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match); void (*free_state)(gpointer state); } RParserNode; typedef gchar *(*RNodeGetValueFunc) (gpointer value); typedef struct _RNode RNode; struct _RNode { guint8 *key; gint keylen; RParserNode *parser; gpointer value; guint num_children; RNode **children; guint num_pchildren; RNode **pchildren; }; typedef struct _RDebugInfo { RNode *node; RParserNode *pnode; gint i; gint match_off; gint match_len; } RDebugInfo; static inline gchar * r_parser_type_name(guint8 type) { switch (type) { case RPT_STRING: return "STRING"; case RPT_QSTRING: return "QSTRING"; case RPT_ESTRING: return "ESTRING"; case RPT_IPV4: return "IPv4"; case RPT_NUMBER: return "NUMBER"; case RPT_ANYSTRING: return "ANYSTRING"; case RPT_IPV6: return "IPv6"; case RPT_IP: return "IP"; case RPT_FLOAT: return "FLOAT"; case RPT_SET: return "SET"; case RPT_MACADDR: return "MACADDR"; case RPT_EMAIL: return "EMAIL"; case RPT_HOSTNAME: return "HOSTNAME"; case RPT_LLADDR: return "LLADDR"; default: return "UNKNOWN"; } } RNode *r_new_node(guint8 *key, gpointer value); void r_free_node(RNode *node, void (*free_fn)(gpointer data)); void r_insert_node(RNode *root, guint8 *key, gpointer value, RNodeGetValueFunc value_func); RNode *r_find_node(RNode *root, guint8 *key, gint keylen, GArray *matches); RNode *r_find_node_dbg(RNode *root, guint8 *key, gint keylen, GArray *matches, GArray *dbg_list); gchar **r_find_all_applicable_nodes(RNode *root, guint8 *key, gint keylen, RNodeGetValueFunc value_func); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/stateful-parser.c000066400000000000000000000040401321171025300241720ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "stateful-parser.h" #include void stateful_parser_set_inject_mode(StatefulParser *self, LogDBParserInjectMode inject_mode) { self->inject_mode = inject_mode; } void stateful_parser_emit_synthetic(StatefulParser *self, LogMessage *msg) { if (self->inject_mode == LDBP_IM_PASSTHROUGH) { LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; path_options.ack_needed = FALSE; log_pipe_forward_msg(&self->super.super, log_msg_ref(msg), &path_options); } else { msg_post_message(log_msg_ref(msg)); } } void stateful_parser_init_instance(StatefulParser *self, GlobalConfig *cfg) { log_parser_init_instance(&self->super, cfg); self->inject_mode = LDBP_IM_PASSTHROUGH; } void stateful_parser_free_method(LogPipe *s) { log_parser_free_method(s); } int stateful_parser_lookup_inject_mode(const gchar *inject_mode) { if (strcasecmp(inject_mode, "internal") == 0) return LDBP_IM_INTERNAL; else if (strcasecmp(inject_mode, "pass-through") == 0 || strcasecmp(inject_mode, "pass_through") == 0) return LDBP_IM_PASSTHROUGH; return -1; } syslog-ng-syslog-ng-3.13.2/modules/dbparser/stateful-parser.h000066400000000000000000000034771321171025300242140ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef STATEFUL_PARSER_H_INCLUDED #define STATEFUL_PARSER_H_INCLUDED 1 #include "parser/parser-expr.h" typedef enum { LDBP_IM_PASSTHROUGH = 0, LDBP_IM_INTERNAL = 1, } LogDBParserInjectMode; typedef struct _StatefulParser { LogParser super; LogDBParserInjectMode inject_mode; } StatefulParser; static inline gboolean stateful_parser_init_method(LogPipe *s) { return log_parser_init_method(s); } static inline gboolean stateful_parser_deinit_method(LogPipe *s) { return log_parser_deinit_method(s); } void stateful_parser_set_inject_mode(StatefulParser *self, LogDBParserInjectMode inject_mode); void stateful_parser_emit_synthetic(StatefulParser *self, LogMessage *msg); void stateful_parser_init_instance(StatefulParser *self, GlobalConfig *cfg); void stateful_parser_free_method(LogPipe *s); int stateful_parser_lookup_inject_mode(const gchar *inject_mode); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/synthetic-context.c000066400000000000000000000036601321171025300245540ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * Copyright (c) 2016 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "synthetic-context.h" #include "pdb-error.h" #include void synthetic_context_set_context_id_template(SyntheticContext *self, LogTemplate *context_id_template) { if (self->id_template) log_template_unref(self->id_template); self->id_template = context_id_template; } void synthetic_context_set_context_timeout(SyntheticContext *self, gint timeout) { self->timeout = timeout; } void synthetic_context_set_context_scope(SyntheticContext *self, const gchar *scope, GError **error) { int context_scope = correllation_key_lookup_scope(scope); if (context_scope < 0) { self->scope = RCS_GLOBAL; g_set_error(error, PDB_ERROR, PDB_ERROR_FAILED, "Unknown context scope: %s", scope); } else self->scope = context_scope; } void synthetic_context_init(SyntheticContext *self) { memset(self, 0, sizeof(*self)); self->scope = RCS_PROCESS; } void synthetic_context_deinit(SyntheticContext *self) { if (self->id_template) log_template_unref(self->id_template); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/synthetic-context.h000066400000000000000000000033061321171025300245560ustar00rootroot00000000000000/* * Copyright (c) 2016 Balabit * Copyright (c) 2016 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_SYNTHETIC_CONTEXT_H_INCLUDED #define PATTERNDB_SYNTHETIC_CONTEXT_H_INCLUDED #include "syslog-ng.h" #include "correllation-key.h" #include "template/templates.h" typedef struct _SyntheticContext { gint timeout; CorrellationScope scope; LogTemplate *id_template; } SyntheticContext; void synthetic_context_set_context_id_template(SyntheticContext *self, LogTemplate *context_id_template); void synthetic_context_set_context_timeout(SyntheticContext *self, gint timeout); void synthetic_context_set_context_scope(SyntheticContext *self, const gchar *scope, GError **error); void synthetic_context_init(SyntheticContext *self); void synthetic_context_deinit(SyntheticContext *self); gint synthetic_context_lookup_context_scope(const gchar *context_scope); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/synthetic-message.c000066400000000000000000000220001321171025300245010ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "synthetic-message.h" #include "pdb-error.h" #include "template/templates.h" #include "logmsg/logmsg.h" #include "logpipe.h" void synthetic_message_set_inherit_mode(SyntheticMessage *self, SyntheticMessageInheritMode inherit_mode) { self->inherit_mode = inherit_mode; } gboolean synthetic_message_set_inherit_mode_string(SyntheticMessage *self, const gchar *inherit_mode_name, GError **error) { gint inherit_mode = synthetic_message_lookup_inherit_mode(inherit_mode_name); if (inherit_mode < 0) { g_set_error(error, PDB_ERROR, PDB_ERROR_FAILED, "Unknown inherit mode %s", inherit_mode_name); return FALSE; } synthetic_message_set_inherit_mode(self, inherit_mode); return TRUE; } void synthetic_message_set_inherit_properties_string(SyntheticMessage *self, const gchar *inherit_properties, GError **error) { SyntheticMessageInheritMode inherit_mode; if (strcasecmp(inherit_properties, "context") == 0) { inherit_mode = RAC_MSG_INHERIT_CONTEXT; } else if (inherit_properties[0] == 'T' || inherit_properties[0] == 't' || inherit_properties[0] == '1') { inherit_mode = RAC_MSG_INHERIT_LAST_MESSAGE; } else if (inherit_properties[0] == 'F' || inherit_properties[0] == 'f' || inherit_properties[0] == '0') { inherit_mode = RAC_MSG_INHERIT_NONE; } else { g_set_error(error, PDB_ERROR, PDB_ERROR_FAILED, "Unknown inherit-properties: %s", inherit_properties); return; } synthetic_message_set_inherit_mode(self, inherit_mode); } void synthetic_message_add_tag(SyntheticMessage *self, const gchar *text) { LogTagId tag; if (!self->tags) self->tags = g_array_new(FALSE, FALSE, sizeof(LogTagId)); tag = log_tags_get_by_name(text); g_array_append_val(self->tags, tag); } gboolean synthetic_message_add_value_template_string(SyntheticMessage *self, GlobalConfig *cfg, const gchar *name, const gchar *value, GError **error) { LogTemplate *value_template; gboolean result = FALSE; /* NOTE: we shouldn't use the name property for LogTemplate structs, see the comment at log_template_set_name() */ value_template = log_template_new(cfg, name); if (log_template_compile(value_template, value, error)) { synthetic_message_add_value_template(self, name, value_template); result = TRUE; } log_template_unref(value_template); return result; } void synthetic_message_add_value_template(SyntheticMessage *self, const gchar *name, LogTemplate *value) { if (!self->values) self->values = g_ptr_array_new(); /* NOTE: we shouldn't use the name property for LogTemplate structs, see the comment at log_template_set_name() */ log_template_set_name(value, name); g_ptr_array_add(self->values, log_template_ref(value)); } void synthetic_message_apply(SyntheticMessage *self, CorrellationContext *context, LogMessage *msg, GString *buffer) { gint i; if (self->tags) { for (i = 0; i < self->tags->len; i++) log_msg_set_tag_by_id(msg, g_array_index(self->tags, LogTagId, i)); } if (self->values) { for (i = 0; i < self->values->len; i++) { log_template_format_with_context(g_ptr_array_index(self->values, i), context ? (LogMessage **) context->messages->pdata : &msg, context ? context->messages->len : 1, NULL, LTZ_LOCAL, 0, context ? context->key.session_id : NULL, buffer); log_msg_set_value_by_name(msg, ((LogTemplate *) g_ptr_array_index(self->values, i))->name, buffer->str, buffer->len); } } } static LogMessage * _generate_message_inheriting_properties_from_the_last_message(LogMessage *msg) { LogPathOptions path_options = LOG_PATH_OPTIONS_INIT; path_options.ack_needed = FALSE; return log_msg_clone_cow(msg, &path_options); } static LogMessage * _generate_new_message_with_timestamp_of_the_triggering_message(LogStamp *msgstamp) { LogMessage *genmsg = log_msg_new_local(); genmsg->timestamps[LM_TS_STAMP] = *msgstamp; return genmsg; } LogMessage * _generate_message_inheriting_properties_from_the_entire_context(CorrellationContext *context) { LogMessage *genmsg = _generate_message_inheriting_properties_from_the_last_message( correllation_context_get_last_message(context)); log_msg_merge_context(genmsg, (LogMessage **) context->messages->pdata, context->messages->len); return genmsg; } static LogMessage * _generate_default_message(SyntheticMessageInheritMode inherit_mode, LogMessage *triggering_msg) { switch (inherit_mode) { case RAC_MSG_INHERIT_LAST_MESSAGE: case RAC_MSG_INHERIT_CONTEXT: return _generate_message_inheriting_properties_from_the_last_message(triggering_msg); case RAC_MSG_INHERIT_NONE: return _generate_new_message_with_timestamp_of_the_triggering_message(&triggering_msg->timestamps[LM_TS_STAMP]); default: g_assert_not_reached(); } } static LogMessage * _generate_default_message_from_context(SyntheticMessageInheritMode inherit_mode, CorrellationContext *context) { LogMessage *triggering_msg = correllation_context_get_last_message(context); if (inherit_mode != RAC_MSG_INHERIT_CONTEXT) return _generate_default_message(inherit_mode, triggering_msg); return _generate_message_inheriting_properties_from_the_entire_context(context); } LogMessage * synthetic_message_generate_with_context(SyntheticMessage *self, CorrellationContext *context, GString *buffer) { LogMessage *genmsg; genmsg = _generate_default_message_from_context(self->inherit_mode, context); switch (context->key.scope) { case RCS_PROCESS: log_msg_set_value(genmsg, LM_V_PID, context->key.pid, -1); case RCS_PROGRAM: log_msg_set_value(genmsg, LM_V_PROGRAM, context->key.program, -1); case RCS_HOST: log_msg_set_value(genmsg, LM_V_HOST, context->key.host, -1); case RCS_GLOBAL: break; default: g_assert_not_reached(); break; } g_ptr_array_add(context->messages, genmsg); synthetic_message_apply(self, context, genmsg, buffer); g_ptr_array_remove_index_fast(context->messages, context->messages->len - 1); return genmsg; } LogMessage * synthetic_message_generate_without_context(SyntheticMessage *self, LogMessage *msg, GString *buffer) { LogMessage *genmsg; genmsg = _generate_default_message(self->inherit_mode, msg); /* no context, which means no correllation. The action * rule contains the generated message at @0 and the one * which triggered the rule in @1. * * We emulate a context having only these two * messages, but without allocating a full-blown * structure. */ LogMessage *dummy_msgs[] = { msg, genmsg, NULL }; GPtrArray dummy_ptr_array = { .pdata = (void **) dummy_msgs, .len = 2 }; CorrellationContext dummy_context = { .messages = &dummy_ptr_array, 0 }; synthetic_message_apply(self, &dummy_context, genmsg, buffer); return genmsg; } void synthetic_message_init(SyntheticMessage *self) { memset(self, 0, sizeof(*self)); } void synthetic_message_deinit(SyntheticMessage *self) { gint i; if (self->tags) g_array_free(self->tags, TRUE); if (self->values) { for (i = 0; i < self->values->len; i++) log_template_unref(g_ptr_array_index(self->values, i)); g_ptr_array_free(self->values, TRUE); } } SyntheticMessage * synthetic_message_new(void) { SyntheticMessage *self = g_new0(SyntheticMessage, 1); self->inherit_mode = RAC_MSG_INHERIT_CONTEXT; return self; } void synthetic_message_free(SyntheticMessage *self) { synthetic_message_deinit(self); g_free(self); } gint synthetic_message_lookup_inherit_mode(const gchar *inherit_mode) { if (strcasecmp(inherit_mode, "none") == 0) return RAC_MSG_INHERIT_NONE; else if (strcasecmp(inherit_mode, "last-message") == 0) return RAC_MSG_INHERIT_LAST_MESSAGE; else if (strcasecmp(inherit_mode, "context") == 0) return RAC_MSG_INHERIT_CONTEXT; return -1; } syslog-ng-syslog-ng-3.13.2/modules/dbparser/synthetic-message.h000066400000000000000000000053031321171025300245150ustar00rootroot00000000000000/* * Copyright (c) 2002-2013, 2015 Balabit * Copyright (c) 1998-2013, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef PATTERNDB_SYNTHETIC_MESSAGE_H_INCLUDED #define PATTERNDB_SYNTHETIC_MESSAGE_H_INCLUDED #include "syslog-ng.h" #include "correllation-context.h" #include "template/templates.h" typedef enum { RAC_MSG_INHERIT_NONE, RAC_MSG_INHERIT_LAST_MESSAGE, RAC_MSG_INHERIT_CONTEXT } SyntheticMessageInheritMode; typedef struct _SyntheticMessage { SyntheticMessageInheritMode inherit_mode; GArray *tags; GPtrArray *values; } SyntheticMessage; LogMessage *synthetic_message_generate_without_context(SyntheticMessage *self, LogMessage *msg, GString *buffer); LogMessage *synthetic_message_generate_with_context(SyntheticMessage *self, CorrellationContext *context, GString *buffer); void synthetic_message_apply(SyntheticMessage *self, CorrellationContext *context, LogMessage *msg, GString *buffer); gboolean synthetic_message_add_value_template_string(SyntheticMessage *self, GlobalConfig *cfg, const gchar *name, const gchar *value, GError **error); void synthetic_message_set_inherit_mode(SyntheticMessage *self, SyntheticMessageInheritMode inherit_mode); void synthetic_message_set_inherit_properties_string(SyntheticMessage *self, const gchar *inherit_properties, GError **error); gboolean synthetic_message_set_inherit_mode_string(SyntheticMessage *self, const gchar *inherit_mode_name, GError **error); void synthetic_message_add_value_template(SyntheticMessage *self, const gchar *name, LogTemplate *value); void synthetic_message_add_tag(SyntheticMessage *self, const gchar *text); void synthetic_message_init(SyntheticMessage *self); void synthetic_message_deinit(SyntheticMessage *self); SyntheticMessage *synthetic_message_new(void); void synthetic_message_free(SyntheticMessage *self); gint synthetic_message_lookup_inherit_mode(const gchar *inherit_mode); #endif syslog-ng-syslog-ng-3.13.2/modules/dbparser/tests/000077500000000000000000000000001321171025300220515ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/dbparser/tests/Makefile.am000066400000000000000000000036041321171025300241100ustar00rootroot00000000000000EXTRA_DIST += modules/dbparser/tests/test_parsers_e2e.c modules_dbparser_tests_TESTS = \ modules/dbparser/tests/test_timer_wheel \ modules/dbparser/tests/test_patternize \ modules/dbparser/tests/test_patterndb \ modules/dbparser/tests/test_radix \ modules/dbparser/tests/test_parsers check_PROGRAMS += \ ${modules_dbparser_tests_TESTS} modules_dbparser_tests_test_timer_wheel_CFLAGS = \ $(TEST_CFLAGS) \ -I$(top_srcdir)/modules/dbparser modules_dbparser_tests_test_timer_wheel_LDADD = \ $(TEST_LDADD) \ $(top_builddir)/modules/dbparser/libsyslog-ng-patterndb.la modules_dbparser_tests_test_timer_wheel_LDFLAGS = \ $(PREOPEN_CORE) modules_dbparser_tests_test_patternize_CFLAGS = \ $(TEST_CFLAGS) \ -I$(top_srcdir)/modules/dbparser modules_dbparser_tests_test_patternize_LDADD = \ $(TEST_LDADD) \ $(top_builddir)/modules/dbparser/libsyslog-ng-patterndb.la modules_dbparser_tests_test_patternize_LDFLAGS = \ $(PREOPEN_CORE) modules_dbparser_tests_test_patterndb_CFLAGS = \ $(TEST_CFLAGS) \ -I$(top_srcdir)/modules/dbparser modules_dbparser_tests_test_patterndb_LDADD = \ $(TEST_LDADD) \ $(top_builddir)/modules/dbparser/libsyslog-ng-patterndb.la modules_dbparser_tests_test_patterndb_LDFLAGS = \ $(PREOPEN_CORE) modules_dbparser_tests_test_radix_CFLAGS = \ $(TEST_CFLAGS) \ -I$(top_srcdir)/modules/dbparser \ @CFLAGS_NOWARN_POINTER_SIGN@ modules_dbparser_tests_test_radix_LDADD = \ $(TEST_LDADD) \ $(top_builddir)/modules/dbparser/libsyslog-ng-patterndb.la modules_dbparser_tests_test_radix_LDFLAGS = \ $(PREOPEN_CORE) modules_dbparser_tests_test_parsers_CFLAGS = \ $(TEST_CFLAGS) \ -I$(top_srcdir)/modules/dbparser \ @CFLAGS_NOWARN_POINTER_SIGN@ modules_dbparser_tests_test_parsers_LDADD = \ $(TEST_LDADD) \ $(top_builddir)/modules/dbparser/libsyslog-ng-patterndb.la modules_dbparser_tests_test_parsers_LDFLAGS = \ $(PREOPEN_CORE) syslog-ng-syslog-ng-3.13.2/modules/dbparser/tests/test_parsers.c000066400000000000000000000124321321171025300247350ustar00rootroot00000000000000/* * Copyright (c) 2013 Balabit * Copyright (c) 2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "testutils.h" #include /* NOTE: including the implementation file to access static functions */ #include "radix.c" #define PARSER_TESTCASE(x, ...) do { parser_testcase_begin(#x, #__VA_ARGS__); x(__VA_ARGS__); parser_testcase_end(); } while(0) #define parser_testcase_begin(func, args) \ do \ { \ testcase_begin("%s(%s)", func, args); \ } \ while (0) #define parser_testcase_end() \ do \ { \ testcase_end(); \ } \ while (0) static gboolean _invoke_parser(gboolean (*parser)(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match), const gchar *str, gpointer param, gpointer state, gchar **result_string) { gboolean result; gint len = 0; guint8 *dup = g_strdup(str); RParserMatch match; memset(&match, 0, sizeof(match)); result = parser(dup, &len, param, state, &match); if (match.match) { if (result) *result_string = g_strdup(match.match); } else { match.ofs = 0 + match.ofs; match.len = (gint16) match.len + len; if (result) *result_string = g_strndup(&dup[match.ofs], match.len); } g_free(dup); return result; } static void assert_parser_success(gboolean (*parser)(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match), const gchar *str, gpointer param, gpointer state, const gchar *expected_string) { gchar *result_string = NULL; gboolean result; result = _invoke_parser(parser, str, param, state, &result_string); assert_true(result, "Mismatching parser result"); assert_string(result_string, expected_string, "Mismatching parser result"); g_free(result_string); } static void assert_parser_failure(gboolean (*parser)(guint8 *str, gint *len, const gchar *param, gpointer state, RParserMatch *match), const gchar *str, gpointer param, gpointer state) { gboolean result; result = _invoke_parser(parser, str, param, state, NULL); assert_false(result, "Mismatching parser result"); } static void test_string_parser_without_parameter_parses_a_word(void) { assert_parser_success(r_parser_string, "foo", NULL, NULL, "foo"); assert_parser_success(r_parser_string, "foo bar", NULL, NULL, "foo"); assert_parser_success(r_parser_string, "foo123 bar", NULL, NULL, "foo123"); assert_parser_success(r_parser_string, "foo{}", NULL, NULL, "foo"); assert_parser_success(r_parser_string, "foo[]", NULL, NULL, "foo"); assert_parser_failure(r_parser_string, "", NULL, NULL); } static void test_string_parser_with_additional_end_characters(void) { assert_parser_success(r_parser_string, "foo", "X", NULL, "foo"); assert_parser_success(r_parser_string, "foo=bar", "=", NULL, "foo=bar"); } void test_string(void) { PARSER_TESTCASE(test_string_parser_without_parameter_parses_a_word); PARSER_TESTCASE(test_string_parser_with_additional_end_characters); } static gpointer compile_qstring_state(const gchar *quotes) { union { gpointer ptr; gchar ending_char; } state; memset(&state, 0, sizeof(state)); state.ending_char = quotes[1]; return state.ptr; } static void assert_qstring_parser_success(const gchar *str, gchar *quotes, const gchar *expected_string) { assert_parser_success(r_parser_qstring, str, quotes, compile_qstring_state(quotes), expected_string); } static void test_qstring_parser_extracts_word_from_quotes(void) { gchar *single_quotes = "''"; gchar *double_quotes = "\"\""; gchar *braces = "{}"; assert_qstring_parser_success("'foo'", single_quotes, "foo"); assert_qstring_parser_success("\"foo\"", double_quotes, "foo"); assert_qstring_parser_success("{foo}", braces, "foo"); } void test_qstring(void) { PARSER_TESTCASE(test_qstring_parser_extracts_word_from_quotes); } /* NOTE: incomplete, the rest of the testcases are missing */ int main(void) { test_string(); test_qstring(); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/tests/test_parsers_e2e.c000066400000000000000000000116751321171025300255000ustar00rootroot00000000000000/* * Copyright (c) 2010-2014 Balabit * Copyright (c) 2010-2014 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ gboolean fail = FALSE; gboolean verbose = FALSE; #define test_fail(fmt, args...) \ do {\ printf(fmt, ##args); \ fail = TRUE; \ } while (0); #define test_msg(fmt, args...) \ do { \ if (verbose) printf(fmt, ##args); \ } while (0); gchar *pdb_parser_skeleton_prefix ="\ \ \ \ test\ \ \ \ \ " /* HERE COMES THE GENERATED PATTERN */ ; gchar *pdb_parser_skeleton_postfix = /* HERE IS THE GENERATED PATTERN */ "\ \ \ \ \ "; void test_pattern(const gchar *pattern, const gchar *rule, gboolean match) { gboolean result; LogMessage *msg = log_msg_new_empty(); log_msg_set_value(msg, LM_V_HOST, MYHOST, strlen(MYHOST)); log_msg_set_value(msg, LM_V_PROGRAM, "test", strlen(MYHOST)); log_msg_set_value(msg, LM_V_MESSAGE, pattern, strlen(pattern)); result = pattern_db_process(patterndb, msg); if (match) { assert_true(result, "Value '%s' is not matching for pattern '%s'\n", rule, pattern); } else { assert_false(result, "Value '%s' is matching for pattern '%s'\n", rule, pattern); } log_msg_unref(msg); } void test_parser(gchar **test) { GString *str; gsize i = 1; str = g_string_new(pdb_parser_skeleton_prefix); g_string_append(str, test[0]); g_string_append(str, pdb_parser_skeleton_postfix); _load_pattern_db_from_string(str->str); g_string_free(str, TRUE); while(test[i] != NULL) test_pattern(test[i++], test[0], TRUE); i++; while(test[i] != NULL) test_pattern(test[i++], test[0], FALSE); _destroy_pattern_db(); } gchar *test1 [] = { "@ANYSTRING:TEST@", "ab ba ab", "ab ba ab", "1234ab", "ab1234", "1.2.3.4", "ab 1234 ba", "<ab ba>", NULL, NULL }; gchar *test2 [] = { "@DOUBLE:TEST@", "1234", "1234.567", "1.2.3.4", "1234ab", NULL, // not match "ab1234",NULL }; gchar *test3 [] = { "@ESTRING:TEST:endmark@", "ab ba endmark", NULL, "ab ba",NULL }; gchar *test4 [] = { "@ESTRING:TEST:>@", "ab ba > ab", NULL, "ab ba",NULL }; gchar *test5 [] = { "@FLOAT:TEST@", "1234", "1234.567", "1.2.3.4", "1234ab", NULL, // not match "ab1234",NULL }; gchar *test6 [] = { "@SET:TEST: @", " a ", " a ", " a ", " a ", NULL, // not match "ab1234",NULL }; gchar *test7 [] = { "@IPv4:TEST@", "1.2.3.4", "0.0.0.0", "255.255.255.255", NULL, "256.256.256.256", "1234", "ab1234", "ab1.2.3.4", "1,2,3,4",NULL }; gchar *test8 [] = { "@IPv6:TEST@", "2001:0db8:0000:0000:0000:0000:1428:57ab", "2001:0db8:0000:0000:0000::1428:57ab", "2001:0db8:0:0:0:0:1428:57ab", "2001:0db8:0:0::1428:57ab", "2001:0db8::1428:57ab", "2001:db8::1428:57ab", NULL, "2001:0db8::34d2::1428:57ab",NULL }; gchar *test9 [] = { "@IPvANY:TEST@", "1.2.3.4", "0.0.0.0", "255.255.255.255", "2001:0db8:0000:0000:0000:0000:1428:57ab", "2001:0db8:0000:0000:0000::1428:57ab", "2001:0db8:0:0:0:0:1428:57ab", "2001:0db8:0:0::1428:57ab", "2001:0db8::1428:57ab", "2001:db8::1428:57ab", NULL, "256.256.256.256", "1234", "ab1234", "ab1.2.3.4", "1,2,3,4", "2001:0db8::34d2::1428:57ab",NULL }; gchar *test10 [] = { "@NUMBER:TEST@", "1234", "1.2", "1.2.3.4", "1234ab", NULL, "ab1234", NULL }; gchar *test11 [] = { "@QSTRING:TEST:<>@", "", "< aabb >", NULL, "aabb>", " * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "apphook.h" #include "logmsg/logmsg.h" #include "messages.h" #include "filter/filter-expr.h" #include "patterndb.h" #include "pdb-file.h" #include "plugin.h" #include "cfg.h" #include "timerwheel.h" #include "libtest/msg_parse_lib.h" #include #include #include #include #include #include #define MYHOST "MYHOST" #define MYPID "999" PatternDB *patterndb; gchar *filename; GPtrArray *messages; gboolean keep_patterndb_state = FALSE; static void _emit_func(LogMessage *msg, gboolean synthetic, gpointer user_data) { g_ptr_array_add(messages, log_msg_ref(msg)); } static void assert_pdb_file_valid(const gchar *filename_, const gchar *pdb) { GError *error = NULL; gboolean success; success = pdb_file_validate_in_tests(filename_, &error); assert_true(success, "Error validating patterndb, error=%s\n>>>\n%s\n<<<", error ? error->message : "unknown", pdb); g_clear_error(&error); } static void _load_pattern_db_from_string(const gchar *pdb) { patterndb = pattern_db_new(); messages = g_ptr_array_new(); pattern_db_set_emit_func(patterndb, _emit_func, NULL); g_file_open_tmp("patterndbXXXXXX.xml", &filename, NULL); g_file_set_contents(filename, pdb, strlen(pdb), NULL); assert_pdb_file_valid(filename, pdb); assert_true(pattern_db_reload_ruleset(patterndb, configuration, filename), "Error loading ruleset [[[%s]]]", pdb); assert_string(pattern_db_get_ruleset_pub_date(patterndb), "2010-02-22", "Invalid pubdate"); } static void _destroy_pattern_db(void) { if (messages) { g_ptr_array_foreach(messages, (GFunc) log_msg_unref, NULL); g_ptr_array_free(messages, TRUE); } messages = NULL; pattern_db_free(patterndb); patterndb = NULL; g_unlink(filename); g_free(filename); filename = NULL; } static void _reset_pattern_db_state(void) { pattern_db_forget_state(patterndb); g_ptr_array_foreach(messages, (GFunc) log_msg_unref, NULL); g_ptr_array_set_size(messages, 0); } static gboolean _process(LogMessage *msg) { if (!keep_patterndb_state) _reset_pattern_db_state(); keep_patterndb_state = FALSE; return pattern_db_process(patterndb, msg); } static void _dont_reset_patterndb_state_for_the_next_call(void) { keep_patterndb_state = TRUE; } static void _advance_time(gint timeout) { if (timeout) pattern_db_advance_time(patterndb, timeout + 1); } static LogMessage * _get_output_message(gint ndx) { assert_true(ndx < messages->len, "Expected the %d. message, but no such message was returned by patterndb\n", ndx); return (LogMessage *) g_ptr_array_index(messages, ndx); } static LogMessage * _construct_message_with_nvpair(const gchar *program, const gchar *message, const gchar *name, const gchar *value) { LogMessage *msg = log_msg_new_empty(); log_msg_set_value(msg, LM_V_MESSAGE, message, strlen(message)); log_msg_set_value(msg, LM_V_PROGRAM, program, strlen(program)); log_msg_set_value(msg, LM_V_HOST, MYHOST, strlen(MYHOST)); log_msg_set_value(msg, LM_V_PID, MYPID, strlen(MYPID)); if (name) log_msg_set_value_by_name(msg, name, value, -1); msg->timestamps[LM_TS_STAMP].tv_sec = msg->timestamps[LM_TS_RECVD].tv_sec; return msg; } static LogMessage * _construct_message(const gchar *program, const gchar *message) { return _construct_message_with_nvpair(program, message, NULL, NULL); } static void _feed_message_to_correllation_state(const gchar *program, const gchar *message, const gchar *name, const gchar *value) { LogMessage *msg; gboolean result; msg = _construct_message_with_nvpair(program, message, name, value); result = _process(msg); log_msg_unref(msg); assert_true(result, "patterndb expected to match but it didn't"); _dont_reset_patterndb_state_for_the_next_call(); } static void assert_msg_with_program_matches_and_nvpair_equals(const gchar *program, const gchar *message, const gchar *name, const gchar *expected_value) { LogMessage *msg; gboolean result; msg = _construct_message(program, message); result = _process(msg); assert_true(result, "patterndb expected to match but it didn't"); assert_log_message_value(msg, log_msg_get_value_handle(name), expected_value); log_msg_unref(msg); } static void assert_msg_doesnot_match(const gchar *message) { LogMessage *msg; gboolean result; msg = _construct_message("prog1", message); result = _process(msg); assert_false(result, "patterndb expected to match but it didn't"); assert_log_message_value(msg, log_msg_get_value_handle(".classifier.class"), "unknown"); assert_log_message_has_tag(msg, ".classifier.unknown"); log_msg_unref(msg); } static void assert_msg_matches_and_nvpair_equals(const gchar *pattern, const gchar *name, const gchar *value) { assert_msg_with_program_matches_and_nvpair_equals("prog1", pattern, name, value); } static void assert_msg_matches_and_has_tag(const gchar *pattern, const gchar *tag, gboolean set) { LogMessage *msg; gboolean result; msg = _construct_message("prog1", pattern); result = _process(msg); assert_true(result, "patterndb expected to match but it didn't"); if (set) assert_log_message_has_tag(msg, tag); else assert_log_message_doesnt_have_tag(msg, tag); log_msg_unref(msg); } void assert_output_message_nvpair_equals(gint ndx, const gchar *name, const gchar *value) { assert_log_message_value(_get_output_message(ndx), log_msg_get_value_handle(name), value); } void assert_msg_matches_and_output_message_nvpair_equals_with_timeout(const gchar *pattern, gint timeout, gint ndx, const gchar *name, const gchar *value) { LogMessage *msg; msg = _construct_message("prog2", pattern); _process(msg); _advance_time(timeout); assert_output_message_nvpair_equals(ndx, name, value); log_msg_unref(msg); } static void assert_no_such_output_message(gint ndx) { assert_true(ndx >= messages->len, "Unexpected message generated at %d index\n", ndx); } void assert_msg_matches_and_no_such_output_message(const gchar *pattern, gint ndx) { LogMessage *msg; msg = _construct_message("prog2", pattern); _process(msg); assert_no_such_output_message(ndx); log_msg_unref(msg); } void assert_msg_matches_and_output_message_nvpair_equals(const gchar *pattern, gint ndx, const gchar *name, const gchar *value) { assert_msg_matches_and_output_message_nvpair_equals_with_timeout(pattern, 0, ndx, name, value); } void assert_output_message_has_tag(gint ndx, const gchar *tag, gboolean set) { if (set) assert_log_message_has_tag(_get_output_message(ndx), tag); else assert_log_message_doesnt_have_tag(_get_output_message(ndx), tag); } void assert_msg_matches_and_output_message_has_tag_with_timeout(const gchar *pattern, gint timeout, gint ndx, const gchar *tag, gboolean set) { LogMessage *msg; msg = _construct_message("prog2", pattern); _process(msg); _advance_time(timeout); assert_output_message_has_tag(ndx, tag, set); log_msg_unref(msg); } void assert_msg_matches_and_output_message_has_tag(const gchar *pattern, gint ndx, const gchar *tag, gboolean set) { assert_msg_matches_and_output_message_has_tag_with_timeout(pattern, 0, ndx, tag, set); } gchar *pdb_conflicting_rules_with_different_parsers = "\ \ \ prog1\ prog2\ \ \ \ \ \ pattern @ESTRING:foo1: @\ \ \ \ \ pattern @ESTRING:foo2: @tail\ \ \ \ \ "; static void test_conflicting_rules_with_different_parsers(void) { _load_pattern_db_from_string(pdb_conflicting_rules_with_different_parsers); /* the short rule matches completely, the other doesn't */ assert_msg_matches_and_nvpair_equals("pattern foobar ", ".classifier.rule_id", "11"); /* we have a longer rule, even though both rules would match */ assert_msg_matches_and_nvpair_equals("pattern foobar tail", ".classifier.rule_id", "12"); /* the longest rule didn't match, so use the shorter one as a partial match */ assert_msg_matches_and_nvpair_equals("pattern foobar something else", ".classifier.rule_id", "11"); _destroy_pattern_db(); } gchar *pdb_conflicting_rules_with_the_same_parsers = "\ \ \ prog1\ prog2\ \ \ \ \ \ pattern @ESTRING:foo: @\ \ \ \ \ pattern @ESTRING:foo: @tail\ \ \ \ \ "; static void test_conflicting_rules_with_the_same_parsers(void) { _load_pattern_db_from_string(pdb_conflicting_rules_with_the_same_parsers); /* the short rule matches completely, the other doesn't */ assert_msg_matches_and_nvpair_equals("pattern foobar ", ".classifier.rule_id", "11"); /* we have a longer rule, even though both rules would match */ assert_msg_matches_and_nvpair_equals("pattern foobar tail", ".classifier.rule_id", "12"); /* the longest rule didn't match, so use the shorter one as a partial match */ assert_msg_matches_and_nvpair_equals("pattern foobar something else", ".classifier.rule_id", "11"); _destroy_pattern_db(); } /* pdb skeleton used to test patterndb rule actions. E.g. whenever a rule * matches, certain actions described in the rule need to be performed. * This tests those */ gchar *pdb_ruletest_skeleton = "\ \ This is a test set\ \ prog1\ prog2\ \ \ \ \ simple-message\ \ \ simple-msg-tag1\ simple-msg-tag2\ \ \ value1\ value2\ ${HOST}\ \ \ \ \ correllated-message-based-on-pid\ \ \ ${CONTEXT_ID}\ $(context-length)\ \ \ \ \ correllated-message-with-action-on-match\ \ \ \ \ \ generated-message-on-match\ ${CONTEXT_ID}\ \ \ correllated-msg-tag\ \ \ \ \ \ \ \ correllated-message-with-action-on-timeout\ \ \ \ \ \ generated-message-on-timeout\ \ \ \ \ \ \ \ correllated-message-with-action-condition\ \ \ \ \ \ not-generated-message\ \ \ \ \ \ \ generated-message-on-condition\ \ \ \ \ \ \ \ correllated-message-with-rate-limited-action\ \ \ \ \ \ generated-message-rate-limit\ \ \ \ \ \ \ \ simple-message-with-action-on-match\ \ \ \ \ \ generated-message-on-match\ ${CONTEXT_ID}\ \ \ simple-msg-tag\ \ \ \ \ \ \ \ simple-message-with-action-condition\ \ \ \ \ \ not-generated-message\ \ \ \ \ \ \ generated-message-on-condition\ \ \ \ \ \ \ \ simple-message-with-rate-limited-action\ \ \ \ \ \ generated-message-rate-limit\ \ \ \ \ \ \ simple-message-with-rate-limited-action\ \ prog1\ foobar\ \ \ \ simple-message-with-rate-limited-action\ \ \ \ \ \ simple-message-with-action-to-create-context\ \ \ \ \ \ \ context message\ \ \ \ \ \ \ \ \ correllated-message-that-uses-context-created-by-rule-id#12\ \ \ ${MESSAGE}@1 assd\ \ \ \ \ correllated-message-with-action-to-create-context\ \ \ ${.classifier.context_id}\ \ \ \ \ \ \ \ context message ${rule-msg-context-id}\ \ \ \ \ \ \ \ \ correllated-message-that-uses-context-created-by-rule-id#14\ \ \ ${MESSAGE}@1 assd\ $(grep ('${rule-msg-context-id}' ne '') ${rule-msg-context-id})\ \ \ \ \ "; static void test_simple_rule_without_context_or_actions(void) { /* tag assigned based on "class" */ assert_msg_matches_and_has_tag("simple-message", ".classifier.system", TRUE); /* tag assignment based on */ assert_msg_matches_and_nvpair_equals("simple-message", "TAGS", ".classifier.system,simple-msg-tag1,simple-msg-tag2"); assert_msg_matches_and_nvpair_equals("simple-message", "simple-msg-value-1", "value1"); assert_msg_matches_and_nvpair_equals("simple-message", "simple-msg-value-2", "value2"); assert_msg_matches_and_nvpair_equals("simple-message", "simple-msg-host", MYHOST); } static void test_correllation_rule_without_actions(void) { /* tag assigned based on "class" */ assert_msg_matches_and_has_tag("correllated-message-based-on-pid", ".classifier.system", TRUE); assert_msg_matches_and_nvpair_equals("correllated-message-based-on-pid", "correllated-msg-context-id", MYPID); assert_msg_matches_and_nvpair_equals("correllated-message-based-on-pid", "correllated-msg-context-length", "1"); _dont_reset_patterndb_state_for_the_next_call(); assert_msg_matches_and_nvpair_equals("correllated-message-based-on-pid", "correllated-msg-context-length", "2"); _dont_reset_patterndb_state_for_the_next_call(); assert_msg_matches_and_nvpair_equals("correllated-message-based-on-pid", "correllated-msg-context-length", "3"); } static void test_correllation_rule_with_action_on_match(void) { /* tag assigned based on "class" */ assert_msg_matches_and_has_tag("correllated-message-with-action-on-match", ".classifier.violation", TRUE); assert_msg_matches_and_output_message_nvpair_equals("correllated-message-with-action-on-match", 1, "MESSAGE", "generated-message-on-match"); assert_msg_matches_and_output_message_nvpair_equals("correllated-message-with-action-on-match", 1, "context-id", "999"); assert_msg_matches_and_output_message_has_tag("correllated-message-with-action-on-match", 1, "correllated-msg-tag", TRUE); } static void test_correllation_rule_with_action_on_timeout(void) { /* tag assigned based on "class" */ assert_msg_matches_and_has_tag("correllated-message-with-action-on-timeout", ".classifier.violation", TRUE); assert_msg_matches_and_output_message_nvpair_equals_with_timeout("correllated-message-with-action-on-timeout", 60, 1, "MESSAGE", "generated-message-on-timeout"); } static void test_correllation_rule_with_action_condition(void) { /* tag assigned based on "class" */ assert_msg_matches_and_has_tag("correllated-message-with-action-condition", ".classifier.violation", TRUE); assert_msg_matches_and_output_message_nvpair_equals("correllated-message-with-action-condition", 1, "MESSAGE", "generated-message-on-condition"); } static void test_correllation_rule_with_rate_limited_action(void) { /* tag assigned based on "class" */ assert_msg_matches_and_has_tag("correllated-message-with-rate-limited-action", ".classifier.violation", TRUE); /* messages in the output: * [0] trigger * [1] GENERATED (as rate limit was met) * [2] trigger * [3] trigger * [4] trigger * [5] GENERATED (as rate limit was met again due to advance time */ assert_msg_matches_and_output_message_nvpair_equals("correllated-message-with-rate-limited-action", 1, "MESSAGE", "generated-message-rate-limit"); _dont_reset_patterndb_state_for_the_next_call(); assert_msg_matches_and_no_such_output_message("correllated-message-with-rate-limited-action", 3); _dont_reset_patterndb_state_for_the_next_call(); assert_msg_matches_and_no_such_output_message("correllated-message-with-rate-limited-action", 4); _dont_reset_patterndb_state_for_the_next_call(); _advance_time(120); assert_msg_matches_and_output_message_nvpair_equals("correllated-message-with-rate-limited-action", 5, "MESSAGE", "generated-message-rate-limit"); } static void test_simple_rule_with_action_on_match(void) { /* tag assigned based on "class" */ assert_msg_matches_and_has_tag("simple-message-with-action-on-match", ".classifier.violation", TRUE); assert_msg_matches_and_output_message_nvpair_equals("simple-message-with-action-on-match", 1, "MESSAGE", "generated-message-on-match"); assert_msg_matches_and_output_message_has_tag("simple-message-with-action-on-match", 1, "simple-msg-tag", TRUE); } static void test_simple_rule_with_rate_limited_action(void) { /* tag assigned based on "class" */ assert_msg_matches_and_has_tag("simple-message-with-rate-limited-action", ".classifier.violation", TRUE); /* messages in the output: * [0] trigger * [1] GENERATED (as rate limit was met) * [2] trigger * [3] trigger * [4] trigger * [5] GENERATED (as rate limit was met again due to advance time */ assert_msg_matches_and_output_message_nvpair_equals("simple-message-with-rate-limited-action", 1, "MESSAGE", "generated-message-rate-limit"); _dont_reset_patterndb_state_for_the_next_call(); assert_msg_matches_and_no_such_output_message("simple-message-with-rate-limited-action", 3); _dont_reset_patterndb_state_for_the_next_call(); assert_msg_matches_and_no_such_output_message("simple-message-with-rate-limited-action", 4); _dont_reset_patterndb_state_for_the_next_call(); _advance_time(120); assert_msg_matches_and_output_message_nvpair_equals("simple-message-with-rate-limited-action", 5, "MESSAGE", "generated-message-rate-limit"); } static void test_simple_rule_with_action_condition(void) { /* tag assigned based on "class" */ assert_msg_matches_and_has_tag("simple-message-with-action-condition", ".classifier.violation", TRUE); assert_msg_matches_and_output_message_nvpair_equals("simple-message-with-action-condition", 1, "MESSAGE", "generated-message-on-condition"); } static void test_correllation_rule_with_create_context(void) { assert_msg_matches_and_nvpair_equals("simple-message-with-action-to-create-context", ".classifier.rule_id", "12"); _dont_reset_patterndb_state_for_the_next_call(); assert_msg_matches_and_nvpair_equals("correllated-message-that-uses-context-created-by-rule-id#12", "triggering-message", "context message assd"); _dont_reset_patterndb_state_for_the_next_call(); assert_msg_matches_and_nvpair_equals("correllated-message-that-uses-context-created-by-rule-id#12", "PROGRAM", "prog1"); assert_msg_matches_and_nvpair_equals("correllated-message-with-action-to-create-context", ".classifier.rule_id", "14"); _dont_reset_patterndb_state_for_the_next_call(); assert_msg_matches_and_nvpair_equals("correllated-message-that-uses-context-created-by-rule-id#14", "triggering-message", "context message 1001 assd"); _dont_reset_patterndb_state_for_the_next_call(); assert_msg_matches_and_nvpair_equals("correllated-message-that-uses-context-created-by-rule-id#14", "PROGRAM", "prog1"); _dont_reset_patterndb_state_for_the_next_call(); assert_msg_matches_and_nvpair_equals("correllated-message-that-uses-context-created-by-rule-id#14", "triggering-message-context-id", "1001"); } static void test_patterndb_rule(void) { _load_pattern_db_from_string(pdb_ruletest_skeleton); test_simple_rule_without_context_or_actions(); test_correllation_rule_without_actions(); test_correllation_rule_with_action_on_match(); test_correllation_rule_with_action_on_timeout(); test_correllation_rule_with_action_condition(); test_correllation_rule_with_rate_limited_action(); test_simple_rule_with_action_on_match(); test_simple_rule_with_action_condition(); test_simple_rule_with_rate_limited_action(); test_correllation_rule_with_create_context(); assert_msg_doesnot_match("non-matching-pattern"); _destroy_pattern_db(); } const gchar *pdb_complete_syntax = "\ \ \ http://foobar.org/\ \ http://foobar.org/1\ http://foobar.org/2\ \ This is a test set\ \ prog2\ prog3\ \ prog1\ \ \ This is a rule description\ \ http://foobar.org/1\ http://foobar.org/2\ \ \ simple-message\ simple-message-alternative\ \ \ simple-msg-tag1\ simple-msg-tag2\ \ \ value1\ value2\ ${HOST}\ \ \ \ This is foobar message\ \ foo\ bar\ \ \ \ \ \ \ \ foo\ bar\ \ \ tag1\ tag2\ \ \ \ \ \ \ \ foo\ bar\ \ \ tag1\ tag2\ \ \ \ \ \ \ \ \ \ "; static void test_patterndb_loads_a_syntactically_complete_xml_properly(void) { _load_pattern_db_from_string(pdb_complete_syntax); /* check we did indeed load the patterns */ assert_msg_matches_and_has_tag("simple-message", ".classifier.system", TRUE); _destroy_pattern_db(); } gchar *pdb_inheritance_enabled_skeleton = "\ \ \ prog2\ \ \ \ \ pattern-with-inheritance-enabled\ \ \ basetag1\ basetag2\ \ \ \ \ \ actionvalue\ \ \ actiontag\ \ \ \ \ \ \ \ "; void test_patterndb_message_property_inheritance_enabled(void) { _load_pattern_db_from_string(pdb_inheritance_enabled_skeleton); assert_msg_matches_and_output_message_nvpair_equals("pattern-with-inheritance-enabled", 1, "MESSAGE", "pattern-with-inheritance-enabled"); assert_msg_matches_and_output_message_has_tag("pattern-with-inheritance-enabled", 1, "basetag1", TRUE); assert_msg_matches_and_output_message_has_tag("pattern-with-inheritance-enabled", 1, "basetag2", TRUE); assert_msg_matches_and_output_message_has_tag("pattern-with-inheritance-enabled", 1, "actiontag", TRUE); assert_msg_matches_and_output_message_nvpair_equals("pattern-with-inheritance-enabled", 1, "actionkey", "actionvalue"); _destroy_pattern_db(); } gchar *pdb_inheritance_disabled_skeleton = "\ \ \ prog2\ \ \ \ \ pattern-with-inheritance-disabled\ \ \ basetag1\ basetag2\ \ \ \ \ \ actionvalue\ \ \ actiontag\ \ \ \ \ \ \ \ "; void test_patterndb_message_property_inheritance_disabled(void) { _load_pattern_db_from_string(pdb_inheritance_disabled_skeleton); assert_msg_matches_and_output_message_nvpair_equals("pattern-with-inheritance-disabled", 1, "MESSAGE", NULL); assert_msg_matches_and_output_message_has_tag("pattern-with-inheritance-disabled", 1, "basetag1", FALSE); assert_msg_matches_and_output_message_has_tag("pattern-with-inheritance-disabled", 1, "basetag2", FALSE); assert_msg_matches_and_output_message_has_tag("pattern-with-inheritance-disabled", 1, "actiontag", TRUE); assert_msg_matches_and_output_message_nvpair_equals("pattern-with-inheritance-disabled", 1, "actionkey", "actionvalue"); _destroy_pattern_db(); } gchar *pdb_inheritance_context_skeleton = "\ \ \ \ prog2\ \ \ \ \ pattern-with-inheritance-context\ \ \ basetag1\ basetag2\ \ \ \ \ \ action message\ \ \ actiontag\ \ \ \ \ \ \ \ "; void test_patterndb_message_property_inheritance_context(void) { _load_pattern_db_from_string(pdb_inheritance_context_skeleton); _feed_message_to_correllation_state("prog2", "pattern-with-inheritance-context", "merged1", "merged1"); _feed_message_to_correllation_state("prog2", "pattern-with-inheritance-context", "merged2", "merged2"); _advance_time(60); assert_output_message_nvpair_equals(2, "MESSAGE", "action message"); assert_output_message_nvpair_equals(2, "merged1", "merged1"); assert_output_message_nvpair_equals(2, "merged2", "merged2"); assert_output_message_has_tag(2, "actiontag", TRUE); _destroy_pattern_db(); } void test_patterndb_message_property_inheritance(void) { test_patterndb_message_property_inheritance_enabled(); test_patterndb_message_property_inheritance_disabled(); test_patterndb_message_property_inheritance_context(); } gchar *pdb_msg_count_skeleton = "\ \ \ prog1\ prog2\ \ \ \ \ pattern13\ \ \ v13-1\ \ \ \ \ \ $(context-length)\ \ \ \ \ \ \ \ pattern14\ \ \ \ \ \ $(context-length)\ \ \ \ \ \ \ \ pattern15@ANYSTRING:p15@\ \ \ \ \ \ true\ \ \ \ \ \ \ \ "; void test_patterndb_context_length(void) { _load_pattern_db_from_string(pdb_msg_count_skeleton); assert_msg_matches_and_output_message_nvpair_equals("pattern13", 1, "CONTEXT_LENGTH", "2"); assert_msg_matches_and_output_message_nvpair_equals("pattern14", 1, "CONTEXT_LENGTH", "2"); assert_msg_with_program_matches_and_nvpair_equals("prog2", "pattern15-a", "p15", "-a"); _dont_reset_patterndb_state_for_the_next_call(); assert_msg_matches_and_output_message_nvpair_equals("pattern15-b", 2, "fired", "true"); _destroy_pattern_db(); } gchar *tag_outside_of_rule_skeleton = "\ \ \ prog1\ \ \ tag1\ \ \ "; void test_patterndb_tags_outside_of_rule(void) { patterndb = pattern_db_new(); messages = NULL; g_file_open_tmp("patterndbXXXXXX.xml", &filename, NULL); g_file_set_contents(filename, tag_outside_of_rule_skeleton, strlen(tag_outside_of_rule_skeleton), NULL); assert_false(pattern_db_reload_ruleset(patterndb, configuration, filename), "successfully loaded an invalid patterndb file"); _destroy_pattern_db(); } #include "test_parsers_e2e.c" int main(int argc, char *argv[]) { app_startup(); msg_init(TRUE); configuration = cfg_new_snippet(); cfg_load_module(configuration, "basicfuncs"); cfg_load_module(configuration, "syslogformat"); pattern_db_global_init(); test_conflicting_rules_with_different_parsers(); test_conflicting_rules_with_the_same_parsers(); test_patterndb_rule(); test_patterndb_loads_a_syntactically_complete_xml_properly(); test_patterndb_parsers(); test_patterndb_message_property_inheritance(); test_patterndb_context_length(); test_patterndb_tags_outside_of_rule(); app_shutdown(); return 0; } syslog-ng-syslog-ng-3.13.2/modules/dbparser/tests/test_patternize.c000066400000000000000000000257051321171025300254520ustar00rootroot00000000000000/* * Copyright (c) 2010-2013 Balabit * Copyright (c) 2010-2013 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "patternize.h" #include "logmsg/logmsg.h" #include "cfg.h" #include "plugin.h" #include "apphook.h" #include #include #include gboolean fail = FALSE; MsgFormatOptions parse_options; static void _debug_print(gpointer key, gpointer value, gpointer dummy) { fprintf(stderr, "%s: %d\n", (gchar *) key, *((guint *) value)); } static void _debug_print2(gpointer key, gpointer value, gpointer dummy) { fprintf(stderr, "%s: %d\n", (gchar *) key, ((Cluster *) value)->loglines->len); } typedef struct _loglinesType { GPtrArray *logmessages; guint num_of_logs; } loglinesType; loglinesType * testcase_get_logmessages(gchar *logs) { int i, len; loglinesType *self; gchar **input_lines; gchar *logline; GSockAddr *addr = g_sockaddr_inet_new("10.10.10.10", 1010); LogMessage *msg; self = g_new(loglinesType, 1); self->logmessages = g_ptr_array_sized_new(10); self->num_of_logs = 0; input_lines = g_strsplit(logs, "\n", 0); for (i = 0; input_lines[i]; ++i) { logline = g_strdup_printf("Jul 29 06:25:41 vav zorp/inter_http[27940]: %s", input_lines[i]); len = strlen(logline); if (logline[len-1] == '\n') logline[len-1] = 0; msg = log_msg_new(logline, len, addr, &parse_options); g_ptr_array_add(self->logmessages, msg); ++(self->num_of_logs); g_free(logline); } msg_format_options_destroy(&parse_options); g_strfreev(input_lines); return self; } void testcase_frequent_words(gchar *logs, guint support, gchar *expected) { int i, twopass; gchar **expecteds; GHashTable *wordlist; loglinesType *logmessages; gchar *delimiters = " :&~?![]=,;()'\""; logmessages = testcase_get_logmessages(logs); expecteds = g_strsplit(expected, ",", 0); for (twopass = 1; twopass <= 2; ++twopass) { wordlist = ptz_find_frequent_words(logmessages->logmessages, support, delimiters, twopass == 1); for (i = 0; expecteds[i]; ++i) { char **expected_item; char *expected_word; int expected_occurance; guint ret; gpointer retp; expected_item = g_strsplit(expecteds[i], ":", 2); expected_word = expected_item[0]; sscanf(expected_item[1], "%d", &expected_occurance); retp = g_hash_table_lookup(wordlist, expected_word); if (retp) { ret = *((guint *) retp); } else { ret = 0; } if (ret != (guint) expected_occurance) { fail = TRUE; fprintf(stderr, "Frequent words test case failed; word: '%s', expected=%d, got=%d, support=%d\n", expected_word, expected_occurance, ret, support); fprintf(stderr, "Input:\n%s\n", logs); fprintf(stderr, "Full results:\n"); g_hash_table_foreach(wordlist, _debug_print, NULL); } g_strfreev(expected_item); } } // cleanup g_strfreev(expecteds); for (i = 0; i < logmessages->num_of_logs; ++i) log_msg_unref((LogMessage *) g_ptr_array_index(logmessages->logmessages, i)); g_ptr_array_free(logmessages->logmessages, TRUE); g_free(logmessages); } void frequent_words_tests(void) { /* simple tests */ testcase_frequent_words( "a\n", 0, "0 a:1"); testcase_frequent_words( "a b\n", 0, "0 a:1," "1 b:1"); testcase_frequent_words( "a a\n" "b b", 0, "0 a:1,1 a:1," "0 b:1,1 b:1"); testcase_frequent_words( "a b\n" "b a", 0, "0 a:1,1 a:1," "0 b:1,1 b:1"); testcase_frequent_words( "a b\n" "a b", 0, "0 a:2," "1 b:2"); /* support threshold tests */ testcase_frequent_words( "a\n", 1, ""); testcase_frequent_words( "a b\n", 1, ""); testcase_frequent_words( "a b\n" "b a", 1, "0 a:1,1 a:1," "0 b:1,1 b:1"); testcase_frequent_words( "a b\n" "b a\n" "a c", 2, "0 a:2"); } typedef struct _clusterfindData { guint *lines; guint num_of_lines; guint support; GPtrArray *logs; } clusterfindData; typedef struct _clusterfind2Data { gchar *search_line; gboolean found; guint lines_in_cluster; } clusterfind2Data; void test_clusters_loglines_find(gpointer value, gpointer user_data) { clusterfind2Data *data; LogMessage *msg; gchar *msgstr; gssize msglen; data = (clusterfind2Data *) user_data; msg = (LogMessage *) value; ++(data->lines_in_cluster); msgstr = (gchar *) log_msg_get_value(msg, LM_V_MESSAGE, &msglen); if (strcmp(data->search_line, msgstr) == 0) data->found = TRUE; } gboolean test_clusters_find(gpointer key, gpointer value, gpointer user_data) { int i; gchar *line; clusterfindData *data; clusterfind2Data *find_data; gboolean found; guint lines_in_cluster = 0, lines_found = 0; gssize msglen; data = ((clusterfindData *) user_data); found = TRUE; for (i = 0; i < data->num_of_lines; ++i) { line = g_strdup((gchar *) log_msg_get_value((LogMessage *) g_ptr_array_index(data->logs, data->lines[i]), LM_V_MESSAGE, &msglen)); find_data = g_new(clusterfind2Data, 1); find_data->search_line = line; find_data->found = FALSE; /* we count the number of lines in the cluster several times this way, * but why on earth should we optimize a unit test?... :) */ find_data->lines_in_cluster = 0; g_ptr_array_foreach(((Cluster *) value)->loglines, test_clusters_loglines_find, find_data); if (find_data->found) ++lines_found; else found = FALSE; lines_in_cluster = find_data->lines_in_cluster; g_free(find_data); g_free(line); /* at least one line is missing, this cannot be a match */ if (!found) return FALSE; } /* if we got to this point, this means we have found all required rows, so we * only have to check for completeness */ if (data->num_of_lines == lines_in_cluster) return TRUE; else return FALSE; } void testcase_find_clusters_slct(gchar *logs, guint support, gchar *expected) { int i,j; gchar **expecteds; loglinesType *logmessages; clusterfindData *find_data; GHashTable *clusters; Cluster *test_cluster; gchar *delimiters = " :&~?![]=,;()'\""; logmessages = testcase_get_logmessages(logs); clusters = ptz_find_clusters_slct(logmessages->logmessages, support, delimiters, 0); expecteds = g_strsplit(expected, "|", 0); for (i = 0; expecteds[i]; ++i) { gchar **expected_item, **expected_lines_s; guint expected_lines[100]; guint num_of_expected_lines = 0; guint expected_support; expected_item = g_strsplit(expecteds[i], ":", 0); sscanf(expected_item[1], "%d", &expected_support); expected_lines_s = g_strsplit(expected_item[0], ",", 0); for (j = 0; expected_lines_s[j]; ++j) { sscanf(expected_lines_s[j], "%d", &expected_lines[j]); ++num_of_expected_lines; } find_data = g_new(clusterfindData, 1); find_data->lines = expected_lines; find_data->num_of_lines = num_of_expected_lines; find_data->logs = logmessages->logmessages; test_cluster = (Cluster *) g_hash_table_find(clusters, test_clusters_find, find_data); if (!test_cluster || test_cluster->loglines->len != expected_support) { if (!test_cluster) fprintf(stderr, "No cluster found;"); else fprintf(stderr, "Support value does not match;"); fprintf(stderr, " expected_cluster='%s', expected_support='%d'\n", expected_item[0], expected_support); fprintf(stderr, "Input:\n%s\n", logs); fprintf(stderr, "Got clusters:\n"); g_hash_table_foreach(clusters, _debug_print2, NULL); fail = TRUE; } g_free(find_data); // g_strfreev(expected_line_strings); // FIXME: this segfaults, so let's leak it instead :) g_strfreev(expected_item); g_strfreev(expected_lines_s); } g_hash_table_unref(clusters); for (i = 0; i < logmessages->num_of_logs; ++i) log_msg_unref((LogMessage *) g_ptr_array_index(logmessages->logmessages, i)); g_ptr_array_free(logmessages->logmessages, TRUE); g_free(logmessages); g_strfreev(expecteds); } void find_clusters_slct_tests(void) { testcase_find_clusters_slct( "a\n", 0, "0:1"); testcase_find_clusters_slct( "a\n" "b\n", 0, "0:1|1:1"); testcase_find_clusters_slct( "a\n" "b\n" "a\n" "b\n", 2, "0,2:2|1,3:2"); testcase_find_clusters_slct( "alma korte korte alma\n" "alma korte\n" "bela korte\n" "alma\n", 1, "0:1|1:1|2:1|3:1"); /* testcase_find_clusters_slct( "alma korte korte alma\n" "alma korte\n" "bela korte\n" "alma\n", 2, "0,1:2"); testcase_find_clusters_slct( "alma korte korte alma\n" "alma korte\n" "bela korte\n" "alma\n", 3, "0,1,3:3"); // FIXME: will this happen this way? */ testcase_find_clusters_slct( "alma korte\n" "alma korte\n" "alma korte\n" "alma korte\n" "bela korte\n" "bela korte\n" "alma\n", 2, "0,1,2,3:4|4,5:2"); testcase_find_clusters_slct( "alma korte\n" "alma korte\n" "alma korte\n" "alma korte\n" "bela korte\n" "bela korte\n" "alma\n", 3, "0,1,2,3:4"); testcase_find_clusters_slct( "alma korte asdf1 labda\n" "alma korte asdf2 labda\n" "alma korte asdf3 labda\n" "sallala\n", 3, "0,1,2:3"); testcase_find_clusters_slct( "alma korte asdf1 labda qwe1\n" "alma korte asdf2 labda qwe2\n" "alma korte asdf3 labda qwe3\n" "sallala\n", 3, "0,1,2:3"); } int main(void) { app_startup(); configuration = cfg_new_snippet(); cfg_load_module(configuration, "syslogformat"); msg_format_options_defaults(&parse_options); msg_format_options_init(&parse_options, configuration); frequent_words_tests(); find_clusters_slct_tests(); log_tags_global_deinit(); return (fail ? 1 : 0); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/tests/test_radix.c000066400000000000000000000707141321171025300243740ustar00rootroot00000000000000/* * Copyright (c) 2008-2015 Balabit * Copyright (c) 2008-2015 Balázs Scheidler * Copyright (c) 2009 Marton Illes * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "apphook.h" #include "radix.h" #include "messages.h" #include #include #include #include #include gboolean fail = FALSE; gboolean verbose = FALSE; void r_print_node(RNode *node, int depth); void r_print_pnode(RNode *node, int depth) { int i; for (i = 0; i < depth; i++) printf(" "); printf("%dPNODE: %d('%s') => '%s'\n", depth, node->parser->type, log_msg_get_value_name(node->parser->handle, NULL), (char *)node->value); for (i = 0; i < node->num_children; i++) r_print_node(node->children[i], depth + 1); for (i = 0; i < node->num_pchildren; i++) r_print_pnode(node->pchildren[i], depth + 1); } void r_print_node(RNode *node, int depth) { int i; for (i = 0; i < depth; i++) printf(" "); printf("%dNODE: '%s' => '%s'\n", depth, node->key, (char *)node->value); for (i = 0; i < node->num_children; i++) r_print_node(node->children[i], depth + 1); for (i = 0; i < node->num_pchildren; i++) r_print_pnode(node->pchildren[i], depth + 1); } void insert_node_with_value(RNode *root, gchar *key, gpointer value) { gchar *dup; /* NOTE: we need to duplicate the key as r_insert_node modifies its input * and it might be a read-only string literal */ dup = g_strdup(key); r_insert_node(root, dup, value ? : key, NULL); g_free(dup); } void insert_node(RNode *root, gchar *key) { insert_node_with_value(root, key, NULL); } void test_search_value(RNode *root, gchar *key, gchar *expected_value) { RNode *ret = r_find_node(root, key, strlen(key), NULL); if (ret && expected_value) { if (strcmp(ret->value, expected_value) != 0) { printf("FAIL: returned value does not match expected: '%s' <> '%s'\n", (gchar *) ret->value, expected_value); fail = TRUE; } else if (verbose) { printf("PASS: found expected: '%s' => '%s'\n", key, (gchar *) ret->value); } } else if (ret && !expected_value) { printf("FAIL: found unexpected: '%s' => '%s'\n", key, (gchar *) ret->value); fail = TRUE; } else if (expected_value) { printf("FAIL: not found while expected: '%s' => none\n", key); fail = TRUE; } } void test_search(RNode *root, gchar *key, gboolean expect) { test_search_value(root, key, expect ? key : NULL); } void test_search_matches(RNode *root, gchar *key, gchar *name1, ...) { RNode *ret; va_list args; GArray *matches = g_array_new(FALSE, TRUE, sizeof(RParserMatch)); RParserMatch *match; const gchar *match_name; g_array_set_size(matches, 1); va_start(args, name1); ret = r_find_node(root, key, strlen(key), matches); if (ret && !name1) { printf("FAIL: found unexpected: '%s' => '%s' matches: ", key, (gchar *) ret->value); for (gsize i = 0; i < matches->len; i++) { match = &g_array_index(matches, RParserMatch, i); match_name = log_msg_get_value_name(match->handle, NULL); if (match_name) { if (!match->match) printf("'%s' => '%.*s'", match_name, match->len, &key[match->ofs]); else printf("'%s' => '%s'", match_name, match->match); } } printf("\n"); fail = TRUE; } else if (ret && name1) { gsize i = 1; gchar *name, *value; name = name1; value = va_arg(args, gchar *); while (name) { if (i >= matches->len) { printf("FAIL: not enough matches: '%s' => expecting %" G_GSIZE_FORMAT ". match, value %s, " " total %u\n", key, i, value, matches->len); fail = TRUE; goto out; } match = &g_array_index(matches, RParserMatch, i); match_name = log_msg_get_value_name(match->handle, NULL); if (strcmp(match_name, name) != 0) { printf("FAIL: name does not match: '%s' => expecting %" G_GSIZE_FORMAT ". match, " "name %s != %s\n", key, i, name, match_name); fail = TRUE; } if (!match->match) { if (strncmp(&key[match->ofs], value, match->len) != 0 || strlen(value) != match->len) { printf("FAIL: value does not match: '%s' => expecting %" G_GSIZE_FORMAT ". match, " "value '%s' != '%.*s', total %d\n", key, i, value, match->len, &key[match->ofs], matches->len); fail = TRUE; } } else { if (strcmp(match->match, value) != 0) { printf("FAIL: value does not match: '%s' => expecting %" G_GSIZE_FORMAT ". match, " "value '%s' != '%s', total %d\n", key, i, value, match->match, matches->len); fail = TRUE; } } name = va_arg(args, gchar *); if (name) value = va_arg(args, gchar *); i++; } if (verbose) printf("PASS: all values match: '%s'\n", key); } else if (!ret && !name1) { if (verbose) printf("PASS: nothing was matched as expected: '%s'\n", key); } else { printf("FAIL: not found while expected: '%s' => none\n", key); fail = TRUE; } out: va_end(args); for (gsize i = 0; i < matches->len; i++) { match = &g_array_index(matches, RParserMatch, i); if (match->match) { g_free(match->match); } } g_array_free(matches, TRUE); } void test_literals(void) { RNode *root = r_new_node("", NULL); insert_node(root, "alma"); insert_node(root, "korte"); insert_node(root, "barack"); insert_node(root, "dinnye"); insert_node(root, "almafa"); insert_node(root, "almabor"); insert_node(root, "almafa2"); insert_node(root, "ko"); insert_node(root, "koros"); insert_node(root, "koro"); insert_node(root, "koromporkolt"); insert_node(root, "korom"); insert_node(root, "korozott"); insert_node(root, "al"); insert_node(root, "all"); insert_node(root, "uj\nsor"); test_search(root, "alma", TRUE); test_search(root, "korte", TRUE); test_search(root, "barack", TRUE); test_search(root, "dinnye", TRUE); test_search(root, "almafa", TRUE); test_search(root, "almabor", TRUE); test_search(root, "almafa2", TRUE); test_search(root, "ko", TRUE); test_search(root, "koros", TRUE); test_search(root, "koro", TRUE); test_search(root, "koromporkolt", TRUE); test_search(root, "korom", TRUE); test_search(root, "korozott", TRUE); test_search(root, "al", TRUE); test_search(root, "all", TRUE); test_search(root, "uj", FALSE); test_search(root, "uj\nsor", TRUE); test_search_value(root, "uj\r\nsor", "uj\nsor"); test_search(root, "mmm", FALSE); test_search_value(root, "kor", "ko"); test_search_value(root, "ko", "ko"); test_search_value(root, "kort", "ko"); test_search_value(root, "korti", "ko"); test_search_value(root, "korte", "korte"); test_search_value(root, "kortes", "korte"); test_search_value(root, "koromp", "korom"); test_search_value(root, "korompo", "korom"); test_search_value(root, "korompor", "korom"); test_search_value(root, "korompok", "korom"); test_search_value(root, "korompa", "korom"); test_search_value(root, "koromi", "korom"); test_search(root, "qwqw", FALSE); r_free_node(root, NULL); } void test_parsers(void) { RNode *root = r_new_node("", NULL); /* FIXME: more parsers */ insert_node(root, "a@@NUMBER@@aa@@@@"); insert_node(root, "a@@ab"); insert_node(root, "a@@a@@"); insert_node(root, "a@@@NUMBER:szam0@"); insert_node(root, "a@NUMBER:szamx@aaa"); insert_node(root, "a@NUMBER@"); insert_node(root, "a@NUMBER@aa"); insert_node(root, "a@NUMBER:szamx@@@"); insert_node(root, "baa@NUMBER@"); insert_node(root, "bxa@NUMBER:szam5@"); insert_node(root, "baa@@"); insert_node(root, "baa@@@@"); insert_node(root, "ba@@a"); insert_node(root, "bc@@a"); insert_node(root, "@@a@NUMBER:szam4@@@"); insert_node(root, "@@a@NUMBER:szam4@b"); insert_node(root, "@@a"); insert_node(root, "@@"); insert_node(root, "@@@@"); printf("We excpect an error message\n"); insert_node(root, "xxx@ESTRING@"); printf("We excpect an error message\n"); insert_node(root, "xxx@QSTRING@"); insert_node(root, "xxx@STRING@"); insert_node(root, "xxx@ANYSTRING@"); printf("We excpect an error message\n"); insert_node(root, "xxx@ESTRING@x"); printf("We excpect an error message\n"); insert_node(root, "xxx@QSTRING@x"); insert_node(root, "xxx@STRING@x"); insert_node(root, "xxx@ANYSTRING@x"); printf("We excpect an error message\n"); insert_node(root, "AAA@NUMBER:invalid=@AAA"); printf("We excpect an error message\n"); insert_node(root, "AAA@SET@AAA"); printf("We excpect an error message\n"); insert_node(root, "AAA@SET:set@AAA"); insert_node(root, "AAA@MACADDR@AAA"); insert_node(root, "newline@NUMBER@\n2ndline\n"); printf("We excpect an error message\n"); insert_node(root, "AAA@PCRE:set@AAA"); test_search_value(root, "a@", NULL); test_search_value(root, "a@NUMBER@aa@@", "a@@NUMBER@@aa@@@@"); test_search_value(root, "a@a", NULL); test_search_value(root, "a@ab", "a@@ab"); test_search_value(root, "a@a@", "a@@a@@"); test_search_value(root, "a@ax", NULL); test_search_value(root, "a@15555", "a@@@NUMBER:szam0@"); /* CRLF sequence immediately after a parser, e.g. in the initial position */ test_search_value(root, "newline123\r\n2ndline\n", "newline@NUMBER@\n2ndline\n"); /* FIXME: this one fails, because the shorter match is returned. The * current radix implementation does not ensure the longest match when the * radix tree is split on a parser node. */ #if 0 test_search_value(root, "a15555aaa", "a@NUMBER:szamx@aaa"); #endif test_search_value(root, "@a", "@@a"); test_search_value(root, "@", "@@"); test_search_value(root, "@@", "@@@@"); r_free_node(root, NULL); } void test_ip_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@IPvANY:ip@"); test_search_matches(root, "192.168.1.1 huhuhu", "ip", "192.168.1.1", NULL); test_search_matches(root, "192.168.1.1 huhuhu", "ip", "192.168.1.1", NULL); test_search_matches(root, "192.168.1.1. huhuhu", "ip", "192.168.1.1", NULL); test_search_matches(root, "192.168.1huhuhu", NULL); test_search_matches(root, "192.168.1.huhuhu", NULL); test_search_matches(root, "192.168.1 huhuhu", NULL); test_search_matches(root, "192.168.1. huhuhu", NULL); test_search_matches(root, "192.168.1.1huhuhu", "ip", "192.168.1.1", NULL); test_search_matches(root, "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789 huhuhu", "ip", "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789", NULL); test_search_matches(root, "abcd:ef01:2345:6789:abcd:ef01:2345:6789 huhuhu", "ip", "abcd:ef01:2345:6789:abcd:ef01:2345:6789", NULL); test_search_matches(root, ":: huhuhu", "ip", "::", NULL); test_search_matches(root, "0:0:0:0:0:0:13.1.68.3 huhuhu", "ip", "0:0:0:0:0:0:13.1.68.3", NULL); test_search_matches(root, "::202.1.68.3 huhuhu", "ip", "::202.1.68.3", NULL); test_search_matches(root, "2001:0DB8:0:CD30:: huhuhu", "ip", "2001:0DB8:0:CD30::", NULL); test_search_matches(root, "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789.huhuhu", "ip", "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789", NULL); test_search_matches(root, "abcd:ef01:2345:6789:abcd:ef01:2345:6789.huhuhu", "ip", "abcd:ef01:2345:6789:abcd:ef01:2345:6789", NULL); test_search_matches(root, "::.huhuhu", "ip", "::", NULL); test_search_matches(root, "0:0:0:0:0:0:13.1.68.3.huhuhu", "ip", "0:0:0:0:0:0:13.1.68.3", NULL); test_search_matches(root, "::202.1.68.3.huhuhu", "ip", "::202.1.68.3", NULL); test_search_matches(root, "2001:0DB8:0:CD30::.huhuhu", "ip", "2001:0DB8:0:CD30::", NULL); test_search_matches(root, "1:2:3:4:5:6:7:8.huhuhu", "ip", "1:2:3:4:5:6:7:8", NULL); test_search_matches(root, "1:2:3:4:5:6:7:8 huhuhu", "ip", "1:2:3:4:5:6:7:8", NULL); test_search_matches(root, "1:2:3:4:5:6:7:8:huhuhu", "ip", "1:2:3:4:5:6:7:8", NULL); test_search_matches(root, "1:2:3:4:5:6:7 huhu", NULL); test_search_matches(root, "1:2:3:4:5:6:7.huhu", NULL); test_search_matches(root, "1:2:3:4:5:6:7:huhu", NULL); test_search_matches(root, "1:2:3:4:5:6:77777:8 huhu", NULL); test_search_matches(root, "1:2:3:4:5:6:1.2.333.4 huhu", NULL); test_search_matches(root, "v12345", NULL); r_free_node(root, NULL); } void test_ipv4_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@IPv4:ipv4@"); test_search_matches(root, "192.168.1.1 huhuhu", "ipv4", "192.168.1.1", NULL); test_search_matches(root, "192.168.1.1. huhuhu", "ipv4", "192.168.1.1", NULL); test_search_matches(root, "192.168.1.1.huhuhu", "ipv4", "192.168.1.1", NULL); test_search_matches(root, "192.168.1.1.. huhuhu", "ipv4", "192.168.1.1", NULL); test_search_matches(root, "192.168.1.1.2 huhuhu", "ipv4", "192.168.1.1", NULL); test_search_matches(root, "192.168.1.1..huhuhu", "ipv4", "192.168.1.1", NULL); test_search_matches(root, "192.168.1.1huhuhu", "ipv4", "192.168.1.1", NULL); test_search_matches(root, "192.168.1huhuhu", NULL); test_search_matches(root, "192.168.1.huhuhu", NULL); test_search_matches(root, "192.168.1 huhuhu", NULL); test_search_matches(root, "192.168.1. huhuhu", NULL); test_search_matches(root, "v12345", NULL); r_free_node(root, NULL); } void test_ipv6_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@IPv6:ipv6@"); test_search_matches(root, "1:2:3:4:5:6:7 huhu", NULL); test_search_matches(root, "1:2:3:4:5:6:7.huhu", NULL); test_search_matches(root, "1:2:3:4:5:6:7:huhu", NULL); test_search_matches(root, "v12345", NULL); test_search_matches(root, "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789 huhuhu", "ipv6", "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789", NULL); test_search_matches(root, "abcd:ef01:2345:6789:abcd:ef01:2345:6789 huhuhu", "ipv6", "abcd:ef01:2345:6789:abcd:ef01:2345:6789", NULL); test_search_matches(root, "0:0:0:0:0:0:0:0 huhuhu", "ipv6", "0:0:0:0:0:0:0:0", NULL); test_search_matches(root, "2001:DB8::8:800:200C:417A huhuhu", "ipv6", "2001:DB8::8:800:200C:417A", NULL); test_search_matches(root, "FF01::101 huhuhu", "ipv6", "FF01::101", NULL); test_search_matches(root, "::1 huhuhu", "ipv6", "::1", NULL); test_search_matches(root, ":: huhuhu", "ipv6", "::", NULL); test_search_matches(root, "0:0:0:0:0:0:13.1.68.3 huhuhu", "ipv6", "0:0:0:0:0:0:13.1.68.3", NULL); test_search_matches(root, "::202.1.68.3 huhuhu", "ipv6", "::202.1.68.3", NULL); test_search_matches(root, "2001:0DB8:0:CD30:: huhuhu", "ipv6", "2001:0DB8:0:CD30::", NULL); test_search_matches(root, "2001:0DB8:0:CD30::huhuhu", "ipv6", "2001:0DB8:0:CD30::", NULL); test_search_matches(root, "::ffff:200.200.200.200huhuhu", "ipv6", "::ffff:200.200.200.200", NULL); test_search_matches(root, "2001:0DB8:0:CD30::huhuhu", "ipv6", "2001:0DB8:0:CD30::", NULL); test_search_matches(root, "::ffff:200.200.200.200 :huhuhu", "ipv6", "::ffff:200.200.200.200", NULL); test_search_matches(root, "::ffff:200.200.200.200: huhuhu", "ipv6", "::ffff:200.200.200.200", NULL); test_search_matches(root, "::ffff:200.200.200.200. :huhuhu", "ipv6", "::ffff:200.200.200.200", NULL); test_search_matches(root, "::ffff:200.200.200.200.:huhuhu", "ipv6", "::ffff:200.200.200.200", NULL); test_search_matches(root, "::ffff:200.200.200.200.2:huhuhu", "ipv6", "::ffff:200.200.200.200", NULL); test_search_matches(root, "::0: huhuhu", "ipv6", "::0", NULL); test_search_matches(root, "0:0:0:0:0:0:0:0: huhuhu", "ipv6", "0:0:0:0:0:0:0:0", NULL); test_search_matches(root, "::129.144.52.38: huhuhu", "ipv6", "::129.144.52.38", NULL); test_search_matches(root, "::ffff:129.144.52.38: huhuhu", "ipv6", "::ffff:129.144.52.38", NULL); test_search_matches(root, "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789.huhuhu", "ipv6", "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789", NULL); test_search_matches(root, "abcd:ef01:2345:6789:abcd:ef01:2345:6789.huhuhu", "ipv6", "abcd:ef01:2345:6789:abcd:ef01:2345:6789", NULL); test_search_matches(root, "0:0:0:0:0:0:0:0.huhuhu", "ipv6", "0:0:0:0:0:0:0:0", NULL); test_search_matches(root, "2001:DB8::8:800:200C:417A.huhuhu", "ipv6", "2001:DB8::8:800:200C:417A", NULL); test_search_matches(root, "FF01::101.huhuhu", "ipv6", "FF01::101", NULL); test_search_matches(root, "::1.huhuhu", "ipv6", "::1", NULL); test_search_matches(root, "::.huhuhu", "ipv6", "::", NULL); test_search_matches(root, "0:0:0:0:0:0:13.1.68.3.huhuhu", "ipv6", "0:0:0:0:0:0:13.1.68.3", NULL); test_search_matches(root, "::202.1.68.3.huhuhu", "ipv6", "::202.1.68.3", NULL); test_search_matches(root, "2001:0DB8:0:CD30::.huhuhu", "ipv6", "2001:0DB8:0:CD30::", NULL); r_free_node(root, NULL); } void test_number_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@NUMBER:number@"); test_search_matches(root, "12345 hihihi", "number", "12345", NULL); test_search_matches(root, "12345 hihihi", "number", "12345", NULL); test_search_matches(root, "0xaf12345 hihihi", "number", "0xaf12345", NULL); test_search_matches(root, "0xAF12345 hihihi", "number", "0xAF12345", NULL); test_search_matches(root, "0x12345 hihihi", "number", "0x12345", NULL); test_search_matches(root, "0XABCDEF12345ABCDEF hihihi", "number", "0XABCDEF12345ABCDEF", NULL); test_search_matches(root, "-12345 hihihi", "number", "-12345", NULL); test_search_matches(root, "v12345", NULL); r_free_node(root, NULL); } void test_qstring_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@QSTRING:qstring:'@"); test_search_matches(root, "'quoted string' hehehe", "qstring", "quoted string", NULL); test_search_matches(root, "v12345", NULL); r_free_node(root, NULL); } void test_estring_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "ddd @ESTRING:estring::@"); insert_node(root, "dddd @ESTRING:estring::*@"); insert_node(root, "dddd2 @ESTRING:estring::*@ d"); insert_node(root, "zzz @ESTRING:test:gép@"); test_search_matches(root, "ddd estring: hehehe", "estring", "estring", NULL); test_search_matches(root, "ddd v12345", NULL); test_search_matches(root, "dddd estring:* hehehe", "estring", "estring", NULL); test_search_matches(root, "dddd estring:estring:* hehehe", "estring", "estring:estring", NULL); test_search_matches(root, "dddd estring:estring::* hehehe", "estring", "estring:estring:", NULL); test_search_matches(root, "dddd2 estring:estring::* d", "estring", "estring:estring:", NULL); test_search_matches(root, "dddd2 estring:estring::* ", NULL); test_search_matches(root, "dddd2 estring:estring::*", NULL); test_search_matches(root, "dddd2 estring:estring:*", NULL); test_search_matches(root, "dddd2 estring:estring", NULL); test_search_matches(root, "dddd v12345", NULL); test_search_matches(root, "zzz árvíztűrőtükörfúrógép", "test", "árvíztűrőtükörfúró", NULL); r_free_node(root, NULL); } void test_string_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@STRING:string@"); test_search_matches(root, "string hehehe", "string", "string", NULL); r_free_node(root, NULL); } void test_float_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@FLOAT:float@"); test_search_matches(root, "12345 hihihi", "float", "12345", NULL); test_search_matches(root, "12345hihihi", "float", "12345", NULL); test_search_matches(root, "12.345hihihi", "float", "12.345", NULL); test_search_matches(root, "12.345.hihihi", "float", "12.345", NULL); test_search_matches(root, "12.345.6hihihi", "float", "12.345", NULL); test_search_matches(root, "12345.hihihi", "float", "12345.", NULL); test_search_matches(root, "-12.345 hihihi", "float", "-12.345", NULL); test_search_matches(root, "-12.345e12 hihihi", "float", "-12.345e12", NULL); test_search_matches(root, "-12.345e-12 hihihi", "float", "-12.345e-12", NULL); test_search_matches(root, "12.345e12 hihihi", "float", "12.345e12", NULL); test_search_matches(root, "12.345e-12 hihihi", "float", "12.345e-12", NULL); test_search_matches(root, "-12.345E12 hihihi", "float", "-12.345E12", NULL); test_search_matches(root, "-12.345E-12 hihihi", "float", "-12.345E-12", NULL); test_search_matches(root, "12.345E12 hihihi", "float", "12.345E12", NULL); test_search_matches(root, "12.345E-12 hihihi", "float", "12.345E-12", NULL); test_search_matches(root, "v12345", NULL); test_search_matches(root, "12345.hihihi","float", "12345.", NULL); r_free_node(root, NULL); } void test_set_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@SET:set: @"); test_search_matches(root, " aaa", "set", " ", NULL); test_search_matches(root, " aaa", "set", " ", NULL); r_free_node(root, NULL); } void test_macaddr_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@MACADDR:macaddr@"); test_search_matches(root, "82:63:25:93:eb:51.iii", "macaddr", "82:63:25:93:eb:51", NULL); test_search_matches(root, "82:63:25:93:EB:51.iii", "macaddr", "82:63:25:93:EB:51", NULL); r_free_node(root, NULL); } void test_email_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@EMAIL:email:[<]>@"); test_search_matches(root, "blint@balabit.hu","email", "blint@balabit.hu", NULL); test_search_matches(root, "","email", "blint@balabit.hu", NULL); test_search_matches(root, "[blint@balabit.hu]","email", "blint@balabit.hu", NULL); r_free_node(root, NULL); } void test_hostname_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@HOSTNAME:hostname@"); test_search_matches(root, "www.example.org", "hostname", "www.example.org", NULL); test_search_matches(root, "www.example.org. kkk", "hostname", "www.example.org.", NULL); r_free_node(root, NULL); } void test_lladdr_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@LLADDR:lladdr6:6@"); test_search_matches(root, "83:63:25:93:eb:51:aa:bb.iii", "lladdr6", "83:63:25:93:eb:51", NULL); test_search_matches(root, "83:63:25:93:EB:51:aa:bb.iii", "lladdr6", "83:63:25:93:EB:51", NULL); r_free_node(root, NULL); } void test_pcre_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "jjj @PCRE:regexp:[abc]+@"); insert_node(root, "jjjj @PCRE:regexp:[abc]+@d foobar"); test_search_matches(root, "jjj abcabcd", "regexp", "abcabc", NULL); test_search_matches(root, "jjjj abcabcd foobar", "regexp", "abcabc", NULL); r_free_node(root, NULL); } void test_nlstring_matches(void) { RNode *root = r_new_node("", NULL); insert_node(root, "@NLSTRING:nlstring@\n"); test_search_matches(root, "foobar\r\nbaz", "nlstring", "foobar", NULL); test_search_matches(root, "foobar\nbaz", "nlstring", "foobar", NULL); test_search_matches(root, "\nbaz", "nlstring", "", NULL); test_search_matches(root, "\r\nbaz", "nlstring", "", NULL); r_free_node(root, NULL); } void test_zorp_logs(void) { RNode *root = r_new_node("", NULL); /* these are conflicting logs */ insert_node_with_value(root, "core.error(2): (svc/@STRING:service:._@:@NUMBER:instance_id@/plug): Connection to remote end failed; local='AF_INET(@IPv4:local_ip@:@NUMBER:local_port@)', remote='AF_INET(@IPv4:remote_ip@:@NUMBER:remote_port@)', error=@QSTRING:errormsg:'@", "ZORP"); insert_node_with_value(root, "core.error(2): (svc/@STRING:service:._@:@NUMBER:instance_id@/plug): Connection to remote end failed; local=@QSTRING:p:'@, remote=@QSTRING:p:'@, error=@QSTRING:p:'@", "ZORP1"); insert_node_with_value(root, "Deny@QSTRING:FIREWALL.DENY_PROTO: @src@QSTRING:FIREWALL.DENY_O_INT: :@@IPv4:FIREWALL.DENY_SRCIP@/@NUMBER:FIREWALL.DENY_SRCPORT@ dst", "CISCO"); insert_node_with_value(root, "@NUMBER:Seq@, @ESTRING:DateTime:,@@ESTRING:Severity:,@@ESTRING:Comp:,@", "3com"); test_search_value(root, "core.error(2): (svc/intra.servers.alef_SSH_dmz.zajin:111/plug): Connection to remote end failed; local='AF_INET(172.16.0.1:56867)', remote='AF_INET(172.18.0.1:22)', error='No route to host'PAS", "ZORP"); test_search_value(root, "Deny udp src OUTSIDE:10.0.0.0/1234 dst INSIDE:192.168.0.0/5678 by access-group \"OUTSIDE\" [0xb74026ad, 0x0]", "CISCO"); test_search_matches(root, "1, 2006-08-22 16:31:39,INFO,BLK,", "Seq", "1", "DateTime", "2006-08-22 16:31:39", "Severity", "INFO", "Comp", "BLK", NULL); r_free_node(root, NULL); } int main(int argc, char *argv[]) { app_startup(); if (argc > 1) verbose = TRUE; msg_init(TRUE); test_literals(); test_parsers(); test_ip_matches(); test_ipv4_matches(); test_ipv6_matches(); test_number_matches(); test_qstring_matches(); test_estring_matches(); test_string_matches(); test_float_matches(); test_set_matches(); test_macaddr_matches(); test_email_matches(); test_hostname_matches(); test_lladdr_matches(); test_pcre_matches(); test_nlstring_matches(); test_zorp_logs(); app_shutdown(); return (fail ? 1 : 0); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/tests/test_timer_wheel.c000066400000000000000000000102771321171025300255670ustar00rootroot00000000000000/* * Copyright (c) 2010, 2015 Balabit * Copyright (c) 2010, 2015 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "timerwheel.h" #include #include #include #include #define NUM_TIMERS 10000 gint num_callbacks; guint64 prev_now; void timer_callback(TimerWheel *self, guint64 now, gpointer user_data) { guint64 expires = *(guint64 *) user_data; if (now != expires) { fprintf(stderr, "Expected time is not matching current time in callback, " "now=%" G_GUINT64_FORMAT ", expires=%" G_GUINT64_FORMAT "\n", now, expires); exit(1); } if (prev_now > now) { fprintf(stderr, "Callback current time is not monotonically increasing, " "prev_now=%" G_GUINT64_FORMAT ", now=%" G_GUINT64_FORMAT "\n", prev_now, now); } prev_now = now; num_callbacks++; } #define ASSOC_DATA_STRING "timerwheel associated data, check whether it's freed" static void _test_assoc_data(TimerWheel *wheel) { timer_wheel_set_associated_data(wheel, g_strdup(ASSOC_DATA_STRING), (GDestroyNotify) g_free); if (strcmp(timer_wheel_get_associated_data(wheel), ASSOC_DATA_STRING) != 0) { fprintf(stderr, "Associated data mismatch, found=%s, expected=%s", (gchar *) timer_wheel_get_associated_data(wheel), ASSOC_DATA_STRING); exit(1); } } void test_wheel(gint seed) { TimerWheel *wheel; gint i; guint64 latest = 0; gint expected_callbacks; prev_now = 0; num_callbacks = 0; expected_callbacks = 0; srand(seed); wheel = timer_wheel_new(); _test_assoc_data(wheel); timer_wheel_set_time(wheel, 1); for (i = 0; i < NUM_TIMERS; i++) { guint64 expires; TWEntry *timer1, *timer2, *timer3; gint r; expires = rand() & ((1 << 24) - 1); if (expires <= 1) expires = 1; if (expires > latest) latest = expires; timer1 = timer_wheel_add_timer(wheel, expires - 1, timer_callback, g_memdup(&expires, sizeof(expires)), (GDestroyNotify) g_free); timer2 = timer_wheel_add_timer(wheel, expires - 1, timer_callback, g_memdup(&expires, sizeof(expires)), (GDestroyNotify) g_free); timer3 = timer_wheel_add_timer(wheel, expires - 1, timer_callback, g_memdup(&expires, sizeof(expires)), (GDestroyNotify) g_free); expected_callbacks += 3; r = rand() & 0xFF; if (r < 64) { /* delete the timer with 25% chance */ timer_wheel_del_timer(wheel, timer1); expected_callbacks--; } else if (r < 128) { /* delete the timer with 25% chance */ timer_wheel_del_timer(wheel, timer2); expected_callbacks--; } else if (r < 192) { /* delete the timer with 25% chance */ timer_wheel_del_timer(wheel, timer3); expected_callbacks--; } } timer_wheel_set_time(wheel, latest + 1); if (num_callbacks != expected_callbacks) { fprintf(stderr, "Error: not enough callbacks received, " "num_callbacks=%d, expected=%d\n", num_callbacks, expected_callbacks); exit(1); } timer_wheel_free(wheel); } int main(void) { test_wheel(1234567890); test_wheel(time(NULL)); return 0; } syslog-ng-syslog-ng-3.13.2/modules/dbparser/timerwheel.c000066400000000000000000000226011321171025300232210ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "timerwheel.h" #include struct _TWEntry { struct iv_list_head list; guint64 target; TWCallbackFunc callback; gpointer user_data; GDestroyNotify user_data_free; }; void tw_entry_add(struct iv_list_head *head, TWEntry *new) { iv_list_add_tail(&new->list, head); } void tw_entry_unlink(TWEntry *entry) { iv_list_del_init(&entry->list); } static void tw_entry_free(TWEntry *entry) { if (entry->user_data && entry->user_data_free) entry->user_data_free(entry->user_data); g_free(entry); } #if SYSLOG_NG_ENABLE_DEBUG static void tw_entry_list_validate(struct iv_list_head *head) { struct iv_list_head *lh, *llh; llh = head; for (lh = head->next; lh != head; lh = lh->next) { g_assert(lh->prev == llh); llh = lh; } } #else static inline void tw_entry_list_validate(struct iv_list_head *head) { } #endif typedef struct _TWLevel { /* mask of the bits that index the current level */ guint64 mask; /* */ guint64 slot_mask; guint16 num; guint8 shift; struct iv_list_head slots[0]; } TWLevel; TWLevel * tw_level_new(gint bits, gint shift) { TWLevel *self; gint num; gint i; num = (1 << bits); self = g_malloc0(sizeof(TWLevel) + num * sizeof(self->slots[0])); self->shift = shift; self->mask = (num - 1) << shift; self->slot_mask = (1 << shift) - 1; self->num = num; for (i = 0; i < num; i++) INIT_IV_LIST_HEAD(&self->slots[i]); return self; } void tw_level_free(TWLevel *self) { gint i; for (i = 0; i < self->num; i++) { TWEntry *entry; struct iv_list_head *lh, *lh_next; iv_list_for_each_safe(lh, lh_next, &self->slots[i]) { entry = iv_list_entry(lh, TWEntry, list); tw_entry_free(entry); } } g_free(self); } struct _TimerWheel { TWLevel *levels[4]; struct iv_list_head future; guint64 now; guint64 base; gint num_timers; gpointer assoc_data; GDestroyNotify assoc_data_free; }; void timer_wheel_add_timer_entry(TimerWheel *self, TWEntry *entry) { guint64 level_base; gint slot; gint level_ndx; for (level_ndx = 0; level_ndx < G_N_ELEMENTS(self->levels); level_ndx++) { TWLevel *level = self->levels[level_ndx]; /* level_base contains the time of associated with level->slots[0] */ level_base = self->base & ~level->slot_mask & ~level->mask; if (entry->target > level_base + (level->num << level->shift)) { if (entry->target < level_base + (level->num << level->shift) * 2 && (self->now & level->mask) > (entry->target & level->mask)) { /* target is in the next slot at the next level and we've already crossed the slot in the current level */ } else { /* target over the current array */ continue; } } slot = (entry->target & level->mask) >> level->shift; tw_entry_add(&level->slots[slot], entry); tw_entry_list_validate(&level->slots[slot]); break; } if (level_ndx >= G_N_ELEMENTS(self->levels)) { tw_entry_add(&self->future, entry); tw_entry_list_validate(&self->future); } } TWEntry * timer_wheel_add_timer(TimerWheel *self, gint timeout, TWCallbackFunc cb, gpointer user_data, GDestroyNotify user_data_free) { TWEntry *entry; entry = g_new0(TWEntry, 1); entry->target = self->now + timeout; entry->callback = cb; entry->user_data = user_data; entry->user_data_free = user_data_free; INIT_IV_LIST_HEAD(&entry->list); timer_wheel_add_timer_entry(self, entry); self->num_timers++; return entry; } void timer_wheel_del_timer(TimerWheel *self, TWEntry *entry) { tw_entry_unlink(entry); tw_entry_free(entry); self->num_timers--; } void timer_wheel_mod_timer(TimerWheel *self, TWEntry *entry, gint new_timeout) { tw_entry_unlink(entry); entry->target = self->now + new_timeout; timer_wheel_add_timer_entry(self, entry); } guint64 timer_wheel_get_timer_expiration(TimerWheel *self, TWEntry *entry) { return entry->target; } static void timer_wheel_cascade(TimerWheel *self) { gint level_ndx; TWLevel *source_level, *target_level; TWEntry *entry; gint source_slot, target_slot; guint64 target_level_base; struct iv_list_head *lh, *lh_next, *target_head, *source_head; for (level_ndx = 1; level_ndx < G_N_ELEMENTS(self->levels); level_ndx++) { source_level = self->levels[level_ndx]; target_level = self->levels[level_ndx - 1]; source_slot = ((self->now & source_level->mask) >> source_level->shift); if (source_slot == source_level->num - 1) source_slot = 0; else source_slot++; source_head = &source_level->slots[source_slot]; iv_list_for_each_safe(lh, lh_next, source_head) { entry = iv_list_entry(lh, TWEntry, list); target_slot = (entry->target & target_level->mask) >> target_level->shift; target_head = &target_level->slots[target_slot]; tw_entry_unlink(entry); tw_entry_list_validate(source_head); tw_entry_add(target_head, entry); tw_entry_list_validate(target_head); } if (source_slot < source_level->num - 1) break; } if (level_ndx == G_N_ELEMENTS(self->levels)) { target_level = self->levels[level_ndx - 1]; source_head = &self->future; iv_list_for_each_safe(lh, lh_next, source_head) { entry = iv_list_entry(lh, TWEntry, list); target_level_base = self->base & ~target_level->slot_mask & ~target_level->mask; if (entry->target < target_level_base + 2 * (target_level->num << target_level->shift)) { target_slot = (entry->target & target_level->mask) >> target_level->shift; target_head = &target_level->slots[target_slot]; /* unlink current entry */ tw_entry_unlink(entry); tw_entry_list_validate(source_head); tw_entry_add(target_head, entry); tw_entry_list_validate(target_head); } } } self->base += self->levels[0]->num; } /* * Main time adjustment function */ void timer_wheel_set_time(TimerWheel *self, guint64 new_now) { /* time is not allowed to go backwards */ if (self->now >= new_now) return; if (self->num_timers == 0) { /* if there are no timers registered with the current base, we can simply switch to a new one */ self->now = new_now; self->base = new_now & ~self->levels[0]->mask; return; } for (; self->now < new_now; self->now++) { TWEntry *entry; struct iv_list_head *head, *lh, *lh_next; gint slot; TWLevel *level = self->levels[0]; slot = (self->now & level->mask) >> level->shift; head = &self->levels[0]->slots[slot]; iv_list_for_each_safe(lh, lh_next, head) { entry = iv_list_entry(lh, TWEntry, list); tw_entry_unlink(entry); entry->callback(self, self->now, entry->user_data); tw_entry_free(entry); self->num_timers--; } if (self->num_timers == 0) { self->now = new_now; self->base = new_now & ~self->levels[0]->mask; break; } if (slot == level->num - 1) timer_wheel_cascade(self); } } guint64 timer_wheel_get_time(TimerWheel *self) { return self->now; } void timer_wheel_expire_all(TimerWheel *self) { guint64 now; now = self->now; timer_wheel_set_time(self, (guint64) -1); self->now = now; } static void _free_assoc_data(TimerWheel *self) { if (self->assoc_data && self->assoc_data_free) self->assoc_data_free(self->assoc_data); self->assoc_data = NULL; } void timer_wheel_set_associated_data(TimerWheel *self, gpointer assoc_data, GDestroyNotify assoc_data_free) { _free_assoc_data(self); self->assoc_data = assoc_data; self->assoc_data_free = assoc_data_free; } gpointer timer_wheel_get_associated_data(TimerWheel *self) { return self->assoc_data; } TimerWheel * timer_wheel_new(void) { TimerWheel *self; gint bits[] = { 10, 6, 6, 6, 0 }; gint shift = 0; gint i; self = g_new0(TimerWheel, 1); for (i = 0; i < G_N_ELEMENTS(self->levels); i++) { self->levels[i] = tw_level_new(bits[i], shift); shift += bits[i]; } INIT_IV_LIST_HEAD(&self->future); return self; } void timer_wheel_free(TimerWheel *self) { gint i; for (i = 0; i < G_N_ELEMENTS(self->levels); i++) tw_level_free(self->levels[i]); _free_assoc_data(self); g_free(self); } syslog-ng-syslog-ng-3.13.2/modules/dbparser/timerwheel.h000066400000000000000000000036471321171025300232370ustar00rootroot00000000000000/* * Copyright (c) 2002-2012 Balabit * Copyright (c) 1998-2012 Balázs Scheidler * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef TIMERWHEEL_H_INCLUDED #define TIMERWHEEL_H_INCLUDED #include "syslog-ng.h" typedef struct _TWEntry TWEntry; typedef struct _TimerWheel TimerWheel; typedef void (*TWCallbackFunc)(TimerWheel *tw, guint64 now, gpointer user_data); TWEntry *timer_wheel_add_timer(TimerWheel *self, gint timeout, TWCallbackFunc cb, gpointer user_data, GDestroyNotify user_data_free); void timer_wheel_del_timer(TimerWheel *self, TWEntry *entry); void timer_wheel_mod_timer(TimerWheel *self, TWEntry *entry, gint new_timeout); guint64 timer_wheel_get_timer_expiration(TimerWheel *self, TWEntry *entry); void timer_wheel_set_time(TimerWheel *self, guint64 new_now); guint64 timer_wheel_get_time(TimerWheel *self); void timer_wheel_expire_all(TimerWheel *self); void timer_wheel_set_associated_data(TimerWheel *self, gpointer assoc_data, GDestroyNotify assoc_data_free); gpointer timer_wheel_get_associated_data(TimerWheel *self); TimerWheel *timer_wheel_new(void); void timer_wheel_free(TimerWheel *self); #endif syslog-ng-syslog-ng-3.13.2/modules/diskq/000077500000000000000000000000001321171025300202205ustar00rootroot00000000000000syslog-ng-syslog-ng-3.13.2/modules/diskq/CMakeLists.txt000066400000000000000000000027521321171025300227660ustar00rootroot00000000000000set(SYSLOG_NG_DISK_BUFFER_SOURCES diskq-options.h diskq-options.c logqueue-disk.c logqueue-disk.h logqueue-disk-non-reliable.c logqueue-disk-non-reliable.h logqueue-disk-reliable.c logqueue-disk-reliable.h qdisk.h qdisk.c ) add_library(syslog-ng-disk-buffer ${SYSLOG_NG_DISK_BUFFER_SOURCES}) target_link_libraries(syslog-ng-disk-buffer PUBLIC syslog-ng) set(DISK_BUFFER_SOURCES diskq.c diskq.h diskq-grammar.y diskq-parser.c diskq-parser.h diskq-plugin.c ${CMAKE_CURRENT_BINARY_DIR}/diskq-grammar.c ${CMAKE_CURRENT_BINARY_DIR}/diskq-grammar.h ) generate_y_from_ym(modules/diskq/diskq-grammar) bison_target(DiskBufferGrammar ${CMAKE_CURRENT_BINARY_DIR}/diskq-grammar.y ${CMAKE_CURRENT_BINARY_DIR}/diskq-grammar.c COMPILE_FLAGS ${BISON_FLAGS}) add_library(disk-buffer MODULE ${DISK_BUFFER_SOURCES}) target_link_libraries(disk-buffer PRIVATE syslog-ng-disk-buffer) target_include_directories(disk-buffer PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(disk-buffer PRIVATE syslog-ng) set(DQTOOL_SOURCES dqtool.c) add_executable(dqtool ${DQTOOL_SOURCES}) target_link_libraries(dqtool PRIVATE syslog-ng-disk-buffer) target_include_directories(dqtool PRIVATE ${PROJECT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) install(TARGETS dqtool RUNTIME DESTINATION bin COMPONENT diskbuffer) install(TARGETS disk-buffer LIBRARY DESTINATION lib/syslog-ng COMPONENT diskbuffer) syslog-ng-syslog-ng-3.13.2/modules/diskq/Makefile.am000066400000000000000000000037431321171025300222630ustar00rootroot00000000000000bin_PROGRAMS += modules/diskq/dqtool noinst_LTLIBRARIES += modules/diskq/libsyslog-ng-disk-buffer.la module_LTLIBRARIES += modules/diskq/libdisk-buffer.la modules_diskq_libsyslog_ng_disk_buffer_la_SOURCES = \ modules/diskq/diskq-options.h \ modules/diskq/diskq-options.c \ modules/diskq/logqueue-disk.c \ modules/diskq/logqueue-disk.h \ modules/diskq/logqueue-disk-non-reliable.c \ modules/diskq/logqueue-disk-non-reliable.h \ modules/diskq/logqueue-disk-reliable.c \ modules/diskq/logqueue-disk-reliable.h \ modules/diskq/qdisk.h \ modules/diskq/qdisk.c modules_diskq_libsyslog_ng_disk_buffer_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ -I$(top_srcdir)/modules/diskq modules_diskq_libsyslog_ng_disk_buffer_la_LIBADD = \ $(MODULE_DEPS_LIBS) modules_diskq_libsyslog_ng_disk_buffer_la_DEPENDENCIES = \ $(MODULE_DEPS_LIBS) modules_diskq_libdisk_buffer_la_SOURCES = \ modules/diskq/diskq.c \ modules/diskq/diskq.h \ modules/diskq/diskq-grammar.y \ modules/diskq/diskq-parser.c \ modules/diskq/diskq-parser.h \ modules/diskq/diskq-plugin.c BUILT_SOURCES += \ modules/diskq/diskq-grammar.y \ modules/diskq/diskq-grammar.c \ modules/diskq/diskq-grammar.h EXTRA_DIST += modules/diskq/diskq-grammar.ym LIBSYSLOG_NG_DISK_BUFFER = $(top_builddir)/modules/diskq/libsyslog-ng-disk-buffer.la modules_diskq_libdisk_buffer_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/modules/diskq -I$(top_builddir)/modules/diskq modules_diskq_libdisk_buffer_la_LIBADD = $(MODULE_DEPS_LIBS) $(LIBSYSLOG_NG_DISK_BUFFER) modules_diskq_libdisk_buffer_la_LDFLAGS = $(MODULE_LDFLAGS) modules_diskq_libdisk_buffer_la_DEPENDENCIES = $(MODULE_DEPS_LIBS) $(LIBSYSLOG_NG_DISK_BUFFER) modules_diskq_dqtool_SOURCES = modules/diskq/dqtool.c modules_diskq_dqtool_LDADD = \ $(TOOL_DEPS_LIBS) \ $(MODULE_DEPS_LIBS) \ $(LIBSYSLOG_NG_DISK_BUFFER) modules/diskq modules/diskq/ mod-diskq: modules/diskq/libdisk-buffer.la \ modules/diskq/dqtool include modules/diskq/tests/Makefile.am .PHONY: modules/diskq/ mod-diskq syslog-ng-syslog-ng-3.13.2/modules/diskq/diskq-grammar.ym000066400000000000000000000055701321171025300233350ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2016 Viktor Juhasz * * This 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 2.1 of the License, or (at your option) any later version. * * This 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ %code top { #include "diskq-parser.h" } %code { #include "cfg-parser.h" #include "syslog-names.h" #include "messages.h" #include "diskq.h" #include "diskq-options.h" #include "diskq-grammar.h" #include DiskQDestPlugin *last_plugin; DiskQueueOptions *last_options; } %name-prefix "diskq_" /* this parameter is needed in order to instruct bison to use a complete * argument list for yylex/yyerror */ %lex-param {CfgLexer *lexer} %parse-param {CfgLexer *lexer} %parse-param {LogDriverPlugin **instance} %parse-param {gpointer arg} /* INCLUDE_DECLS */ %token KW_DISK_BUFFER %token KW_MEM_BUF_LENGTH %token KW_DISK_BUF_SIZE %token KW_RELIABLE %token KW_MEM_BUF_SIZE %token KW_QOUT_SIZE %token KW_DIR %% start : LL_CONTEXT_INNER_DEST dest_diskq { YYACCEPT; } ; dest_diskq : KW_DISK_BUFFER { last_plugin = diskq_dest_plugin_new(); *instance = &last_plugin->super; last_options = &last_plugin->options; } '(' dest_diskq_options ')' { disk_queue_options_check_plugin_settings(last_options); } ; dest_diskq_options : dest_diskq_option dest_diskq_options | ; dest_diskq_option : KW_RELIABLE '(' yesno ')' { disk_queue_options_reliable_set(last_options, $3); } | KW_MEM_BUF_SIZE '(' nonnegative_integer ')' { disk_queue_options_mem_buf_size_set(last_options, $3); } | KW_MEM_BUF_LENGTH '(' nonnegative_integer ')' { disk_queue_options_mem_buf_length_set(last_options, $3); } | KW_DISK_BUF_SIZE '(' nonnegative_integer ')' { disk_queue_options_disk_buf_size_set(last_options, $3); } | KW_QOUT_SIZE '(' nonnegative_integer ')' { disk_queue_options_qout_size_set(last_options, $3); } | KW_DIR '(' string ')' { disk_queue_options_set_dir(last_options, $3); free($3); } ; /* INCLUDE_RULES */ %% syslog-ng-syslog-ng-3.13.2/modules/diskq/diskq-options.c000066400000000000000000000066741321171025300232050ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2016 Viktor Juhasz * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "diskq-options.h" #include "syslog-ng.h" #include "messages.h" #include "reloc.h" void disk_queue_options_qout_size_set(DiskQueueOptions *self, gint qout_size) { if (qout_size < 64) { msg_warning("WARNING: The configured qout size is smaller than the minimum allowed", evt_tag_int("configured size", qout_size), evt_tag_int("minimum allowed size", 64), evt_tag_int("new size", 64)); qout_size = 64; } self->qout_size = qout_size; } void disk_queue_options_disk_buf_size_set(DiskQueueOptions *self, gint64 disk_buf_size) { if (disk_buf_size < MIN_DISK_BUF_SIZE) { msg_warning("WARNING: The configured disk buffer size is smaller than the minimum allowed", evt_tag_int("configured size", disk_buf_size), evt_tag_int("minimum allowed size", MIN_DISK_BUF_SIZE), evt_tag_int("new size", MIN_DISK_BUF_SIZE)); disk_buf_size = MIN_DISK_BUF_SIZE; } self->disk_buf_size = disk_buf_size; } void disk_queue_options_reliable_set(DiskQueueOptions *self, gboolean reliable) { self->reliable = reliable; } void disk_queue_options_mem_buf_size_set(DiskQueueOptions *self, gint mem_buf_size) { self->mem_buf_size = mem_buf_size; } void disk_queue_options_mem_buf_length_set(DiskQueueOptions *self, gint mem_buf_length) { self->mem_buf_length = mem_buf_length; } void disk_queue_options_check_plugin_settings(DiskQueueOptions *self) { if (self->reliable) { if (self->mem_buf_length > 0) { msg_warning("WARNING: mem-buf-length parameter was ignored as it is not compatible with reliable queue. Did you mean mem-buf-size?"); } } else { if (self->mem_buf_size > 0) { msg_warning("WARNING: mem-buf-size parameter was ignored as it is not compatible with non-reliable queue. Did you mean mem-buf-length?"); } } } void disk_queue_options_set_dir(DiskQueueOptions *self, const gchar *dir) { if (self->dir) { g_free(self->dir); } self->dir = g_strdup(dir); } void disk_queue_options_set_default_options(DiskQueueOptions *self) { self->disk_buf_size = -1; self->mem_buf_length = -1; self->reliable = FALSE; self->mem_buf_size = -1; self->qout_size = -1; self->dir = g_strdup(get_installation_path_for(SYSLOG_NG_PATH_LOCALSTATEDIR)); } void disk_queue_options_destroy(DiskQueueOptions *self) { if (self->dir) { g_free(self->dir); self->dir = NULL; } } syslog-ng-syslog-ng-3.13.2/modules/diskq/diskq-options.h000066400000000000000000000040011321171025300231700ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2016 Viktor Juhasz * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DISKQ_OPTIONS_H_ #define DISKQ_OPTIONS_H_ #include "syslog-ng.h" #include "logmsg/logmsg-serialize.h" #define MIN_DISK_BUF_SIZE 1024*1024 typedef struct _DiskQueueOptions { gint64 disk_buf_size; gint qout_size; gboolean read_only; gboolean reliable; gint mem_buf_size; gint mem_buf_length; gchar *dir; } DiskQueueOptions; void disk_queue_options_qout_size_set(DiskQueueOptions *self, gint qout_size); void disk_queue_options_disk_buf_size_set(DiskQueueOptions *self, gint64 disk_buf_size); void disk_queue_options_reliable_set(DiskQueueOptions *self, gboolean reliable); void disk_queue_options_mem_buf_size_set(DiskQueueOptions *self, gint mem_buf_size); void disk_queue_options_mem_buf_length_set(DiskQueueOptions *self, gint mem_buf_length); void disk_queue_options_check_plugin_settings(DiskQueueOptions *self); void disk_queue_options_set_dir(DiskQueueOptions *self, const gchar *dir); void disk_queue_options_set_default_options(DiskQueueOptions *self); void disk_queue_options_destroy(DiskQueueOptions *self); #endif /* DISKQ_OPTIONS_H_ */ syslog-ng-syslog-ng-3.13.2/modules/diskq/diskq-parser.c000066400000000000000000000034711321171025300227760ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2016 Viktor Juhasz * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "diskq.h" #include "cfg-parser.h" #include "diskq-grammar.h" extern int diskq_debug; int diskq_parse(CfgLexer *lexer, LogDriverPlugin **instance, gpointer arg); static CfgLexerKeyword diskq_keywords[] = { { "disk_buffer", KW_DISK_BUFFER }, { "mem_buf_length", KW_MEM_BUF_LENGTH }, { "disk_buf_size", KW_DISK_BUF_SIZE }, { "reliable", KW_RELIABLE }, { "mem_buf_size", KW_MEM_BUF_SIZE }, { "qout_size", KW_QOUT_SIZE }, { "dir", KW_DIR }, { NULL } }; CfgParser diskq_parser = { #if SYSLOG_NG_ENABLE_DEBUG .debug_flag = &diskq_debug, #endif .name = "disk_buffer", .keywords = diskq_keywords, .parse = (int (*)(CfgLexer *lexer, gpointer *instance, gpointer arg)) diskq_parse, .cleanup = (void (*)(gpointer)) log_pipe_unref, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(diskq_, LogDriverPlugin **) syslog-ng-syslog-ng-3.13.2/modules/diskq/diskq-parser.h000066400000000000000000000022411321171025300227750ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2016 Viktor Juhasz * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DISKQ_PARSER_H_INCLUDED #define DISKQ_PARSER_H_INCLUDED #include "cfg-parser.h" #include "diskq.h" extern CfgParser diskq_parser; CFG_PARSER_DECLARE_LEXER_BINDING(diskq_, LogDriverPlugin **) #endif syslog-ng-syslog-ng-3.13.2/modules/diskq/diskq-plugin.c000066400000000000000000000032461321171025300230000ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2016 Viktor Juhasz * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "plugin.h" #include "plugin-types.h" extern CfgParser diskq_parser; static Plugin diskq_plugins[] = { { .type = LL_CONTEXT_INNER_DEST, .name = "disk_buffer", .parser = &diskq_parser, }, }; #ifndef STATIC const ModuleInfo module_info = { .canonical_name = "disk_buffer", .version = SYSLOG_NG_VERSION, .description = "This module provides disk buffer based queuing mechanism", .core_revision = SYSLOG_NG_SOURCE_REVISION, .plugins = diskq_plugins, .plugins_len = G_N_ELEMENTS(diskq_plugins), }; #endif gboolean disk_buffer_module_init(PluginContext *context, CfgArgs *args) { plugin_register(context, diskq_plugins, G_N_ELEMENTS(diskq_plugins)); return TRUE; } syslog-ng-syslog-ng-3.13.2/modules/diskq/diskq.c000066400000000000000000000116431321171025300215040ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2016 Viktor Juhasz * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "driver.h" #include "messages.h" #include "diskq.h" #include "logqueue-disk.h" #include "logqueue-disk-reliable.h" #include "logqueue-disk-non-reliable.h" #include "persist-state.h" static LogQueue * _acquire_queue(LogDestDriver *dd, const gchar *persist_name, gpointer user_data) { DiskQDestPlugin *self = (DiskQDestPlugin *) user_data; GlobalConfig *cfg = log_pipe_get_config(&dd->super.super); LogQueue *queue = NULL; gchar *qfile_name; gboolean success; if (persist_name) queue = cfg_persist_config_fetch(cfg, persist_name); if (queue) { log_queue_unref(queue); queue = NULL; } if (self->options.reliable) queue = log_queue_disk_reliable_new(&self->options, persist_name); else queue = log_queue_disk_non_reliable_new(&self->options, persist_name); log_queue_set_throttle(queue, dd->throttle); qfile_name = persist_state_lookup_string(cfg->state, persist_name, NULL, NULL); success = log_queue_disk_load_queue(queue, qfile_name); if (!success) { if (qfile_name && log_queue_disk_load_queue(queue, NULL)) { msg_error("Error opening disk-queue file, a new one started", evt_tag_str("old_filename", qfile_name), evt_tag_str("new_filename", log_queue_disk_get_filename(queue))); } else { g_free(qfile_name); msg_error("Error initializing log queue"); return NULL; } } g_free(qfile_name); if (persist_name) { /* save the queue file name to permanent state */ qfile_name = (gchar *) log_queue_disk_get_filename(queue); if (qfile_name) { persist_state_alloc_string(cfg->state, persist_name, qfile_name, -1); } } return queue; } void _release_queue(LogDestDriver *dd, LogQueue *queue, gpointer user_data) { GlobalConfig *cfg = log_pipe_get_config(&dd->super.super); gboolean persistent; log_queue_disk_save_queue(queue, &persistent); if (queue->persist_name) { cfg_persist_config_add(cfg, queue->persist_name, queue, (GDestroyNotify) log_queue_unref, FALSE); } else { log_queue_unref(queue); } } static gboolean _attach(LogDriverPlugin *s, LogDriver *d) { DiskQDestPlugin *self = (DiskQDestPlugin *) s; LogDestDriver *dd = (LogDestDriver *) d; GlobalConfig *cfg = log_pipe_get_config(&d->super); if (self->options.disk_buf_size == -1) { msg_error("The required 'disk_buf_size()' parameter of diskq module has not been set."); return FALSE; } if (self->options.disk_buf_size < MIN_DISK_BUF_SIZE && self->options.disk_buf_size != 0) { msg_warning("The value of 'disk_buf_size()' is too low, setting to the smallest acceptable value", evt_tag_int("min_space", MIN_DISK_BUF_SIZE)); self->options.disk_buf_size = MIN_DISK_BUF_SIZE; } if (dd->acquire_queue_data || dd->release_queue_data) if (dd->acquire_queue_data != self) { msg_error("Another queueing plugin is registered in this destination, unable to register diskq again", evt_tag_str("driver", dd->super.id)); return FALSE; } if (self->options.mem_buf_length < 0) self->options.mem_buf_length = dd->log_fifo_size; if (self->options.mem_buf_length < 0) self->options.mem_buf_length = cfg->log_fifo_size; if (self->options.qout_size < 0) self->options.qout_size = 64; dd->acquire_queue_data = self; dd->acquire_queue = _acquire_queue; dd->release_queue_data = self; dd->release_queue = _release_queue; return TRUE; } static void _free(LogDriverPlugin *s) { DiskQDestPlugin *self = (DiskQDestPlugin *)s; disk_queue_options_destroy(&self->options); } DiskQDestPlugin * diskq_dest_plugin_new(void) { DiskQDestPlugin *self = g_new0(DiskQDestPlugin, 1); log_driver_plugin_init_instance(&self->super); disk_queue_options_set_default_options(&self->options); self->super.attach = _attach; self->super.free_fn = _free; return self; } syslog-ng-syslog-ng-3.13.2/modules/diskq/diskq.h000066400000000000000000000023741321171025300215120ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2016 Viktor Juhasz * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #ifndef DISKQ_H #define DISKQ_H #include "logqueue.h" #include "driver.h" #include "logmsg/logmsg-serialize.h" #include "diskq-options.h" typedef struct _DiskQDestPlugin { LogDriverPlugin super; DiskQueueOptions options; } DiskQDestPlugin; DiskQDestPlugin *diskq_dest_plugin_new(void); #endif syslog-ng-syslog-ng-3.13.2/modules/diskq/dqtool.c000066400000000000000000000167721321171025300217030ustar00rootroot00000000000000/* * Copyright (c) 2002-2016 Balabit * Copyright (c) 2016 Viktor Juhasz * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "syslog-ng.h" #include "logqueue.h" #include "template/templates.h" #include "logmsg/logmsg.h" #include "messages.h" #include "logpipe.h" #include "logqueue-disk.h" #include "logqueue-disk-reliable.h" #include "logqueue-disk-non-reliable.h" #include "logmsg/logmsg-serialize.h" #include "scratch-buffers.h" #include #include #include #include gchar *template_string; gboolean display_version; gboolean debug_flag; gboolean verbose_flag; static GOptionEntry cat_options[] = { { "template", 't', 0, G_OPTION_ARG_STRING, &template_string, "Template to format the serialized messages", "