diff options
64 files changed, 937 insertions, 432 deletions
@@ -1,10 +1,175 @@ ---------------------------------------------------------------------------- -Version 7.4.2 [v7.4-stable] 2013-06-?? +Version 7.4.7 [v7.4-stable] 2013-11-?? - bugfix: call to ruleset with async queue did not use the queue closes: http://bugzilla.adiscon.com/show_bug.cgi?id=443 +--------------------------------------------------------------------------- +Version 7.4.6 [v7.4-stable] 2013-10-31 +- bugfix: potential abort during HUP + This could happen when one of imklog, imzmq3, imkmsg, impstats, + imjournal, or imuxsock were under heavy load during a HUP. + closes: http://bugzilla.adiscon.com/show_bug.cgi?id=489 + Thanks to Guy Rozendorn for reporting the problem and Peval Levhshin for + his analysis. +- bugfix: imtcp flowControl parameter incorrectly defaulted to "off" + This could cause message loss on systems under heavy load and was + a change-of-behaviour to previous version. This is a regression + most probably introduced in 5.9.0 (but did not try hard to find the + exact point of its introduction). +- now requires libestr 0.1.9 as earlier versions lead to problems with + number handling in RainerScript +- bugfix: memory leak in strlen() RainerScript function + Thanks to Gregoire Seux for reportig this bug. + closes: http://bugzilla.adiscon.com/show_bug.cgi?id=486 +- bugfix: buffer overrun if re_extract function was called for submatch 50 + Thanks to Pavel Levshin for reporting the problem and its location. +- bugfix: memleak in re_extract() function + Thanks to Pavel Levshin for reporting this problem. +- bugfix: potential abort in RainerScript optimizer + closes: http://bugzilla.adiscon.com/show_bug.cgi?id=488 + Thanks to Thomas Doll for reporting the problem and Pavel Levshin for + fixing it. +- bugfix: memory leak in omhiredis + Thanks to Pavel Levshin for the fix +- bugfix: segfault if variable was assigned to non-container subtree + Thanks to Pavel Levshin for the fix +--------------------------------------------------------------------------- +Version 7.4.5 [v7.4-stable] 2013-10-22 +- mmanon: removed the check for specific "terminator characters" after + last octet. As it turned out, this didn't work in practice as there + was an enormous set of potential terminator chars -- so removing + them was the best thing to do. Note that this may change behaviour of + existing installations. Yet, we still consider this an important + bugfix, that should be applied to the stable branch. + closes: http://bugzilla.adiscon.com/show_bug.cgi?id=477 + Thanks to Muri Cicanor for initiating the discussion +- now requires libestr 0.1.8 as early versions had a nasty bug in + string comparisons +- omelasticsearch: add failed.httprequests stats counter +- bugfix: invalid property filter was not properly disabled in ruleset + Note that this bugfix introduces a very slight memory leak, which is + cosmetic, as it just holds data until termination that is no longer + needed. It is just the part of the config that was invalid. We will + "fix" this "issue" in the devel version first, as the fix is a bit + too intrusive to do without hard need in the stable version. +- bugfix: segfault if re_extract() function was used and no match found +- bugfix: potential misadressing on startup if property-filter was used + This could happen if the property name was longer than 127 chars, a case + that would not happen in practice. +- bugfix: omelasticsearch: correct failed.http stats counter +- bugfix: omelasticsearch: did not correctly initialize stats counters +- bugfix: omelasticsearch: failed.es counter was only maintained in bulk mode + This usually did not lead to any problems, because they are in static + memory, which is initialized to zero by the OS when the plugin is + loaded. But it may cause problems especially on systems that do not + support atomic instructions - in this case the associated mutexes also + did not get properly initialized. +- bugfix: mmanon did not detect all IP addresses in rewrite mode + The problem occured if two IPs were close to each other and the first one + was shrunk. + closes: http://bugzilla.adiscon.com/show_bug.cgi?id=485 + Thanks to micah-at-riseup.net for reporting this bug +- bugfix: mmanon sometimes used invalid replacement char in simple mode + depending on configuration sequence, the replacement character was set + to 's' instead of the correct value. Most importantly, it was set to + 's' if simple mode was selected and no replacement char set. + closes: http://bugzilla.adiscon.com/show_bug.cgi?id=484 + Thanks to micah-at-riseup.net for reporting this bug +- bugfix: memory leak in mmnormalize +- bugfix: array-based ==/!= comparisions lead to invalid results + This was a regression introduced in 7.3.5 bei the PRI optimizer +- bugfix: omprog blocked signals to executed programs + The made it impossible to send signals to programs executed via + omprog. + Thanks to Risto Vaarandi for the analysis and a patch. +- bugfix: doc: imuxsock legacy param $SystemLogSocketParseTrusted was + misspelled + Thanks to David Lang for alerting us +- bugfix: imfile "facility" input parameter improperly handled + caused facility not to be set, and severity to be overwritten with + the facility value. + Thanks to forum user dmunny for reporting this bug. +- bugfix: small memory leak in imfile when $ResetConfigVariables was used + Thanks to Grégory Nuyttens for reporting this bug and providig a fix +- bugfix: segfault on startup if TLS was used but no CA cert set +- bugfix: segfault on startup if TCP TLS was used but no cert or key set +- bugfix: some more build problems with newer json-c versions + Thanks to Michael Biebl for mentioning the problem. +- bugfix: build system: libgcrypt.h needed even if libgrcypt was disabled + Thanks to Jonny Törnbom for reporting this problem +--------------------------------------------------------------------------- +Version 7.4.4 [v7.4-stable] 2013-09-03 +- better error messages in GuardTime signature provider + Thanks to Ahto Truu for providing the patch. +- make rsyslog use the new json-c pkgconfig file if available + Thanks to the Gentoo team for the patches. +- bugfix: imfile parameter "persistStateInterval" was unusable + due to a case typo in imfile; work-around was to use legacy config + Thanks to Brandon Murphy for reporting this bug. +- bugfix: TLV16 flag encoding error in signature files from GT provider + This fixes a problem where the TLV16 flag was improperly encoded. + Unfortunately, existing files already have the bug and may not properly + be processed. The fix uses constants from the GuardTime API lib to + prevent such problems in the future. + Thanks to Ahto Truu for providing the patch. +- bugfix: slightly malformed SMTP handling in ommail +- bugfix: segfault in omprog if no template was provided (now dflt is used) +- bugfix: segfault in ompipe if no template was provided (now dflt is used) +- bugfix: segfault in omsnmp if no template was provided (now dflt is used) +- bugfix: some omsnmp optional config params were flagged as mandatory +- bugfix: segfault in omelasticsearch when resuming queued messages + after restarting Elasticsearch + closes: http://bugzilla.adiscon.com/show_bug.cgi?id=464 +- bugfix: imtcp addtlframedelimiter could not be set to zero + Thanks to Chris Norton for alerting us. +- doc bugfix: remove no-longer existing omtemplate from developer doc + was specifically mentioned as a sample for creating new plugins + Thanks to Yannick Brosseau for alerting us of this problem. + closes: http://bugzilla.adiscon.com/show_bug.cgi?id=473 +--------------------------------------------------------------------------- +Version 7.4.3 [v7.4-stable] 2013-07-18 +- bugfix: queue file size was not correctly processed + this could lead to using one queue file per message for sizes >2GiB + Thanks to Tomas Heinrich for the patch. +- bugfix: $QHOUR/$HHOUR were always "00" or "01" + regression some time between v5 and here + Thanks to forum user rjmcinty for reporting this bug +- bugfix: testbench tool chkseq did improperly report invalid file + This happened when permitted duplicate values existed in the very + last lines, right before end-of-file. + Thanks to Radu Gheorghe for reporting this bug. +--------------------------------------------------------------------------- +Version 7.4.3 [v7.4-stable] 2013-07-18 +- bugfix: memory leak if disk queues were used and json data present +- bugfix: CEE/json data was lost during disk queue operation +- bugfix: potential segfault during startup on invalid config + could happen if invalid actions were present, which could lead + to improper handling in optimizer. +- bugfix: 100% CPU utilization when DA queue became full +- bugfix: omlibdbi did not properly close connection on some errors + This happened to errors occuring in Begin/End Transaction entry + points. +- cosmetic bugfix: file name buffer was not freed on disk queue destruction + This was an extremely small one-time per run memleak, so nothing of + concern. However, it bugs under valgrind and similar memory debuggers. +- fix build on FreeBSD + Thanks to Christiano Rolim for the patch +--------------------------------------------------------------------------- +Version 7.4.2 [v7.4-stable] 2013-07-04 +- bugfix: in RFC5425 TLS, multiple wildcards in auth could cause segfault - bugfix: RainerScript object required parameters were not properly checked - this clould result to segfaults on startup if parameters were missing. +- bugfix: double-free in omelasticsearch + closes: http://bugzilla.adiscon.com/show_bug.cgi?id=461 + a security advisory for this bug is available at: + http://www.lsexperts.de/advisories/lse-2013-07-03.txt + CVE: CVE-2013-4758 + PLEASE NOTE: This issue only existed if omelasticsearch was used + in a non-default configuration, where the "errorfile" parameter + was specified. Without that parameter set, the bug could not + be triggered. + Thanks to Markus Vervier and Marius Ionescu for providing a detailled + bug report. Special thanks to Markus for coordinating his security + advisory with us. - bugfix: omrelp potential segfault at startup on invalid config parameters - bugfix: small memory leak when $uptime property was used - bugfix: potential segfault on rsyslog termination in imudp @@ -18,6 +183,7 @@ Version 7.4.2 [v7.4-stable] 2013-06-?? closes: http://bugzilla.adiscon.com/show_bug.cgi?id=457 closes: http://bugzilla.adiscon.com/show_bug.cgi?id=458 Thanks to Christiano for reproting and suggesting patches +- solved build problems on CENTOS5 --------------------------------------------------------------------------- Version 7.4.1 [v7.4-stable] 2013-06-17 - imjournal: add ratelimiting capability @@ -1444,6 +1610,9 @@ expected that interfaces, even new ones, break during the initial [ported from v4] --------------------------------------------------------------------------- Version 5.10.2 [V5-STABLE], 201?-??-?? +- bugfix: queue file size was not correctly processed + this could lead to using one queue file per message for sizes >2GiB + Thanks to Tomas Heinrich for the patch. - updated systemd files to match current systemd source - bugfix: spurios error messages from imuxsock about (non-error) EAGAIN Thanks to Marius Tomaschewski for the patch. @@ -98,7 +98,7 @@ #include <strings.h> #include <time.h> #include <errno.h> -#include <json/json.h> +#include <json.h> #include "dirty.h" #include "template.h" diff --git a/configure.ac b/configure.ac index a62bc687..ee3394b5 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([rsyslog],[7.4.1],[rsyslog@lists.adiscon.com]) +AC_INIT([rsyslog],[7.4.6],[rsyslog@lists.adiscon.com]) AM_INIT_AUTOMAKE m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) @@ -32,8 +32,10 @@ AC_CANONICAL_HOST PKG_PROG_PKG_CONFIG # modules we require -PKG_CHECK_MODULES(LIBESTR, libestr >= 0.1.5) -PKG_CHECK_MODULES([JSON_C], [json]) +PKG_CHECK_MODULES(LIBESTR, libestr >= 0.1.9) +PKG_CHECK_MODULES([JSON_C], [json],, [ + PKG_CHECK_MODULES([JSON_C], [json-c]) +]) case "${host}" in *-*-linux*) @@ -119,7 +121,7 @@ AC_TYPE_SIGNAL AC_FUNC_STAT AC_FUNC_STRERROR_R AC_FUNC_VPRINTF -AC_CHECK_FUNCS([flock basename alarm clock_gettime gethostbyname gethostname gettimeofday localtime_r memset mkdir regcomp select setid socket strcasecmp strchr strdup strerror strndup strnlen strrchr strstr strtol strtoul uname ttyname_r getline malloc_trim prctl epoll_create epoll_create1 fdatasync syscall lseek64]) +AC_CHECK_FUNCS([flock basename alarm clock_gettime gethostbyname gethostname gettimeofday localtime_r memset mkdir regcomp select setsid socket strcasecmp strchr strdup strerror strndup strnlen strrchr strstr strtol strtoul uname ttyname_r getline malloc_trim prctl epoll_create epoll_create1 fdatasync syscall lseek64]) # getifaddrs is in libc (mostly) or in libsocket (eg Solaris 11) or not defined (eg Solaris 10) AC_SEARCH_LIBS([getifaddrs], [socket], [AC_DEFINE(HAVE_GETIFADDRS, [1], [set define])]) @@ -821,7 +823,7 @@ if test "x$enable_rsyslogrt" = "xyes"; then RSRT_LIBS1="\$(top_builddir)/runtime/librsyslog.la" fi AM_CONDITIONAL(ENABLE_RSYSLOGRT, test x$enable_rsyslogrt = xyes) -RSRT_CFLAGS="\$(RSRT_CFLAGS1) \$(LIBESTR_CFLAGS) \$(JSON_C_FLAGS)" +RSRT_CFLAGS="\$(RSRT_CFLAGS1) \$(LIBESTR_CFLAGS) \$(JSON_C_CFLAGS)" RSRT_LIBS="\$(RSRT_LIBS1) \$(LIBESTR_LIBS) \$(JSON_C_LIBS)" AC_SUBST(RSRT_CFLAGS1) AC_SUBST(RSRT_LIBS1) diff --git a/doc/debug.html b/doc/debug.html index 557ca6d3..229aeb08 100644 --- a/doc/debug.html +++ b/doc/debug.html @@ -160,7 +160,11 @@ enable DebugOnDemand mode only for a reason. Note that when no debug mode is ena SIGUSR1 and SIGUSR2 are completely ignored. <p>When running in any of the debug modes (including on demand mode), an interactive instance of rsyslogd can be aborted by pressing ctl-c. -<p> +<p><b>See Also</b> +<ul> +<li><a href="http://www.rsyslog.com/how-to-use-debug-on-demand/">How to use debug on demand</a></li> +</ul> +</p> <p>[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p> <p><font size="2">This documentation is part of the <a href="http://www.rsyslog.com/">rsyslog</a> project.<br> diff --git a/doc/dev_oplugins.html b/doc/dev_oplugins.html index b33b67f9..4a9cd15d 100644 --- a/doc/dev_oplugins.html +++ b/doc/dev_oplugins.html @@ -18,19 +18,10 @@ means they are primarily thought of being message sinks. In theory, however, out plugins may aggergate other functionality, too. Nobody has taken this route so far so if you would like to do that, it is highly suggested to post your plan on the rsyslog mailing list, first (so that we can offer advise). -<p>The rsyslog distribution tarball contains two plugins that are extremely well -targeted for getting started: -<ul> -<li>omtemplate -<li>omstdout -</ul> -Plugin omtemplate was specifically created to provide a copy template for new output -plugins. It is bare of real functionality but has ample comments. Even if you decide -to start from another plugin (or even from scratch), be sure to read omtemplate source -and comments first. The omstdout is primarily a testing aide, but offers support for -the two different parameter-passing conventions plugins can use (plus the way to -differentiate between the two). It also is not bare of functionaly, only mostly -bare of it ;). But you can actually execute it and play with it. +<p>The rsyslog distribution tarball contains the omstdout plugin which is extremely well +targeted for getting started. Just note that this plugin itself is not meant for +production use. But it is very simplistic and so a really good starting point to +grasp the core ideas. <p>In any case, you should also read the comments in ./runtime/module-template.h. Output plugins are build based on a large set of code-generating macros. These macros handle most of the plumbing needed by the interface. As long as no @@ -38,19 +29,7 @@ special callback to rsyslog is needed (it typically is not), an output plugin do not really need to be aware that it is executed by rsyslog. As a plug-in programmer, you can (in most cases) "code as usual". However, all macros and entry points need to be provided and thus reading the code comments in the files mentioned is highly suggested. -<p>In short, the best idea is to start with a template. Let's assume you start by -copying omtemplate. Then, the basic steps you need to do are: -<ul> -<li>cp ./plugins/omtemplate ./plugins/your-plugin -<li>mv cd ./plugins/your-plugin -<li>vi Makefile.am, adjust to your-plugin -<li>mv omtemplate.c your-plugin.c -<li>cd ../.. -<li>vi Makefile.am configure.ac -<br>search for omtemplate, copy and modify (follow comments) -</ul> -<p>Basically, this is all you need to do ... Well, except, of course, coding -your plugin ;). For testing, you need rsyslog's debugging support. Some useful +<p>For testing, you need rsyslog's debugging support. Some useful information is given in "<a href="troubleshoot.html">troubleshooting rsyslog</a> from the doc set. <h2>Special Topics</h2> diff --git a/doc/imfile.html b/doc/imfile.html index 88f0d39f..a69f62e9 100644 --- a/doc/imfile.html +++ b/doc/imfile.html @@ -1,156 +1,218 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> - <head> - <meta content="en" http-equiv="Content-Language" /> - <title>Text File Input Monitor</title> - </head> - <body> - <p> - <a href="rsyslog_conf_modules.html">back</a></p> - <h1> - Text File Input Module</h1> - <p> - <b>Module Name: imfile</b></p> - <p> - <b>Author: </b>Rainer Gerhards <rgerhards@adiscon.com></p> - <p> - <b>Description</b>:</p> - <p> - Provides the ability to convert any standard text file into a syslog message. A standard text file is a file consisting of printable characters with lines being delimited by LF.</p> - <p> - The file is read line-by-line and any line read is passed to rsyslog's rule engine. The rule engine applies filter conditons and selects which actions needs to be carried out. Empty lines are <b>not</b> processed, as they would result in empty syslog records. They are simply ignored.</p> - <p> - As new lines are written they are taken from the file and processed. Please note that this happens based on a polling interval and not immediately. The file monitor support file rotation. To fully work, rsyslogd must run while the file is rotated. Then, any remaining lines from the old file are read and processed and when done with that, the new file is being processed from the beginning. If rsyslogd is stopped during rotation, the new file is read, but any not-yet-reported lines from the previous file can no longer be obtained.</p> - <p> - When rsyslogd is stopped while monitoring a text file, it records the last processed location and continues to work from there upon restart. So no data is lost during a restart (except, as noted above, if the file is rotated just in this very moment).</p> - <p> - Currently, the file must have a fixed name and location (directory). It is planned to add support for dynamically generating file names in the future.</p> - <p> - Multiple files may be monitored by specifying $InputRunFileMonitor multiple times.</p> - <p> - <b>Configuration Directives</b>:</p> - <p> - <b>Module Directives</b></p> - <ul> - <li> - <span style="font-weight: bold;">PollingInterval seconds</span><br /> - This is a global setting. It specifies how often files are to be polled for new data. The time specified is in seconds. The <span style="font-weight: bold;">default value</span> is 10 seconds. Please note that future releases of imfile may support per-file polling intervals, but currently this is not the case. If multiple PollingInterval statements are present in rsyslog.conf, only the last one is used.<br /> - A short poll interval provides more rapid message forwarding, but requires more system ressources. While it is possible, we stongly recommend not to set the polling interval to 0 seconds. That will make rsyslogd become a CPU hog, taking up considerable ressources. It is supported, however, for the few very unusual situations where this level may be needed. Even if you need quick response, 1 seconds should be well enough. Please note that imfile keeps reading files as long as there is any data in them. So a "polling sleep" will only happen when nothing is left to be processed.</li> - </ul> - <p> - <b>Action Directives</b></p> - <ul> - <li> - <strong>(required) File /path/to/file</strong><br /> - The file being monitored. So far, this must be an absolute name (no macros or templates).</li> - <li> - <span style="font-weight: bold;">(required) Tag tag:</span><br /> - The syslog tag to be used for messages that originate from this file. If you would like to see the colon after the tag, you need to specify it here (as shown above).</li> - <li> - <span style="font-weight: bold;">(required) StateFile <name-of-state-file></span><br /> - Rsyslog must keep track of which parts of the to be monitored file it already processed. This is done in the state file. This file always is created in the rsyslog working directory (configurable via $WorkDirectory). So you need to provide a file name here, not a path. Be careful to use unique names for different files being monitored. If there are duplicates, all sorts of "interesting" things may happen. Rsyslog currently does not check if a name is specified multiple times. Note that when $WorkDirectory is not set or set to a non-writable location, the state file will not be generated.</li> - <li> - <span style="font-weight: bold;">Facility facility</span><br /> - The syslog facility to be assigned to lines read. Can be specified in textual form (e.g. "local0", "local1", ...) or as numbers (e.g. 128 for "local0"). Textual form is suggested. <span style="font-weight: bold;">Default</span> is "local0".</li> - <li> - <span style="font-weight: bold;">Severity</span><br /> - The syslog severity to be assigned to lines read. Can be specified in textual form (e.g. "info", "warning", ...) or as numbers (e.g. 4 for "info"). Textual form is suggested. <span style="font-weight: bold;">Default</span> is "notice".</li> - <li> - <b>PersistStateInterval</b> [lines]<br /> - Specifies how often the state file shall be written when processing the input file. The <strong>default</strong> value is 0, which means a new state file is only written when the monitored files is being closed (end of rsyslogd execution). Any other value n means that the state file is written every time n file lines have been processed. This setting can be used to guard against message duplication due to fatal errors (like power fail). Note that this setting affects imfile performance, especially when set to a low value. Frequently writing the state file is very time consuming.</li> - <li> - <b>ReadMode</b> [mode]<br /> - This mode should defined when having multiline messages. The value can range from 0-2 and determines the multiline detection method.<br /> - 0 (<strong>default</strong>) - line based (Each line is a new message)<br /> - 1 - paragraph (There is a blank line between log messages)<br /> - 2 - indented (New log messages start at the beginning of a line. If a line starts with a space it is part of the log message before it)</li> - <li> - <b>MaxLinesAtOnce</b> [number]<br /> - This is useful if multiple files need to be monitored. If set to 0, each file will be fully processed and then processing switches to the next file (this was the default in previous versions). If it is set, a maximum of [number] lines is processed in sequence for each file, and then the file is switched. This provides a kind of mutiplexing the load of multiple files and probably leads to a more natural distribution of events when multiple busy files are monitored. The <strong>default</strong> is 1024.</li> - <li> - <b>MaxSubmitAtOnce</b> [number]<br /> - This is an expert option. It can be used to set the maximum input batch size that imfile can generate. The <strong>default</strong> is 1024, which is suitable for a wide range of applications. Be sure to understand rsyslog message batch processing before you modify this option. If you do not know what this doc here talks about, this is a good indication that you should NOT modify the default.</li> - <li> - <b>Ruleset</b> <ruleset> Binds the listener to a specific <a href="multi_ruleset.html">ruleset</a>.</li> - </ul> - <p> - <b>Caveats/Known Bugs:</b></p> - <p> - So far, only 100 files can be monitored. If more are needed, the source needs to be patched. See define MAX_INPUT_FILES in imfile.c</p> - <p> - Powertop users may want to notice that imfile utilizes polling. Thus, it is no good citizen when it comes to conserving system power consumption. We are currently evaluating to move to inotify(). However, there are a number of subtle issues, which needs to be worked out first. We will make the change as soon as we can. If you can afford it, we recommend using a long polling interval in the mean time.</p> - <p> - <b>Sample:</b></p> - <p> - The following sample monitors two files. If you need just one, remove the second one. If you need more, add them according to the sample ;). This code must be placed in /etc/rsyslog.conf (or wherever your distro puts rsyslog's config files). Note that only commands actually needed need to be specified. The second file uses less commands and uses defaults instead.</p> - <p> - <textarea cols="60" rows="15">module(load="imfile" PollingInterval="10") #needs to be done just once +<html><head> +<meta http-equiv="Content-Language" content="en"><title>Text File Input Monitor</title></head> +<body> +<a href="rsyslog_conf_modules.html">back</a> + +<h1>Text File Input Module</h1> +<p><b>Module Name: imfile</b></p> +<p><b>Author: </b>Rainer Gerhards +<rgerhards@adiscon.com></p> +<p><b>Description</b>:</p> +<p>Provides the ability to convert any standard text file into +a syslog message. A standard +text file is a file consisting of printable characters with lines +being delimited by LF.</p> +<p>The file is read line-by-line and any line read is passed to +rsyslog's rule engine. The rule engine applies filter conditions and +selects which actions needs to be carried out. Empty lines are <b>not</b> +processed, as they would result in empty syslog records. They are simply +ignored.</p> +<p>As new lines are written they are taken from the file and +processed. Please note that this happens based on a polling interval +and not immediately. The file monitor support file rotation. To fully +work, rsyslogd must run while the file is rotated. Then, any remaining +lines from the old file are read and processed and when done with that, +the new file is being processed from the beginning. If rsyslogd is +stopped during rotation, the new file is read, but any not-yet-reported +lines from the previous file can no longer be obtained.</p> +<p>When rsyslogd is stopped while monitoring a text file, it +records the last processed location and continues to work from there +upon restart. So no data is lost during a restart (except, as noted +above, if the file is rotated just in this very moment).</p> +<p>Currently, the file must have a fixed name and location +(directory). It is planned to add support for dynamically generating +file names in the future.</p> +<p>Multiple files may be monitored by specifying +$InputRunFileMonitor multiple times. +</p> + +<p><b>Configuration Directives</b>:</p> +<p><b>Module Directives</b></p> +<ul> +<li><span style="font-weight: bold;">PollingInterval +seconds</span><br> +This is a global setting. It specifies how often files are to be polled +for new data. The time specified is in seconds. The <span style="font-weight: bold;">default value</span> is 10 +seconds. Please note that future +releases of imfile may support per-file polling intervals, but +currently this is not the case. If multiple PollingInterval +statements are present in rsyslog.conf, only the last one is used.<br> +A short poll interval provides more rapid message forwarding, but +requires more system resources. While it is possible, we stongly +recommend not to set the polling interval to 0 seconds. That will make +rsyslogd become a CPU hog, taking up considerable resources. It is +supported, however, for the few very unusual situations where this +level may be needed. Even if you need quick response, 1 seconds should +be well enough. Please note that imfile keeps reading files as long as +there is any data in them. So a "polling sleep" will only happen when +nothing is left to be processed.</li> +</ul> + +<p><b>Action Directives</b></p> +<ul> +<li><strong>(required) File /path/to/file</strong><br> +The file being monitored. So far, this must be an absolute name (no +macros or templates)</li> +<li><span style="font-weight: bold;">(required) Tag +tag:</span><br> +The tag to be used for messages that originate from this file. If you +would like to see the colon after the tag, you need to specify it here +(as shown above).</li> +<li><span style="font-weight: bold;">(required) StateFile +<name-of-state-file></span><br> +Rsyslog must keep track of which parts of the to be monitored file it +already processed. This is done in the state file. This file always is +created in the rsyslog working directory (configurable via +$WorkDirectory). Be careful to use unique names for different files +being monitored. If there are duplicates, all sorts of "interesting" +things may happen. Rsyslog currently does not check if a name is +specified multiple times. +Note that when $WorkDirectory is not set or set to a non-writable +location, the state file will not be generated.</li> +<li><span style="font-weight: bold;">Facility +facility</span><br> +The syslog facility to be assigned to lines read. Can be specified in +textual form (e.g. "local0", "local1", ...) or as numbers (e.g. 128 for +"local0"). Textual form is suggested. <span style="font-weight: bold;">Default</span> is +"local0".<span style="font-weight: bold;"></span></li> +<li><span style="font-weight: bold;">Severity</span><br> +The +syslog severity to be assigned to lines read. Can be specified in +textual form (e.g. "info", "warning", ...) or as numbers (e.g. 4 for +"info"). Textual form is suggested. <span style="font-weight: bold;">Default</span> +is "notice".</li> +<li><b>PersistStateInterval</b> [lines]</b><br> +Specifies how often the state file shall be written when processing the input +file. The <strong>default</strong> value is 0, which means a new state file is only written when +the monitored files is being closed (end of rsyslogd execution). Any other +value n means that the state file is written every time n file lines have +been processed. This setting can be used to guard against message duplication due +to fatal errors (like power fail). Note that this setting affects imfile +performance, especially when set to a low value. Frequently writing the state +file is very time consuming. +<li><b>ReadMode</b> [mode]</b><br> +This mode should defined when having multiline messages. The value can range from 0-2 and determines the multiline detection method. +<br>0 (<strong>default</strong>) - line based (Each line is a new message) +<br>1 - paragraph (There is a blank line between log messages) +<br>2 - indented (New log messages start at the beginning of a line. If a line starts with a space it is part of the log message before it) +<li><b>MaxLinesAtOnce</b> [number]</b> +<br> +This is useful if multiple files need to be monitored. If set to 0, each file +will be fully processed and then processing switches to the next file +(this was the default in previous versions). If it is set, a maximum of +[number] lines is processed in sequence for each file, and then the file is +switched. This provides a kind of mutiplexing the load of multiple files and +probably leads to a more natural distribution of events when multiple busy files +are monitored. The <strong>default</strong> is 1024. +<li><b>MaxSubmitAtOnce</b> [number]</b> +<br> +This is an expert option. It can be used to set the maximum input batch size that +imfile can generate. The <strong>default</strong> is 1024, which is suitable for a wide range of +applications. Be sure to understand rsyslog message batch processing before you +modify this option. If you do not know what this doc here talks about, this is a +good indication that you should NOT modify the default. +<li><b>Ruleset</b> <ruleset> +Binds the listener to a specific <a href="multi_ruleset.html">ruleset</a>.</li> +</ul> +<b>Caveats/Known Bugs:</b> +<p>So far, only 100 files can be monitored. If more are needed, +the source needs to be patched. See define MAX_INPUT_FILES in imfile.c</p><p>Powertop +users may want to notice that imfile utilizes polling. Thus, it is no +good citizen when it comes to conserving system power consumption. We +are currently evaluating to move to inotify(). However, there are a +number of subtle issues, which needs to be worked out first. We will +make the change as soon as we can. If you can afford it, we recommend +using a long polling interval in the mean time. +</p> +<p><b>Sample:</b></p> +<p>The following sample monitors two files. If you need just one, +remove the second one. If you need more, add them according to the +sample ;). This code must be placed in /etc/rsyslog.conf (or wherever +your distro puts rsyslog's config files). Note that only commands +actually needed need to be specified. The second file uses less +commands and uses defaults instead.<br> +</p> +<textarea rows="15" cols="60">module(load="imfile" PollingInterval="10") #needs to be done just once # File 1 -input(type="imfile" - File="/path/to/file1" - Tag="tag1" - StateFile="statefile1" - Severity="error" - Facility="local7") +input(type="imfile" File="/path/to/file1" + Tag="tag1" + StateFile="statefile1" + Severity="error" + Facility="local7") # File 2 -input(type="imfile" - File="/path/to/file2" - Tag="tag2" - StateFile="statefile2") -# ... and so on ... #</textarea></p> - <p> - <b>Legacy Configuration Directives</b>:</p> - <ul> - <li> - <strong>$InputFileName /path/to/file</strong><br /> - equivalent to: File</li> - <li> - <span style="font-weight: bold;">$InputFileTag tag:</span><br /> - equivalent to: Tag</li> - <li> - <span style="font-weight: bold;">$InputFileStateFile <name-of-state-file></span><br /> - equivalent to: StateFile</li> - <li> - <span style="font-weight: bold;">$InputFileFacility facility</span><br /> - equivalent to: Facility</li> - <li> - <span style="font-weight: bold;">$InputFileSeverity</span><br /> - equivalent to: Severity</li> - <li> - <span style="font-weight: bold;">$InputRunFileMonitor</span><br /> - This <span style="font-weight: bold;">activates</span> the current monitor. It has no parameters. If you forget this directive, no file monitoring will take place.</li> - <li> - <span style="font-weight: bold;">$InputFilePollInterval seconds</span><br /> - equivalent to: PollingInterva</li> - <li> - <b>$InputFilePersistStateInterval</b> [lines]<br /> - Available in 4.7.3+, 5.6.2+<br /> - equivalent to: PersistStateInterval</li> - <li> - <b>$InputFileReadMode</b> [mode]<br /> - Available in 5.7.5+<br /> - equivalent to: ReadMode</li> - <li> - <b>$InputFileMaxLinesAtOnce</b> [number]<br /> - Available in 5.9.0+<br /> - equivalent to: MaxLinesAtOnce</li> - <li> - $InputFileBindRuleset <ruleset><br /> - Available in 5.7.5+, 6.1.5+<br /> - equivalent to: Ruleset</li> - </ul> - <p> - <b>Caveats/Known Bugs:</b></p> - <p> - So far, only 100 files can be monitored. If more are needed, the source needs to be patched. See define MAX_INPUT_FILES in imfile.c</p> - <p> - Powertop users may want to notice that imfile utilizes polling. Thus, it is no good citizen when it comes to conserving system power consumption. We are currently evaluating to move to inotify(). However, there are a number of subtle issues, which needs to be worked out first. We will make the change as soon as we can. If you can afford it, we recommend using a long polling interval in the mean time.</p> - <p> - <b>Sample:</b></p> - <p> - The following sample monitors two files. If you need just one, remove the second one. If you need more, add them according to the sample ;). This code must be placed in /etc/rsyslog.conf (or wherever your distro puts rsyslog's config files). Note that only commands actually needed need to be specified. The second file uses less commands and uses defaults instead.</p> - <p> - <textarea cols="60" rows="15">$ModLoad imfile # needs to be done just once +input(type="imfile" File="/path/to/file2" + Tag="tag2" + StateFile="statefile2") +# ... and so on ... +# +</textarea> + + +<p><b>Legacy Configuration Directives</b>:</p> +<ul> +<li><strong>$InputFileName /path/to/file</strong><br> +equivalent to: File </li> +<li><span style="font-weight: bold;">$InputFileTag +tag:</span><br> +equivalent to: Tag </li> +<li><span style="font-weight: bold;">$InputFileStateFile +<name-of-state-file></span><br> +equivalent to: StateFile </li> +<li><span style="font-weight: bold;">$InputFileFacility +facility</span><br> +equivalent to: Facility </span></li> +<li><span style="font-weight: bold;">$InputFileSeverity</span><br> +equivalent to: Severity</li> +<li><span style="font-weight: bold;">$InputRunFileMonitor</span><br> +This <span style="font-weight: bold;">activates</span> +the current monitor. It has no parameters. If you forget this +directive, no file monitoring will take place.</li> +<li><span style="font-weight: bold;">$InputFilePollInterval +seconds</span><br> +equivalent to: PollingInterval</li> +<li><b>$InputFilePersistStateInterval</b> [lines]</b><br> +Available in 4.7.3+, 5.6.2+<br> +equivalent to: PersistStateInterval +<li><b>$InputFileReadMode</b> [mode]</b><br> +Available in 5.7.5+<br> +equivalent to: ReadMode +<li><b>$InputFileMaxLinesAtOnce</b> [number]</b><br> +Available in 5.9.0+<br> +equivalent to: MaxLinesAtOnce +<li>$InputFileBindRuleset <ruleset><br> +Available in 5.7.5+, 6.1.5+<br> +equivalent to: Ruleset </li> +</ul> +<b>Caveats/Known Bugs:</b> +<p>So far, only 100 files can be monitored. If more are needed, +the source needs to be patched. See define MAX_INPUT_FILES in imfile.c</p><p>Powertop +users may want to notice that imfile utilizes polling. Thus, it is no +good citizen when it comes to conserving system power consumption. We +are currently evaluating to move to inotify(). However, there are a +number of subtle issues, which needs to be worked out first. We will +make the change as soon as we can. If you can afford it, we recommend +using a long polling interval in the mean time. +</p> +<p><b>Sample:</b></p> +<p>The following sample monitors two files. If you need just one, +remove the second one. If you need more, add them according to the +sample ;). This code must be placed in /etc/rsyslog.conf (or wherever +your distro puts rsyslog's config files). Note that only commands +actually needed need to be specified. The second file uses less +commands and uses defaults instead.<br> +</p> +<textarea rows="15" cols="60">$ModLoad imfile # needs to be done just once # File 1 $InputFileName /path/to/file1 $InputFileTag tag1: @@ -158,18 +220,21 @@ $InputFileStateFile stat-file1 $InputFileSeverity error $InputFileFacility local7 $InputRunFileMonitor -# File 2 -$InputFileName /path/to/file2 -$InputFileTag tag2: -$InputFileStateFile stat-file2 -$InputRunFileMonitor -# ... and so on ... # -# check for new lines every 10 seconds -$InputFilePollingInterval 10</textarea></p> - <p> - [<a href="rsyslog_conf.html">rsyslog.conf overview</a>] [<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p> - <p> - <font size="2">This documentation is part of the <a href="http://www.rsyslog.com/">rsyslog</a> project.<br /> - Copyright © 2008 by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and <a href="http://www.adiscon.com/">Adiscon</a>. Released under the GNU GPL version 3 or higher.</font></p> - </body> -</html> +# File 2 +$InputFileName /path/to/file2 +$InputFileTag tag2: +$InputFileStateFile stat-file2 +$InputRunFileMonitor +# ... and so on ... +# +# check for new lines every 10 seconds +$InputFilePollInterval 10 +</textarea> +<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>] +[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p> +<p><font size="2">This documentation is part of the +<a href="http://www.rsyslog.com/">rsyslog</a> project.<br> +Copyright © 2008 by <a href="http://www.gerhards.net/rainer">Rainer +Gerhards</a> and <a href="http://www.adiscon.com/">Adiscon</a>. +Released under the GNU GPL version 3 or higher.</font></p> +</body></html> diff --git a/doc/impstats.html b/doc/impstats.html index 8db9c6f6..392fc431 100644 --- a/doc/impstats.html +++ b/doc/impstats.html @@ -81,6 +81,12 @@ If set to on, stats messages are emitted as structured cee-enhanced syslog. If set to off, legacy format is used (which is compatible with pre v6-rsyslog). </li> </ul> +<p><b>See Also</b> +<ul> +<li><a href="http://www.rsyslog.com/rsyslog-statistic-counter/">rsyslog statistics counter</a></li> +<li><a href="http://www.rsyslog.com/impstats-delayed-or-lost/">impstats delayed or lost</a> - cause and cure +</ul> +</p> <b>Caveats/Known Bugs:</b> <ul> <li>This module MUST be loaded right at the top of rsyslog.conf, otherwise diff --git a/doc/imuxsock.html b/doc/imuxsock.html index 0affe8c3..e89a67aa 100644 --- a/doc/imuxsock.html +++ b/doc/imuxsock.html @@ -180,7 +180,13 @@ oneself has the advantage that a limited amount of messages may be queued by the OS if rsyslog is not running. </li> </ul> - +<p><b>See Also</b> +<ul> +<li><a href="http://www.rsyslog.com/what-are-trusted-properties/">What are "trusted properties"?</a></li> +<li><a href="http://www.rsyslog.com/why-does-imuxsock-not-work-on-solaris/">Why does imuxsock not work +on Solaris?</a></li> +</ul> +</p> <b>Caveats/Known Bugs:</b><br> <ul> <li>There is a compile-time limit of 50 concurrent sockets. If you need more, you need to diff --git a/doc/manual.html b/doc/manual.html index bc57c136..a8477bcd 100644 --- a/doc/manual.html +++ b/doc/manual.html @@ -19,7 +19,7 @@ professional services</a> available directly from the source!</p> <p><b>Please visit the <a href="http://www.rsyslog.com/sponsors">rsyslog sponsor's page</a> to honor the project sponsors or become one yourself!</b> We are very grateful for any help towards the project goals.</p> -<p><b>This documentation is for version 7.4.1 (v7.4-stable branch) of rsyslog.</b> +<p><b>This documentation is for version 7.4.6 (v7.4-stable branch) of rsyslog.</b> Visit the <i><a href="http://www.rsyslog.com/status">rsyslog status page</a></i></b> to obtain current version information and project status. </p><p><b>If you like rsyslog, you might diff --git a/doc/mmanon.html b/doc/mmanon.html index 16065a1f..e14d75cf 100644 --- a/doc/mmanon.html +++ b/doc/mmanon.html @@ -18,14 +18,7 @@ Note that anonymization will break digital signatures on the message, if they exist. <p><i>How are IP-Addresses defined?</i> <p>We assume that an IP address consists of four octets in dotted notation, -where each of the octets has a value between 0 and 255, inclusively. After -the last octet, there must be either a space or a colon. So, for example, -"1.2.3.4 Test" and "1.2.3.4:514 Test" are detected as containing valid IP -addresses, whereas this is not the case for "1.2.300.4 Test" or -"1.2.3.4-Test". The message text may contain multiple addresses. If so, -each of them is anonimized (according to the same rules). -<b>Important:</b> We may change the set of acceptable characters after -the last octet in the future, if there are good reasons to do so. +where each of the octets has a value between 0 and 255, inclusively. <p> </p> <p><b>Module Configuration Parameters</b>:</p> diff --git a/doc/mmnormalize.html b/doc/mmnormalize.html index 787bd957..81100235 100644 --- a/doc/mmnormalize.html +++ b/doc/mmnormalize.html @@ -46,6 +46,17 @@ parameter. <li>$mmnormalizeUseRawMsg <on/off> - equivalent to the "useRawMsg" parameter. </ul> +<p><b>See Also</b> +<ul> +<li><a href="http://www.rsyslog.com/normalizer-first-steps-for-mmnormalize/">First steps for mmnormalize</a></li> +<li><a href="http://www.rsyslog.com/log-normalization-and-special-characters/">Log normalization and +special characters</a></li> +<li><a href="http://www.rsyslog.com/log-normalization-and-the-leading-space/">Log normalization and +the leading space</a></li> +<li><a href="http://www.rsyslog.com/using-rsyslog-mmnormalize-module-effectively-with-adiscon-loganalyzer/">Using +mmnormalize effectively with Adiscon LogAnalyzer</a></li> +</ul> +</p> <b>Caveats/Known Bugs:</b> <p>None known at this time. </ul> diff --git a/doc/omfile.html b/doc/omfile.html index cd53fd1d..0f64f26f 100644 --- a/doc/omfile.html +++ b/doc/omfile.html @@ -97,7 +97,31 @@ sets a new default template for file actions.<br></li><br> </ul> -<p><b>Caveats/Known Bugs:</b></p><ul><li>None.</li></ul> +<p><b>See Also</b> +<ul> +<li><a href="http://www.rsyslog.com/how-to-sign-log-messages-through-signature-provider-guardtime/">Sign log messages through signature provider Guardtime</a></li> +</ul> +</p> +<p><b>Caveats/Known Bugs:</b></p> +<ul> +<li>One needs to be careful with log rotation if signatures and/or encryption +are being used. These create side-files, which form a set and must be kept +together. +<br> +For signatures, the ".sigstate" file must NOT be rotated away if +signature chains are to be build across multiple files. This is because +.sigstate contains just global information for the whole file set. However, +all other files need to be rotated together. The proper sequence is to + <ol> + <li> move all files inside the file set + <li> only AFTER this is completely done, HUP rsyslog + </ol> +This sequence will ensure that all files inside the set are atomically +closed and in sync. HUPing only after a subset of files have been moved +results in inconsistencies and will most probably render the file set +unusable. +</li> +</ul> <p><b>Sample:</b></p> <p>The following command writes all syslog messages into a file.</p> <textarea rows="5" cols="60">Module (load="builtin:omfile") diff --git a/doc/omfwd.html b/doc/omfwd.html index 53f9e527..a541dd27 100644 --- a/doc/omfwd.html +++ b/doc/omfwd.html @@ -56,6 +56,11 @@ Permits to resend the last message when a connection is reconnected. This setting affects TCP-based syslog, only. It is most useful for traditional, plain TCP syslog. Using this protocol, it is not always possible to know which messages were successfully transmitted to the receiver when a connection breaks. In many cases, the last message sent is lost. By switching this setting to "yes", rsyslog will always retransmit the last message when a connection is reestablished. This reduces potential message loss, but comes at the price that some messages may be duplicated (what usually is more acceptable). <br></li><br> </ul> +<p><b>See Also</b> +<ul> +<li><a href="http://www.rsyslog.com/encrypted-disk-queues/">Encrypted Disk Queues</a></li> +</ul> +</p> <p><b>Caveats/Known Bugs:</b></p><ul><li>None.</li></ul> <p><b>Sample:</b></p> <p>The following command sends all syslog messages to a remote server via TCP port 10514.</p> diff --git a/doc/omruleset.html b/doc/omruleset.html index 41d6ccfc..f0d5f7bd 100644 --- a/doc/omruleset.html +++ b/doc/omruleset.html @@ -122,6 +122,11 @@ $ActionOmrulesetRulesetName nested # of course, we can have "regular" actions alongside :omrulset: actions *.* /path/to/general-message-file.log </textarea> +<p><b>See Also</b> +<ul> +<li><a href="http://www.rsyslog.com/rulesets-and-rsyslog-7-2/">Calling rulesets since rsyslog 7.2</a></li> +</ul> +</p> <p><b>Caveats/Known Bugs:</b> <p>The current configuration file language is not really adequate for a complex construct like omruleset. Unfortunately, more important work is currently preventing me from redoing the diff --git a/doc/property_replacer.html b/doc/property_replacer.html index 13ff41c3..7218c22e 100644 --- a/doc/property_replacer.html +++ b/doc/property_replacer.html @@ -746,13 +746,15 @@ use drop-cc and "drop-cc,escape-cc" will use escape-cc mode. options. It was initially introduced to support the "jsonf" option, for which it provides the capability to set an alternative field name. If it is not specified, it defaults to the property name. -<h2>Further Links</h2> +<b>See also</b> <ul> <li>Article on "<a href="rsyslog_recording_pri.html">Recording the Priority of Syslog Messages</a>" (describes use of templates to record severity and facility of a message)</li> <li><a href="rsyslog_conf.html">Configuration file format</a>, this is where you actually use the property replacer.</li> +<li><a href="http://www.rsyslog.com/what-is-the-difference-between-timereported-and-timegenerated/"> +Difference between timereported and timegenerated.</li> </ul> <p>[<a href="manual.html">manual index</a>] [<a href="rsyslog_conf.html">rsyslog.conf</a>] diff --git a/doc/queues.html b/doc/queues.html index 75b70fbf..85df9fef 100644 --- a/doc/queues.html +++ b/doc/queues.html @@ -386,6 +386,11 @@ it terminates. This includes data elements there were begun being processed by workers that needed to be cancelled due to too-long processing. For a large queue, this operation may be lengthy. No timeout applies to a required shutdown save.</p> +<p><b>See Also</b> +<ul> +<li><a href="http://www.rsyslog.com/encrypted-disk-queues/">Encrypted Disk Queues</a></li> +</ul> +</p> [<a href="manual.html">manual index</a>] [<a href="rsyslog_conf.html">rsyslog.conf</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p> diff --git a/doc/rsyslog_conf_filter.html b/doc/rsyslog_conf_filter.html index a795193f..c8a40b6c 100644 --- a/doc/rsyslog_conf_filter.html +++ b/doc/rsyslog_conf_filter.html @@ -275,6 +275,11 @@ supported (except for "not" as outlined above). Please note that while it is possible to query facility and severity via property-based filters, it is far more advisable to use classic selectors (see above) for those cases.</p> +<p><b>See Also</b> +<ul> +<li><a href="http://www.rsyslog.com/filter-optimization-with-arrays/">Filter optimization with arrays</a></li> +</ul> +</p> <p>[<a href="manual.html">manual index</a>] [<a href="rsyslog_conf.html">rsyslog.conf</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p> diff --git a/doc/rsyslog_conf_templates.html b/doc/rsyslog_conf_templates.html index 9a6e1619..562aa9a3 100644 --- a/doc/rsyslog_conf_templates.html +++ b/doc/rsyslog_conf_templates.html @@ -288,8 +288,8 @@ Note that the template string itself must be on a single line. <h4>Standard Template for Forwarding to a Remote Host (RFC3164 mode)</h4> <p><pre><code>template(name="ForwardFormat" type="list") { constant(value="<") - property(name="PRI") - constant(value="<") + property(name="pri") + constant(value=">") property(name="timestamp" dateFormat="rfc3339") constant(value=" ") property(name="hostname") @@ -524,7 +524,13 @@ $template TraditionalForwardFormat,"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag:1:3 <br><br> $template StdSQLFormat,"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')",SQL </code></p> - +<p><b>See Also</b> +<ul> +<li><a href="http://www.rsyslog.com/how-to-bind-a-template/">How to bind a template</a></li> +<li><a href="http://www.rsyslog.com/adding-the-bom-to-a-message/">Adding the BOM to a message</a></li> +<li><a href="http://www.rsyslog.com/article60/">How to separate log files by host name of the sending device</a></li> +</ul> +</p> <p>[<a href="manual.html">manual index</a>] [<a href="rsyslog_conf.html">rsyslog.conf</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p> diff --git a/doc/rsyslog_packages.html b/doc/rsyslog_packages.html index 80ba96c5..014791a3 100644 --- a/doc/rsyslog_packages.html +++ b/doc/rsyslog_packages.html @@ -12,20 +12,29 @@ like to maintain a package for a new distribution, please mail me at appreciated. While I create the core daemon, the package maintainers are really filling it with life, making it available to the average user. I am very grateful for that!</p> -<p>This list has last been updated on 2008-07-11 by +<p>This list has last been updated on 2013-07-25 by <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>. New packages may appear at any time, so be sure to check this page whenever you need a new one.</p> <ul> +<li><b>Ubuntu</b> (maintained by Adiscon) + <ul> + <li><a href="http://www.rsyslog.com/ubuntu-repository/">http://www.rsyslog.com/ubuntu-repository/</a> + </ul> + +<li><b>RHEL/CentOS</b> (maintained by Adiscon) + <ul> + <li><a href="http://www.rsyslog.com/rhelcentos-rpms/">http://www.rsyslog.com/rhelcentos-rpms/</a> + </ul> + <li><b>BSD</b> (maintained by infofarmer) <ul> - <li><a href="http://www.freshports.org/sysutils/rsyslog/"> http://www.freshports.org/sysutils/rsyslog/</a> + <li><a href="http://www.freshports.org/sysutils/rsyslog/">http://www.freshports.org/sysutils/rsyslog/</a> </ul> <li><b>CentOS 4.3</b> (maintained by James Bergamin) <ul> - <li><a href="http://www.se-community.com/~james/rsyslog/"> -http://www.se-community.com/~james/rsyslog/</a> + <li><a href="http://www.se-community.com/~james/rsyslog/">http://www.se-community.com/~james/rsyslog/</a> </ul> <li><b>Debian</b> (maintained by Michael Biebl) @@ -72,5 +81,10 @@ of the distribution name. <p>If you do not find a suitable package for your distribution, there is no reason to panic. It is quite simple to install rsyslog from the source tarball, so you should consider that. +<p><b>See Also</b> +<ul> +<li><a href="http://www.rsyslog.com/how-to-use-the-ubuntu-repository/">How to use the Ubuntu repository</a></li> +</ul> +</p> </body> </html> diff --git a/doc/sigprov_gt.html b/doc/sigprov_gt.html index caeee116..5ffd26d8 100644 --- a/doc/sigprov_gt.html +++ b/doc/sigprov_gt.html @@ -64,6 +64,12 @@ sig.keepRecordHashes requries). Note that both Tree and Record hashes can be kept inside the signature file. </li> </ul> +<p><b>See Also</b> +<ul> +<li><a href="http://www.rsyslog.com/how-to-sign-log-messages-through-signature-provider-guardtime/">How +to sign log messages through signature provider Guardtime</a></li> +</ul> +</p> <b>Caveats/Known Bugs:</b> <ul> <li>currently none known diff --git a/doc/troubleshoot.html b/doc/troubleshoot.html index 0f0c7fca..a0303a24 100644 --- a/doc/troubleshoot.html +++ b/doc/troubleshoot.html @@ -88,15 +88,19 @@ passwords or other sensitive data. If it does, you can change it to some <b>cons meaningless value. <b>Do not delete the lines</b>, as this renders the debug log unusable (and makes Rainer quite angry for wasted time, aka significantly reduces the chance he will remain motivated to look at your problem ;)). For the same reason, make sure -whatever you change is change consistently. Really! -<p>Debug log file can get quite large. Before submitting them, it is a good idea to zip them. -Rainer has handled files of around 1 to 2 GB. If your's is larger ask before submitting. Often, -it is sufficient to submit the first 2,000 lines of the log file and around another 1,000 around -the area where you see a problem. Also, -ask you can submit a file via private mail. Private mail is usually a good way to go for large files -or files with sensitive content. However, do NOT send anything sensitive that you do not want -the outside to be known. While Rainer so far made effort no to leak any sensitive information, -there is no guarantee that doesn't happen. If you need a guarantee, you are probably a +whatever you change is changed consistently. Really! +<p>While most debug log files are moderately large, some can get quite to extremly large. +For those on the larger side, it is a good idea to zip them. If the file is less than +around 100KiB, it's probably not necessary. +<p>A good place to post your debug log is at the +<a href="http://kb.monitorware.com/rsyslog-f40.html">rsyslog support forums</a>, together with +your question. This also enables us to keep track of the case. The forums accept attachments in +various common formats, but rejects others for security reasons. The zip, txt, and log extensions +are definitely permitted, so it probably is a good idea to use one of them. For others, please +simply try and revert to another format if the forum doesn't like what you used. +<p> +Please note that all information in your debug file is publically visiable. +If this is not acceptable for you, you are probably a candidate for a <a href="professional_support.html">commercial support contract</a>. Free support comes without any guarantees, include no guarantee on confidentiality [aka "we don't want to be sued for work were are not even paid for ;)]. @@ -156,7 +160,7 @@ need to program or do anything else except get a problem solved ;) [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p> <p><font size="2">This documentation is part of the <a href="http://www.rsyslog.com/">rsyslog</a> project.<br> -Copyright © 2008-2010 by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and +Copyright © 2008-2013 by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a> and <a href="http://www.adiscon.com/">Adiscon</a>. Released under the GNU GPL version 3 or higher.</font></p> </body> diff --git a/grammar/lexer.l b/grammar/lexer.l index 237eb2a6..ed5d8a80 100644 --- a/grammar/lexer.l +++ b/grammar/lexer.l @@ -88,7 +88,9 @@ extern int yydebug; /* somehow, I need these prototype even though the headers are * included. I guess that's some autotools magic I don't understand... */ +#if !defined(__FreeBSD__) int fileno(FILE *stream); +#endif %} diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index a7828839..a1de6442 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -854,7 +854,7 @@ nvlstGetParam(struct nvlst *valnode, struct cnfparamdescr *param, r = doGetInt(valnode, param, val); break; case eCmdHdlrNonNegInt: - r = doGetPositiveInt(valnode, param, val); + r = doGetNonNegInt(valnode, param, val); break; case eCmdHdlrPositiveInt: r = doGetPositiveInt(valnode, param, val); @@ -1259,7 +1259,7 @@ doFunc_re_extract(struct cnffunc *func, struct var *ret, void* usrptr) str = (char*) var2CString(&r[0], &bMustFree); matchnbr = (short) var2Number(&r[2], NULL); submatchnbr = (size_t) var2Number(&r[3], NULL); - if(submatchnbr > sizeof(pmatch)/sizeof(regmatch_t)) { + if(submatchnbr >= sizeof(pmatch)/sizeof(regmatch_t)) { DBGPRINTF("re_extract() submatch %d is too large\n", submatchnbr); bHadNoMatch = 1; goto finalize_it; @@ -1307,15 +1307,19 @@ doFunc_re_extract(struct cnffunc *func, struct var *ret, void* usrptr) iLenBuf); } +finalize_it: if(bMustFree) free(str); if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr); if(r[2].datatype == 'S') es_deleteStr(r[2].d.estr); if(r[3].datatype == 'S') es_deleteStr(r[3].d.estr); -finalize_it: + if(bHadNoMatch) { cnfexprEval(func->expr[4], &r[4], usrptr); estr = var2String(&r[4], &bMustFree); - if(r[4].datatype == 'S') es_deleteStr(r[4].d.estr); + /* Note that we do NOT free the string that was returned/created + * for r[4]. We pass it to the caller, which in turn frees it. + * This saves us doing one unnecessary memory alloc & write. + */ } ret->datatype = 'S'; ret->d.estr = estr; @@ -1355,6 +1359,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr) estr = var2String(&r[0], &bMustFree); ret->d.n = es_strlen(estr); if(bMustFree) es_deleteStr(estr); + if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr); } ret->datatype = 'N'; break; @@ -2279,7 +2284,8 @@ cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree) free(cstr); break; case S_ACT: - doIndent(indent); dbgprintf("ACTION %p [%s]\n", stmt->d.act, stmt->printable); + doIndent(indent); dbgprintf("ACTION %p [%s:%s]\n", stmt->d.act, + modGetName(stmt->d.act->pMod), stmt->printable); break; case S_IF: doIndent(indent); dbgprintf("IF\n"); @@ -2447,59 +2453,69 @@ cnfstmtNew(unsigned s_type) return cnfstmt; } +void cnfstmtDestructLst(struct cnfstmt *root); + +/* delete a single stmt */ +static void +cnfstmtDestruct(struct cnfstmt *stmt) +{ + switch(stmt->nodetype) { + case S_NOP: + case S_STOP: + break; + case S_CALL: + es_deleteStr(stmt->d.s_call.name); + break; + case S_ACT: + actionDestruct(stmt->d.act); + break; + case S_IF: + cnfexprDestruct(stmt->d.s_if.expr); + if(stmt->d.s_if.t_then != NULL) { + cnfstmtDestructLst(stmt->d.s_if.t_then); + } + if(stmt->d.s_if.t_else != NULL) { + cnfstmtDestructLst(stmt->d.s_if.t_else); + } + break; + case S_SET: + free(stmt->d.s_set.varname); + cnfexprDestruct(stmt->d.s_set.expr); + break; + case S_UNSET: + free(stmt->d.s_set.varname); + break; + case S_PRIFILT: + cnfstmtDestructLst(stmt->d.s_prifilt.t_then); + cnfstmtDestructLst(stmt->d.s_prifilt.t_else); + break; + case S_PROPFILT: + if(stmt->d.s_propfilt.propName != NULL) + es_deleteStr(stmt->d.s_propfilt.propName); + if(stmt->d.s_propfilt.regex_cache != NULL) + rsCStrRegexDestruct(&stmt->d.s_propfilt.regex_cache); + if(stmt->d.s_propfilt.pCSCompValue != NULL) + cstrDestruct(&stmt->d.s_propfilt.pCSCompValue); + cnfstmtDestructLst(stmt->d.s_propfilt.t_then); + break; + default: + dbgprintf("error: unknown stmt type during destruct %u\n", + (unsigned) stmt->nodetype); + break; + } + free(stmt->printable); + free(stmt); +} + +/* delete a stmt and all others following it */ void -cnfstmtDestruct(struct cnfstmt *root) +cnfstmtDestructLst(struct cnfstmt *root) { struct cnfstmt *stmt, *todel; for(stmt = root ; stmt != NULL ; ) { - switch(stmt->nodetype) { - case S_NOP: - case S_STOP: - break; - case S_CALL: - es_deleteStr(stmt->d.s_call.name); - break; - case S_ACT: - actionDestruct(stmt->d.act); - break; - case S_IF: - cnfexprDestruct(stmt->d.s_if.expr); - if(stmt->d.s_if.t_then != NULL) { - cnfstmtDestruct(stmt->d.s_if.t_then); - } - if(stmt->d.s_if.t_else != NULL) { - cnfstmtDestruct(stmt->d.s_if.t_else); - } - break; - case S_SET: - free(stmt->d.s_set.varname); - cnfexprDestruct(stmt->d.s_set.expr); - break; - case S_UNSET: - free(stmt->d.s_set.varname); - break; - case S_PRIFILT: - cnfstmtDestruct(stmt->d.s_prifilt.t_then); - cnfstmtDestruct(stmt->d.s_prifilt.t_else); - break; - case S_PROPFILT: - if(stmt->d.s_propfilt.propName != NULL) - es_deleteStr(stmt->d.s_propfilt.propName); - if(stmt->d.s_propfilt.regex_cache != NULL) - rsCStrRegexDestruct(&stmt->d.s_propfilt.regex_cache); - if(stmt->d.s_propfilt.pCSCompValue != NULL) - cstrDestruct(&stmt->d.s_propfilt.pCSCompValue); - cnfstmtDestruct(stmt->d.s_propfilt.t_then); - break; - default: - dbgprintf("error: unknown stmt type during destruct %u\n", - (unsigned) stmt->nodetype); - break; - } - free(stmt->printable); todel = stmt; stmt = stmt->next; - free(todel); + cnfstmtDestruct(todel); } } @@ -2557,14 +2573,15 @@ struct cnfstmt * cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then) { struct cnfstmt* cnfstmt; - rsRetVal lRet; if((cnfstmt = cnfstmtNew(S_PROPFILT)) != NULL) { cnfstmt->printable = (uchar*)propfilt; cnfstmt->d.s_propfilt.t_then = t_then; cnfstmt->d.s_propfilt.propName = NULL; cnfstmt->d.s_propfilt.regex_cache = NULL; cnfstmt->d.s_propfilt.pCSCompValue = NULL; - lRet = DecodePropFilter((uchar*)propfilt, cnfstmt); + if(DecodePropFilter((uchar*)propfilt, cnfstmt) != RS_RET_OK) { + cnfstmt->nodetype = S_NOP; /* disable action! */ + } } return cnfstmt; } @@ -2769,7 +2786,7 @@ cnfexprOptimize_CMP_var(struct cnfexpr *expr) parser_errmsg("invalid facility '%s', expression will always " "evaluate to FALSE", cstr); } else { - /* we can acutally optimize! */ + /* we can actually optimize! */ DBGPRINTF("optimizer: change comparison OP to FUNC prifilt()\n"); func = cnffuncNew_prifilt(fac); if(expr->nodetype == CMP_NE) @@ -2848,7 +2865,7 @@ cnfexprOptimize_AND_OR(struct cnfexpr *expr) static inline void cnfexprOptimize_CMPEQ_arr(struct cnfarray *arr) { - DBGPRINTF("optimizer: sorting array for CMP_EQ/NEQ comparison\n"); + DBGPRINTF("optimizer: sorting array of %d members for CMP_EQ/NEQ comparison\n", arr->nmemb); qsort(arr->arr, arr->nmemb, sizeof(es_str_t*), qs_arrcmp); } @@ -2910,10 +2927,14 @@ cnfexprOptimize(struct cnfexpr *expr) expr->r = exprswap; } } + if(expr->r->nodetype == 'A') { + cnfexprOptimize_CMPEQ_arr((struct cnfarray *)expr->r); + } + /* This should be evaluated last because it may change expr + * to a function. + */ if(expr->l->nodetype == 'V') { expr = cnfexprOptimize_CMP_var(expr); - } else if(expr->r->nodetype == 'A') { - cnfexprOptimize_CMPEQ_arr((struct cnfarray *)expr->r); } break; case CMP_LE: @@ -3050,7 +3071,7 @@ cnfstmtOptimizePRIFilt(struct cnfstmt *stmt) DBGPRINTF("optimizer: removing always-true PRIFILT %p\n", stmt); if(stmt->d.s_prifilt.t_else != NULL) { parser_errmsg("error: always-true PRI filter has else part!\n"); - cnfstmtDestruct(stmt->d.s_prifilt.t_else); + cnfstmtDestructLst(stmt->d.s_prifilt.t_else); } free(stmt->printable); stmt->printable = NULL; diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index 7debc420..06573307 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -333,7 +333,7 @@ struct cnfstmt * cnfstmtNewSet(char *var, struct cnfexpr *expr); struct cnfstmt * cnfstmtNewUnset(char *var); struct cnfstmt * cnfstmtNewCall(es_str_t *name); struct cnfstmt * cnfstmtNewContinue(void); -void cnfstmtDestruct(struct cnfstmt *root); +void cnfstmtDestructLst(struct cnfstmt *root); void cnfstmtOptimize(struct cnfstmt *root); struct cnfarray* cnfarrayNew(es_str_t *val); struct cnfarray* cnfarrayDup(struct cnfarray *old); diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 2e80ffc8..9c824c18 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -473,12 +473,12 @@ CODESTARTnewInpInst } else if(!strcmp(inppblk.descr[i].name, "severity")) { inst->iSeverity = pvals[i].val.d.n; } else if(!strcmp(inppblk.descr[i].name, "facility")) { - inst->iSeverity = pvals[i].val.d.n; + inst->iFacility = pvals[i].val.d.n; } else if(!strcmp(inppblk.descr[i].name, "readmode")) { inst->readMode = pvals[i].val.d.n; } else if(!strcmp(inppblk.descr[i].name, "maxlinesatonce")) { inst->maxLinesAtOnce = pvals[i].val.d.n; - } else if(!strcmp(inppblk.descr[i].name, "persistStateInterval")) { + } else if(!strcmp(inppblk.descr[i].name, "persiststateinterval")) { inst->iPersistStateInterval = pvals[i].val.d.n; } else if(!strcmp(inppblk.descr[i].name, "maxsubmitatonce")) { inst->nMultiSub = pvals[i].val.d.n; @@ -832,8 +832,8 @@ resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unus cs.pszFileName = NULL; free(cs.pszFileTag); cs.pszFileTag = NULL; - free(cs.pszFileTag); - cs.pszFileTag = NULL; + free(cs.pszStateFile); + cs.pszStateFile = NULL; /* set defaults... */ cs.iPollInterval = DFLT_PollInterval; diff --git a/plugins/imkmsg/kmsg.c b/plugins/imkmsg/kmsg.c index 822d3dbd..172ff4d1 100644 --- a/plugins/imkmsg/kmsg.c +++ b/plugins/imkmsg/kmsg.c @@ -34,7 +34,7 @@ #include <ctype.h> #include <sys/klog.h> #include <sys/sysinfo.h> -#include <json/json.h> +#include <json.h> #include "rsyslog.h" #include "srUtils.h" diff --git a/plugins/impstats/impstats.c b/plugins/impstats/impstats.c index 79749e21..47378445 100644 --- a/plugins/impstats/impstats.c +++ b/plugins/impstats/impstats.c @@ -135,9 +135,9 @@ static inline void doSubmitMsg(uchar *line) { msg_t *pMsg; - DEFiRet; - CHKiRet(msgConstruct(&pMsg)); + if(msgConstruct(&pMsg) != RS_RET_OK) + goto finalize_it; MsgSetInputName(pMsg, pInputName); MsgSetRawMsgWOSize(pMsg, (char*)line); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c index 2d9761cb..e10a8ba3 100644 --- a/plugins/imtcp/imtcp.c +++ b/plugins/imtcp/imtcp.c @@ -138,7 +138,7 @@ static struct cnfparamdescr modpdescr[] = { { "disablelfdelimiter", eCmdHdlrBinary, 0 }, { "octetcountedframing", eCmdHdlrBinary, 0 }, { "notifyonconnectionclose", eCmdHdlrBinary, 0 }, - { "addtlframedelimiter", eCmdHdlrPositiveInt, 0 }, + { "addtlframedelimiter", eCmdHdlrNonNegInt, 0 }, { "maxsessions", eCmdHdlrPositiveInt, 0 }, { "maxlistners", eCmdHdlrPositiveInt, 0 }, { "maxlisteners", eCmdHdlrPositiveInt, 0 }, @@ -408,7 +408,7 @@ CODESTARTbeginCnfLoad loadModConf->iTCPLstnMax = 20; loadModConf->bSuppOctetFram = 1; loadModConf->iStrmDrvrMode = 0; - loadModConf->bUseFlowControl = 0; + loadModConf->bUseFlowControl = 1; loadModConf->bKeepAlive = 0; loadModConf->bEmitMsgOnClose = 0; loadModConf->iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER; @@ -631,7 +631,7 @@ resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unus cs.iTCPLstnMax = 20; cs.bSuppOctetFram = 1; cs.iStrmDrvrMode = 0; - cs.bUseFlowControl = 0; + cs.bUseFlowControl = 1; cs.bKeepAlive = 0; cs.bEmitMsgOnClose = 0; cs.iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER; diff --git a/plugins/mmanon/mmanon.c b/plugins/mmanon/mmanon.c index a1c99d09..16a4f34b 100644 --- a/plugins/mmanon/mmanon.c +++ b/plugins/mmanon/mmanon.c @@ -170,7 +170,6 @@ CODESTARTnewActInst cstr); free(cstr); } - pData->replChar = es_getBufAddr(pvals[i].val.d.estr)[0]; } else if(!strcmp(actpblk.descr[i].name, "replacementchar")) { pData->replChar = es_getBufAddr(pvals[i].val.d.estr)[0]; } else if(!strcmp(actpblk.descr[i].name, "ipv4.bits")) { @@ -307,7 +306,7 @@ anonip(instanceData *pData, uchar *msg, int *pLenMsg, int *idx) ++i; ipstart[3] = i; octet = getnum(msg, lenMsg, &i); - if(octet > 255 || !(msg[i] == ' ' || msg[i] == ':')) goto done; + if(octet > 255) goto done; ipv4addr |= octet; /* OK, we now found an ip address */ @@ -339,6 +338,8 @@ anonip(instanceData *pData, uchar *msg, int *pLenMsg, int *idx) if(i - endpos > 0) { *pLenMsg = lenMsg - (i - endpos); memmove(msg+endpos, msg+i, lenMsg - i + 1); + /* correct index for next search! */ + i -= (i - endpos); } } diff --git a/plugins/mmaudit/mmaudit.c b/plugins/mmaudit/mmaudit.c index 6b6b804c..c7cff2cb 100644 --- a/plugins/mmaudit/mmaudit.c +++ b/plugins/mmaudit/mmaudit.c @@ -43,7 +43,7 @@ #include <errno.h> #include <unistd.h> #include <ctype.h> -#include <json/json.h> +#include <json.h> #include "conf.h" #include "syslogd-types.h" #include "template.h" diff --git a/plugins/mmjsonparse/mmjsonparse.c b/plugins/mmjsonparse/mmjsonparse.c index 35f69aab..b16aef0e 100644 --- a/plugins/mmjsonparse/mmjsonparse.c +++ b/plugins/mmjsonparse/mmjsonparse.c @@ -35,7 +35,7 @@ #include <errno.h> #include <unistd.h> #include <ctype.h> -#include <json/json.h> +#include <json.h> #include "conf.h" #include "syslogd-types.h" #include "template.h" diff --git a/plugins/mmnormalize/mmnormalize.c b/plugins/mmnormalize/mmnormalize.c index fcadc328..7e25824a 100644 --- a/plugins/mmnormalize/mmnormalize.c +++ b/plugins/mmnormalize/mmnormalize.c @@ -40,7 +40,7 @@ #include <unistd.h> #include <libestr.h> #include <libee/libee.h> -#include <json/json.h> +#include <json.h> #include <liblognorm.h> #include "conf.h" #include "syslogd-types.h" @@ -227,6 +227,7 @@ CODESTARTdoAction /* TODO: this is all extremly ineffcient! */ ee_fmtEventToJSON(event, &str); cstrJSON = es_str2cstr(str, NULL); + ee_deleteEvent(event); dbgprintf("mmnormalize generated: %s\n", cstrJSON); tokener = json_tokener_new(); diff --git a/plugins/omelasticsearch/omelasticsearch.c b/plugins/omelasticsearch/omelasticsearch.c index 33e58c1a..b82968d0 100644 --- a/plugins/omelasticsearch/omelasticsearch.c +++ b/plugins/omelasticsearch/omelasticsearch.c @@ -4,7 +4,7 @@ * NOTE: read comments in module-template.h for more specifics! * * Copyright 2011 Nathan Scott. - * Copyright 2009-2012 Rainer Gerhards and Adiscon GmbH. + * Copyright 2009-2013 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * @@ -58,10 +58,10 @@ DEFobjCurrIf(errmsg) DEFobjCurrIf(statsobj) statsobj_t *indexStats; -STATSCOUNTER_DEF(indexConFail, mutIndexConFail) STATSCOUNTER_DEF(indexSubmit, mutIndexSubmit) -STATSCOUNTER_DEF(indexFailed, mutIndexFailed) -STATSCOUNTER_DEF(indexSuccess, mutIndexSuccess) +STATSCOUNTER_DEF(indexHTTPFail, mutIndexHTTPFail) +STATSCOUNTER_DEF(indexHTTPReqFail, mutIndexHTTPReqFail) +STATSCOUNTER_DEF(indexESFail, mutIndexESFail) /* REST API for elasticsearch hits this URL: * http://<hostName>:<restPort>/<searchIndex>/<searchType> @@ -91,6 +91,7 @@ typedef struct _instanceData { sbool asyncRepl; struct { es_str_t *data; + int nmemb; /* number of messages in batch (for statistics counting) */ uchar *currTpl1; uchar *currTpl2; } batch; @@ -224,6 +225,12 @@ checkConn(instanceData *pData) DBGPRINTF("omelasticsearch: checkConn() curl_easy_init() failed\n"); ABORT_FINALIZE(RS_RET_SUSPENDED); } + /* Bodypart of request not needed, so set curl opt to nobody and httpget, otherwise lib-curl could sigsegv */ + curl_easy_setopt(curl, CURLOPT_HTTPGET, TRUE); + curl_easy_setopt(curl, CURLOPT_NOBODY, TRUE); + /* Only enable for debugging + curl_easy_setopt(curl, CURLOPT_VERBOSE, TRUE); */ + cstr = es_str2cstr(url, NULL); curl_easy_setopt(curl, CURLOPT_URL, cstr); free(cstr); @@ -426,6 +433,7 @@ buildBatch(instanceData *pData, uchar *message, uchar **tpls) DBGPRINTF("omelasticsearch: growing batch failed with code %d\n", r); ABORT_FINALIZE(RS_RET_ERR); } + ++pData->batch.nmemb; iRet = RS_RET_DEFER_COMMIT; finalize_it: @@ -483,13 +491,11 @@ writeDataError(instanceData *pData, cJSON **pReplyRoot, uchar *reqmsg) DBGPRINTF("omelasticsearch: error %d writing error file, write returns %lld\n", errno, (long long) wrRet); } - free(rendered); cJSON_Delete(errRoot); *pReplyRoot = NULL; /* tell caller not to delete once again! */ finalize_it: - if(rendered != NULL) - free(rendered); + free(rendered); RETiRet; } @@ -573,12 +579,15 @@ checkResult(instanceData *pData, uchar *reqmsg) finalize_it: if(root != NULL) cJSON_Delete(root); + if(iRet != RS_RET_OK) { + STATSCOUNTER_INC(indexESFail, mutIndexESFail); + } RETiRet; } static rsRetVal -curlPost(instanceData *pData, uchar *message, int msglen, uchar **tpls) +curlPost(instanceData *pData, uchar *message, int msglen, uchar **tpls, int nmsgs) { CURLcode code; CURL *curl = pData->curlHandle; @@ -599,18 +608,21 @@ curlPost(instanceData *pData, uchar *message, int msglen, uchar **tpls) case CURLE_COULDNT_RESOLVE_PROXY: case CURLE_COULDNT_CONNECT: case CURLE_WRITE_ERROR: - STATSCOUNTER_INC(indexConFail, mutIndexConFail); + STATSCOUNTER_INC(indexHTTPReqFail, mutHTTPReqFail); + indexHTTPFail += nmsgs; DBGPRINTF("omelasticsearch: we are suspending ourselfs due " "to failure %lld of curl_easy_perform()\n", (long long) code); ABORT_FINALIZE(RS_RET_SUSPENDED); default: - STATSCOUNTER_INC(indexSubmit, mutIndexSubmit); break; } - pData->reply[pData->replyLen] = '\0'; /* byte has been reserved in malloc */ - DBGPRINTF("omelasticsearch: es reply: '%s'\n", pData->reply); + DBGPRINTF("omelasticsearch: pData replyLen = '%d'\n", pData->replyLen); + if (pData->replyLen > 0) { + pData->reply[pData->replyLen] = '\0'; /* Append 0 Byte if replyLen is above 0 - byte has been reserved in malloc */ + } + DBGPRINTF("omelasticsearch: pData reply: '%s'\n", pData->reply); CHKiRet(checkResult(pData, message)); finalize_it: @@ -626,17 +638,19 @@ dbgprintf("omelasticsearch: beginTransaction\n"); } es_emptyStr(pData->batch.data); + pData->batch.nmemb = 0; finalize_it: ENDbeginTransaction BEGINdoAction CODESTARTdoAction + STATSCOUNTER_INC(indexSubmit, mutIndexSubmit); if(pData->bulkmode) { CHKiRet(buildBatch(pData, ppString[0], ppString)); } else { CHKiRet(curlPost(pData, ppString[0], strlen((char*)ppString[0]), - ppString)); + ppString, 1)); } finalize_it: dbgprintf("omelasticsearch: result doAction: %d (bulkmode %d)\n", iRet, pData->bulkmode); @@ -644,12 +658,17 @@ ENDdoAction BEGINendTransaction - char *cstr; + char *cstr = NULL; CODESTARTendTransaction dbgprintf("omelasticsearch: endTransaction init\n"); - cstr = es_str2cstr(pData->batch.data, NULL); - dbgprintf("omelasticsearch: endTransaction, batch: '%s'\n", cstr); - CHKiRet(curlPost(pData, (uchar*) cstr, strlen(cstr), NULL)); + /* End Transaction only if batch data is not empty */ + if (pData->batch.data != NULL ) { + cstr = es_str2cstr(pData->batch.data, NULL); + dbgprintf("omelasticsearch: endTransaction, batch: '%s'\n", cstr); + CHKiRet(curlPost(pData, (uchar*) cstr, strlen(cstr), NULL, pData->batch.nmemb)); + } + else + dbgprintf("omelasticsearch: endTransaction, pData->batch.data is NULL, nothing to send. \n"); finalize_it: free(cstr); dbgprintf("omelasticsearch: endTransaction done with %d\n", iRet); @@ -981,15 +1000,19 @@ CODEmodInit_QueryRegCFSLineHdlr /* support statistics gathering */ CHKiRet(statsobj.Construct(&indexStats)); - CHKiRet(statsobj.SetName(indexStats, (uchar *)"elasticsearch")); - CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"connfail", - ctrType_IntCtr, &indexConFail)); - CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"submits", + CHKiRet(statsobj.SetName(indexStats, (uchar *)"omelasticsearch")); + STATSCOUNTER_INIT(indexSubmit, mutCtrIndexSubmit); + CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"submitted", ctrType_IntCtr, &indexSubmit)); - CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"failed", - ctrType_IntCtr, &indexFailed)); - CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"success", - ctrType_IntCtr, &indexSuccess)); + STATSCOUNTER_INIT(indexHTTPFail, mutCtrIndexHTTPFail); + CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"failed.http", + ctrType_IntCtr, &indexHTTPFail)); + STATSCOUNTER_INIT(indexHTTPReqFail, mutCtrIndexHTTPReqFail); + CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"failed.httprequests", + ctrType_IntCtr, &indexHTTPReqFail)); + STATSCOUNTER_INIT(indexESFail, mutCtrIndexESFail); + CHKiRet(statsobj.AddCounter(indexStats, (uchar *)"failed.es", + ctrType_IntCtr, &indexESFail)); CHKiRet(statsobj.ConstructFinalize(indexStats)); ENDmodInit diff --git a/plugins/omhiredis/omhiredis.c b/plugins/omhiredis/omhiredis.c index 051ac0bf..7a35bac2 100644 --- a/plugins/omhiredis/omhiredis.c +++ b/plugins/omhiredis/omhiredis.c @@ -198,7 +198,7 @@ CODESTARTendTransaction /* TODO: add error checking here! */ free ( pData->replies[i] ); } - free ( pData->replies ); + freeReplyObject ( pData->replies ); pData->count = 0; ENDendTransaction diff --git a/plugins/omlibdbi/omlibdbi.c b/plugins/omlibdbi/omlibdbi.c index 6e27ad22..3beba4f0 100644 --- a/plugins/omlibdbi/omlibdbi.c +++ b/plugins/omlibdbi/omlibdbi.c @@ -10,7 +10,7 @@ * * File begun on 2008-02-14 by RGerhards (extracted from syslogd.c) * - * Copyright 2008-2012 Adiscon GmbH. + * Copyright 2008-2013 Adiscon GmbH. * * This file is part of rsyslog. * @@ -340,8 +340,12 @@ CODESTARTbeginTransaction # if HAVE_DBI_TXSUPP if (pData->txSupport == 1) { if (dbi_conn_transaction_begin(pData->conn) != 0) { - dbgprintf("libdbi server error: begin transaction not successful\n"); - iRet = RS_RET_SUSPENDED; + const char *emsg; + dbi_conn_error(pData->conn, &emsg); + dbgprintf("libdbi server error: begin transaction " + "not successful: %s\n", emsg); + closeConn(pData); + ABORT_FINALIZE(RS_RET_SUSPENDED); } } # endif @@ -365,7 +369,11 @@ BEGINendTransaction CODESTARTendTransaction # if HAVE_DBI_TXSUPP if (dbi_conn_transaction_commit(pData->conn) != 0) { - dbgprintf("libdbi server error: transaction not committed\n"); + const char *emsg; + dbi_conn_error(pData->conn, &emsg); + dbgprintf("libdbi server error: transaction not committed: %s\n", + emsg); + closeConn(pData); iRet = RS_RET_SUSPENDED; } # endif diff --git a/plugins/ommail/ommail.c b/plugins/ommail/ommail.c index 6044d2e9..0a781e10 100644 --- a/plugins/ommail/ommail.c +++ b/plugins/ommail/ommail.c @@ -176,7 +176,7 @@ WriteRcpts(instanceData *pData, uchar *pszOp, size_t lenOp, int iStatusToCheck) for(pRcpt = pData->md.smtp.lstRcpt ; pRcpt != NULL ; pRcpt = pRcpt->pNext) { dbgprintf("Sending '%s: <%s>'\n", pszOp, pRcpt->pszTo); CHKiRet(Send(pData->md.smtp.sock, (char*)pszOp, lenOp)); - CHKiRet(Send(pData->md.smtp.sock, ": <", sizeof(": <") - 1)); + CHKiRet(Send(pData->md.smtp.sock, ":<", sizeof(":<") - 1)); CHKiRet(Send(pData->md.smtp.sock, (char*)pRcpt->pszTo, strlen((char*)pRcpt->pszTo))); CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); if(iStatusToCheck >= 0) @@ -522,7 +522,7 @@ sendSMTP(instanceData *pData, uchar *body, uchar *subject) CHKiRet(Send(pData->md.smtp.sock, "\r\n", sizeof("\r\n") - 1)); CHKiRet(readResponse(pData, &iState, 250)); - CHKiRet(Send(pData->md.smtp.sock, "MAIL FROM: <", sizeof("MAIL FROM: <") - 1)); + CHKiRet(Send(pData->md.smtp.sock, "MAIL FROM:<", sizeof("MAIL FROM:<") - 1)); CHKiRet(Send(pData->md.smtp.sock, (char*)pData->md.smtp.pszFrom, strlen((char*)pData->md.smtp.pszFrom))); CHKiRet(Send(pData->md.smtp.sock, ">\r\n", sizeof(">\r\n") - 1)); CHKiRet(readResponse(pData, &iState, 250)); diff --git a/plugins/ommongodb/ommongodb.c b/plugins/ommongodb/ommongodb.c index dd997410..ecfd2518 100644 --- a/plugins/ommongodb/ommongodb.c +++ b/plugins/ommongodb/ommongodb.c @@ -33,9 +33,9 @@ #include <stdint.h> #include <time.h> #include <mongo.h> -#include <json/json.h> +#include <json.h> /* For struct json_object_iter, should not be necessary in future versions */ -#include <json/json_object_private.h> +#include <json_object_private.h> #include "rsyslog.h" #include "conf.h" diff --git a/plugins/omprog/omprog.c b/plugins/omprog/omprog.c index e425b428..d821ff16 100644 --- a/plugins/omprog/omprog.c +++ b/plugins/omprog/omprog.c @@ -122,6 +122,7 @@ static void execBinary(instanceData *pData, int fdStdin) { int i; struct sigaction sigAct; + sigset_t set; char *newargv[] = { NULL }; char *newenviron[] = { NULL }; @@ -146,10 +147,12 @@ static void execBinary(instanceData *pData, int fdStdin) /* reset signal handlers to default */ memset(&sigAct, 0, sizeof(sigAct)); - sigfillset(&sigAct.sa_mask); + sigemptyset(&sigAct.sa_mask); sigAct.sa_handler = SIG_DFL; for(i = 1 ; i < NSIG ; ++i) sigaction(i, &sigAct, NULL); + sigemptyset(&set); + sigprocmask(SIG_SETMASK, &set, NULL); alarm(0); @@ -350,14 +353,9 @@ CODESTARTnewActInst } } - if(pData->tplName == NULL) { - CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*) "RSYSLOG_FileFormat", - OMSR_NO_RQD_TPL_OPTS)); - } else { - CHKiRet(OMSRsetEntry(*ppOMSR, 0, - (uchar*) strdup((char*) pData->tplName), - OMSR_NO_RQD_TPL_OPTS)); - } + CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ? + "RSYSLOG_FileFormat" : (char*)pData->tplName), + OMSR_NO_RQD_TPL_OPTS)); CODE_STD_FINALIZERnewActInst cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst diff --git a/plugins/omsnmp/omsnmp.c b/plugins/omsnmp/omsnmp.c index 79e555b3..42d1de6b 100644 --- a/plugins/omsnmp/omsnmp.c +++ b/plugins/omsnmp/omsnmp.c @@ -112,15 +112,15 @@ static configSettings_t cs; /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { { "server", eCmdHdlrString, CNFPARAM_REQUIRED }, - { "port", eCmdHdlrInt, CNFPARAM_REQUIRED }, - { "transport", eCmdHdlrString, CNFPARAM_REQUIRED }, - { "version", eCmdHdlrInt, CNFPARAM_REQUIRED }, - { "community", eCmdHdlrString, CNFPARAM_REQUIRED }, - { "enterpriseoid", eCmdHdlrString, CNFPARAM_REQUIRED }, - { "trapoid", eCmdHdlrString, CNFPARAM_REQUIRED }, - { "messageoid", eCmdHdlrString, CNFPARAM_REQUIRED }, - { "traptype", eCmdHdlrInt, CNFPARAM_REQUIRED }, - { "specifictype", eCmdHdlrInt, CNFPARAM_REQUIRED }, + { "port", eCmdHdlrInt, 0 }, + { "transport", eCmdHdlrString, 0 }, + { "version", eCmdHdlrInt, 0 }, + { "community", eCmdHdlrString, 0 }, + { "enterpriseoid", eCmdHdlrString, 0 }, + { "trapoid", eCmdHdlrString, 0 }, + { "messageoid", eCmdHdlrString, 0 }, + { "traptype", eCmdHdlrInt, 0 }, + { "specifictype", eCmdHdlrInt, 0 }, { "template", eCmdHdlrGetWord, 0 } }; static struct cnfparamblk actpblk = @@ -429,14 +429,10 @@ CODESTARTnewActInst } } - if(pData->tplName == NULL) { - CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*) "RSYSLOG_FileFormat", - OMSR_NO_RQD_TPL_OPTS)); - } else { - CHKiRet(OMSRsetEntry(*ppOMSR, 0, - (uchar*) strdup((char*) pData->tplName), - OMSR_NO_RQD_TPL_OPTS)); - } + CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ? + "RSYSLOG_FileFormat" : (char*)pData->tplName), + OMSR_NO_RQD_TPL_OPTS)); + CODE_STD_FINALIZERnewActInst cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst diff --git a/runtime/Makefile.am b/runtime/Makefile.am index dea06fe0..34384bea 100644 --- a/runtime/Makefile.am +++ b/runtime/Makefile.am @@ -97,12 +97,13 @@ librsyslog_la_SOURCES = \ # if WITH_MODDIRS -librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/:$(moddirs)\" $(PTHREADS_CFLAGS) -I\$(top_srcdir)/tools +librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/:$(moddirs)\" else -librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/\" -I$(top_srcdir) $(PTHREADS_CFLAGS) -I\$(top_srcdir)/tools -I\$(top_srcdir)/grammar +librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/\" -I\$(top_srcdir) -I\$(top_srcdir)/grammar endif #librsyslog_la_LDFLAGS = -module -avoid-version -librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS) +librsyslog_la_CPPFLAGS += $(PTHREADS_CFLAGS) $(LIBEE_CFLAGS) $(LIBUUID_CFLAGS) $(JSON_C_CFLAGS) -I\$(top_srcdir)/tools +librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS) $(LIBEE_LIBS) $(LIBUUID_LIBS) $(JSON_C_LIBS) # # regular expression support diff --git a/runtime/conf.c b/runtime/conf.c index c3c7e447..c01715cb 100644 --- a/runtime/conf.c +++ b/runtime/conf.c @@ -573,6 +573,7 @@ rsRetVal DecodePropFilter(uchar *pline, struct cnfstmt *stmt) } else { errmsg.LogError(0, NO_ERRCODE, "error: invalid compare operation '%s' - ignoring selector", (char*) rsCStrGetSzStrNoNULL(pCSCompOp)); + return(RS_RET_ERR); } rsCStrDestruct(&pCSCompOp); /* no longer needed */ diff --git a/runtime/cryprov.h b/runtime/cryprov.h index 8496b745..005b33f7 100644 --- a/runtime/cryprov.h +++ b/runtime/cryprov.h @@ -24,8 +24,6 @@ #ifndef INCLUDED_CRYPROV_H #define INCLUDED_CRYPROV_H -#include <gcrypt.h> - /* interface */ BEGINinterface(cryprov) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(void *ppThis); diff --git a/runtime/glbl.c b/runtime/glbl.c index b3fe3a1d..41d56c2c 100644 --- a/runtime/glbl.c +++ b/runtime/glbl.c @@ -32,6 +32,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +#include <pthread.h> #include <assert.h> #include "rsyslog.h" @@ -71,6 +72,7 @@ static int option_DisallowWarning = 1; /* complain if message from disallowed se static int bDisableDNS = 0; /* don't look up IP addresses of remote messages */ static prop_t *propLocalIPIF = NULL;/* IP address to report for the local host (default is 127.0.0.1) */ static prop_t *propLocalHostName = NULL;/* our hostname as FQDN - read-only after startup */ +static prop_t *propLocalHostNameToDelete = NULL;/* see GenerateLocalHostName function hdr comment! */ static uchar *LocalHostName = NULL;/* our hostname - read-only after startup, except HUP */ static uchar *LocalHostNameOverride = NULL;/* user-overridden hostname - read-only after startup */ static uchar *LocalFQDNName = NULL;/* our hostname as FQDN - read-only after startup, except HUP */ @@ -379,17 +381,31 @@ GetLocalDomain(void) /* generate the local hostname property. This must be done after the hostname info * has been set as well as PreserveFQDN. * rgerhards, 2009-06-30 + * NOTE: This function tries to avoid locking by not destructing the previous value + * immediately. This is so that current readers can continue to use the previous name. + * Otherwise, we would need to use read/write locks to protect the update process. + * In order to do so, we save the previous value and delete it when we are called again + * the next time. Note that this in theory is racy and can lead to a double-free. + * In practice, however, the window of exposure to trigger this is extremely short + * and as this functions is very infrequently being called (on HUP), the trigger + * condition for this bug is so highly unlikely that it never occurs in practice. + * Probably if you HUP rsyslog every few milliseconds, but who does that... + * To further reduce risk potential, we do only update the property when there + * actually is a hostname change, which makes it even less likely. + * rgerhards, 2013-10-28 */ static rsRetVal GenerateLocalHostNameProperty(void) { - DEFiRet; + uchar *pszPrev; + int lenPrev; + prop_t *hostnameNew; uchar *pszName; + DEFiRet; - if(propLocalHostName != NULL) - prop.Destruct(&propLocalHostName); + if(propLocalHostNameToDelete != NULL) + prop.Destruct(&propLocalHostNameToDelete); - CHKiRet(prop.Construct(&propLocalHostName)); if(LocalHostNameOverride == NULL) { if(LocalHostName == NULL) pszName = (uchar*) "[localhost]"; @@ -403,8 +419,20 @@ GenerateLocalHostNameProperty(void) pszName = LocalHostNameOverride; } DBGPRINTF("GenerateLocalHostName uses '%s'\n", pszName); - CHKiRet(prop.SetString(propLocalHostName, pszName, ustrlen(pszName))); - CHKiRet(prop.ConstructFinalize(propLocalHostName)); + + if(propLocalHostName == NULL) + pszPrev = (uchar*)""; /* make sure strcmp() below does not match */ + else + prop.GetString(propLocalHostName, &pszPrev, &lenPrev); + + if(ustrcmp(pszPrev, pszName)) { + /* we need to update */ + CHKiRet(prop.Construct(&hostnameNew)); + CHKiRet(prop.SetString(hostnameNew, pszName, ustrlen(pszName))); + CHKiRet(prop.ConstructFinalize(hostnameNew)); + propLocalHostNameToDelete = propLocalHostName; + propLocalHostName = hostnameNew; + } finalize_it: RETiRet; @@ -667,6 +695,8 @@ BEGINObjClassExit(glbl, OBJ_IS_CORE_MODULE) /* class, version */ free(LocalHostNameOverride); free(LocalFQDNName); objRelease(prop, CORE_COMPONENT); + if(propLocalHostNameToDelete != NULL) + prop.Destruct(&propLocalHostNameToDelete); DESTROY_ATOMIC_HELPER_MUT(mutTerminateInputs); ENDObjClassExit(glbl) diff --git a/runtime/libgcry.h b/runtime/libgcry.h index b77b0f9e..692ce408 100644 --- a/runtime/libgcry.h +++ b/runtime/libgcry.h @@ -21,7 +21,7 @@ #ifndef INCLUDED_LIBGCRY_H #define INCLUDED_LIBGCRY_H #include <stdint.h> - +#include <gcrypt.h> struct gcryctx_s { uchar *key; @@ -52,6 +52,7 @@ void rsgcryCtxDel(gcryctx ctx); int gcryfileDestruct(gcryfile gf, off64_t offsLogfile); rsRetVal rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, uchar *fname); int rsgcryEncrypt(gcryfile pF, uchar *buf, size_t *len); +int gcryGetKeyFromProg(char *cmd, char **key, unsigned *keylen); /* error states */ #define RSGCRYE_EI_OPEN 1 /* error opening .encinfo file */ diff --git a/runtime/librsgt.c b/runtime/librsgt.c index 85fc7742..a8124568 100644 --- a/runtime/librsgt.c +++ b/runtime/librsgt.c @@ -75,7 +75,7 @@ reportGTAPIErr(gtctx ctx, gtfile gf, char *apiname, int ecode) char errbuf[4096]; snprintf(errbuf, sizeof(errbuf), "%s[%s:%d]: %s", (gf == NULL) ? (uchar*)"" : gf->sigfilename, - apiname, ecode, GT_getErrorString(ecode)); + apiname, ecode, GTHTTP_getErrorString(ecode)); errbuf[sizeof(errbuf)-1] = '\0'; reportErr(ctx, errbuf); } @@ -285,7 +285,9 @@ int tlv8Write(gtfile gf, int flags, int tlvtype, int len) { int r; - r = tlvbufAddOctet(gf, (flags << 5)|tlvtype); + assert((flags & RSGT_TYPE_MASK) == 0); + assert((tlvtype & RSGT_TYPE_MASK) == tlvtype); + r = tlvbufAddOctet(gf, (flags & ~RSGT_FLAG_TLV16) | tlvtype); if(r != 0) goto done; r = tlvbufAddOctet(gf, len & 0xff); done: return r; @@ -296,7 +298,9 @@ tlv16Write(gtfile gf, int flags, int tlvtype, uint16_t len) { uint16_t typ; int r; - typ = ((flags|1) << 15)|tlvtype; + assert((flags & RSGT_TYPE_MASK) == 0); + assert((tlvtype >> 8 & RSGT_TYPE_MASK) == (tlvtype >> 8)); + typ = ((flags | RSGT_FLAG_TLV16) << 8) | tlvtype; r = tlvbufAddOctet(gf, typ >> 8); if(r != 0) goto done; r = tlvbufAddOctet(gf, typ & 0xff); diff --git a/runtime/librsgt.h b/runtime/librsgt.h index bfcc4628..bf9c9c31 100644 --- a/runtime/librsgt.h +++ b/runtime/librsgt.h @@ -151,7 +151,10 @@ struct rsgtstatefile { }; /* Flags and record types for TLV handling */ +#define RSGT_FLAG_NONCRIT 0x80 +#define RSGT_FLAG_FORWARD 0x40 #define RSGT_FLAG_TLV16 0x20 +#define RSGT_TYPE_MASK 0x1f /* error states */ #define RSGTE_IO 1 /* any kind of io error */ diff --git a/runtime/librsgt_read.c b/runtime/librsgt_read.c index a6e33160..a9a50798 100644 --- a/runtime/librsgt_read.c +++ b/runtime/librsgt_read.c @@ -249,7 +249,7 @@ rsgt_tlvRecRead(FILE *fp, tlvrecord_t *rec) NEXTC; rec->hdr[0] = c; rec->tlvtype = c & 0x1f; - if(c & 0x80) { /* tlv16? */ + if(c & RSGT_FLAG_TLV16) { /* tlv16? */ rec->lenHdr = 4; NEXTC; rec->hdr[1] = c; @@ -290,7 +290,7 @@ rsgt_tlvDecodeSUBREC(tlvrecord_t *rec, uint16_t *stridx, tlvrecord_t *newrec) c = rec->data[(*stridx)++]; newrec->hdr[0] = c; newrec->tlvtype = c & 0x1f; - if(c & 0x80) { /* tlv16? */ + if(c & RSGT_FLAG_TLV16) { /* tlv16? */ newrec->lenHdr = 4; if(rec->tlvlen == *stridx) {r=RSGTE_LEN; goto done;} c = rec->data[(*stridx)++]; diff --git a/runtime/msg.c b/runtime/msg.c index 9d5fa883..10ecf48a 100644 --- a/runtime/msg.c +++ b/runtime/msg.c @@ -41,9 +41,9 @@ #endif #include <netdb.h> #include <libestr.h> -#include <json/json.h> +#include <json.h> /* For struct json_object_iter, should not be necessary in future versions */ -#include <json/json_object_private.h> +#include <json_object_private.h> #if HAVE_MALLOC_H # include <malloc.h> #endif @@ -1113,7 +1113,6 @@ MsgDeserialize(msg_t *pMsg, strm_t *pStrm) prop_t *propRcvFrom = NULL; prop_t *propRcvFromIP = NULL; struct json_tokener *tokener; - struct json_object *json; var_t *pVar = NULL; DEFiRet; @@ -1197,8 +1196,9 @@ MsgDeserialize(msg_t *pMsg, strm_t *pStrm) } if(isProp("json")) { tokener = json_tokener_new(); - json = json_tokener_parse_ex(tokener, (char*)rsCStrGetSzStrNoNULL(pVar->val.pStr), + pMsg->json = json_tokener_parse_ex(tokener, (char*)rsCStrGetSzStrNoNULL(pVar->val.pStr), cstrLen(pVar->val.pStr)); + json_tokener_free(tokener); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } @@ -2495,10 +2495,10 @@ static uchar *getNOW(eNOWType eNow, struct syslogTime *t) memcpy(pBuf, two_digits[(int)t->hour], 3); break; case NOW_HHOUR: - memcpy(pBuf, two_digits[t->hour/30], 3); + memcpy(pBuf, two_digits[t->minute/30], 3); break; case NOW_QHOUR: - memcpy(pBuf, two_digits[t->hour/15], 3); + memcpy(pBuf, two_digits[t->minute/15], 3); break; case NOW_MINUTE: memcpy(pBuf, two_digits[(int)t->minute], 3); @@ -3934,6 +3934,12 @@ msgAddJSON(msg_t *pM, uchar *name, struct json_object *json) } leaf = jsonPathGetLeaf(name, ustrlen(name)); CHKiRet(jsonPathFindParent(pM, name, leaf, &parent, 1)); + if (json_object_get_type(parent) != json_type_object) { + DBGPRINTF("msgAddJSON: not a container in json path," + "name is '%s'\n", name); + json_object_put(json); + ABORT_FINALIZE(RS_RET_INVLD_SETOP); + } leafnode = json_object_object_get(parent, (char*)leaf); if(leafnode == NULL) { json_object_object_add(parent, (char*)leaf, json); diff --git a/runtime/msg.h b/runtime/msg.h index 6faf066a..e7babdbb 100644 --- a/runtime/msg.h +++ b/runtime/msg.h @@ -30,7 +30,7 @@ #include <pthread.h> #include <libestr.h> -#include <json/json.h> +#include <json.h> #include "obj.h" #include "syslogd-types.h" #include "template.h" @@ -62,7 +62,6 @@ struct msg { once data has entered the queue, this property is no longer needed. */ pthread_mutex_t mut; int iRefCount; /* reference counter (0 = unused) */ - sbool bAlreadyFreed; /* aid to help detect a well-hidden bad bug -- TODO: remove when no longer needed */ sbool bParseSuccess; /* set to reflect state of last executed higher level parser */ short iSeverity; /* the severity 0..7 */ short iFacility; /* Facility code 0 .. 23*/ diff --git a/runtime/net.c b/runtime/net.c index b291213e..13391cc0 100644 --- a/runtime/net.c +++ b/runtime/net.c @@ -232,6 +232,7 @@ finalize_it: /* enqueue the element */ if(pPeer->pWildcardRoot == NULL) { pPeer->pWildcardRoot = pNew; + pPeer->pWildcardLast = pNew; } else { pPeer->pWildcardLast->pNext = pNew; } diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c index 6ef4feba..1110c7a4 100644 --- a/runtime/nsd_gtls.c +++ b/runtime/nsd_gtls.c @@ -2,7 +2,7 @@ * * An implementation of the nsd interface for GnuTLS. * - * Copyright (C) 2007, 2008 Rainer Gerhards and Adiscon GmbH. + * Copyright (C) 2007-2013 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * @@ -547,10 +547,20 @@ gtlsAddOurCert(void) keyFile = glbl.GetDfltNetstrmDrvrKeyFile(); dbgprintf("GTLS certificate file: '%s'\n", certFile); dbgprintf("GTLS key file: '%s'\n", keyFile); + if(certFile == NULL) { + errmsg.LogError(0, RS_RET_CERT_MISSING, "error: certificate file is not set, cannot " + "continue"); + ABORT_FINALIZE(RS_RET_CERT_MISSING); + } + if(keyFile == NULL) { + errmsg.LogError(0, RS_RET_CERTKEY_MISSING, "error: key file is not set, cannot " + "continue"); + ABORT_FINALIZE(RS_RET_CERTKEY_MISSING); + } CHKgnutls(gnutls_certificate_set_x509_key_file(xcred, (char*)certFile, (char*)keyFile, GNUTLS_X509_FMT_PEM)); finalize_it: - if(iRet != RS_RET_OK) { + if(iRet != RS_RET_OK && iRet != RS_RET_CERT_MISSING && iRet != RS_RET_CERTKEY_MISSING) { pGnuErr = gtlsStrerror(gnuRet); errno = 0; errmsg.LogError(0, iRet, "error adding our certificate. GnuTLS error %d, message: '%s', " @@ -580,6 +590,11 @@ gtlsGlblInit(void) /* sets the trusted cas file */ cafile = glbl.GetDfltNetstrmDrvrCAF(); + if(cafile == NULL) { + errmsg.LogError(0, RS_RET_CA_CERT_MISSING, "error: ca certificate is not set, cannot " + "continue"); + ABORT_FINALIZE(RS_RET_CA_CERT_MISSING); + } dbgprintf("GTLS CA file: '%s'\n", cafile); gnuRet = gnutls_certificate_set_x509_trust_file(xcred, (char*)cafile, GNUTLS_X509_FMT_PEM); if(gnuRet < 0) { diff --git a/runtime/queue.c b/runtime/queue.c index 85b1e45b..935a8106 100644 --- a/runtime/queue.c +++ b/runtime/queue.c @@ -877,7 +877,8 @@ static rsRetVal qDestructDisk(qqueue_t *pThis) DEFiRet; ASSERT(pThis != NULL); - + + free(pThis->pszQIFNam); if(pThis->tVars.disk.pWrite != NULL) strm.Destruct(&pThis->tVars.disk.pWrite); if(pThis->tVars.disk.pReadDeq != NULL) @@ -1022,7 +1023,7 @@ qqueueAdd(qqueue_t *pThis, msg_t *pMsg) if(pThis->qType != QUEUETYPE_DIRECT) { ATOMIC_INC(&pThis->iQueueSize, &pThis->mutQueueSize); - DBGOPRINT((obj_t*) pThis, "entry added, size now log %d, phys %d entries\n", + DBGOPRINT((obj_t*) pThis, "qqueueAdd: entry added, size now log %d, phys %d entries\n", getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis)); } @@ -1466,7 +1467,7 @@ DoDeleteBatchFromQStore(qqueue_t *pThis, int nElem) */ if(bytesDel != 0) { pThis->tVars.disk.sizeOnDisk -= bytesDel; - DBGOPRINT((obj_t*) pThis, "a %lld octet file has been deleted, now %lld octets disk " + DBGOPRINT((obj_t*) pThis, "doDeleteBatch: a %lld octet file has been deleted, now %lld octets disk " "space used\n", bytesDel, pThis->tVars.disk.sizeOnDisk); /* awake possibly waiting enq process */ pthread_cond_signal(&pThis->notFull); /* we hold the mutex while we are in here! */ @@ -1480,7 +1481,7 @@ DoDeleteBatchFromQStore(qqueue_t *pThis, int nElem) /* iQueueSize is not decremented by qDel(), so we need to do it ourselves */ ATOMIC_SUB(&pThis->iQueueSize, nElem, &pThis->mutQueueSize); ATOMIC_SUB(&pThis->nLogDeq, nElem, &pThis->mutLogDeq); - DBGPRINTF("delete batch from store, new sizes: log %d, phys %d\n", + DBGPRINTF("doDeleteBatch: delete batch from store, new sizes: log %d, phys %d\n", getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis)); ++pThis->deqIDDel; /* one more batch dequeued */ @@ -1550,13 +1551,13 @@ DeleteProcessedBatch(qqueue_t *pThis, batch_t *pBatch) localRet = doEnqSingleObj(pThis, eFLOWCTL_NO_DELAY, MsgAddRef(pMsg)); ++nEnqueued; if(localRet != RS_RET_OK) { - DBGPRINTF("error %d re-enqueuing unprocessed data element - discarded\n", localRet); + DBGPRINTF("DeleteProcessedBatch: error %d re-enqueuing unprocessed data element - discarded\n", localRet); } } msgDestruct(&pMsg); } - DBGPRINTF("we deleted %d objects and enqueued %d objects\n", i-nEnqueued, nEnqueued); + DBGPRINTF("DeleteProcessedBatch: we deleted %d objects and enqueued %d objects\n", i-nEnqueued, nEnqueued); if(nEnqueued > 0) qqueueChkPersist(pThis, nEnqueued); @@ -1913,8 +1914,16 @@ ConsumerDA(qqueue_t *pThis, wti_t *pWti) /* iterate over returned results and enqueue them in DA queue */ for(i = 0 ; i < pWti->batch.nElem && !pThis->bShutdownImmediate ; i++) { - CHKiRet(qqueueEnqMsg(pThis->pqDA, eFLOWCTL_NO_DELAY, - MsgAddRef(pWti->batch.pElem[i].pMsg))); + iRet = qqueueEnqMsg(pThis->pqDA, eFLOWCTL_NO_DELAY, MsgAddRef(pWti->batch.pElem[i].pMsg)); + if(iRet != RS_RET_OK) { + if(iRet == RS_RET_ERR_QUEUE_EMERGENCY) { + /* Queue emergency error occured */ + DBGOPRINT((obj_t*) pThis, "ConsumerDA:qqueueEnqMsg caught RS_RET_ERR_QUEUE_EMERGENCY, aborting loop.\n"); + FINALIZE; + } else { + DBGOPRINT((obj_t*) pThis, "ConsumerDA:qqueueEnqMsg item (%d) returned with error state: '%d'\n", i, iRet); + } + } pWti->batch.eltState[i] = BATCH_STATE_COMM; /* commited to other queue! */ } @@ -1922,10 +1931,38 @@ ConsumerDA(qqueue_t *pThis, wti_t *pWti) pthread_setcancelstate(iCancelStateSave, NULL); finalize_it: + /* Check the last return state of qqueueEnqMsg. If an error was returned, we acknowledge it only. + * Unless the error code is RS_RET_ERR_QUEUE_EMERGENCY, we reset the return state to RS_RET_OK. + * Otherwise the Caller functions would run into an infinite Loop trying to enqueue the + * same messages over and over again. + * + * However we do NOT overwrite positive return states like + * RS_RET_TERMINATE_NOW, + * RS_RET_NO_RUN, + * RS_RET_IDLE, + * RS_RET_TERMINATE_WHEN_IDLE + * These return states are important for Queue handling of the upper laying functions. + * RGer: Note that checking for iRet < 0 is a bit bold. In theory, positive iRet + * values are "OK" states, and things that the caller shall deal with. However, + * this has not been done so consistently. Andre convinced me that the current + * code is an elegant solution. However, if problems with queue workers and/or + * shutdown come up, this code here should be looked at suspiciously. In those + * cases it may work out to check all status codes explicitely, just to avoid + * a pitfall due to unexpected states being passed on to the caller. + */ + if( iRet != RS_RET_OK && + iRet != RS_RET_ERR_QUEUE_EMERGENCY && + iRet < 0) { + DBGOPRINT((obj_t*) pThis, "ConsumerDA:qqueueEnqMsg Resetting iRet from %d back to RS_RET_OK\n", iRet); + iRet = RS_RET_OK; + } else { + DBGOPRINT((obj_t*) pThis, "ConsumerDA:qqueueEnqMsg returns with iRet %d\n", iRet); + } + /* now we are done, but potentially need to re-aquire the mutex */ if(bNeedReLock) d_pthread_mutex_lock(pThis->mut); - DBGOPRINT((obj_t*) pThis, "DAConsumer returns with iRet %d\n", iRet); + RETiRet; } @@ -2089,12 +2126,12 @@ qqueueStart(qqueue_t *pThis) /* this is the ConstructionFinalizer */ pThis->iFullDlyMrk = wrk; } - DBGOPRINT((obj_t*) pThis, "type %d, enq-only %d, disk assisted %d, maxFileSz %lld, lqsize %d, pqsize %d, child %d, " - "full delay %d, light delay %d, deq batch size %d starting\n", - pThis->qType, pThis->bEnqOnly, pThis->bIsDA, pThis->iMaxFileSize, + DBGOPRINT((obj_t*) pThis, "type %d, enq-only %d, disk assisted %d, maxFileSz %lld, maxQSize %d, lqsize %d, pqsize %d, child %d, " + "full delay %d, light delay %d, deq batch size %d starting, high wtrrmrk %d, low wtrmrk %d\n", + pThis->qType, pThis->bEnqOnly, pThis->bIsDA, pThis->iMaxFileSize, pThis->iMaxQueueSize, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis), pThis->pqParent == NULL ? 0 : 1, pThis->iFullDlyMrk, pThis->iLightDlyMrk, - pThis->iDeqBatchSize); + pThis->iDeqBatchSize, pThis->iHighWtrMrk, pThis->iLowWtrMrk); pThis->bQueueStarted = 1; if(pThis->qType == QUEUETYPE_DIRECT) @@ -2491,7 +2528,7 @@ doEnqSingleObj(qqueue_t *pThis, flowControl_t flowCtlType, msg_t *pMsg) * In any case, this was the old code (if we do the TODO): * pthread_cond_wait(&pThis->belowFullDlyWtrMrk, pThis->mut); */ - DBGOPRINT((obj_t*) pThis, "enqueueMsg: FullDelay mark reached for full delayable message " + DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: FullDelay mark reached for full delayable message " "- blocking, queue size is %d.\n", pThis->iQueueSize); timeoutComp(&t, 1000); err = pthread_cond_timedwait(&pThis->belowLightDlyWtrMrk, pThis->mut, &t); @@ -2508,7 +2545,7 @@ doEnqSingleObj(qqueue_t *pThis, flowControl_t flowCtlType, msg_t *pMsg) } } else if(flowCtlType == eFLOWCTL_LIGHT_DELAY && !glbl.GetGlobalInputTermState()) { if(pThis->iQueueSize >= pThis->iLightDlyMrk) { - DBGOPRINT((obj_t*) pThis, "enqueueMsg: LightDelay mark reached for light " + DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: LightDelay mark reached for light " "delayable message - blocking a bit.\n"); timeoutComp(&t, 1000); /* 1000 millisconds = 1 second TODO: make configurable */ err = pthread_cond_timedwait(&pThis->belowLightDlyWtrMrk, pThis->mut, &t); @@ -2531,24 +2568,26 @@ doEnqSingleObj(qqueue_t *pThis, flowControl_t flowCtlType, msg_t *pMsg) && pThis->tVars.disk.sizeOnDisk > pThis->sizeOnDiskMax)) { STATSCOUNTER_INC(pThis->ctrFull, pThis->mutCtrFull); if(pThis->toEnq == 0 || pThis->bEnqOnly) { - DBGOPRINT((obj_t*) pThis, "enqueueMsg: queue FULL - configured for immediate discarding.\n"); + DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: queue FULL - configured for immediate discarding QueueSize=%d " + "MaxQueueSize=%d sizeOnDisk=%lld sizeOnDiskMax=%lld\n", pThis->iQueueSize, pThis->iMaxQueueSize, + pThis->tVars.disk.sizeOnDisk, pThis->sizeOnDiskMax); STATSCOUNTER_INC(pThis->ctrFDscrd, pThis->mutCtrFDscrd); msgDestruct(&pMsg); ABORT_FINALIZE(RS_RET_QUEUE_FULL); } else { - DBGOPRINT((obj_t*) pThis, "enqueueMsg: queue FULL - waiting %dms to drain.\n", pThis->toEnq); + DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: queue FULL - waiting %dms to drain.\n", pThis->toEnq); if(glbl.GetGlobalInputTermState()) { - DBGOPRINT((obj_t*) pThis, "enqueueMsg: queue FULL, discard due to FORCE_TERM.\n"); + DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: queue FULL, discard due to FORCE_TERM.\n"); ABORT_FINALIZE(RS_RET_FORCE_TERM); } timeoutComp(&t, pThis->toEnq); if(pthread_cond_timedwait(&pThis->notFull, pThis->mut, &t) != 0) { - DBGOPRINT((obj_t*) pThis, "enqueueMsg: cond timeout, dropping message!\n"); + DBGOPRINT((obj_t*) pThis, "doEnqSingleObject: cond timeout, dropping message!\n"); STATSCOUNTER_INC(pThis->ctrFDscrd, pThis->mutCtrFDscrd); msgDestruct(&pMsg); ABORT_FINALIZE(RS_RET_QUEUE_FULL); } - dbgoprint((obj_t*) pThis, "enqueueMsg: wait solved queue full condition, enqueing\n"); + dbgoprint((obj_t*) pThis, "doEnqSingleObject: wait solved queue full condition, enqueing\n"); } } diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index 47b34783..e62ba867 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -3,7 +3,7 @@ * * Begun 2005-09-15 RGerhards * - * Copyright (C) 2005-2008 by Rainer Gerhards and Adiscon GmbH + * Copyright (C) 2005-2013 by Rainer Gerhards and Adiscon GmbH * * This file is part of the rsyslog runtime library. * @@ -413,6 +413,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_CRY_INVLD_ALGO = -2326,/**< user specified invalid (unkonwn) crypto algorithm */ RS_RET_CRY_INVLD_MODE = -2327,/**< user specified invalid (unkonwn) crypto mode */ RS_RET_QUEUE_DISK_NO_FN = -2328,/**< disk queue configured, but filename not set */ + RS_RET_CA_CERT_MISSING = -2329,/**< a CA cert is missing where one is required (e.g. TLS) */ + RS_RET_CERT_MISSING = -2330,/**< a cert is missing where one is required (e.g. TLS) */ + RS_RET_CERTKEY_MISSING = -2331,/**< a cert (private) key is missing where one is required (e.g. TLS) */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ diff --git a/runtime/ruleset.c b/runtime/ruleset.c index cbfd847a..1afb4039 100644 --- a/runtime/ruleset.c +++ b/runtime/ruleset.c @@ -766,7 +766,7 @@ CODESTARTobjDestruct(ruleset) parser.DestructParserList(&pThis->pParserLst); } free(pThis->pszName); - cnfstmtDestruct(pThis->root); + cnfstmtDestructLst(pThis->root); ENDobjDestruct(ruleset) @@ -976,7 +976,7 @@ rulesetProcessCnf(struct cnfobj *o) errmsg.LogError(0, RS_RET_RULESET_EXISTS, "error: ruleset '%s' specified more than once", rsName); - cnfstmtDestruct(o->script); + cnfstmtDestructLst(o->script); ABORT_FINALIZE(RS_RET_RULESET_EXISTS); } else if(localRet != RS_RET_NOT_FOUND) { ABORT_FINALIZE(localRet); diff --git a/runtime/stream.c b/runtime/stream.c index 54210e40..94fc0ca7 100644 --- a/runtime/stream.c +++ b/runtime/stream.c @@ -1605,7 +1605,7 @@ finalize_it: /* property set methods */ /* simple ones first */ DEFpropSetMeth(strm, bDeleteOnClose, int) -DEFpropSetMeth(strm, iMaxFileSize, int) +DEFpropSetMeth(strm, iMaxFileSize, int64) DEFpropSetMeth(strm, iFileNumDigits, int) DEFpropSetMeth(strm, tOperationsMode, int) DEFpropSetMeth(strm, tOpenMode, mode_t) diff --git a/runtime/stream.h b/runtime/stream.h index 61d5ede2..4f4a4301 100644 --- a/runtime/stream.h +++ b/runtime/stream.h @@ -158,7 +158,6 @@ BEGINinterface(strm) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(strm_t **ppThis); rsRetVal (*ConstructFinalize)(strm_t *pThis); rsRetVal (*Destruct)(strm_t **ppThis); - rsRetVal (*SetMaxFileSize)(strm_t *pThis, int64 iMaxFileSize); rsRetVal (*SetFileName)(strm_t *pThis, uchar *pszName, size_t iLenName); rsRetVal (*ReadChar)(strm_t *pThis, uchar *pC); rsRetVal (*UnreadChar)(strm_t *pThis, uchar c); @@ -176,7 +175,7 @@ BEGINinterface(strm) /* name must also be changed in ENDinterface macro! */ rsRetVal (*SetWCntr)(strm_t *pThis, number_t *pWCnt); rsRetVal (*Dup)(strm_t *pThis, strm_t **ppNew); INTERFACEpropSetMeth(strm, bDeleteOnClose, int); - INTERFACEpropSetMeth(strm, iMaxFileSize, int); + INTERFACEpropSetMeth(strm, iMaxFileSize, int64); INTERFACEpropSetMeth(strm, iMaxFiles, int); INTERFACEpropSetMeth(strm, iFileNumDigits, int); INTERFACEpropSetMeth(strm, tOperationsMode, int); diff --git a/runtime/stringbuf.c b/runtime/stringbuf.c index cb4f0457..13f38710 100644 --- a/runtime/stringbuf.c +++ b/runtime/stringbuf.c @@ -107,7 +107,8 @@ finalize_it: /* a helper function for rsCStr*Strf() */ -static rsRetVal rsCStrConstructFromszStrv(cstr_t **ppThis, uchar *fmt, va_list ap) +static rsRetVal rsCStrConstructFromszStrv(cstr_t **ppThis, char *fmt, va_list ap) __attribute__((format(gnu_printf,2, 0))); +static rsRetVal rsCStrConstructFromszStrv(cstr_t **ppThis, char *fmt, va_list ap) { DEFiRet; cstr_t *pThis; @@ -147,7 +148,7 @@ rsRetVal rsCStrConstructFromszStrf(cstr_t **ppThis, char *fmt, ...) va_list ap; va_start(ap, fmt); - iRet = rsCStrConstructFromszStrv(ppThis, (uchar*)fmt, ap); + iRet = rsCStrConstructFromszStrv(ppThis, fmt, ap); va_end(ap); RETiRet; @@ -315,7 +316,7 @@ rsRetVal rsCStrAppendStrf(cstr_t *pThis, uchar *fmt, ...) cstr_t *pStr = NULL; va_start(ap, fmt); - iRet = rsCStrConstructFromszStrv(&pStr, fmt, ap); + iRet = rsCStrConstructFromszStrv(&pStr, (char*)fmt, ap); va_end(ap); CHKiRet(iRet); @@ -563,7 +564,7 @@ rsRetVal cstrTrimTrailingWhiteSpace(cstr_t *pThis) } /* i now is the new string length! */ pThis->iStrLen = i; - pThis->pBuf[pThis->iStrLen] = '0'; /* we always have this space */ + pThis->pBuf[pThis->iStrLen] = '\0'; /* we always have this space */ done: return RS_RET_OK; } diff --git a/runtime/typedefs.h b/runtime/typedefs.h index 8db567f0..d3f68b4a 100644 --- a/runtime/typedefs.h +++ b/runtime/typedefs.h @@ -29,6 +29,10 @@ #include <sys/types.h> #endif +#ifndef HAVE_LSEEK64 +#include <unistd.h> +#endif + /* some universal fixed size integer defines ... */ typedef long long int64; typedef long long unsigned uint64; @@ -948,6 +948,8 @@ finalize_it: if(iRet != RS_RET_OK) { if(pThis->pNS != NULL) netstrms.Destruct(&pThis->pNS); + errmsg.LogError(0, iRet, "tcpsrv could not create listener (inputname: '%s')", + (pThis->pszInputName == NULL) ? (uchar*)"*UNSET*" : pThis->pszInputName); } RETiRet; } @@ -34,7 +34,7 @@ #include <string.h> #include <ctype.h> #include <assert.h> -#include <json/json.h> +#include <json.h> #include "stringbuf.h" #include "syslogd-types.h" #include "template.h" @@ -30,7 +30,7 @@ #ifndef TEMPLATE_H_INCLUDED #define TEMPLATE_H_INCLUDED 1 -#include <json/json.h> +#include <json.h> #include <libestr.h> #include "regexp.h" #include "stringbuf.h" diff --git a/tests/chkseq.c b/tests/chkseq.c index b22c8992..bea9f83a 100644 --- a/tests/chkseq.c +++ b/tests/chkseq.c @@ -48,6 +48,7 @@ int main(int argc, char *argv[]) int start = 0, end = 0; int opt; int nDups = 0; + int reachedEOF; int edLen; /* length of extra data */ static char edBuf[500*1024]; /* buffer for extra data (pretty large to be on the save side...) */ char *file = NULL; @@ -126,15 +127,47 @@ int main(int argc, char *argv[]) } } - if(nDups != 0) - printf("info: had %d duplicates (this is no error)\n", nDups); - if(i - 1 != end) { printf("only %d records in file, expected %d\n", i - 1, end); exit(1); } - if(!feof(fp)) { + if(feof(fp)) { + reachedEOF = 1; + } else { + /* if duplicates are permitted, we need to do a final check if we have duplicates at the + * end of file. + */ + if(dupsPermitted) { + i = end; + while(!feof(fp)) { + if(bHaveExtraData) { + scanfOK = fscanf(fp, "%d,%d,%s\n", &val, &edLen, edBuf) == 3 ? 1 : 0; + if(edLen != (int) strlen(edBuf)) { + printf("extra data length specified %d, but actually is %ld in record %d\n", + edLen, (long) strlen(edBuf), i); + exit(1); + } + } else { + scanfOK = fscanf(fp, "%d\n", &val) == 1 ? 1 : 0; + } + + if(val != i) { + reachedEOF = 0; + goto breakIF; + } + } + reachedEOF = feof(fp) ? 1 : 0; + } else { + reachedEOF = 0; + } + } + +breakIF: + if(nDups != 0) + printf("info: had %d duplicates (this is no error)\n", nDups); + + if(!reachedEOF) { printf("end of processing, but NOT end of file!\n"); exit(1); } diff --git a/tools/ompipe.c b/tools/ompipe.c index 420e2b11..df8066b1 100644 --- a/tools/ompipe.c +++ b/tools/ompipe.c @@ -329,6 +329,10 @@ CODESTARTnewActInst } } + CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ? + "RSYSLOG_ForwardFormat" : (char*)pData->tplName), + OMSR_NO_RQD_TPL_OPTS)); + /* Old flawed template code if(pData->tplName == NULL) { CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*) "RSYSLOG_FileFormat", OMSR_NO_RQD_TPL_OPTS)); @@ -336,7 +340,7 @@ CODESTARTnewActInst CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*) strdup((char*) pData->tplName), OMSR_NO_RQD_TPL_OPTS)); - } + }*/ CODE_STD_FINALIZERnewActInst cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst diff --git a/tools/rsgtutil.c b/tools/rsgtutil.c index 095b8066..567dcf4c 100644 --- a/tools/rsgtutil.c +++ b/tools/rsgtutil.c @@ -74,7 +74,7 @@ dumpFile(char *name) if(fp != stdin) fclose(fp); return; -err: fprintf(stderr, "error %d processing file %s\n", r, name); +err: fprintf(stderr, "error %d (%s) processing file %s\n", r, RSGTE2String(r), name); } static void @@ -113,7 +113,7 @@ showSigblkParams(char *name) return; err: if(r != RSGTE_EOF) - fprintf(stderr, "error %d processing file %s\n", r, name); + fprintf(stderr, "error %d (%s) processing file %s\n", r, RSGTE2String(r), name); } static void @@ -145,7 +145,7 @@ detectFileType(char *name) if(fp != stdin) fclose(fp); return; -err: fprintf(stderr, "error %d processing file %s\n", r, name); +err: fprintf(stderr, "error %d (%s) processing file %s\n", r, RSGTE2String(r), name); } static inline int @@ -327,7 +327,7 @@ done: return; err: - fprintf(stderr, "error %d processing file %s\n", r, name); + fprintf(stderr, "error %d (%s) processing file %s\n", r, RSGTE2String(r), name); if(logfp != NULL) fclose(logfp); if(sigfp != NULL) |