summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog70
-rw-r--r--Makefile.am4
-rwxr-xr-xautogen.sh2
-rw-r--r--configure.ac35
-rw-r--r--doc/imtcp.html47
-rw-r--r--doc/imudp.html58
-rw-r--r--doc/imuxsock.html28
-rw-r--r--doc/manual.html2
-rw-r--r--doc/rsconf1_abortonuncleanconfig.html37
-rw-r--r--doc/rsconf1_omfileforcechown.html64
-rw-r--r--doc/rsyslog_conf_global.html23
-rw-r--r--doc/rsyslog_conf_modules.html2
-rw-r--r--doc/status.html24
-rw-r--r--java/Makefile.am35
-rw-r--r--java/com/rsyslog/diag/DiagTalker.java70
-rw-r--r--java/com/rsyslog/gui/diaggui/Counters.java138
-rw-r--r--java/com/rsyslog/gui/diaggui/DiagGUI.java77
-rw-r--r--java/com/rsyslog/gui/msggen/MsgGen.java140
-rw-r--r--java/com/rsyslog/gui/simpServ/simpServ.java45
-rw-r--r--java/com/rsyslog/gui/simpServ/simpServConsumer.java32
-rw-r--r--java/com/rsyslog/lib/DiagSess.java78
-rw-r--r--java/com/rsyslog/lib/SyslogMessage.java75
-rw-r--r--java/com/rsyslog/lib/SyslogMsgConsumer.java29
-rw-r--r--java/com/rsyslog/lib/SyslogSender.java96
-rw-r--r--java/com/rsyslog/lib/SyslogServerTCP.java126
-rw-r--r--java/com/rsyslog/lib/SyslogTrafficGenerator.java81
-rw-r--r--java/com/rsyslog/lib/UDPSyslogSender.java75
-rw-r--r--m4/shave.m499
-rw-r--r--plugins/imdiag/imdiag.c1
-rw-r--r--plugins/imfile/imfile.c1
-rw-r--r--plugins/imklog/imklog.c1
-rw-r--r--plugins/immark/immark.c18
-rw-r--r--plugins/imtemplate/imtemplate.c36
-rw-r--r--plugins/imudp/imudp.c168
-rw-r--r--plugins/imuxsock/imuxsock.c92
-rw-r--r--runtime/msg.c4
-rw-r--r--runtime/msg.h1
-rw-r--r--runtime/ruleset.c7
-rw-r--r--shave-libtool.in109
-rw-r--r--shave.in102
-rw-r--r--tcps_sess.c2
-rw-r--r--threads.c5
-rw-r--r--tools/omfile.c48
-rw-r--r--tools/syslogd.c377
44 files changed, 1753 insertions, 811 deletions
diff --git a/ChangeLog b/ChangeLog
index 99fac9d9..0b5ea67a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,51 @@
---------------------------------------------------------------------------
+Version 5.3.2 [DEVEL] (rgerhards), 2009-10-??
+- enhanced omfile to support transactional interface. This will increase
+ performance in many cases.
+- added multi-ruleset support to imudp
+- re-enabled input thread termination handling that does avoid thread
+ cancellation where possible. This provides a more reliable mode of
+ rsyslogd termination (canceling threads my result in not properly
+ freed resouces and potential later hangs, even though we perform
+ proper cancel handling in our code). This is part of an effort to
+ reduce thread cnacellation as much as possible in rsyslog.
+ NOTE: some comments indicated that there were problems with some code
+ that has been re-activated. Testing did not show any issues. My current
+ assumption is that these issues were related to some other code that
+ has been removed/changed during the previous restructuring events.
+ In any case, if there is a shutdown issue, one should carefully look
+ at this change here!
+- enhanced immark to support non-cancel input module termination
+- some cleanup/slight improvement:
+ * changed imuxsock to no longer use deprecated submitAndParseMsg() IF
+ * changed submitAndParseMsg() interface to be a wrapper around the new
+ way of message creation/submission. This enables older plugins to be
+ used together with the new interface. The removal also enables us to
+ drop a lot of duplicate code, reducing complexity and increasing
+ maintainability.
+---------------------------------------------------------------------------
+Version 5.3.1 [DEVEL] (rgerhards), 2009-10-05
+- added $AbortOnUncleanConfig directive - permits to prevent startup when
+ there are problems with the configuration file. See it's doc for
+ details.
+- included some important fixes from v4-stable:
+ * bugfix: invalid handling of zero-sized messages
+ * bugfix: zero-sized UDP messages are no longer processed
+ * bugfix: random data could be appended to message
+ * bugfix: reverse lookup reduction logic in imudp do DNS queries too often
+- bugfixes imported from 4.5.4:
+ * bugfix: potential segfault in stream writer on destruction
+ * bugfix: potential race in object loader (obj.c) during use/release
+ * bugfixes: potential problems in out file zip writer
+---------------------------------------------------------------------------
+Version 5.3.0 [DEVEL] (rgerhards), 2009-09-14
+- begun to add simple GUI programs to gain insight into running rsyslogd
+ instances and help setup and troubleshooting (active via the
+ --enable-gui ./configure switch)
+- changed imudp to utilize epoll(), where available. This shall provide
+ slightly better performance (just slightly because we called select()
+ rather infrequently on a busy system)
+---------------------------------------------------------------------------
Version 5.1.6 [v5-beta] (rgerhards), 2009-09-??
- feature imports from v4.5.6
- bugfix: potential race condition when queue worker threads were
@@ -22,6 +69,14 @@ Version 5.1.5 [v5-beta] (rgerhards), 2009-09-11
this option permites to process mark messages under all circumstances,
even if an action was recently called. This can be useful to use mark
messages as a kind of heartbeat.
+- added new config option $InputUnixListenSocketCreatePath
+ to permit the auto-creation of pathes to additional log sockets. This
+ turns out to be useful if they reside on temporary file systems and
+ rsyslogd starts up before the daemons that create these sockets
+ (rsyslogd always creates the socket itself if it does not exist).
+- added $LogRSyslogStatusMessages configuration directive
+ permitting to turn off rsyslog start/stop/HUP messages. See Debian
+ ticket http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=463793
- bugfix: hostnames with dashes in them were incorrectly treated as
malformed, thus causing them to be treated as TAG (this was a regression
introduced from the "rfc3164 strict" change in 4.5.0). Testbench has been
@@ -29,6 +84,7 @@ Version 5.1.5 [v5-beta] (rgerhards), 2009-09-11
- bugfix: strings improperly reused, resulting in some message properties
be populated with strings from previous messages. This was caused by
an improper predicate check.
+- added new config directive $omfileForceChown [import from 4.7.0]
---------------------------------------------------------------------------
Version 5.1.4 [DEVEL] (rgerhards), 2009-08-20
- legacy syslog parser changed so that it now accepts date stamps in
@@ -128,6 +184,20 @@ increase.
- increased ompgsql performance by adapting to new transactional
output module interface
---------------------------------------------------------------------------
+Version 4.7.0 [v4-devel] (rgerhards), 2009-09-??
+- added new config option $InputUnixListenSocketCreatePath
+ to permit the auto-creation of pathes to additional log sockets. This
+ turns out to be useful if they reside on temporary file systems and
+ rsyslogd starts up before the daemons that create these sockets
+ (rsyslogd always creates the socket itself if it does not exist).
+- added $LogRSyslogStatusMessages configuration directive
+ permitting to turn off rsyslog start/stop/HUP messages. See Debian
+ ticket http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=463793
+- added new config directive $omfileForceChown to (try to) fix some broken
+ system configs.
+ See ticket for details: http://bugzilla.adiscon.com/show_bug.cgi?id=150
+- imported changes from 4.5.6 and below
+---------------------------------------------------------------------------
Version 4.5.6 [v4-beta] (rgerhards), 2009-09-??
- bugfix(minor): diag function returned wrong queue memeber count
for the main queue if an active DA queue existed. This had no relevance
diff --git a/Makefile.am b/Makefile.am
index 7ab48455..6791b859 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -127,6 +127,10 @@ if ENABLE_ORACLE
SUBDIRS += plugins/omoracle
endif
+if ENABLE_GUI
+SUBDIRS += java
+endif
+
# tests are added as last element, because tests may need different
# modules that need to be generated first
SUBDIRS += tests
diff --git a/autogen.sh b/autogen.sh
index daa87a2a..c4055c50 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -19,7 +19,7 @@ fi
(cd $srcdir && autoreconf --verbose --force --install) || exit 1
-conf_flags="--enable-shave --cache-file=config.cache"
+conf_flags="--cache-file=config.cache"
if test x$NOCONFIGURE = x; then
echo Running $srcdir/configure $conf_flags "$@" ...
diff --git a/configure.ac b/configure.ac
index 5bbc5e55..e3f60b5c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,8 +2,11 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([rsyslog],[5.1.6],[rsyslog@lists.adiscon.com])
+AC_INIT([rsyslog],[5.3.2],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
AC_CONFIG_SRCDIR([ChangeLog])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
@@ -104,7 +107,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 epoll_wait getline malloc_trim prctl fdatasync])
+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_create1 fdatasync])
# Check for MAXHOSTNAMELEN
AC_MSG_CHECKING(for MAXHOSTNAMELEN)
@@ -773,6 +776,27 @@ AC_ARG_ENABLE(omstdout,
)
AM_CONDITIONAL(ENABLE_OMSTDOUT, test x$enable_omstdout = xyes)
+
+# building the GUI (mostly for diagnostic reasons)
+AC_ARG_ENABLE(gui,
+ [AS_HELP_STRING([--enable-gui],[Enable GUI programs @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_gui="yes" ;;
+ no) enable_gui="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-gui) ;;
+ esac],
+ [enable_gui=no]
+)
+if test "x$enable_gui" = "xyes"; then
+ if test x$HAVE_JAVAC = x; then
+ AC_MSG_ERROR([GUI components need Java, but Java development system is not installed on this system])
+ fi
+fi
+AM_CONDITIONAL(ENABLE_GUI, test x$enable_gui = xyes)
+
+
+AC_SUBST(RELP_CFLAGS)
+AC_SUBST(RELP_LIBS)
# This provides a vehicle to integrate custom modules, that are not
# part of rsyslog, into the build process. It is named cust1, so that
# additional such modules can easily be added.
@@ -828,12 +852,7 @@ AM_CONDITIONAL(ENABLE_OMTEMPLATE, test x$enable_omtemplate = xyes)
# end of copy template - be sure to search for omtemplate to find everything!
-SHAVE_INIT
-
-
AC_CONFIG_FILES([Makefile \
- shave \
- shave-libtool \
runtime/Makefile \
tools/Makefile \
doc/Makefile \
@@ -862,6 +881,7 @@ AC_CONFIG_FILES([Makefile \
plugins/omoracle/Makefile \
plugins/omudpspoof/Makefile \
plugins/cust1/Makefile \
+ java/Makefile \
tests/Makefile])
AC_OUTPUT
@@ -874,6 +894,7 @@ echo " Regular expressions support enabled: $enable_regexp"
echo " Zlib compression support enabled: $enable_zlib"
echo " rsyslog runtime will be built: $enable_rsyslogrt"
echo " rsyslogd will be built: $enable_rsyslogd"
+echo " GUI components will be built: $enable_gui"
echo " custom module 1 will be built: $enable_cust1"
echo
echo "---{ input plugins }---"
diff --git a/doc/imtcp.html b/doc/imtcp.html
index 0ccdecc7..0671d6d5 100644
--- a/doc/imtcp.html
+++ b/doc/imtcp.html
@@ -1,21 +1,23 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html><head>
-<meta http-equiv="Content-Language" content="en"><title>TCP Syslog Input Module</title></head>
+<html>
+<head>
+<meta http-equiv="Content-Language" content="en">
+<title>TCP Syslog Input Module</title>
+</head>
+
<body>
-<a href="rsyslog_conf_modules.html">back</a>
+<a href="rsyslog_conf_modules.html">back to rsyslog module overview</a>
<h1>TCP Syslog Input Module</h1>
<p><b>Module Name:&nbsp;&nbsp;&nbsp; imtcp</b></p>
-<p><b>Author: </b>Rainer Gerhards
-&lt;rgerhards@adiscon.com&gt;</p>
+<p><b>Author: </b>Rainer Gerhards &lt;rgerhards@adiscon.com&gt;</p>
+<p><b>Multi-Ruleset Support: </b>since 4.5.0 and 5.1.1
<p><b>Description</b>:</p>
<p>Provides the ability to receive syslog messages via TCP.
-Encryption can be provided by using <a href="rsyslog_stunnel.html">stunnel</a>
-(an alternative is the use
-the&nbsp;<a href="imgssapi.html">imgssapi</a>
-modul).</p>
-<p>Multiple receivers may be configured by
-specifying
+Encryption is natively provided by selecting the approprioate network stream driver and
+can also be provided by using <a href="rsyslog_stunnel.html">stunnel</a>
+(an alternative is the use the <a href="imgssapi.html">imgssapi</a> module).</p>
+<p>Multiple receivers may be configured by specifying
$InputTCPServerRun multiple times. This is available since version 4.3.1, earlier
versions do NOT support it.
</p>
@@ -49,8 +51,7 @@ after loading imtcp, otherwise it may have no effect.</li>
Starts a TCP server on selected port</li>
<li>$InputTCPMaxListeners &lt;number&gt;<br>
Sets the maximum number of listeners (server ports) supported. Default is 20. This must be set before the first $InputTCPServerRun directive.</li>
-<li>$InputTCPMaxSessions &lt;number&gt;<br>
-Sets the maximum number of sessions supported. Default is 200. This must be set before the first $InputTCPServerRun directive</li>
+<li>$InputTCPMaxSessions &lt;number&gt;<br> Sets the maximum number of sessions supported. Default is 200. This must be set before the first $InputTCPServerRun directive</li>
<li>$InputTCPServerStreamDriverMode &lt;number&gt;<br>
Sets the driver mode for the currently selected <a href="netstream.html">network stream driver</a>. &lt;number&gt; is driver specifc.</li>
<li>$InputTCPServerInputName &lt;name&gt;<br>
@@ -63,6 +64,8 @@ Sets the authentication mode for the currently selected <a href="netstream.html"
Sets permitted peer IDs. Only these peers are able to connect to the
listener. &lt;id-string&gt; semantics depend on the currently selected
AuthMode and&nbsp; <a href="netstream.html">network stream driver</a>. PermittedPeers may not be set in anonymous modes.</li>
+<li>$InputTCPServerBindRuleset &lt;ruleset&gt;<br>
+Binds the listener to a specific <a href="multi_ruleset.html">ruleset</a>.</li>
</ul>
<b>Caveats/Known Bugs:</b>
<ul>
@@ -71,19 +74,21 @@ AuthMode and&nbsp; <a href="netstream.html">network stream driver</a>. Permitted
(which includes the functionality of imtcp)</li>
</ul>
<p><b>Sample:</b></p>
-<p>This sets up a TCP server on port 514:<br>
+<p>This sets up a TCP server on port 514 and permits it to accept up to 500 connections:<br>
</p>
-<textarea rows="15" cols="60">$ModLoad imtcp #
-needs to be done just once
+<textarea rows="15" cols="60">$ModLoad imtcp # needs to be done just once
+$InputTCPMaxSessions 500
$InputTCPServerRun 514
</textarea>
+<p>Note that the parameters (here: max sessions) need to be set <b>before</b> the listener
+is activated. Otherwise, the parameters will not apply.
+</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>
+<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
+Copyright &copy; 2008,2009 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>
+</body>
+</html>
diff --git a/doc/imudp.html b/doc/imudp.html
new file mode 100644
index 00000000..f0e86307
--- /dev/null
+++ b/doc/imudp.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Language" content="en">
+<title>TCP Syslog Input Module</title>
+</head>
+
+<body>
+<a href="rsyslog_conf_modules.html">back to rsyslog module overview</a>
+
+<h1>UDP Syslog Input Module</h1>
+<p><b>Module Name:&nbsp;&nbsp;&nbsp; imudp</b></p>
+<p><b>Author: </b>Rainer Gerhards &lt;rgerhards@adiscon.com&gt;</p>
+<p><b>Multi-Ruleset Support: </b>since 5.3.2
+<p><b>Description</b>:</p>
+<p>Provides the ability to receive syslog messages via UDP.
+<p>Multiple receivers may be configured by specifying
+$UDPServerRun multiple times.
+</p>
+<p><b>Configuration Directives</b>:</p>
+<ul>
+<li>$UDPServerAddress &lt;IP&gt;<br>
+local IP address (or name) the UDP listens should bind to</li>
+<li>$UDPServerRun &lt;port&gt;<br>
+former -r&lt;port&gt; option, default 514, start UDP server on this
+port, "*" means all addresses</li>
+<li>$UDPServerTimeRequery &lt;nbr-of-times&gt;<br>
+this is a performance
+optimization. Getting the system time is very costly. With this setting, imudp can
+be instructed to obtain the precise time only once every n-times. This logic is
+only activated if messages come in at a very fast rate, so doing less frequent
+time calls should usually be acceptable. The default value is two, because we have
+seen that even without optimization the kernel often returns twice the identical time.
+You can set this value as high as you like, but do so at your own risk. The higher
+the value, the less precise the timestamp.
+<li>$InputUDPServerBindRuleset &lt;ruleset&gt;<br>
+Binds the listener to a specific <a href="multi_ruleset.html">ruleset</a>.</li>
+</ul>
+<b>Caveats/Known Bugs:</b>
+<ul>
+<li>currently none known</li>
+</ul>
+<p><b>Sample:</b></p>
+<p>This sets up an UPD server on port 514:<br>
+</p>
+<textarea rows="15" cols="60">$ModLoad imudp # needs to be done just once
+$UDPServerRun 514
+</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 &copy; 2009 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/imuxsock.html b/doc/imuxsock.html
index 472470a0..15c365a6 100644
--- a/doc/imuxsock.html
+++ b/doc/imuxsock.html
@@ -46,6 +46,18 @@ Ignore timestamps included in the messages, applies to messages received via the
<li><b>$SystemLogSocketName</b> &lt;name-of-socket&gt; -- former -p option</li>
<li><b>$SystemLogFlowControl</b> [on/<b>off</b>] - specifies if flow control should be applied
to the system log socket.</li>
+<li><b>$InputUnixListenSocketCreatePath</b> [on/<b>off</b>] - create directories in the socket path
+if they do not already exist. They are created with 0755 permissions with the owner being the process under
+which rsyslogd runs. The default is not to create directories. Keep in mind, though, that rsyslogd always
+creates the socket itself if it does not exist (just not the directories by default).
+<br>Note that this statement affects the
+next $AddUnixListenSocket directive that follows in sequence in the configuration file. It never works
+on the system log socket (where it is deemed unnecessary). Also note that it is automatically
+being reset to &quot;off&quot; after the $AddUnixListenSocket directive, so if you would have it active
+for two additional listen sockets, you need to specify it in front of each one. This option is primarily considered
+useful for defining additional sockets that reside on non-permanent file systems. As rsyslogd probably starts
+up before the daemons that create these sockets, it is a vehicle to enable rsyslogd to listen to those
+sockets even though their directories do not yet exist. [available since 4.7.0 and 5.3.0]</li>
<li><b>$AddUnixListenSocket</b> &lt;name-of-socket&gt; adds additional unix socket, default none -- former -a option</li>
<li><b>$InputUnixListenSocketHostName</b> &lt;hostname&gt; permits to override the hostname that
shall be used inside messages taken from the <b>next</b> $AddUnixListenSocket socket. Note that
@@ -57,20 +69,32 @@ that the local hostname can be overridden in cases where that is desired.</li>
<br>
This documentation is sparse and incomplete.
<p><b>Sample:</b></p>
-<p>The following sample is the minimum setup required to accept syslog messages from applications running on the local system.<br>
+<p>The following sample is the minimum setup required to accept syslog messages from applications running
+on the local system.<br>
</p>
<textarea rows="2" cols="70">$ModLoad imuxsock # needs to be done just once
$SystemLogSocketFlowControl on # enable flow control (use if needed)
</textarea>
<p>The following sample is a configuration where rsyslogd pulls logs from two
jails, and assigns different hostnames to each of the jails: </p>
-<textarea rows="6" cols="60">$ModLoad imuxsock # needs to be done just once
+<textarea rows="6" cols="70">$ModLoad imuxsock # needs to be done just once
$InputUnixListenSocketHostName jail1.example.net
$AddUnixListenSocket /jail/1/dev/log
$InputUnixListenSocketHostName jail2.example.net
$AddUnixListenSocket /jail/2/dev/log
</textarea>
+<p>The following sample is a configuration where rsyslogd reads the openssh log
+messages via a separate socket, but this socket is created on a temporary file
+system. As rsyslogd starts up before the sshd, it needs to create the socket
+directories, because it otherwise can not open the socket and thus not listen
+to openssh messages. Note that it is vital not to place any other socket between
+the $InputUnixListenSocketCreatePath and the $InputUnixListenSocketHostName.</p>
+<textarea rows="6" cols="70">$ModLoad imuxsock # needs to be done just once
+
+$InputUnixListenSocketCreatePath on # turn on for *next* socket
+$InputUnixListenSocketHostName /var/run/sshd/dev/log
+</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
diff --git a/doc/manual.html b/doc/manual.html
index 90af6940..a6d64872 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -19,7 +19,7 @@ rsyslog support</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 5.1.6 (devel branch) of rsyslog.</b>
+<p><b>This documentation is for version 5.3.2 (devel branch) of rsyslog.</b>
Visit the <i><a href="http://www.rsyslog.com/doc-status.html">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/rsconf1_abortonuncleanconfig.html b/doc/rsconf1_abortonuncleanconfig.html
new file mode 100644
index 00000000..77526c07
--- /dev/null
+++ b/doc/rsconf1_abortonuncleanconfig.html
@@ -0,0 +1,37 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<a href="rsyslog_conf_global.html">rsyslog.conf configuration directive</a>
+
+<h2>$AboortOnUncleanConfig</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Parameter Values:</b> boolean (on/off, yes/no)</p>
+<p><b>Available since:</b> 5.3.1+</p>
+<p><b>Default:</b> off</p>
+<p><b>Description:</b></p>
+<p>This directive permits to prevent rsyslog from running when the configuration file
+is not clean. "Not Clean" means there are errors or some other annoyances that rsyslgod
+reports on startup. This is a user-requested feature to have a strict startup mode. Note
+that with the current code base it is not always possible to differentiate between an
+real error and a warning-like condition. As such, the startup will also prevented if
+warnings are present. I consider this a good thing in being &quot;strict&quot;, but I admit
+there also currently is no other way of doing it.
+<p><b>Caveats:</b></p>
+Note that the consequences of a failed rsyslogd startup can be much more serious than a
+startup with only partial configuration. For example, log data may be lost or systems that
+depend on the log server in question will not be able to send logs, what in the ultimate
+result could result in a system hang on those systems. Also, the local system may hang when
+the local log socket has become full and is not read. There exist many such scenarios.
+As such, it is strongly recommended not to turn on this directive.
+
+<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 &copy; 2009 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 2 or higher.</font></p>
+</body>
+</html>
diff --git a/doc/rsconf1_omfileforcechown.html b/doc/rsconf1_omfileforcechown.html
new file mode 100644
index 00000000..7415a6f6
--- /dev/null
+++ b/doc/rsconf1_omfileforcechown.html
@@ -0,0 +1,64 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<a href="rsyslog_conf_global.html">back</a>
+
+<h2>$omfileForceChown</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Parameter Values:</b> boolean (on/off, yes/no)</p>
+<p><b>Available since:</b> 4.7.0+, 5.3.0+</p>
+<p><b>Default:</b> off</p>
+<p><b>Description:</b></p>
+<p>Forces rsyslogd to change the ownership for output files that already exist. Please note
+that this tries to fix a potential problem that exists outside the scope of rsyslog. Actually,
+it tries to fix invalid ownership/permission settings set by the original file creator.
+<p>Rsyslog changes the ownership during initial execution with root privileges. When a privelege
+drop is configured, privileges are dropped after the file owner ship is changed. Not that this currently
+is a limitation in rsyslog's privilege drop code, which is on the TODO list to be removed. See Caveats
+section below for the important implications.
+<p><b>Caveats:</b></p>
+<p>This directive tries to fix a problem that actually is outside the scope of rsyslog. As such,
+there are a couple of restrictions and situations in which it will not work. <b>Users are strongly
+encouraged to fix their system instead of turning this directive on</b> - it should only be used
+as a last resort.
+<p>At least in the following scenario, this directive will fail expectedly:
+<p>It does not address
+the situation that someone changes the ownership *after* rsyslogd has started.
+Let's, for example, consider a log rotation script.
+<ul>
+<li>rsyslog is started
+<li>ownership is changed
+<li>privileges dropped
+<li>log rotation (lr) script starts
+<li>lr removes files
+<li>lr creates new files with root:adm (or whatever else)
+<li>lr HUPs rsyslogd
+<li>rsyslogd closes files
+<li>rsyslogd tries to open files
+<li>rsyslogd tries to change ownership --&gt; fail as we are non-root now
+<li>file open fails
+</ul>
+
+Please note that once the privilege drop code is refactored, this directive will
+no longer work, because then privileges will be dropped before any action is performed,
+and thus we will no longer be able to chown files that do not belong to the
+user rsyslogd is configured to run under.
+
+<p>So <b>expect the directive to go away</b>. It will not
+be removed in version 4, but may disappear at any time for any version greater than 4.
+
+<p><b>Sample:</b></p>
+<p><code><b>$FileOwner loguser</b>
+<br><b>$omfileForceChown on</b></code></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 &copy; 2007 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 2 or higher.</font></p>
+</body>
+</html>
diff --git a/doc/rsyslog_conf_global.html b/doc/rsyslog_conf_global.html
index 45eeabe6..885dbdc7 100644
--- a/doc/rsyslog_conf_global.html
+++ b/doc/rsyslog_conf_global.html
@@ -17,6 +17,8 @@ appear as implementation progresses.
many parameter settings modify queue parameters. If in doubt, use the
default, it is usually well-chosen and applicable in most cases.</p>
<ul>
+<li><a href="rsconf1_abortonuncleanconfig.html">$AbortOnUncleanConfig</a> - abort startup if there is
+any issue with the config file</li>
<li><a href="rsconf1_actionexeconlywhenpreviousissuspended.html">$ActionExecOnlyWhenPreviousIsSuspended</a></li>
<li>$ActionName &lt;a_single_word&gt; - used primarily for documentation, e.g. when
generating a configuration graph. Available sice 4.3.1.
@@ -158,7 +160,12 @@ Usually that should not be a big issue, as the restart-type HUP can easily be re
something along the lines of &quot;/etc/init.d/rsyslog restart&quot;.
</li>
<li><a href="rsconf1_includeconfig.html">$IncludeConfig</a></li><li>MainMsgQueueCheckpointInterval &lt;number&gt;</li>
-<li>$MainMsgQueueDequeueBatchSize &lt;number&gt; [default 32]</li>
+<li><b>$LogRSyslogStatusMessages</b> [<b>on</b>/off] - If set to on (the default),
+rsyslog emits message on startup and shutdown as well as when it is HUPed.
+This information might be needed by some log analyzers. If set to off, no such
+status messages are logged, what may be useful for other scenarios.
+[available since 4.7.0 and 5.3.0]
+<li><b>$MainMsgQueueDequeueBatchSize</b> &lt;number&gt; [default 32]</li>
<li>$MainMsgQueueDequeueSlowdown &lt;number&gt; [number
is timeout in <i> micro</i>seconds (1000000us is 1sec!),
default 0 (no delay). Simple rate-limiting!]</li>
@@ -231,6 +238,7 @@ error recovery thus can handle write errors without data loss. Note that this op
severely reduces the effect of zip compression and should be switched to off
for that use case. Note that the default -off- is primarily an aid to preserve
the traditional syslogd behaviour.</li>
+<li><a href="rsconf1_omfileforcechown.html">$omfileForceChown</a> - force ownership change for all files</li>
<li><b>$RepeatedMsgContainsOriginalMsg</b> [on/<b>off</b>] - "last message repeated n times" messages, if generated,
have a different format that contains the message that is being repeated.
Note that only the first "n" characters are included, with n to be at least 80 characters, most
@@ -252,19 +260,6 @@ default may change as uniprocessor systems become less common. [available since
to sysklogd), the domain part from a name that is within the same domain as the receiving
system is stripped. If set to on, full names are always used.</li>
<li>$WorkDirectory &lt;name&gt; (directory for spool and other work files)</li>
-<li>$UDPServerAddress &lt;IP&gt; (imudp) -- local IP
-address (or name) the UDP listens should bind to</li>
-<li>$UDPServerRun &lt;port&gt; (imudp) -- former
--r&lt;port&gt; option, default 514, start UDP server on this
-port, "*" means all addresses</li>
-<li>$UDPServerTimeRequery &lt;nbr-of-times&gt; (imudp) -- this is a performance
-optimization. Getting the system time is very costly. With this setting, imudp can
-be instructed to obtain the precise time only once every n-times. This logic is
-only activated if messages come in at a very fast rate, so doing less frequent
-time calls should usually be acceptable. The default value is two, because we have
-seen that even without optimization the kernel often returns twice the identical time.
-You can set this value as high as you like, but do so at your own risk. The higher
-the value, the less precise the timestamp.
<li><a href="droppriv.html">$PrivDropToGroup</a></li>
<li><a href="droppriv.html">$PrivDropToGroupID</a></li>
<li><a href="droppriv.html">$PrivDropToUser</a></li>
diff --git a/doc/rsyslog_conf_modules.html b/doc/rsyslog_conf_modules.html
index f9bdad4a..d408fc60 100644
--- a/doc/rsyslog_conf_modules.html
+++ b/doc/rsyslog_conf_modules.html
@@ -25,7 +25,7 @@ permits rsyslog to alert folks by mail if something important happens</li>
-&nbsp; input module for text files</li>
<li><a href="imrelp.html">imrelp</a> - RELP
input module</li>
-<li>imudp - udp syslog message input</li>
+<li><a href="imudp.html">imudp</a> - udp syslog message input</li>
<li><a href="imtcp.html">imtcp</a> - input
plugin for plain tcp syslog</li>
<li><a href="imgssapi.html">imgssapi</a> -
diff --git a/doc/status.html b/doc/status.html
index 02cc0d70..e65b9182 100644
--- a/doc/status.html
+++ b/doc/status.html
@@ -2,12 +2,12 @@
<html><head><title>rsyslog status page</title></head>
<body>
<h2>rsyslog status page</h2>
-<p>This page reflects the status as of 2009-08-21.</p>
+<p>This page reflects the status as of 2009-10-09.</p>
<h2>Current Releases</h2>
-<p><b>v5 development:</b> 5.1.4 [2009-08-20] -
-<a href="http://www.rsyslog.com/Article392.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-170.phtml">download</a>
+<p><b>v5 development:</b> 5.3.1 [2009-10-05] -
+<a href="http://www.rsyslog.com/Article407.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-178.phtml">download</a>
<br>
<!-- not at the moment!
<b>v4 development:</b> 4.5.1 [2009-07-15] -
@@ -15,13 +15,17 @@
<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-167.phtml">download</a></p>
-->
-<br><b>v4-beta:</b> 4.5.2 [2009-08-21] -
-<a href="http://www.rsyslog.com/Article395.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-172.phtml">download</a></p>
+<br><b>v5-beta:</b> 5.1.5 [2009-09-11] -
+<a href="http://www.rsyslog.com/Article400.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-174.phtml">download</a>
-<p><b>v4 stable:</b> 4.4.0 [2009-08-21] -
-<a href="http://www.rsyslog.com/Article394.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-171.phtml">download</a>
+<br><b>v4-beta:</b> 4.5.4 [2009-09-29] -
+<a href="http://www.rsyslog.com/Article406.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-177.phtml">download</a></p>
+
+<p><b>v4 stable:</b> 4.4.2 [2009-10-09] -
+<a href="http://www.rsyslog.com/Article409.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-179.phtml">download</a>
<br><b>v3 stable:</b> 3.22.1 [2009-07-02] -
<a href="http://www.rsyslog.com/Article381.phtml">change log</a> -
diff --git a/java/Makefile.am b/java/Makefile.am
new file mode 100644
index 00000000..67f5eb43
--- /dev/null
+++ b/java/Makefile.am
@@ -0,0 +1,35 @@
+# very rough support for compiling the java components of rsyslog
+# Some usage notes: you need to use the Sun JDK compiler (jdk-devel)
+# with this. At least it didn't work for me with the eclipse compiler.
+# There is no real installation support. If you intend to run a program,
+# change to the ./java subdirectory and issue
+# java -cp . <class>
+# e.g.: java -cp . com.rsyslog.gui.diaggui.DiagGUI
+# or any equivalent command.
+#
+# I am very glad to hear suggestions about how to improve this part
+# of the build system. -- rgerhards, 2009-08-27
+
+javadir = $(top_builddir)/java
+JAVAROOT = $(javadir)
+# I don't know why CLASSPATH_ENV works this way, but at least it works...
+CLASSPATH_ENV = CLASSPATH=$(javadir):$$CLASSPATH
+
+JAVA_SOURCE_FILES = \
+ com/rsyslog/lib/DiagSess.java \
+ com/rsyslog/lib/SyslogMessage.java \
+ com/rsyslog/lib/SyslogMsgConsumer.java \
+ com/rsyslog/lib/SyslogTrafficGenerator.java \
+ com/rsyslog/lib/SyslogSender.java \
+ com/rsyslog/lib/UDPSyslogSender.java \
+ com/rsyslog/diag/DiagTalker.java \
+ com/rsyslog/gui/simpServ/simpServ.java \
+ com/rsyslog/gui/simpServ/simpServConsumer.java \
+ com/rsyslog/gui/msggen/MsgGen.java \
+ com/rsyslog/gui/diaggui/Counters.java \
+ com/rsyslog/gui/diaggui/DiagGUI.java
+
+
+java_JAVA = $(JAVA_SOURCE_FILES)
+
+dist_java = $(JAVA_SOURCE_FILES)
diff --git a/java/com/rsyslog/diag/DiagTalker.java b/java/com/rsyslog/diag/DiagTalker.java
new file mode 100644
index 00000000..c4e77e95
--- /dev/null
+++ b/java/com/rsyslog/diag/DiagTalker.java
@@ -0,0 +1,70 @@
+/* A yet very simple tool to talk to imdiag.
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+package com.rsyslog.diag;
+import java.io.*;
+import java.net.*;
+
+public class DiagTalker {
+ public static void main(String[] args) throws IOException {
+
+ Socket diagSocket = null;
+ PrintWriter out = null;
+ BufferedReader in = null;
+ final String host = "127.0.0.1";
+ final int port = 13500;
+
+ try {
+ diagSocket = new Socket(host, port);
+ diagSocket.setSoTimeout(0); /* wait for lenghty operations */
+ out = new PrintWriter(diagSocket.getOutputStream(), true);
+ in = new BufferedReader(new InputStreamReader(
+ diagSocket.getInputStream()));
+ } catch (UnknownHostException e) {
+ System.err.println("can not resolve " + host + "!");
+ System.exit(1);
+ } catch (IOException e) {
+ System.err.println("Couldn't get I/O for "
+ + "the connection to: " + host + ".");
+ System.exit(1);
+ }
+
+ BufferedReader stdIn = new BufferedReader(
+ new InputStreamReader(System.in));
+ String userInput;
+
+ try {
+ while ((userInput = stdIn.readLine()) != null) {
+ out.println(userInput);
+ System.out.println("imdiag returns: " + in.readLine());
+ }
+ } catch (SocketException e) {
+ System.err.println("We had a socket exception and consider this to be OK: "
+ + e.getMessage());
+ }
+
+ out.close();
+ in.close();
+ stdIn.close();
+ diagSocket.close();
+ }
+}
+
diff --git a/java/com/rsyslog/gui/diaggui/Counters.java b/java/com/rsyslog/gui/diaggui/Counters.java
new file mode 100644
index 00000000..363bff43
--- /dev/null
+++ b/java/com/rsyslog/gui/diaggui/Counters.java
@@ -0,0 +1,138 @@
+/* Display some basic rsyslogd counter variables.
+ *
+ * Please note that this program requires imdiag to be loaded inside rsyslogd.
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+package com.rsyslog.gui.diaggui;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+
+import com.rsyslog.lib.DiagSess;
+
+public class Counters extends Frame {
+
+ private TextField MainQItems;
+ private TextField RefreshInterval;
+ private Checkbox AutoRefresh;
+ private DiagSess diagSess;
+ private Timer timer;
+
+ private void createDiagSess() {
+ try {
+ diagSess = new DiagSess("127.0.0.1", 13500); // TODO: values from GUI
+ diagSess.connect();
+ }
+ catch(IOException e) {
+ System.out.println("Exception trying to open diag session:\n" + e.toString());
+ }
+ }
+
+ private void createGUI() {
+ MainQItems = new TextField();
+ MainQItems.setColumns(8);
+ Panel pCenter = new Panel();
+ pCenter.setLayout(new FlowLayout());
+ pCenter.add(new Label("MainQ Items:"));
+ pCenter.add(MainQItems);
+
+ RefreshInterval = new TextField();
+ RefreshInterval.setColumns(5);
+ RefreshInterval.setText("100");
+ AutoRefresh = new Checkbox("Auto Refresh", false);
+ AutoRefresh.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ setAutoRefresh();
+ }
+
+ });
+ Button b = new Button("Refresh now");
+ b.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ refreshCounters();
+ }
+ });
+ Panel pSouth = new Panel();
+ pSouth.setLayout(new FlowLayout());
+ pSouth.add(AutoRefresh);
+ pSouth.add(new Label("Interval (ms):"));
+ pSouth.add(RefreshInterval);
+ pSouth.add(b);
+
+ pack();
+ setTitle("rsyslogd Counters");
+ setLayout(new BorderLayout());
+ add(pCenter, BorderLayout.CENTER);
+ add(pSouth, BorderLayout.SOUTH);
+ setSize(400,500);
+ }
+
+ public Counters() {
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e){
+ Counters.this.dispose();
+ }
+ });
+ createGUI();
+ createDiagSess();
+ setAutoRefresh();
+ setVisible(true);
+ }
+
+
+ private void startTimer() {
+ timer = new Timer();
+ timer.scheduleAtFixedRate(new TimerTask() {
+ public void run() {
+ refreshCounters();
+ }
+ }, 0, 100);
+ }
+
+ private void stopTimer() {
+ if(timer != null) {
+ timer.cancel();
+ timer = null;
+ }
+ }
+
+ /** set auto-refresh mode. It is either turned on or off, depending on the
+ * status of the relevant check box. */
+ private void setAutoRefresh() {
+ if(AutoRefresh.getState() == true) {
+ startTimer();
+ } else {
+ stopTimer();
+ }
+ }
+
+ /** refresh counter display from rsyslogd data. Does a network round-trip. */
+ private void refreshCounters() {
+ try {
+ String res = diagSess.request("getmainmsgqueuesize");
+ MainQItems.setText(res);
+ }
+ catch(IOException e) {
+ System.out.println("Exception during request:\n" + e.toString());
+ }
+ }
+}
diff --git a/java/com/rsyslog/gui/diaggui/DiagGUI.java b/java/com/rsyslog/gui/diaggui/DiagGUI.java
new file mode 100644
index 00000000..1a03299c
--- /dev/null
+++ b/java/com/rsyslog/gui/diaggui/DiagGUI.java
@@ -0,0 +1,77 @@
+/* A yet very simple diagnostic GUI for rsyslog.
+ *
+ * Please note that this program requires imdiag to be loaded inside rsyslogd.
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+package com.rsyslog.gui.diaggui;
+import java.awt.*;
+import java.awt.event.*;
+
+public class DiagGUI extends Frame {
+ public Counters counterWin;
+ public static void main(String args[]) {
+ new DiagGUI();
+ }
+
+ /** show counter window. creates it if not already present */
+ public void showCounters() {
+ if(counterWin == null) {
+ counterWin = new Counters();
+ } else {
+ counterWin.setVisible(true);
+ counterWin.toFront();
+ }
+ }
+
+ /** initialize the GUI. */
+ public DiagGUI(){
+ MenuItem item;
+ MenuBar menuBar = new MenuBar();
+ Menu fileMenu = new Menu("File");
+ item = new MenuItem("Exit");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ System.exit(0);
+ }
+ });
+ fileMenu.add(item);
+ menuBar.add(fileMenu);
+
+ Menu viewMenu = new Menu("View");
+ item = new MenuItem("Counters");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ showCounters();
+ }
+ });
+ viewMenu.add(item);
+ menuBar.add(viewMenu);
+
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e){
+ System.exit(0);
+ }
+ });
+ setMenuBar(menuBar);
+ setSize(300,400);
+ setVisible(true);
+ }
+}
diff --git a/java/com/rsyslog/gui/msggen/MsgGen.java b/java/com/rsyslog/gui/msggen/MsgGen.java
new file mode 100644
index 00000000..c57027ff
--- /dev/null
+++ b/java/com/rsyslog/gui/msggen/MsgGen.java
@@ -0,0 +1,140 @@
+/* A yet very simple syslog message generator
+ *
+ * The purpose of this program is to provide a facility that enables
+ * to generate complex traffic patterns for testing purposes. It still is
+ * in its infancy, but hopefully will evolve.
+ *
+ * Note that this has been created as a stand-alone application because it
+ * was considered useful to have it as a separate program. But it should still
+ * be possible to call its class from any other program, specifically the debug
+ * GUI.
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+package com.rsyslog.gui.msggen;
+import com.rsyslog.lib.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+public class MsgGen extends Frame {
+ private TextField target;
+ private TextField message;
+ private TextField nummsgs;
+ private TextField numthrds;
+
+ public static void main(String args[]) {
+ new MsgGen();
+ }
+
+ /** creates the menu bar INCLUDING all menu handlers */
+ private void createMenu() {
+ MenuItem item;
+ MenuBar menuBar = new MenuBar();
+ Menu fileMenu = new Menu("File");
+ item = new MenuItem("Exit");
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ System.exit(0);
+ }
+ });
+ fileMenu.add(item);
+ menuBar.add(fileMenu);
+
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e){
+ System.exit(0);
+ }
+ });
+ setMenuBar(menuBar);
+ }
+
+ /** creates the main GUI */
+ private void createGUI() {
+ //target = new TextField("127.0.0.1", 32);
+ target = new TextField("172.19.3.3", 32);
+ message = new TextField(80);
+ //message.setText("<161>Test malformed");
+ message.setText("<5>iaalog[171652]: AIB|dcu|2009/08/12 14:48:43|mfa challenge|NNNNNNN|XX.XX.XX.XX");
+ nummsgs = new TextField("1000", 8);
+ numthrds = new TextField("10", 5);
+ Panel pCenter = new Panel();
+
+ Panel pnl = new Panel();
+ pnl.setLayout(new FlowLayout());
+ pnl.add(new Label("Target Host:"));
+ pnl.add(target);
+ pCenter.add(pnl);
+
+ pnl = new Panel();
+ pnl.setLayout(new FlowLayout());
+ pnl.add(new Label("Number of Msgs:"));
+ pnl.add(nummsgs);
+ pCenter.add(pnl);
+
+ pnl = new Panel();
+ pnl.setLayout(new FlowLayout());
+ pnl.add(new Label("Msg:"));
+ pnl.add(message);
+ pCenter.add(pnl);
+
+ Panel pSouth = new Panel();
+ pSouth.setLayout(new FlowLayout());
+
+ pnl = new Panel();
+ pnl.setLayout(new FlowLayout());
+ pnl.add(new Label("Number of Threads:"));
+ pnl.add(numthrds);
+ pSouth.add(pnl);
+
+ Button b = new Button("Start Test");
+ b.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ performTest();
+ }
+ });
+ pSouth.add(b);
+
+ pack();
+ setTitle("Syslog Message Generator");
+ setLayout(new BorderLayout());
+ add(pCenter, BorderLayout.CENTER);
+ add(pSouth, BorderLayout.SOUTH);
+ setSize(800,400);
+ }
+
+ /** perform the test, a potentially complex operation */
+ private void performTest() {
+ for(short i = 0 ; i < Integer.parseInt(numthrds.getText()) ; ++ i) {
+ SyslogTrafficGenerator gen =
+ new SyslogTrafficGenerator(target.getText(), message.getText(),
+ Long.parseLong(nummsgs.getText()));
+ gen.start();
+ }
+ }
+
+
+ /** initialize the GUI. */
+ public MsgGen(){
+ createMenu();
+ createGUI();
+ setVisible(true);
+ }
+}
diff --git a/java/com/rsyslog/gui/simpServ/simpServ.java b/java/com/rsyslog/gui/simpServ/simpServ.java
new file mode 100644
index 00000000..2a83dad0
--- /dev/null
+++ b/java/com/rsyslog/gui/simpServ/simpServ.java
@@ -0,0 +1,45 @@
+/**
+ * Implementation of a tcp-based syslog server.
+ *
+ * @author Rainer Gerhards
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see http://www.gnu.org/licenses/.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+
+package com.rsyslog.gui.simpServ;
+import com.rsyslog.lib.*;
+//import com.rsyslog.gui.*;
+
+public class simpServ {
+
+ public static void main(String args[]) {
+ try {
+ simpServConsumer cons = new simpServConsumer();
+ System.out.println("Starting server on port " + args[0] + "\n");
+ SyslogServerTCP myServ = new
+ SyslogServerTCP(Integer.parseInt(args[0]), cons);
+ myServ.start();
+ System.out.println("Press ctl-c to terminate\n");
+ }
+ catch(Exception e) {
+ System.out.println("Error: " + e.toString());
+ }
+ }
+}
diff --git a/java/com/rsyslog/gui/simpServ/simpServConsumer.java b/java/com/rsyslog/gui/simpServ/simpServConsumer.java
new file mode 100644
index 00000000..588f2640
--- /dev/null
+++ b/java/com/rsyslog/gui/simpServ/simpServConsumer.java
@@ -0,0 +1,32 @@
+/** A syslog message consumer for the simple syslog server.
+ *
+ * @author Rainer Gerhards
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see http://www.gnu.org/licenses/.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+package com.rsyslog.gui.simpServ;
+import com.rsyslog.lib.*;
+
+class simpServConsumer implements SyslogMsgConsumer {
+ public void consumeMsg(String ln) {
+ SyslogMessage msg = new SyslogMessage(ln);
+ System.out.println("Line received '" + msg.getRawMsgAfterPRI() + "'\n");
+ }
+}
diff --git a/java/com/rsyslog/lib/DiagSess.java b/java/com/rsyslog/lib/DiagSess.java
new file mode 100644
index 00000000..799b9a4a
--- /dev/null
+++ b/java/com/rsyslog/lib/DiagSess.java
@@ -0,0 +1,78 @@
+/* The diagnostic session to an imdiag module (running inside rsyslogd).
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+package com.rsyslog.lib;
+import java.io.*;
+import java.net.*;
+
+public class DiagSess {
+
+ private String host = new String("127.0.0.1");
+ private int port = 13500;
+ int timeout = 0;
+ private PrintWriter out = null;
+ private BufferedReader in = null;
+ private Socket diagSocket = null;
+
+ /** set connection timeout */
+ public void setTimeout(int timeout_) {
+ timeout = timeout_;
+ }
+
+ public DiagSess(String host_, int port_) {
+ host = host_;
+ port = port_;
+ }
+
+ /** connect to remote server. Initializes everything for request-reply
+ * processing.
+ *
+ * @throws IOException
+ */
+ public void connect() throws IOException {
+ diagSocket = new Socket(host, port);
+ diagSocket.setSoTimeout(timeout);
+ out = new PrintWriter(diagSocket.getOutputStream(), true);
+ in = new BufferedReader(new InputStreamReader(
+ diagSocket.getInputStream()));
+
+ }
+
+ /** end session with remote server. */
+ public void disconnect() throws IOException {
+ out.close();
+ in.close();
+ diagSocket.close();
+ }
+
+ /** issue a request to imdiag and return its response.
+ *
+ * @param req request string
+ * @return response string (unparsed)
+ * @throws IOException
+ */
+ public String request(String req) throws IOException {
+ out.println(req);
+ String resp = in.readLine();
+ return resp;
+ }
+
+}
diff --git a/java/com/rsyslog/lib/SyslogMessage.java b/java/com/rsyslog/lib/SyslogMessage.java
new file mode 100644
index 00000000..b544a6db
--- /dev/null
+++ b/java/com/rsyslog/lib/SyslogMessage.java
@@ -0,0 +1,75 @@
+/**
+ * Implementation of the syslog message object.
+ *
+ * This is a limited-capability implementation of a syslog message together
+ * with all its properties. It is limit to what is currently needed and may
+ * be extended as further need arises.
+ *
+ * @author Rainer Gerhards
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see http://www.gnu.org/licenses/.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+package com.rsyslog.lib;
+
+public class SyslogMessage {
+
+ /** message as received from the wire */
+ private String rawmsg;
+ /** the rawmsg without the PRI part */
+ private String rawMsgAfterPRI;
+ /** PRI part */
+ private int pri;
+
+ /** a very simple syslog parser. So far, it only parses out the
+ * PRI part of the message. May be extended later. Rawmsg must have
+ * been set before the parser is called. It will populate "all" other
+ * fields.
+ */
+ private void parse() {
+ int i;
+ if(rawmsg.charAt(0) == '<') {
+ pri = 0;
+ for(i = 1 ; Character.isDigit(rawmsg.charAt(i)) && i < 4 ; ++i) {
+ pri = pri * 10 + rawmsg.charAt(i) - '0';
+ }
+ if(rawmsg.charAt(i) != '>')
+ /* not a real cure, but sufficient for the current
+ * mini-parser... */
+ --i;
+ rawMsgAfterPRI = rawmsg.substring(i + 1);
+ } else {
+ pri = 116;
+ rawMsgAfterPRI = rawmsg;
+ }
+ }
+
+ public SyslogMessage(String _rawmsg) {
+ rawmsg = _rawmsg;
+ parse();
+ }
+
+ public String getRawMsg() {
+ return rawmsg;
+ }
+
+ public String getRawMsgAfterPRI() {
+ return rawMsgAfterPRI;
+ }
+}
diff --git a/java/com/rsyslog/lib/SyslogMsgConsumer.java b/java/com/rsyslog/lib/SyslogMsgConsumer.java
new file mode 100644
index 00000000..42c9931a
--- /dev/null
+++ b/java/com/rsyslog/lib/SyslogMsgConsumer.java
@@ -0,0 +1,29 @@
+/**
+ * Interface for SyslogConsumers.
+ *
+ * @author Rainer Gerhards
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see http://www.gnu.org/licenses/.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+package com.rsyslog.lib;
+
+public interface SyslogMsgConsumer {
+ public void consumeMsg(String msg);
+}
diff --git a/java/com/rsyslog/lib/SyslogSender.java b/java/com/rsyslog/lib/SyslogSender.java
new file mode 100644
index 00000000..fc0e3fec
--- /dev/null
+++ b/java/com/rsyslog/lib/SyslogSender.java
@@ -0,0 +1,96 @@
+/**
+ * This class specifies all methods common to syslog senders. It also implements
+ * some generic ways to send data. Actual syslog senders (e.g. UDP, TCP, ...) shall
+ * be derived from this class.
+ *
+ * This is a limited-capability implementation of a syslog message together
+ * with all its properties. It is limit to what is currently needed and may
+ * be extended as further need arises.
+ *
+ * @author Rainer Gerhards
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see http://www.gnu.org/licenses/.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+package com.rsyslog.lib;
+
+public abstract class SyslogSender {
+
+ /** the rawmsg without the PRI part */
+ private String target;
+
+ /** the rawmsg without the PRI part */
+ private boolean isConnected = false;
+
+ /** Constructs Sender, sets target system.
+ * @param target the system to connect to. Syntax of target is depending
+ * on the underlying transport.
+ */
+ public SyslogSender(String target) {
+ this.target = target;
+ }
+
+
+ /** send a message on the wire.
+ * This needs a complete formatted message, which will be extended by
+ * the transport framing, if necessary.
+ *
+ * @param MSG a validly formatted syslog message as of the RFC (all parts)
+ * @throws Exception (depending on transport)
+ */
+ protected abstract void sendTransport(String MSG) throws Exception;
+
+ /** send an alread-formatted message.
+ * Sends a preformatted syslog message payload to the target. Connects
+ * to the target if not already connected.
+ *
+ * @param MSG a validly formatted syslog message as of the RFC (all parts)
+ * @throws Exception (depending on transport)
+ */
+ public void sendMSG(String MSG) throws Exception {
+ if(!isConnected)
+ connect();
+ sendTransport(MSG);
+ }
+
+ /** connect to the target.
+ * Note that this may be a null operation if there is no session-like entity
+ * in the underlying transport (as is for example in UDP).
+ */
+ public void connect() throws Exception {
+ /* the default implementation does (almost) nothing */
+ isConnected = true;
+ }
+
+ /** disconnects from the target.
+ * Note that this may be a null operation if there is no session-like entity
+ * in the underlying transport (as is for example in UDP).
+ */
+ public void disconnect() {
+ /* the default implementation does (almost) nothing */
+ isConnected = false;
+ }
+
+ /** return target of this Sender.
+ * @returns target as initially set
+ */
+ public String getTarget() {
+ return target;
+ }
+}
diff --git a/java/com/rsyslog/lib/SyslogServerTCP.java b/java/com/rsyslog/lib/SyslogServerTCP.java
new file mode 100644
index 00000000..d5376a32
--- /dev/null
+++ b/java/com/rsyslog/lib/SyslogServerTCP.java
@@ -0,0 +1,126 @@
+/**
+ * Implementation of a tcp-based syslog server.
+ *
+ * This is a limited-capability implementation of a syslog tcp server.
+ *
+ * @author Rainer Gerhards
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see http://www.gnu.org/licenses/.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+package com.rsyslog.lib;
+
+import com.rsyslog.lib.SyslogMsgConsumer;
+import java.io.*;
+import java.net.*;
+
+
+/** a small test consumer */
+/*
+class TestConsumer implements SyslogMsgConsumer {
+ public void consumeMsg(String ln) {
+ System.out.println("Line received '" + ln + "'\n");
+ }
+}
+*/
+
+public class SyslogServerTCP extends Thread {
+ private ServerSocket lstnSock;
+ private boolean contRun; /* continue processing requests? */
+ public SyslogMsgConsumer consumer;
+
+ /** Process a single connection */
+ class Session extends Thread {
+ private Socket sock;
+ private SyslogServerTCP srvr;
+
+ public Session(Socket so, SyslogServerTCP _srvr) {
+ sock = so;
+ srvr = _srvr;
+ }
+
+ public void run() {
+ try {
+ BufferedReader data = new BufferedReader(
+ new InputStreamReader(sock.getInputStream()));
+
+ String ln = data.readLine();
+ while(ln != null) {
+ srvr.getConsumer().consumeMsg(ln);
+ ln = data.readLine();
+ }
+ System.out.println("End of Session.\n");
+ sock.close();
+ }
+ catch(Exception e) {
+ /* we ignore any errors we may have... */
+ System.out.println("Session exception " + e.toString());
+ }
+ }
+ }
+
+ /** a small test driver */
+/*
+ public static void main(String args[]) {
+ try {
+ SyslogMsgConsumer cons = new TestConsumer();
+ System.out.println("Starting server on port " + args[0] + "\n");
+ SyslogServerTCP myServ = new
+ SyslogServerTCP(Integer.parseInt(args[0]), cons);
+ myServ.start();
+ System.out.println("Press ctl-c to terminate\n");
+ }
+ catch(Exception e) {
+ System.out.println("Fehler! " + e.toString());
+ }
+ }
+*/
+
+ public SyslogServerTCP(int port, SyslogMsgConsumer cons) throws java.io.IOException {
+ if(lstnSock != null)
+ terminate();
+ lstnSock = new ServerSocket(port);
+ consumer = cons;
+ contRun = true;
+ }
+
+ public void terminate() {
+ contRun = false;
+ }
+
+ public SyslogMsgConsumer getConsumer() {
+ return consumer;
+ }
+
+ public void run() {
+ try {
+ while(contRun) {
+ Socket sock = lstnSock.accept();
+ System.out.println("New connection request! " + sock.toString());
+ Thread sess = new Session(sock, this);
+ sock = null;
+ sess.start();
+ }
+ }
+ catch(Exception e) {
+ System.out.println("Error during server run " + e.toString());
+ }
+
+ }
+}
diff --git a/java/com/rsyslog/lib/SyslogTrafficGenerator.java b/java/com/rsyslog/lib/SyslogTrafficGenerator.java
new file mode 100644
index 00000000..79a99495
--- /dev/null
+++ b/java/com/rsyslog/lib/SyslogTrafficGenerator.java
@@ -0,0 +1,81 @@
+/**
+ * This class is a syslog traffic generator. It is primarily intended to be used
+ * together with testing tools, but may have some use cases outside that domain.
+ *
+ * @author Rainer Gerhards
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see http://www.gnu.org/licenses/.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+package com.rsyslog.lib;
+
+public class SyslogTrafficGenerator extends Thread {
+
+ /** the target host to receive traffic */
+ private String target;
+
+ /** the message (template) to be sent */
+ private String message;
+
+ /** number of messages to be sent */
+ private long nummsgs;
+
+ /** Constructs Sender, sets target system.
+ * @param target the system to connect to. Syntax of target is depending
+ * on the underlying transport.
+ */
+ public SyslogTrafficGenerator(String target, String message, long nummsgs) {
+ this.target = target;
+ this.message = message;
+ this.nummsgs = nummsgs;
+ }
+
+ /** Generates the traffic. Stops when either called to terminate
+ * or the max number of messages have been sent. Note that all
+ * necessary properties must have been set up before starting the
+ * generator thread!
+ */
+ private void performTest() throws Exception {
+ int doDisp = 0;
+ UDPSyslogSender sender = new UDPSyslogSender(target);
+ for(long i = 0 ; i < nummsgs ; ++i) {
+ sender.sendMSG(message + " " + Long.toString(i) + " " + this.toString() + "\0");
+ if((doDisp++ % 1000) == 0)
+ System.out.println(this.toString() + " send message " + Long.toString(i));
+ sleep(1);
+ }
+ }
+
+
+/** Wrapper around the real traffic generator, catches exceptions.
+ */
+ public void run() {
+ System.out.println("traffic generator " + this.toString() + " thread started");
+ try {
+ performTest();
+ }
+ catch(Exception e) {
+ /* at some time, we may find a more intelligent way to
+ * handle this! ;)
+ */
+ System.out.println(e.toString());
+ }
+ System.out.println("traffic generator " + this.toString() + " thread finished");
+ }
+}
diff --git a/java/com/rsyslog/lib/UDPSyslogSender.java b/java/com/rsyslog/lib/UDPSyslogSender.java
new file mode 100644
index 00000000..1a2c4726
--- /dev/null
+++ b/java/com/rsyslog/lib/UDPSyslogSender.java
@@ -0,0 +1,75 @@
+/**
+ * A UDP transport implementation of a syslog sender.
+ *
+ * Note that there is an anomaly in this version of the code: we query the remote system
+ * address only once during the connection setup and resue it. If we potentially run for
+ * an extended period of time, the remote address may change, what we do not reflect. For
+ * the current use case, this is acceptable, but if this code is put into more wide-spread
+ * use outside of debugging, a periodic requery should be added.
+ *
+ * @author Rainer Gerhards
+ *
+ * Copyright 2009 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see http://www.gnu.org/licenses/.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+package com.rsyslog.lib;
+import java.net.*;
+
+public class UDPSyslogSender extends SyslogSender {
+
+ private final int port = 514; // TODO: take from target!
+ private InetAddress targetAddr;
+
+ /** the socket to communicate over with the remote system. */
+ private DatagramSocket sock;
+
+ /** Constructs Sender, sets target system.
+ * @param target the system to connect to. Syntax of target is depending
+ * on the underlying transport.
+ */
+ public UDPSyslogSender(String target) throws Exception {
+ super(target);
+ }
+
+ /** send a message on the wire.
+ * This needs a complete formatted message, which will be extended by
+ * the transport framing, if necessary.
+ *
+ * @param MSG a validly formatted syslog message as of the RFC (all parts)
+ * @throws Exception (depending on transport)
+ */
+ protected void sendTransport(String MSG) throws Exception {
+ byte msg[] = MSG.getBytes();
+ DatagramPacket pkt = new DatagramPacket(msg, msg.length, targetAddr, port);
+ sock.send(pkt);
+ }
+
+
+ /** connect to the target.
+ * For UDP, this means we create the socket.
+ */
+ public void connect() throws Exception {
+ super.connect();
+ sock = new DatagramSocket();
+
+ // TODO: we should extract the actual hostname & port!
+ targetAddr = InetAddress.getByName(getTarget());
+ }
+
+}
diff --git a/m4/shave.m4 b/m4/shave.m4
deleted file mode 100644
index e647e579..00000000
--- a/m4/shave.m4
+++ /dev/null
@@ -1,99 +0,0 @@
-dnl Make automake/libtool output more friendly to humans
-dnl
-dnl Copyright (c) 2009, Damien Lespiau <damien.lespiau@gmail.com>
-dnl
-dnl Permission is hereby granted, free of charge, to any person
-dnl obtaining a copy of this software and associated documentation
-dnl files (the "Software"), to deal in the Software without
-dnl restriction, including without limitation the rights to use,
-dnl copy, modify, merge, publish, distribute, sublicense, and/or sell
-dnl copies of the Software, and to permit persons to whom the
-dnl Software is furnished to do so, subject to the following
-dnl conditions:
-dnl
-dnl The above copyright notice and this permission notice shall be
-dnl included in all copies or substantial portions of the Software.
-dnl
-dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-dnl EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-dnl OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-dnl NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-dnl HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-dnl WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-dnl FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-dnl OTHER DEALINGS IN THE SOFTWARE.
-dnl
-dnl SHAVE_INIT([shavedir],[default_mode])
-dnl
-dnl shavedir: the directory where the shave scripts are, it defaults to
-dnl $(top_builddir)
-dnl default_mode: (enable|disable) default shave mode. This parameter
-dnl controls shave's behaviour when no option has been
-dnl given to configure. It defaults to disable.
-dnl
-dnl * SHAVE_INIT should be called late in your configure.(ac|in) file (just
-dnl before AC_CONFIG_FILE/AC_OUTPUT is perfect. This macro rewrites CC and
-dnl LIBTOOL, you don't want the configure tests to have these variables
-dnl re-defined.
-dnl * This macro requires GNU make's -s option.
-
-AC_DEFUN([_SHAVE_ARG_ENABLE],
-[
- AC_ARG_ENABLE([shave],
- AS_HELP_STRING(
- [--enable-shave],
- [use shave to make the build pretty [[default=$1]]]),,
- [enable_shave=$1]
- )
-])
-
-AC_DEFUN([SHAVE_INIT],
-[
- dnl you can tweak the default value of enable_shave
- m4_if([$2], [enable], [_SHAVE_ARG_ENABLE(yes)], [_SHAVE_ARG_ENABLE(no)])
-
- if test x"$enable_shave" = xyes; then
- dnl where can we find the shave scripts?
- m4_if([$1],,
- [shavedir="$ac_pwd"],
- [shavedir="$ac_pwd/$1"])
- AC_SUBST(shavedir)
-
- dnl make is now quiet
- AC_SUBST([MAKEFLAGS], [-s])
- AC_SUBST([AM_MAKEFLAGS], ['`test -z $V && echo -s`'])
-
- dnl we need sed
- AC_CHECK_PROG(SED,sed,sed,false)
-
- dnl substitute libtool
- SHAVE_SAVED_LIBTOOL=$LIBTOOL
- LIBTOOL="${SHELL} ${shavedir}/shave-libtool '${SHAVE_SAVED_LIBTOOL}'"
- AC_SUBST(LIBTOOL)
-
- dnl substitute cc/cxx
- SHAVE_SAVED_CC=$CC
- SHAVE_SAVED_CXX=$CXX
- SHAVE_SAVED_FC=$FC
- SHAVE_SAVED_F77=$F77
- SHAVE_SAVED_OBJC=$OBJC
- CC="${SHELL} ${shavedir}/shave cc ${SHAVE_SAVED_CC}"
- CXX="${SHELL} ${shavedir}/shave cxx ${SHAVE_SAVED_CXX}"
- FC="${SHELL} ${shavedir}/shave fc ${SHAVE_SAVED_FC}"
- F77="${SHELL} ${shavedir}/shave f77 ${SHAVE_SAVED_F77}"
- OBJC="${SHELL} ${shavedir}/shave objc ${SHAVE_SAVED_OBJC}"
- AC_SUBST(CC)
- AC_SUBST(CXX)
- AC_SUBST(FC)
- AC_SUBST(F77)
- AC_SUBST(OBJC)
-
- V=@
- else
- V=1
- fi
- Q='$(V:1=)'
- AC_SUBST(V)
- AC_SUBST(Q)
-])
-
diff --git a/plugins/imdiag/imdiag.c b/plugins/imdiag/imdiag.c
index 9602f50d..4359cda1 100644
--- a/plugins/imdiag/imdiag.c
+++ b/plugins/imdiag/imdiag.c
@@ -213,7 +213,6 @@ doInjectMsg(int iNum)
MsgSetInputName(pMsg, pInputName);
MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);
pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
- pMsg->bParseHOSTNAME = 1;
MsgSetRcvFrom(pMsg, pRcvDummy);
CHKiRet(MsgSetRcvFromIP(pMsg, pRcvIPDummy));
CHKiRet(submitMsg(pMsg));
diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
index 7c588f90..7cfde940 100644
--- a/plugins/imfile/imfile.c
+++ b/plugins/imfile/imfile.c
@@ -107,7 +107,6 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine)
MsgSetTAG(pMsg, pInfo->pszTag, pInfo->lenTag);
pMsg->iFacility = LOG_FAC(pInfo->iFacility);
pMsg->iSeverity = LOG_PRI(pInfo->iSeverity);
- pMsg->bParseHOSTNAME = 0;
CHKiRet(submitMsg(pMsg));
finalize_it:
RETiRet;
diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c
index 7994c5eb..c59ce04f 100644
--- a/plugins/imklog/imklog.c
+++ b/plugins/imklog/imklog.c
@@ -111,7 +111,6 @@ enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity)
MsgSetTAG(pMsg, pszTag, ustrlen(pszTag));
pMsg->iFacility = LOG_FAC(iFacility);
pMsg->iSeverity = LOG_PRI(iSeverity);
- pMsg->bParseHOSTNAME = 0;
CHKiRet(submitMsg(pMsg));
finalize_it:
diff --git a/plugins/immark/immark.c b/plugins/immark/immark.c
index 8504f872..19f43456 100644
--- a/plugins/immark/immark.c
+++ b/plugins/immark/immark.c
@@ -42,6 +42,7 @@
#include "module-template.h"
#include "errmsg.h"
#include "msg.h"
+#include "glbl.h"
MODULE_TYPE_INPUT
@@ -50,8 +51,16 @@ MODULE_TYPE_INPUT
/* Module static data */
DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
static int iMarkMessagePeriod = DEFAULT_MARK_PERIOD;
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
/* This function is called to gather input. It must terminate only
* a) on failure (iRet set accordingly)
* b) on termination of the input module (as part of the unload process)
@@ -77,6 +86,10 @@ CODESTARTrunInput
* rgerhards, 2007-12-17
*/
CHKiRet(thrdSleep(pThrd, iMarkMessagePeriod, 0)); /* seconds, micro seconds */
+
+ if(glbl.GetGlobalInputTermState() == 1)
+ break; /* terminate input! */
+
logmsgInternal(NO_ERRCODE, LOG_INFO, (uchar*)"-- MARK --", MARK);
}
finalize_it:
@@ -106,6 +119,7 @@ ENDmodExit
BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
ENDqueryEtryPt
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
@@ -119,9 +133,9 @@ BEGINmodInit()
CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"markmessageperiod", 0, eCmdHdlrInt, NULL, &iMarkMessagePeriod, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
-/*
- * vi:set ai:
+/* vi:set ai:
*/
diff --git a/plugins/imtemplate/imtemplate.c b/plugins/imtemplate/imtemplate.c
index 366408a0..82084745 100644
--- a/plugins/imtemplate/imtemplate.c
+++ b/plugins/imtemplate/imtemplate.c
@@ -231,49 +231,25 @@ CODESTARTrunInput
* logs an error message as syslogd, just as printf, e.g.
* errmsg.LogError(NO_ERRCODE, "Error %d occured during %s", 1, "test");
*
- * There are several ways how a message can be enqueued. This part of the
- * interface is currently underspecified. Have a look at the function definitions
- * in syslogd.c (sorry, folks...).
- *
- * If you received a full syslog message that must be decoded by a message
- * parser, parseAndSubmitMessage() is the way to go. It's not just a funny name
- * but also a quite some legacy. Consequently, its interface is, ummm, not
- * well designed.
- * parseAndSubmitMessage((char*)fromHost, (char*) pRcvBuf, lenRcvd, bParseHost);
- * fromHost
- * is the host that we received the message from (a string)
- * pRcvBuf
- * is the received (to-be-decoded) message
- * lenRcvd
- * is the length of the received message. Please note that pRcvBuf is
- * NOT a standard C-string. Most importantly it is NOT expected to be
- * \0-terminated. Thus the lenght is vitally imporant (if it is wrong,
- * rsyslogd will probably segfault).
- * bParseHost
- * is a boolean (0-no, 1-yes). It tells the parser whether or not
- * a hostname should be parsed from the message. This is important
- * for sources that are known not to provide a hostname.
- * Use define MSG_PARSE_HOSTNAME and MSG_DONT_PARSE_HOSTNAME
- *
- * Another, more elaborate, way is to create the message object ourselves and
- * pass it to the rule engine. That way is more appropriate if the message
+ * To submit the message to the queue engine, we must create the message
+ * object and fill it with data. If it contains a syslog message that must
+ * be parsed, we can add a flag that requests parsing. Otherwise, we must
+ * fill the properties ourselves. That is appropriate if the message
* does not need to be parsed, for example when reading text (log) files. In that way,
* we can set the message properties as of our liking. This is how it works:
*
msg_t *pMsg;
CHKiRet(msgConstruct(&pMsg));
- MsgSetUxTradMsg(pMsg, msg);
MsgSetRawMsg(pMsg, msg);
MsgSetHOSTNAME(pMsg, LocalHostName);
MsgSetTAG(pMsg, "rsyslogd:");
pMsg->iFacility = LOG_FAC(pri);
pMsg->iSeverity = LOG_PRI(pri);
- pMsg->bParseHOSTNAME = 0;
flags |= INTERNAL_MSG;
logmsg(pMsg, flags); / * some time, CHKiRet() will work here, too [today NOT!] * /
*
- * Note that UxTradMsg is a wild construct. For the time being, set it to
- * the raw message text. I am hard thinking at dropping that beast at all...
+ * NOTE: for up-to-date usage samples, see the other provided input modules.
+ * A good starting point is probably imuxsock.
*
* This example probably does not set all message properties (but the ones
* that are of practical importance). If you need all, check msg.h. Use
diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c
index a393cf96..12946c39 100644
--- a/plugins/imudp/imudp.c
+++ b/plugins/imudp/imudp.c
@@ -32,6 +32,9 @@
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
+#if HAVE_SYS_EPOLL_H
+# include <sys/epoll.h>
+#endif
#include "rsyslog.h"
#include "dirty.h"
#include "net.h"
@@ -44,6 +47,7 @@
#include "parser.h"
#include "datetime.h"
#include "prop.h"
+#include "ruleset.h"
#include "unicode-helper.h"
MODULE_TYPE_INPUT
@@ -57,6 +61,7 @@ DEFobjCurrIf(glbl)
DEFobjCurrIf(net)
DEFobjCurrIf(datetime)
DEFobjCurrIf(prop)
+DEFobjCurrIf(ruleset)
static int iMaxLine; /* maximum UDP message size supported */
static time_t ttLastDiscard = 0; /* timestamp when a message from a non-permitted sender was last discarded
@@ -65,13 +70,14 @@ static time_t ttLastDiscard = 0; /* timestamp when a message from a non-permitte
*/
static int *udpLstnSocks = NULL; /* Internet datagram sockets, first element is nbr of elements
* read-only after init(), but beware of restart! */
+static ruleset_t **udpRulesets = NULL; /* ruleset to be used with sockets in question (entry 0 is empty) */
static uchar *pszBindAddr = NULL; /* IP to bind socket to */
static uchar *pRcvBuf = NULL; /* receive buffer (for a single packet). We use a global and alloc
* it so that we can check available memory in willRun() and request
* termination if we can not get it. -- rgerhards, 2007-12-27
*/
static prop_t *pInputName = NULL; /* our inputName currently is always "imudp", and this will hold it */
-// TODO: static ruleset_t *pBindRuleset = NULL; /* ruleset to bind listener to (use system default if unspecified) */
+static ruleset_t *pBindRuleset = NULL; /* ruleset to bind listener to (use system default if unspecified) */
#define TIME_REQUERY_DFLT 2
static int iTimeRequery = TIME_REQUERY_DFLT;/* how often is time to be queried inside tight recv loop? 0=always */
@@ -90,6 +96,7 @@ static rsRetVal addListner(void __attribute__((unused)) *pVal, uchar *pNewVal)
int *newSocks;
int *tmpSocks;
int iSrc, iDst;
+ ruleset_t **tmpRulesets;
/* check which address to bind to. We could do this more compact, but have not
* done so in order to make the code more readable. -- rgerhards, 2007-12-27
@@ -110,26 +117,39 @@ static rsRetVal addListner(void __attribute__((unused)) *pVal, uchar *pNewVal)
if(udpLstnSocks == NULL) {
/* esay, we can just replace it */
udpLstnSocks = newSocks;
+ CHKmalloc(udpRulesets = (ruleset_t**) malloc(sizeof(ruleset_t*) * (newSocks[0] + 1)));
+ for(iDst = 1 ; iDst < newSocks[0] ; ++iDst)
+ udpRulesets[iDst] = pBindRuleset;
} else {
/* we need to add them */
- if((tmpSocks = malloc(sizeof(int) * (1 + newSocks[0] + udpLstnSocks[0]))) == NULL) {
- dbgprintf("out of memory trying to allocate udp listen socket array\n");
+ tmpSocks = (int*) malloc(sizeof(int) * (1 + newSocks[0] + udpLstnSocks[0]));
+ tmpRulesets = (ruleset_t**) malloc(sizeof(ruleset_t*) * (1 + newSocks[0] + udpLstnSocks[0]));
+ if(tmpSocks == NULL || tmpRulesets == NULL) {
+ DBGPRINTF("out of memory trying to allocate udp listen socket array\n");
/* in this case, we discard the new sockets but continue with what we
* already have
*/
free(newSocks);
+ free(tmpSocks);
+ free(tmpRulesets);
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
} else {
/* ready to copy */
iDst = 1;
- for(iSrc = 1 ; iSrc <= udpLstnSocks[0] ; ++iSrc)
+ for(iSrc = 1 ; iSrc <= udpLstnSocks[0] ; ++iSrc) {
tmpSocks[iDst++] = udpLstnSocks[iSrc];
- for(iSrc = 1 ; iSrc <= newSocks[0] ; ++iSrc)
+ tmpRulesets[iDst++] = udpRulesets[iSrc];
+ }
+ for(iSrc = 1 ; iSrc <= newSocks[0] ; ++iSrc) {
tmpSocks[iDst++] = newSocks[iSrc];
+ tmpRulesets[iDst++] = pBindRuleset;
+ }
tmpSocks[0] = udpLstnSocks[0] + newSocks[0];
free(newSocks);
free(udpLstnSocks);
udpLstnSocks = tmpSocks;
+ free(udpRulesets);
+ udpRulesets = tmpRulesets;
}
}
}
@@ -141,7 +161,6 @@ finalize_it:
}
-#if 0 /* TODO: implement when tehre is time, requires restructure of socket array! */
/* accept a new ruleset to bind. Checks if it exists and complains, if not */
static rsRetVal
setRuleset(void __attribute__((unused)) *pVal, uchar *pszName)
@@ -162,7 +181,6 @@ finalize_it:
free(pszName); /* no longer needed */
RETiRet;
}
-#endif
/* This function is a helper to runInput. I have extracted it
@@ -181,7 +199,7 @@ finalize_it:
*/
static inline rsRetVal
processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted,
- uchar *fromHost, uchar *fromHostFQDN, uchar *fromHostIP)
+ uchar *fromHost, uchar *fromHostFQDN, uchar *fromHostIP, ruleset_t *pRuleset)
{
DEFiRet;
int iNbrTimeUsed;
@@ -205,7 +223,7 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted,
DBGPRINTF("INET socket error: %d = %s.\n", errno, errStr);
errmsg.LogError(errno, NO_ERRCODE, "recvfrom inet");
}
- ABORT_FINALIZE(RS_RET_ERR);
+ ABORT_FINALIZE(RS_RET_ERR); // this most often is NOT an error, state is not checked by caller!
}
if(lenRcvBuf == 0)
@@ -251,12 +269,11 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted,
CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime));
MsgSetRawMsg(pMsg, (char*)pRcvBuf, lenRcvBuf);
MsgSetInputName(pMsg, pInputName);
+ MsgSetRuleset(pMsg, pRuleset);
MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);
pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
- pMsg->bParseHOSTNAME = 1;
MsgSetRcvFromStr(pMsg, fromHost, ustrlen(fromHost), &propFromHost);
CHKiRet(MsgSetRcvFromIPStr(pMsg, fromHostIP, ustrlen(fromHostIP), &propFromHostIP));
-dbgprintf("XXX: submitting msg to queue\n");
CHKiRet(submitMsg(pMsg));
}
}
@@ -271,20 +288,82 @@ finalize_it:
}
-/* This function is called to gather input.
- * Note that udpLstnSocks must be non-NULL because otherwise we would not have
- * indicated that we want to run (or we have a programming error ;)). -- rgerhards, 2008-10-02
- * rgerhards, 2008-10-07: I have implemented a very simple, yet in most cases probably
- * highly efficient "name caching". Before querying a name, I now check if the name to be
- * queried is the same as the one queried in the last message processed. If that is the
- * case, we can simple re-use the previous value. This algorithm works quite well with
- * few sender, especially if they emit messages in bursts. The more sender and the
- * more intermixed messages arrive, the less this algorithm works, but the overhead
- * is so minimal (a simple memory compare and move) that this does not hurt. Even
- * with a real name lookup cache, this optimization here is useful as it is quicker
- * than even a cache lookup).
+/* This function implements the main reception loop. Depending on the environment,
+ * we either use the traditional (but slower) select() or the Linux-specific epoll()
+ * interface. ./configure settings control which one is used.
+ * rgerhards, 2009-09-09
*/
-BEGINrunInput
+#if HAVE_EPOLL_CREATE1
+#define NUM_EPOLL_EVENTS 10
+rsRetVal rcvMainLoop()
+{
+ DEFiRet;
+ int nfds;
+ int efd;
+ int i;
+ struct sockaddr_storage frominetPrev;
+ int bIsPermitted;
+ uchar fromHost[NI_MAXHOST];
+ uchar fromHostIP[NI_MAXHOST];
+ uchar fromHostFQDN[NI_MAXHOST];
+ struct epoll_event *udpEPollEvt = NULL;
+ struct epoll_event currEvt[NUM_EPOLL_EVENTS];
+ char errStr[1024];
+
+ /* start "name caching" algo by making sure the previous system indicator
+ * is invalidated.
+ */
+ bIsPermitted = 0;
+ memset(&frominetPrev, 0, sizeof(frominetPrev));
+
+ CHKmalloc(udpEPollEvt = calloc(udpLstnSocks[0], sizeof(struct epoll_event)));
+
+ efd = epoll_create1(EPOLL_CLOEXEC);
+ if(efd < 0) {
+ DBGPRINTF("epoll_create1() could not create fd\n");
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ /* fill the epoll set - we need to do this only once, as the set
+ * can not change dyamically.
+ */
+ for (i = 0; i < *udpLstnSocks; i++) {
+ if (udpLstnSocks[i+1] != -1) {
+ udpEPollEvt[i].events = EPOLLIN | EPOLLET;
+ udpEPollEvt[i].data.u64 = i+1;
+ if(epoll_ctl(efd, EPOLL_CTL_ADD, udpLstnSocks[i+1], &(udpEPollEvt[i])) < 0) {
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ errmsg.LogError(errno, NO_ERRCODE, "epoll_ctrl failed on fd %d with %s\n",
+ udpLstnSocks[i+1], errStr);
+ }
+ }
+ }
+
+ while(1) {
+ /* wait for io to become ready */
+ nfds = epoll_wait(efd, currEvt, NUM_EPOLL_EVENTS, -1);
+ DBGPRINTF("imudp: epoll_wait() returned with %d fds\n", nfds);
+
+ if(glbl.GetGlobalInputTermState() == 1)
+ break; /* terminate input! */
+
+ for(i = 0 ; i < nfds ; ++i) {
+ processSocket(udpLstnSocks[currEvt[i].data.u64], &frominetPrev, &bIsPermitted,
+ fromHost, fromHostFQDN, fromHostIP, udpRulesets[currEvt[i].data.u64]);
+ }
+ }
+
+finalize_it:
+ if(udpEPollEvt != NULL)
+ free(udpEPollEvt);
+
+ RETiRet;
+}
+#else /* #if HAVE_EPOLL_CREATE1 */
+/* this is the code for the select() interface */
+rsRetVal rcvMainLoop()
+{
+ DEFiRet;
int maxfds;
int nfds;
int i;
@@ -294,16 +373,13 @@ BEGINrunInput
uchar fromHost[NI_MAXHOST];
uchar fromHostIP[NI_MAXHOST];
uchar fromHostFQDN[NI_MAXHOST];
-CODESTARTrunInput
+
/* start "name caching" algo by making sure the previous system indicator
* is invalidated.
*/
bIsPermitted = 0;
memset(&frominetPrev, 0, sizeof(frominetPrev));
- /* this is an endless loop - it is terminated when the thread is
- * signalled to do so. This, however, is handled by the framework,
- * right into the sleep below.
- */
+
while(1) {
/* Add the Unix Domain Sockets to the list of read
* descriptors.
@@ -339,14 +415,28 @@ CODESTARTrunInput
for(i = 0; nfds && i < *udpLstnSocks; i++) {
if(FD_ISSET(udpLstnSocks[i+1], &readfds)) {
processSocket(udpLstnSocks[i+1], &frominetPrev, &bIsPermitted,
- fromHost, fromHostFQDN, fromHostIP);
+ fromHost, fromHostFQDN, fromHostIP, udpRulesets[i+1]);
--nfds; /* indicate we have processed one descriptor */
}
}
/* end of a run, back to loop for next recv() */
}
- return iRet;
+ RETiRet;
+}
+#endif /* #if HAVE_EPOLL_CREATE1 */
+
+/* This function is called to gather input.
+ * Note that udpLstnSocks must be non-NULL because otherwise we would not have
+ * indicated that we want to run (or we have a programming error ;)). -- rgerhards, 2008-10-02
+ */
+BEGINrunInput
+CODESTARTrunInput
+ /* this is an endless loop - it is terminated when the thread is
+ * signalled to do so. This, however, is handled by the framework,
+ * right into the sleep below.
+ */
+ iRet = rcvMainLoop();
ENDrunInput
@@ -366,9 +456,7 @@ CODESTARTwillRun
iMaxLine = glbl.GetMaxLine();
- if((pRcvBuf = malloc((iMaxLine + 1) * sizeof(char))) == NULL) {
- ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
- }
+ CHKmalloc(pRcvBuf = malloc((iMaxLine + 1) * sizeof(char)));
finalize_it:
ENDwillRun
@@ -380,6 +468,8 @@ CODESTARTafterRun
if(udpLstnSocks != NULL) {
net.closeUDPListenSockets(udpLstnSocks);
udpLstnSocks = NULL;
+ free(udpRulesets);
+ udpRulesets = NULL;
}
if(pRcvBuf != NULL) {
free(pRcvBuf);
@@ -397,6 +487,7 @@ CODESTARTmodExit
objRelease(glbl, CORE_COMPONENT);
objRelease(datetime, CORE_COMPONENT);
objRelease(prop, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
objRelease(net, LM_NET_FILENAME);
ENDmodExit
@@ -420,10 +511,6 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
free(pszBindAddr);
pszBindAddr = NULL;
}
- if(udpLstnSocks != NULL) {
- net.closeUDPListenSockets(udpLstnSocks);
- udpLstnSocks = NULL;
- }
iTimeRequery = TIME_REQUERY_DFLT;/* the default is to query only every second time */
return RS_RET_OK;
}
@@ -437,13 +524,12 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(glbl, CORE_COMPONENT));
CHKiRet(objUse(datetime, CORE_COMPONENT));
CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
CHKiRet(objUse(net, LM_NET_FILENAME));
/* register config file handlers */
- /* TODO: add - but this requires more changes, no time right now...
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"udpserverbindruleset", 0, eCmdHdlrGetWord,
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputudpserverbindruleset", 0, eCmdHdlrGetWord,
setRuleset, NULL, STD_LOADABLE_MODULE_ID));
- */
CHKiRet(omsdRegCFSLineHdlr((uchar *)"udpserverrun", 0, eCmdHdlrGetWord,
addListner, NULL, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"udpserveraddress", 0, eCmdHdlrGetWord,
diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c
index c099be56..b8546ce3 100644
--- a/plugins/imuxsock/imuxsock.c
+++ b/plugins/imuxsock/imuxsock.c
@@ -6,7 +6,7 @@
*
* File begun on 2007-12-20 by RGerhards (extracted from syslogd.c)
*
- * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007-2009 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
@@ -70,6 +70,7 @@ DEFobjCurrIf(errmsg)
DEFobjCurrIf(glbl)
DEFobjCurrIf(prop)
+static prop_t *pLocalHostIP = NULL; /* there is only one global IP for all internally-generated messages */
static prop_t *pInputName = NULL; /* our inputName currently is always "imudp", and this will hold it */
static int startIndexUxLocalSockets; /* process funix from that index on (used to
* suppress local logging. rgerhards 2005-08-01
@@ -77,8 +78,9 @@ static int startIndexUxLocalSockets; /* process funix from that index on (used t
*/
static int funixParseHost[MAXFUNIX] = { 0, }; /* should parser parse host name? read-only after startup */
static int funixFlags[MAXFUNIX] = { IGNDATE, }; /* should parser parse host name? read-only after startup */
+static int funixCreateSockPath[MAXFUNIX] = { 0, }; /* auto-creation of socket directory? */
static uchar *funixn[MAXFUNIX] = { (uchar*) _PATH_LOG }; /* read-only after startup */
-static uchar *funixHName[MAXFUNIX] = { NULL, }; /* host-name override - if set, use this instead of actual name */
+static prop_t *funixHName[MAXFUNIX] = { NULL, }; /* host-name override - if set, use this instead of actual name */
static int funixFlowCtl[MAXFUNIX] = { eFLOWCTL_NO_DELAY, }; /* flow control settings for this socket */
static int funix[MAXFUNIX] = { -1, }; /* read-only after startup */
static int nfunix = 1; /* number of Unix sockets open / read-only after startup */
@@ -89,6 +91,8 @@ static uchar *pLogSockName = NULL;
static uchar *pLogHostName = NULL; /* host name to use with this socket */
static int bUseFlowCtl = 0; /* use flow control or not (if yes, only LIGHT is used! */
static int bIgnoreTimestamp = 1; /* ignore timestamps present in the incoming message? */
+#define DFLT_bCreateSockPath 0
+static int bCreateSockPath = DFLT_bCreateSockPath; /* auto-create socket path? */
/* set the timestamp ignore / not ignore option for the system
@@ -119,29 +123,41 @@ static rsRetVal setSystemLogFlowControl(void __attribute__((unused)) *pVal, int
* rgerhards, 2007-12-20
* added capability to specify hostname for socket -- rgerhards, 2008-08-01
*/
-static rsRetVal addLstnSocketName(void __attribute__((unused)) *pVal, uchar *pNewVal)
+static rsRetVal
+addLstnSocketName(void __attribute__((unused)) *pVal, uchar *pNewVal)
{
+ DEFiRet;
+
if(nfunix < MAXFUNIX) {
if(*pNewVal == ':') {
funixParseHost[nfunix] = 1;
- }
- else {
+ } else {
funixParseHost[nfunix] = 0;
}
- funixHName[nfunix] = pLogHostName;
- pLogHostName = NULL; /* re-init for next, not freed because funixHName[] now owns it */
+ CHKiRet(prop.Construct(&(funixHName[nfunix])));
+ if(pLogHostName == NULL) {
+ CHKiRet(prop.SetString(funixHName[nfunix], glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())));
+ } else {
+ CHKiRet(prop.SetString(funixHName[nfunix], pLogHostName, ustrlen(pLogHostName)));
+ /* reset hostname for next socket */
+ free(pLogHostName);
+ pLogHostName = NULL;
+ }
+ CHKiRet(prop.ConstructFinalize(funixHName[nfunix]));
funixFlowCtl[nfunix] = bUseFlowCtl ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY;
funixFlags[nfunix] = bIgnoreTimestamp ? IGNDATE : NOFLAG;
+ funixCreateSockPath[nfunix] = bCreateSockPath;
funixn[nfunix++] = pNewVal;
- }
- else {
+ } else {
errmsg.LogError(0, NO_ERRCODE, "Out of unix socket name descriptors, ignoring %s\n",
pNewVal);
}
- return RS_RET_OK;
+finalize_it:
+ RETiRet;
}
+
/* free the funixn[] socket names - needed as cleanup on several places
* note that nfunix is NOT reset! funixn[0] is never freed, as it comes from
* the constant memory pool - and if not, it is freeed via some other pointer.
@@ -156,8 +172,7 @@ static rsRetVal discardFunixn(void)
funixn[i] = NULL;
}
if(funixHName[i] != NULL) {
- free(funixHName[i]);
- funixHName[i] = NULL;
+ prop.Destruct(&(funixHName[i]));
}
}
@@ -165,7 +180,7 @@ static rsRetVal discardFunixn(void)
}
-static int create_unix_socket(const char *path)
+static int create_unix_socket(const char *path, int bCreatePath)
{
struct sockaddr_un sunx;
int fd;
@@ -177,6 +192,9 @@ static int create_unix_socket(const char *path)
memset(&sunx, 0, sizeof(sunx));
sunx.sun_family = AF_UNIX;
+ if(bCreatePath) {
+ makeFileParentDirs((uchar*)path, strlen(path), 0755, -1, -1, 0);
+ }
(void) strncpy(sunx.sun_path, path, sizeof(sunx.sun_path));
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0 || bind(fd, (struct sockaddr *) &sunx, SUN_LEN(&sunx)) < 0 ||
@@ -190,6 +208,35 @@ static int create_unix_socket(const char *path)
}
+/* submit received message to the queue engine
+ */
+static inline rsRetVal
+SubmitMsg(uchar *pRcv, int lenRcv, int iSock)
+{
+ msg_t *pMsg;
+ DEFiRet;
+
+ /* we now create our own message object and submit it to the queue */
+ CHKiRet(msgConstruct(&pMsg));
+ MsgSetRawMsg(pMsg, (char*)pRcv, lenRcv);
+ MsgSetInputName(pMsg, pInputName);
+ MsgSetFlowControlType(pMsg, funixFlowCtl[iSock]);
+
+ if(funixParseHost[iSock]) {
+ pMsg->msgFlags = funixFlags[iSock] | NEEDS_PARSING | PARSE_HOSTNAME;
+ } else {
+ pMsg->msgFlags = funixFlags[iSock] | NEEDS_PARSING;
+ }
+
+ MsgSetRcvFrom(pMsg, funixHName[iSock]);
+ CHKiRet(MsgSetRcvFromIP(pMsg, pLocalHostIP));
+ CHKiRet(submitMsg(pMsg));
+
+finalize_it:
+ RETiRet;
+}
+
+
/* This function receives data from a socket indicated to be ready
* to receive and submits the message received for processing.
* rgerhards, 2007-12-20
@@ -224,10 +271,7 @@ static rsRetVal readSocket(int fd, int iSock)
iRcvd = recv(fd, pRcv, iMaxLine, 0);
dbgprintf("Message from UNIX socket: #%d\n", fd);
if (iRcvd > 0) {
- parseAndSubmitMessage(funixHName[iSock] == NULL ? glbl.GetLocalHostName() : funixHName[iSock],
- (uchar*)"127.0.0.1", pRcv,
- iRcvd, funixParseHost[iSock] ? (funixFlags[iSock] | PARSE_HOSTNAME) : funixFlags[iSock],
- funixFlowCtl[iSock], pInputName, NULL, 0);
+ CHKiRet(SubmitMsg(pRcv, iRcvd, iSock));
} else if (iRcvd < 0 && errno != EINTR) {
char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
@@ -308,7 +352,7 @@ CODESTARTwillRun
/* initialize and return if will run or not */
for (i = startIndexUxLocalSockets ; i < nfunix ; i++) {
- if ((funix[i] = create_unix_socket((char*) funixn[i])) != -1)
+ if ((funix[i] = create_unix_socket((char*) funixn[i], funixCreateSockPath[i])) != -1)
dbgprintf("Opened UNIX socket '%s' (fd %d).\n", funixn[i], funix[i]);
}
@@ -383,6 +427,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
nfunix = 1;
bIgnoreTimestamp = 1;
bUseFlowCtl = 0;
+ bCreateSockPath = DFLT_bCreateSockPath;
return RS_RET_OK;
}
@@ -405,6 +450,15 @@ CODEmodInit_QueryRegCFSLineHdlr
funix[i] = -1;
}
+ CHKiRet(prop.Construct(&pLocalHostIP));
+ CHKiRet(prop.SetString(pLocalHostIP, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
+ CHKiRet(prop.ConstructFinalize(pLocalHostIP));
+
+ /* now init listen socket zero, the local log socket */
+ CHKiRet(prop.Construct(&(funixHName[0])));
+ CHKiRet(prop.SetString(funixHName[0], glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())));
+ CHKiRet(prop.ConstructFinalize(funixHName[0]));
+
/* register config file handlers */
CHKiRet(omsdRegCFSLineHdlr((uchar *)"omitlocallogging", 0, eCmdHdlrBinary,
NULL, &bOmitLocalLogging, STD_LOADABLE_MODULE_ID));
@@ -416,6 +470,8 @@ CODEmodInit_QueryRegCFSLineHdlr
NULL, &pLogHostName, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketflowcontrol", 0, eCmdHdlrBinary,
NULL, &bUseFlowCtl, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputunixlistensocketcreatepath", 0, eCmdHdlrBinary,
+ NULL, &bCreateSockPath, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"addunixlistensocket", 0, eCmdHdlrGetWord,
addLstnSocketName, NULL, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
diff --git a/runtime/msg.c b/runtime/msg.c
index d28ee350..dd541337 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -632,7 +632,6 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis)
/* initialize members in ORDER they appear in structure (think "cache line"!) */
pM->flowCtlType = 0;
pM->bDoLock = 0;
- pM->bParseHOSTNAME = 0;
pM->iRefCount = 1;
pM->iSeverity = -1;
pM->iFacility = -1;
@@ -861,7 +860,6 @@ msg_t* MsgDup(msg_t* pOld)
pNew->iRefCount = 1;
pNew->iSeverity = pOld->iSeverity;
pNew->iFacility = pOld->iFacility;
- pNew->bParseHOSTNAME = pOld->bParseHOSTNAME;
pNew->msgFlags = pOld->msgFlags;
pNew->iProtocolVersion = pOld->iProtocolVersion;
pNew->ttGenTime = pOld->ttGenTime;
@@ -935,7 +933,7 @@ msg_t* MsgDup(msg_t* pOld)
* We do not serialize the cache properties. We re-create them when needed.
* This saves us a lot of memory. Performance is no concern, as serializing
* is a so slow operation that recration of the caches does not count. Also,
- * we do not serialize bParseHOSTNAME, as this is only a helper variable
+ * we do not serialize --currently none--, as this is only a helper variable
* during msg construction - and never again used later.
* rgerhards, 2008-01-03
*/
diff --git a/runtime/msg.h b/runtime/msg.h
index b006cbec..f7d74597 100644
--- a/runtime/msg.h
+++ b/runtime/msg.h
@@ -60,7 +60,6 @@ struct msg {
once data has entered the queue, this property is no longer needed. */
pthread_mutex_t mut;
bool bDoLock; /* use the mutex? */
- bool bParseHOSTNAME; /* should the hostname be parsed from the message? */
short iRefCount; /* reference counter (0 = unused) */
/* background: the hostname is not present on "regular" messages
* received via UNIX domain sockets from the same machine. However,
diff --git a/runtime/ruleset.c b/runtime/ruleset.c
index 5ac9a8fd..0f4bc46d 100644
--- a/runtime/ruleset.c
+++ b/runtime/ruleset.c
@@ -46,8 +46,6 @@
#include "errmsg.h"
#include "unicode-helper.h"
-static rsRetVal debugPrintAll(void); // TODO: remove!
-
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
@@ -161,13 +159,10 @@ processMsg(msg_t *pMsg)
CHKiRet(llExecFunc(&pThis->llRules, processMsgDoRules, pMsg));
finalize_it:
-
- //if(iRet == RS_RET_DISCARDMSG)
- //iRet = RS_RET_OK;
-
RETiRet;
}
+
/* Add a new rule to the end of the current rule set. We do a number
* of checks and ignore the rule if it does not pass them.
*/
diff --git a/shave-libtool.in b/shave-libtool.in
deleted file mode 100644
index 54ebd690..00000000
--- a/shave-libtool.in
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2009, Damien Lespiau <damien.lespiau@gmail.com>
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use,
-# copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following
-# conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-# OTHER DEALINGS IN THE SOFTWARE.
-
-# we need sed
-SED=@SED@
-if test -z "$SED" ; then
-SED=sed
-fi
-
-lt_unmangle ()
-{
- last_result=`echo $1 | $SED -e 's#.libs/##' -e 's#[0-9a-zA-Z_\-\.]*_la-##'`
-}
-
-# the real libtool to use
-LIBTOOL="$1"
-shift
-
-# if 1, don't print anything, the underlaying wrapper will do it
-pass_though=0
-
-# scan the arguments, keep the right ones for libtool, and discover the mode
-preserved_args=
-
-# have we seen the --tag option of libtool in the command line ?
-tag_seen=0
-
-while test "$#" -gt 0; do
- opt="$1"
- shift
-
- case $opt in
- --mode=*)
- mode=`echo $opt | $SED -e 's/[-_a-zA-Z0-9]*=//'`
- preserved_args="$preserved_args $opt"
- ;;
- -o)
- lt_output="$1"
- preserved_args="$preserved_args $opt"
- ;;
- --tag=*)
- tag_seen=1
- preserved_args="$preserved_args $opt"
- ;;
- *)
- preserved_args="$preserved_args $opt"
- ;;
- esac
-done
-
-case "$mode" in
-compile)
- # shave will be called and print the actual CC/CXX/LINK line
- preserved_args="$preserved_args --shave-mode=$mode"
- pass_though=1
- ;;
-link)
- preserved_args="$preserved_args --shave-mode=$mode"
- Q=" LINK "
- ;;
-*)
- # let's u
- # echo "*** libtool: Unimplemented mode: $mode, fill a bug report"
- ;;
-esac
-
-lt_unmangle "$lt_output"
-output=$last_result
-
-# automake does not add a --tag switch to its libtool invocation when
-# assembling a .s file and rely on libtool to infer the right action based
-# on the compiler name. As shave is using CC to hook a wrapper, libtool gets
-# confused. Let's detect these cases and add a --tag=CC option.
-tag=""
-if test $tag_seen -eq 0 -a x"$mode" = xcompile; then
- tag="--tag=CC"
-fi
-
-if test -z $V; then
- if test $pass_though -eq 0; then
- echo "$Q$output"
- fi
- $LIBTOOL --silent $tag $preserved_args
-else
- echo $LIBTOOL $tag $preserved_args
- $LIBTOOL $tag $preserved_args
-fi
diff --git a/shave.in b/shave.in
deleted file mode 100644
index afed42e1..00000000
--- a/shave.in
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2009, Damien Lespiau <damien.lespiau@gmail.com>
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use,
-# copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following
-# conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-# OTHER DEALINGS IN THE SOFTWARE.
-
-# we need sed
-SED=@SED@
-if test -z "$SED" ; then
-SED=sed
-fi
-
-lt_unmangle ()
-{
- last_result=`echo $1 | $SED -e 's#.libs/##' -e 's#[0-9a-zA-Z_\-\.]*_la-##'`
-}
-
-# the tool to wrap (cc, cxx, ar, ranlib, ..)
-tool="$1"
-shift
-
-# the reel tool (to call)
-REEL_TOOL="$1"
-shift
-
-pass_through=0
-preserved_args=
-while test "$#" -gt 0; do
- opt="$1"
- shift
-
- case $opt in
- --shave-mode=*)
- mode=`echo $opt | $SED -e 's/[-_a-zA-Z0-9]*=//'`
- ;;
- -o)
- lt_output="$1"
- preserved_args="$preserved_args $opt"
- ;;
- *)
- preserved_args="$preserved_args $opt"
- ;;
- esac
-done
-
-# mode=link is handled in the libtool wrapper
-case "$mode,$tool" in
-link,*)
- pass_through=1
- ;;
-*,cxx)
- Q=" CXX "
- ;;
-*,cc)
- Q=" CC "
- ;;
-*,fc)
- Q=" FC "
- ;;
-*,f77)
- Q=" F77 "
- ;;
-*,objc)
- Q=" OBJC "
- ;;
-*,*)
- # should not happen
- Q=" CC "
- ;;
-esac
-
-lt_unmangle "$lt_output"
-output=$last_result
-
-if test -z $V; then
- if test $pass_through -eq 0; then
- echo "$Q$output"
- fi
- $REEL_TOOL $preserved_args
-else
- echo $REEL_TOOL $preserved_args
- $REEL_TOOL $preserved_args
-fi
diff --git a/tcps_sess.c b/tcps_sess.c
index 09861ab9..5a72ea9f 100644
--- a/tcps_sess.c
+++ b/tcps_sess.c
@@ -251,12 +251,10 @@ defaultDoSubmitMessage(tcps_sess_t *pThis, struct syslogTime *stTime, time_t ttG
MsgSetInputName(pMsg, pThis->pLstnInfo->pInputName);
MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
- pMsg->bParseHOSTNAME = 1;
MsgSetRcvFrom(pMsg, pThis->fromHost);
CHKiRet(MsgSetRcvFromIP(pMsg, pThis->fromHostIP));
MsgSetRuleset(pMsg, pThis->pLstnInfo->pRuleset);
-dbgprintf("YYY: submitting msg to queue\n");
if(pMultiSub == NULL) {
CHKiRet(submitMsg(pMsg));
} else {
diff --git a/threads.c b/threads.c
index 05e6159f..a6cbc2ff 100644
--- a/threads.c
+++ b/threads.c
@@ -92,19 +92,14 @@ rsRetVal thrdTerminate(thrdInfo_t *pThis)
DEFiRet;
assert(pThis != NULL);
-#if 0 // TODO: somehow does not really work yet!
if(pThis->bNeedsCancel) {
-#endif
DBGPRINTF("request term via canceling for input thread 0x%x\n", (unsigned) pThis->thrdID);
pthread_cancel(pThis->thrdID);
-#if 0 // TODO: somehow does not really work yet!
- if(pThis->bNeedsCancel) {
} else {
DBGPRINTF("request term via SIGTTIN for input thread 0x%x\n", (unsigned) pThis->thrdID);
pthread_kill(pThis->thrdID, SIGTTIN);
}
-#endif
pthread_join(pThis->thrdID, NULL); /* wait for input thread to complete */
pThis->bIsActive = 0;
diff --git a/tools/omfile.c b/tools/omfile.c
index 9d6b3d1d..a724a695 100644
--- a/tools/omfile.c
+++ b/tools/omfile.c
@@ -89,11 +89,13 @@ typedef struct s_dynaFileCacheEntry dynaFileCacheEntry;
#define IOBUF_DFLT_SIZE 1024 /* default size for io buffers */
#define FLUSH_INTRVL_DFLT 1 /* default buffer flush interval (in seconds) */
+#define DFLT_bForceChown 0
/* globals for default values */
static int iDynaFileCacheSize = 10; /* max cache for dynamic files */
static int fCreateMode = 0644; /* mode to use when creating files */
static int fDirCreateMode = 0700; /* mode to use when creating files */
static int bFailOnChown; /* fail if chown fails? */
+static int bForceChown = DFLT_bForceChown; /* Force chown() on existing files? */
static uid_t fileUID; /* UID to be used for newly created files */
static uid_t fileGID; /* GID to be used for newly created files */
static uid_t dirUID; /* UID to be used for newly created directories */
@@ -116,6 +118,7 @@ typedef struct _instanceData {
int fDirCreateMode; /* creation mode for mkdir() */
int bCreateDirs; /* auto-create directories? */
int bSyncFile; /* should the file by sync()'ed? 1- yes, 0- no */
+ bool bForceChown; /* force chown() on existing files? */
uid_t fileUID; /* IDs for creation */
uid_t dirUID;
gid_t fileGID;
@@ -153,6 +156,7 @@ CODESTARTdbgPrintInstInfo
"\tcreate directories: %s\n"
"\tfile owner %d, group %d\n"
"\tdirectory owner %d, group %d\n"
+ "\tforce chown() for all files: %s\n"
"\tdir create mode 0%3.3o, file create mode 0%3.3o\n"
"\tfail if owner/group can not be set: %s\n",
pData->f_fname,
@@ -160,6 +164,7 @@ CODESTARTdbgPrintInstInfo
pData->bCreateDirs ? "yes" : "no",
pData->fileUID, pData->fileGID,
pData->dirUID, pData->dirGID,
+ pData->bForceChown ? "yes" : "no",
pData->fDirCreateMode, pData->fCreateMode,
pData->bFailOnChown ? "yes" : "no"
);
@@ -349,7 +354,22 @@ prepareFile(instanceData *pData, uchar *newFileName)
int fd;
DEFiRet;
- if(access((char*)newFileName, F_OK) != 0) {
+ if(access((char*)newFileName, F_OK) == 0) {
+ if(pData->bForceChown) {
+ /* Try to fix wrong ownership set by someone else. Note that this code
+ * will no longer work once we have made the $PrivDrop code fully secure.
+ * This change is based on an idea of Michael Terry, provided as part of
+ * the effort to make rsyslogd the Ubuntu default syslogd.
+ * rgerhards, 2009-09-11
+ */
+ if(chown((char*)newFileName, pData->fileUID, pData->fileGID) != 0) {
+ if(pData->bFailOnChown) {
+ int eSave = errno;
+ errno = eSave;
+ }
+ }
+ }
+ } else {
/* file does not exist, create it (and eventually parent directories */
fd = -1;
if(pData->bCreateDirs) {
@@ -370,7 +390,7 @@ prepareFile(instanceData *pData, uchar *newFileName)
pData->fCreateMode);
if(fd != -1) {
/* check and set uid/gid */
- if(pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) {
+ if(pData->bForceChown || pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) {
/* we need to set owner/group */
if(fchown(fd, pData->fileUID, pData->fileGID) != 0) {
if(pData->bFailOnChown) {
@@ -604,12 +624,26 @@ BEGINtryResume
CODESTARTtryResume
ENDtryResume
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+ /* we have nothing to do to begin a transaction */
+ENDbeginTransaction
+
+
+BEGINendTransaction
+CODESTARTendTransaction
+ if(pData->bFlushOnTXEnd) {
+ CHKiRet(strm.Flush(pData->pStrm));
+ }
+finalize_it:
+ENDendTransaction
+
+
BEGINdoAction
CODESTARTdoAction
DBGPRINTF("file to log to: %s\n", pData->f_fname);
CHKiRet(writeFile(ppString, iMsgOpts, pData));
- if(pData->bFlushOnTXEnd) {
- /* TODO v5: do this in endTransaction only! */
+ if(!bCoreSupportsBatching && pData->bFlushOnTXEnd) {
CHKiRet(strm.Flush(pData->pStrm));
}
finalize_it:
@@ -681,6 +715,7 @@ CODESTARTparseSelectorAct
pData->fDirCreateMode = fDirCreateMode;
pData->bCreateDirs = bCreateDirs;
pData->bFailOnChown = bFailOnChown;
+ pData->bForceChown = bForceChown;
pData->fileUID = fileUID;
pData->fileGID = fileGID;
pData->dirUID = dirUID;
@@ -715,6 +750,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
dirUID = -1;
dirGID = -1;
bFailOnChown = 1;
+ bForceChown = DFLT_bForceChown;
iDynaFileCacheSize = 10;
fCreateMode = 0644;
fDirCreateMode = 0700;
@@ -758,6 +794,7 @@ ENDmodExit
BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */
CODEqueryEtryPt_doHUP
ENDqueryEtryPt
@@ -768,6 +805,8 @@ CODESTARTmodInit
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(strm, CORE_COMPONENT));
+ INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
+ DBGPRINTF("omfile: %susing transactional output interface.\n", bCoreSupportsBatching ? "" : "not ");
CHKiRet(omsdRegCFSLineHdlr((uchar *)"dynafilecachesize", 0, eCmdHdlrInt, (void*) setDynaFileCacheSize, NULL, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileziplevel", 0, eCmdHdlrInt, NULL, &iZipLevel, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushinterval", 0, eCmdHdlrInt, NULL, &iFlushInterval, STD_LOADABLE_MODULE_ID));
@@ -781,6 +820,7 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(omsdRegCFSLineHdlr((uchar *)"filecreatemode", 0, eCmdHdlrFileCreateMode, NULL, &fCreateMode, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"createdirs", 0, eCmdHdlrBinary, NULL, &bCreateDirs, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"failonchownfailure", 0, eCmdHdlrBinary, NULL, &bFailOnChown, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileForceChown", 0, eCmdHdlrBinary, NULL, &bForceChown, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfileenablesync", 0, eCmdHdlrBinary, NULL, &bEnableSync, STD_LOADABLE_MODULE_ID));
CHKiRet(regCfSysLineHdlr((uchar *)"actionfiledefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszTplName, NULL));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
diff --git a/tools/syslogd.c b/tools/syslogd.c
index 165c751b..99ccd1f1 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -160,18 +160,6 @@ DEFobjCurrIf(net) /* TODO: make go away! */
static rsRetVal GlobalClassExit(void);
-#ifndef UTMP_FILE
-#ifdef UTMP_FILENAME
-#define UTMP_FILE UTMP_FILENAME
-#else
-#ifdef _PATH_UTMP
-#define UTMP_FILE _PATH_UTMP
-#else
-#define UTMP_FILE "/etc/utmp"
-#endif
-#endif
-#endif
-
#ifndef _PATH_LOGCONF
#define _PATH_LOGCONF "/etc/rsyslog.conf"
#endif
@@ -249,6 +237,8 @@ int bDropTrailingLF = 1; /* drop trailing LF's on reception? */
int iCompatibilityMode = 0; /* version we should be compatible with; 0 means sysklogd. It is
the default, so if no -c<n> option is given, we make ourselvs
as compatible to sysklogd as possible. */
+#define DFLT_bLogStatusMsgs 1
+static int bLogStatusMsgs = DFLT_bLogStatusMsgs; /* log rsyslog start/stop/HUP messages? */
static int bDebugPrintTemplateList = 1;/* output template list in debug mode? */
static int bDebugPrintCfSysLineHandlerList = 1;/* output cfsyslinehandler list in debug mode? */
static int bDebugPrintModuleList = 1;/* output module list in debug mode? */
@@ -256,6 +246,7 @@ uchar cCCEscapeChar = '\\';/* character to be used to start an escape sequence f
int bEscapeCCOnRcv = 1; /* escape control characters on reception: 0 - no, 1 - yes */
static int bErrMsgToStderr = 1; /* print error messages to stderr (in addition to everything else)? */
int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */
+int bAbortOnUncleanConfig = 0; /* abort run (rather than starting with partial config) if there was any issue in conf */
int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */
int iActExecOnceInterval = 0; /* execute action once every nn seconds */
/* end global config file state variables */
@@ -333,6 +324,7 @@ getFIOPName(unsigned iFIOP)
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
cCCEscapeChar = '#';
+ bLogStatusMsgs = DFLT_bLogStatusMsgs;
bActExecWhenPrevSusp = 0;
iActExecOnceInterval = 0;
bDebugPrintTemplateList = 1;
@@ -340,6 +332,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
bDebugPrintModuleList = 1;
bEscapeCCOnRcv = 1; /* default is to escape control characters */
bReduceRepeatMsgs = 0;
+ bAbortOnUncleanConfig = 0;
free(pszMainMsgQFName);
pszMainMsgQFName = NULL;
iMainMsgQueueSize = 10000;
@@ -520,52 +513,21 @@ void untty(void)
#endif
-/* Take a raw input line, decode the message, and print the message
- * on the appropriate log files.
- * rgerhards 2004-11-08: Please note
- * that this function does only a partial decoding. At best, it splits
- * the PRI part. No further decode happens. The rest is done in
- * logmsg().
- * Added the iSource parameter so that we know if we have to parse
- * HOSTNAME or not. rgerhards 2004-11-16.
- * changed parameter iSource to bParseHost. For details, see comment in
- * printchopped(). rgerhards 2005-10-06
- * rgerhards: 2008-03-06: added "flags" to allow an input module to specify
- * flags, most importantly to request ignoring the messages' timestamp.
- *
- * rgerhards, 2008-03-19:
- * I added an additional calling parameter to permit specifying the flow
- * control capability of the source.
- *
- * rgerhards, 2008-05-16:
- * I added an additional calling parameter (hnameIP) to enable specifying the IP
- * of a remote host.
- *
- * rgerhards, 2008-09-11:
- * Interface change: added new parameter "InputName", permits the input to provide
- * a string that identifies it. May be NULL, but must be a valid char* pointer if
- * non-NULL.
- *
- * rgerhards, 2008-10-06:
- * Interface change: added new parameter "stTime", which enables the caller to provide
- * a timestamp that is to be used as timegenerated instead of the current system time.
- * This is meant to facilitate performance optimization. Some inputs support such modes.
- * If stTime is NULL, the current system time is used.
- *
- * rgerhards, 2008-10-09:
- * interface change: bParseHostname removed, now in flags
+/* This takes a received message that must be decoded and submits it to
+ * the main message queue. This is a legacy function which is being provided
+ * to aid older input plugins that do not support message creation via
+ * the new interfaces themselves. It is not recommended to use this
+ * function for new plugins. -- rgerhards, 2009-10-12
*/
-static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int flags, flowControl_t flowCtlType,
+rsRetVal
+parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int flags, flowControl_t flowCtlType,
prop_t *pInputName, struct syslogTime *stTime, time_t ttGenTime)
{
- DEFiRet;
- register uchar *p;
- int pri;
+ prop_t *pProp = NULL;
msg_t *pMsg;
- prop_t *propFromHost = NULL;
- prop_t *propFromHostIP = NULL;
+ DEFiRet;
- /* Now it is time to create the message object (rgerhards) */
+ /* we now create our own message object and submit it to the queue */
if(stTime == NULL) {
CHKiRet(msgConstruct(&pMsg));
} else {
@@ -573,278 +535,21 @@ static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int f
}
if(pInputName != NULL)
MsgSetInputName(pMsg, pInputName);
+ MsgSetRawMsg(pMsg, (char*)msg, len);
MsgSetFlowControlType(pMsg, flowCtlType);
- MsgSetRawMsgWOSize(pMsg, (char*)msg);
-
- /* test for special codes */
- pri = DEFUPRI;
- p = msg;
- if (*p == '<') {
- pri = 0;
- while (isdigit((int) *++p))
- {
- pri = 10 * pri + (*p - '0');
- }
- if (*p == '>')
- ++p;
- }
- if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
- pri = DEFUPRI;
- pMsg->iFacility = LOG_FAC(pri);
- pMsg->iSeverity = LOG_PRI(pri);
-
- /* Now we look at the HOSTNAME. That is a bit complicated...
- * If we have a locally received message, it does NOT
- * contain any hostname information in the message itself.
- * As such, the HOSTNAME is the same as the system that
- * the message was received from (that, for obvious reasons,
- * being the local host). rgerhards 2004-11-16
- */
- if((pMsg->msgFlags & PARSE_HOSTNAME) == 0)
- MsgSetHOSTNAME(pMsg, hname, ustrlen(hname));
- MsgSetRcvFromStr(pMsg, hname, ustrlen(hname), &propFromHost);
- CHKiRet(MsgSetRcvFromIPStr(pMsg, hnameIP, ustrlen(hnameIP), &propFromHostIP));
- MsgSetAfterPRIOffs(pMsg, p - msg);
- prop.Destruct(&propFromHost);
- prop.Destruct(&propFromHostIP);
+ pMsg->msgFlags = flags | NEEDS_PARSING;
- logmsg(pMsg, flags);
+ MsgSetRcvFromStr(pMsg, hname, ustrlen(hname), &pProp);
+ CHKiRet(prop.Destruct(&pProp));
+ CHKiRet(MsgSetRcvFromIPStr(pMsg, hnameIP, ustrlen(hnameIP), &pProp));
+ CHKiRet(prop.Destruct(&pProp));
+ CHKiRet(submitMsg(pMsg));
finalize_it:
RETiRet;
}
-/* This takes a received message that must be decoded and submits it to
- * the main message queue. The function calls the necessary parser.
- *
- * rgerhards, 2006-11-30: I have greatly changed this function. Formerly,
- * it tried to reassemble multi-part messages, which is a legacy stock
- * sysklogd concept. In essence, that was that messages not ending with
- * \0 were glued together. As far as I can see, this is a sysklogd
- * specific feature and, from looking at the code, seems to be used
- * pretty seldom (if at all). I remove this now, not the least because it is totally
- * incompatible with upcoming IETF syslog standards. If you experience
- * strange behaviour with messages beeing split across multiple lines,
- * this function here might be the place to look at.
- *
- * Some previous history worth noting:
- * I added the "iSource" parameter. This is needed to distinguish between
- * messages that have a hostname in them (received from the internet) and
- * those that do not have (most prominently /dev/log). rgerhards 2004-11-16
- * And now I removed the "iSource" parameter and changed it to be "bParseHost",
- * because all that it actually controls is whether the host is parsed or not.
- * For rfc3195 support, we needed to modify the algo for host parsing, so we can
- * no longer rely just on the source (rfc3195d forwarded messages arrive via
- * unix domain sockets but contain the hostname). rgerhards, 2005-10-06
- *
- * rgerhards, 2008-02-18:
- * This function was previously called "printchopped"() and has been renamed
- * as part of the effort to create a clean internal message submission interface.
- * It also has been adopted to our usual calling interface, but currently does
- * not provide any useful return states. But we now have the hook and things can
- * improve in the future. <-- TODO!
- *
- * rgerhards, 2008-03-19:
- * I added an additional calling parameter to permit specifying the flow
- * control capability of the source.
- *
- * rgerhards, 2008-05-16:
- * I added an additional calling parameter (hnameIP) to enable specifying the IP
- * of a remote host.
- *
- * rgerhards, 2008-09-11:
- * Interface change: added new parameter "InputName", permits the input to provide
- * a string that identifies it. May be NULL, but must be a valid char* pointer if
- * non-NULL.
- *
- * rgerhards, 2008-10-06:
- * Interface change: added new parameter "stTime", which enables the caller to provide
- * a timestamp that is to be used as timegenerated instead of the current system time.
- * This is meant to facilitate performance optimization. Some inputs support such modes.
- * If stTime is NULL, the current system time is used.
- *
- * rgerhards, 2008-10-09:
- * interface change: bParseHostname removed, now in flags
- */
-rsRetVal
-parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int flags, flowControl_t flowCtlType,
- prop_t *pInputName, struct syslogTime *stTime, time_t ttGenTime)
-{
- DEFiRet;
- register int iMsg;
- uchar *pMsg;
- uchar *pData;
- uchar *pEnd;
- int iMaxLine;
- uchar *tmpline = NULL;
-# ifdef USE_NETZIP
- uchar *deflateBuf = NULL;
- uLongf iLenDefBuf;
-# endif
-
- assert(hname != NULL);
- assert(hnameIP != NULL);
- assert(msg != NULL);
- assert(len >= 0);
-
- /* we first allocate work buffers large enough to hold the configured maximum
- * size of a message. Over time, we should change this to a more optimal way, i.e.
- * by calling the function with the actual length of the message to be parsed.
- * rgerhards, 2008-09-02
- *
- * TODO: optimize buffer handling */
- iMaxLine = glbl.GetMaxLine();
- CHKmalloc(tmpline = malloc(sizeof(uchar) * (iMaxLine + 1)));
-
- /* we first check if we have a NUL character at the very end of the
- * message. This seems to be a frequent problem with a number of senders.
- * So I have now decided to drop these NULs. However, if they are intentional,
- * that may cause us some problems, e.g. with syslog-sign. On the other hand,
- * current code always has problems with intentional NULs (as it needs to escape
- * them to prevent problems with the C string libraries), so that does not
- * really matter. Just to be on the save side, we'll log destruction of such
- * NULs in the debug log.
- * rgerhards, 2007-09-14
- */
- if(*(msg + len - 1) == '\0') {
- DBGPRINTF("dropped NUL at very end of message\n");
- len--;
- }
-
- /* then we check if we need to drop trailing LFs, which often make
- * their way into syslog messages unintentionally. In order to remain
- * compatible to recent IETF developments, we allow the user to
- * turn on/off this handling. rgerhards, 2007-07-23
- */
- if(bDropTrailingLF && *(msg + len - 1) == '\n') {
- DBGPRINTF("dropped LF at very end of message (DropTrailingLF is set)\n");
- len--;
- }
-
- iMsg = 0; /* initialize receiving buffer index */
- pMsg = tmpline; /* set receiving buffer pointer */
- pData = msg; /* set source buffer pointer */
- pEnd = msg + len; /* this is one off, which is intensional */
-
-# ifdef USE_NETZIP
- /* we first need to check if we have a compressed record. If so,
- * we must decompress it.
- */
- if(len > 0 && *msg == 'z') { /* compressed data present? (do NOT change order if conditions!) */
- /* we have compressed data, so let's deflate it. We support a maximum
- * message size of iMaxLine. If it is larger, an error message is logged
- * and the message is dropped. We do NOT try to decompress larger messages
- * as such might be used for denial of service. It might happen to later
- * builds that such functionality be added as an optional, operator-configurable
- * feature.
- */
- int ret;
- iLenDefBuf = iMaxLine;
- CHKmalloc(deflateBuf = malloc(sizeof(uchar) * (iMaxLine + 1)));
- ret = uncompress((uchar *) deflateBuf, &iLenDefBuf, (uchar *) msg+1, len-1);
- DBGPRINTF("Compressed message uncompressed with status %d, length: new %ld, old %d.\n",
- ret, (long) iLenDefBuf, len-1);
- /* Now check if the uncompression worked. If not, there is not much we can do. In
- * that case, we log an error message but ignore the message itself. Storing the
- * compressed text is dangerous, as it contains control characters. So we do
- * not do this. If someone would like to have a copy, this code here could be
- * modified to do a hex-dump of the buffer in question. We do not include
- * this functionality right now.
- * rgerhards, 2006-12-07
- */
- if(ret != Z_OK) {
- errmsg.LogError(0, NO_ERRCODE, "Uncompression of a message failed with return code %d "
- "- enable debug logging if you need further information. "
- "Message ignored.", ret);
- FINALIZE; /* unconditional exit, nothing left to do... */
- }
- pData = deflateBuf;
- pEnd = deflateBuf + iLenDefBuf;
- }
-# else /* ifdef USE_NETZIP */
- /* in this case, we still need to check if the message is compressed. If so, we must
- * tell the user we can not accept it.
- */
- if(len > 0 && *msg == 'z') {
- errmsg.LogError(0, NO_ERRCODE, "Received a compressed message, but rsyslogd does not have compression "
- "support enabled. The message will be ignored.");
- FINALIZE;
- }
-# endif /* ifdef USE_NETZIP */
-
- while(pData < pEnd) {
- if(iMsg >= iMaxLine) {
- /* emergency, we now need to flush, no matter if
- * we are at end of message or not...
- */
- if(iMsg == iMaxLine) {
- *(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
- printline(hname, hnameIP, tmpline, flags, flowCtlType, pInputName, stTime, ttGenTime);
- } else {
- /* This case in theory never can happen. If it happens, we have
- * a logic error. I am checking for it, because if I would not,
- * we would address memory invalidly with the code above. I
- * do not care much about this case, just a debug log entry
- * (I couldn't do any more smart things anyway...).
- * rgerhards, 2007-9-20
- */
- DBGPRINTF("internal error: iMsg > max msg size in printchopped()\n");
- }
- FINALIZE; /* in this case, we are done... nothing left we can do */
- }
- if(*pData == '\0') { /* guard against \0 characters... */
- /* changed to the sequence (somewhat) proposed in
- * draft-ietf-syslog-protocol-19. rgerhards, 2006-11-30
- */
- if(iMsg + 3 < iMaxLine) { /* do we have space? */
- *(pMsg + iMsg++) = cCCEscapeChar;
- *(pMsg + iMsg++) = '0';
- *(pMsg + iMsg++) = '0';
- *(pMsg + iMsg++) = '0';
- } /* if we do not have space, we simply ignore the '\0'... */
- /* log an error? Very questionable... rgerhards, 2006-11-30 */
- /* decided: we do not log an error, it won't help... rger, 2007-06-21 */
- ++pData;
- } else if(bEscapeCCOnRcv && iscntrl((int) *pData)) {
- /* we are configured to escape control characters. Please note
- * that this most probably break non-western character sets like
- * Japanese, Korean or Chinese. rgerhards, 2007-07-17
- * Note: sysklogd logs octal values only for DEL and CCs above 127.
- * For others, it logs ^n where n is the control char converted to an
- * alphabet character. We like consistency and thus escape it to octal
- * in all cases. If someone complains, we may change the mode. At least
- * we known now what's going on.
- * rgerhards, 2007-07-17
- */
- if(iMsg + 3 < iMaxLine) { /* do we have space? */
- *(pMsg + iMsg++) = cCCEscapeChar;
- *(pMsg + iMsg++) = '0' + ((*pData & 0300) >> 6);
- *(pMsg + iMsg++) = '0' + ((*pData & 0070) >> 3);
- *(pMsg + iMsg++) = '0' + ((*pData & 0007));
- } /* again, if we do not have space, we ignore the char - see comment at '\0' */
- ++pData;
- } else {
- *(pMsg + iMsg++) = *pData++;
- }
- }
-
- *(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
-
- /* typically, we should end up here! */
- printline(hname, hnameIP, tmpline, flags, flowCtlType, pInputName, stTime, ttGenTime);
-
-finalize_it:
- if(tmpline != NULL)
- free(tmpline);
-# ifdef USE_NETZIP
- if(deflateBuf != NULL)
- free(deflateBuf);
-# endif
- RETiRet;
-}
-
-
/* this is a special function used to submit an error message. This
* function is also passed to the runtime library as the generic error
* message handler. -- rgerhards, 2008-04-17
@@ -892,7 +597,6 @@ logmsgInternal(int iErr, int pri, uchar *msg, int flags)
}
pMsg->iFacility = LOG_FAC(pri);
pMsg->iSeverity = LOG_PRI(pri);
- pMsg->bParseHOSTNAME = 0;
flags |= INTERNAL_MSG;
/* we now check if we should print internal messages out to stderr. This was
@@ -1703,7 +1407,7 @@ die(int sig)
thrdTerminateAll();
/* and THEN send the termination log message (see long comment above) */
- if (sig) {
+ if(sig && bLogStatusMsgs) {
(void) snprintf(buf, sizeof(buf) / sizeof(char),
" [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
"\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"]" " exiting on signal %d.",
@@ -2284,6 +1988,14 @@ init(void)
ABORT_FINALIZE(RS_RET_VALIDATION_RUN);
}
+ if(bAbortOnUncleanConfig && bHadConfigErr) {
+ fprintf(stderr, "rsyslogd: $AbortOnUncleanConfig is set, and config is not clean.\n"
+ "Check error log for details, fix errors and restart. As a last\n"
+ "resort, you may want to remove $AbortOnUncleanConfig to permit a\n"
+ "startup with a dirty config.\n");
+ exit(2);
+ }
+
/* switch the message object to threaded operation, if necessary */
if(MainMsgQueType == QUEUETYPE_DIRECT || iMainMsgQueueNumWorkers > 1) {
MsgEnableThreadSafety();
@@ -2365,11 +2077,13 @@ init(void)
/* we now generate the startup message. It now includes everything to
* identify this instance. -- rgerhards, 2005-08-17
*/
- snprintf(bufStartUpMsg, sizeof(bufStartUpMsg)/sizeof(char),
- " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
- "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] start",
- (int) myPid);
- logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)bufStartUpMsg, 0);
+ if(bLogStatusMsgs) {
+ snprintf(bufStartUpMsg, sizeof(bufStartUpMsg)/sizeof(char),
+ " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
+ "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] start",
+ (int) myPid);
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)bufStartUpMsg, 0);
+ }
finalize_it:
RETiRet;
@@ -2514,11 +2228,14 @@ doHUP(void)
{
char buf[512];
- snprintf(buf, sizeof(buf) / sizeof(char),
- " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION
- "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] rsyslogd was HUPed",
- (int) myPid);
- errno = 0;
+ if(bLogStatusMsgs) {
+ snprintf(buf, sizeof(buf) / sizeof(char),
+ " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION
+ "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] rsyslogd was HUPed",
+ (int) myPid);
+ errno = 0;
+ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0);
+ }
ruleset.IterateAllActions(doHUPActions, NULL);
}
@@ -2632,6 +2349,7 @@ static rsRetVal loadBuildInModules(void)
* is that rsyslog will terminate if we can not register our built-in config commands.
* This, I think, is the right thing to do. -- rgerhards, 2007-07-31
*/
+ CHKiRet(regCfSysLineHdlr((uchar *)"logrsyslogstatusmessages", 0, eCmdHdlrBinary, NULL, &bLogStatusMsgs, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeretrycount", 0, eCmdHdlrInt, NULL, &glbliActionResumeRetryCount, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"defaultruleset", 0, eCmdHdlrGetWord, setDefaultRuleset, NULL, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"ruleset", 0, eCmdHdlrGetWord, setCurrRuleset, NULL, NULL));
@@ -2657,6 +2375,7 @@ static rsRetVal loadBuildInModules(void)
CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesaveonshutdown", 0, eCmdHdlrBinary, NULL, &bMainMsgQSaveOnShutdown, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimebegin", 0, eCmdHdlrInt, NULL, &iMainMsgQueueDeqtWinFromHr, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimeend", 0, eCmdHdlrInt, NULL, &iMainMsgQueueDeqtWinToHr, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"abortonuncleanconfig", 0, eCmdHdlrBinary, NULL, &bAbortOnUncleanConfig, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgreduction", 0, eCmdHdlrBinary, NULL, &bReduceRepeatMsgs, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlywhenpreviousissuspended", 0, eCmdHdlrBinary, NULL, &bActExecWhenPrevSusp, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlyonceeveryinterval", 0, eCmdHdlrInt, NULL, &iActExecOnceInterval, NULL));