summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog38
-rw-r--r--Makefile.am12
-rw-r--r--action.c1
-rw-r--r--configure.ac32
-rw-r--r--doc/Makefile.am3
-rw-r--r--doc/imptcp.html80
-rw-r--r--doc/imuxsock.html2
-rw-r--r--doc/index.html2
-rw-r--r--doc/manual.html6
-rw-r--r--doc/omudpspoof.html23
-rw-r--r--doc/omuxsock.html43
-rw-r--r--doc/pmlastmsg.html4
-rw-r--r--doc/professional_support.html27
-rw-r--r--doc/rsconf1_rulesetparser.html8
-rw-r--r--doc/rsyslog_conf_modules.html4
-rw-r--r--doc/status.html70
-rw-r--r--plugins/imptcp/Makefile.am6
-rw-r--r--plugins/imptcp/imptcp.c1174
-rw-r--r--plugins/omudpspoof/omudpspoof.c9
-rw-r--r--plugins/omuxsock/Makefile.am8
-rw-r--r--plugins/omuxsock/omuxsock.c315
-rw-r--r--plugins/pmlastmsg/pmlastmsg.c1
-rw-r--r--plugins/pmrfc3164sd/pmrfc3164sd.c10
-rw-r--r--runtime/conf.c2
-rw-r--r--runtime/rsyslog.h5
-rw-r--r--tcps_sess.c11
-rw-r--r--tests/Makefile.am24
-rwxr-xr-xtests/complex1.sh2
-rwxr-xr-xtests/diag.sh1
-rwxr-xr-xtests/imptcp_addtlframedelim.sh14
-rwxr-xr-xtests/imptcp_conndrop.sh16
-rwxr-xr-xtests/imptcp_large.sh16
-rwxr-xr-xtests/imtcp_addtlframedelim.sh14
-rwxr-xr-xtests/imtcp_conndrop.sh16
-rw-r--r--tests/tcpflood.c109
-rw-r--r--tests/testsuites/imptcp_addtlframedelim.conf13
-rw-r--r--tests/testsuites/imptcp_conndrop.conf16
-rw-r--r--tests/testsuites/imptcp_large.conf16
-rw-r--r--tests/testsuites/imtcp_addtlframedelim.conf13
-rw-r--r--tests/testsuites/imtcp_conndrop.conf16
-rw-r--r--tests/testsuites/uxsock_simple.conf10
-rwxr-xr-xtests/uxsock_simple.sh31
-rw-r--r--tests/uxsockrcvr.c157
-rw-r--r--tools/syslogd.c5
44 files changed, 2184 insertions, 201 deletions
diff --git a/ChangeLog b/ChangeLog
index f4bdc6ae..1b6d57cc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,16 @@
- acquire /dev/log socket optionally from systemd
thanks to Lennart Poettering for this patch
---------------------------------------------------------------------------
-Version 5.5.6 [DEVEL] (rgerhards), 2010-06-??
+Version 5.5.7 [V5-BETA] (rgerhards), 2010-08-09
+- changed omudpspoof default spoof address to simplify typical use case
+ thanks to David Lang for suggesting this
+- doc bugfix: pmlastmsg doc samples had errors
+- bugfix[minor]: pmrfc3164sd had invalid name (resided in rsyslog name
+ space, what should not be the case for a contributed module)
+- added omuxsock, which permits to write message to local Unix sockets
+ this is the counterpart to imuxsock, enabling fast local forwarding
+---------------------------------------------------------------------------
+Version 5.5.6 [DEVEL] (rgerhards), 2010-07-21
- added parser modules
* pmlastmsg, which supports the notoriously malformed "last message
repeated n times" messages from some syslogd's (namely sysklogd)
@@ -19,7 +28,7 @@ Version 5.5.6 [DEVEL] (rgerhards), 2010-06-??
* RSYSLOG_TraditionalFileFormat
* RSYSLOG_ForwardFormat
* RSYSLOG_TraditionalForwardFormat
-- bugfix: mutexes used to similate atomic instructions were not destructed
+- bugfix: mutexes used to simulate atomic instructions were not destructed
- bugfix: regression caused more locking action in msg.c than necessary
- bugfix: "$ActionExecOnlyWhenPreviousIsSuspended on" was broken
- bugfix: segfault on HUP when "HUPIsRestart" was set to "on"
@@ -28,6 +37,8 @@ Version 5.5.6 [DEVEL] (rgerhards), 2010-06-??
This, in default mode, caused buffered writing to be used, what
means that it looked like no output were written or partial
lines. Thanks to Michael Biebl for pointing out this bug.
+- bugfix: programname filter in ! configuration can not be reset
+ Thanks to Kiss Gabor for the patch.
---------------------------------------------------------------------------
Version 5.5.5 [DEVEL] (rgerhards), 2010-05-20
- added new cancel-reduced action thread termination method
@@ -467,6 +478,12 @@ increase.
- increased ompgsql performance by adapting to new transactional
output module interface
---------------------------------------------------------------------------
+Version 4.7.3 [v4-devel] (rgerhards), 2010-??-??
+- added omuxsock, which permits to write message to local Unix sockets
+ this is the counterpart to imuxsock, enabling fast local forwarding
+- added imptcp, a simplified, Linux-specific and potentielly fast
+ syslog plain tcp input plugin (NOT supporting TLS!)
+---------------------------------------------------------------------------
Version 4.7.2 [v4-devel] (rgerhards), 2010-05-03
- bugfix: problems with atomic operations emulaton
replaced atomic operation emulation with new code. The previous code
@@ -474,6 +491,8 @@ Version 4.7.2 [v4-devel] (rgerhards), 2010-05-03
whole atomic operation emulation has been rewritten.
- added new $Sleep directive to hold processing for a couple of seconds
during startup
+- bugfix: programname filter in ! configuration can not be reset
+ Thanks to Kiss Gabor for the patch.
---------------------------------------------------------------------------
Version 4.7.1 [v4-devel] (rgerhards), 2010-04-22
- Solaris support much improved -- was not truely usable in 4.7.0
@@ -509,10 +528,13 @@ Version 4.7.0 [v4-devel] (rgerhards), 2010-04-14
Thanks for varmojfekoj for pointing me at this bug.
- imported changes from 4.5.6 and below
---------------------------------------------------------------------------
-Version 4.6.3 [v4-stable] (rgerhards), 2010-03-??
-- bugfix: potential segfaults during queue shutdown
- (bugs require certain non-standard settings to appear)
- Thanks to varmojfekoj for the patch [imported from 4.5.8]
+Version 4.6.4 [v4-stable] (rgerhards), 2010-08-05
+- bugfix: zero-sized (empty) messages were processed by imtcp
+ they are now dropped as they always should have been
+- bugfix: programname filter in ! configuration can not be reset
+ Thanks to Kiss Gabor for the patch.
+---------------------------------------------------------------------------
+Version 4.6.3 [v4-stable] (rgerhards), 2010-07-07
- improvded testbench
- added test with truly random data received via syslog to test
robustness
@@ -1132,7 +1154,7 @@ version before switching to this one.
- bugfix: memory leak in ompgsql
Thanks to Ken for providing the patch
---------------------------------------------------------------------------
-Version 3.22.2 [v3-stable] (rgerhards), 2009-07-??
+Version 3.22.2 [v3-stable] (rgerhards), 2010-08-05
- bugfix: comment char ('#') in literal terminated script parsing
and thus could not be used.
but tracker: http://bugzilla.adiscon.com/show_bug.cgi?id=119
@@ -1149,6 +1171,8 @@ Version 3.22.2 [v3-stable] (rgerhards), 2009-07-??
was random (but most often "on")
- bugfix: potential segfault when -p command line option was used
thanks to varmojfekoj for pointing me at this bug
+- bugfix: programname filter in ! configuration can not be reset
+ Thanks to Kiss Gabor for the patch.
---------------------------------------------------------------------------
Version 3.22.1 [v3-stable] (rgerhards), 2009-07-02
- bugfix: invalid error message issued if $inlcudeConfig was on an empty
diff --git a/Makefile.am b/Makefile.am
index a7670f64..76a38322 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -119,6 +119,10 @@ if ENABLE_OMUDPSPOOF
SUBDIRS += plugins/omudpspoof
endif
+if ENABLE_OMUXSOCK
+SUBDIRS += plugins/omuxsock
+endif
+
if ENABLE_OMTEMPLATE
SUBDIRS += plugins/omtemplate
endif
@@ -127,6 +131,10 @@ if ENABLE_IMFILE
SUBDIRS += plugins/imfile
endif
+if ENABLE_IMPTCP
+SUBDIRS += plugins/imptcp
+endif
+
if ENABLE_IMDIAG
SUBDIRS += plugins/imdiag
endif
@@ -168,8 +176,6 @@ DISTCHECK_CONFIGURE_FLAGS= --enable-gssapi_krb5 \
--enable-pgsql \
--enable-libdbi \
--enable-mysql \
- --enable-omtemplate \
- --enable-imtemplate \
--enable-relp \
--enable-rsyslogd \
--enable-mail \
@@ -181,6 +187,8 @@ DISTCHECK_CONFIGURE_FLAGS= --enable-gssapi_krb5 \
--enable-omruleset \
--enable-omprog \
--enable-imdiag \
+ --enable-imptcp \
+ --enable-omuxsock \
--enable-shave \
--enable-extended-tests \
--enable-memcheck
diff --git a/action.c b/action.c
index 32a07dcb..90ec1bf0 100644
--- a/action.c
+++ b/action.c
@@ -508,6 +508,7 @@ static rsRetVal actionDoRetry(action_t *pThis, time_t ttNow)
iRet = pThis->pMod->tryResume(pThis->pModData);
if((pThis->iResumeOKinRow > 999) && (pThis->iResumeOKinRow % 1000 == 0)) {
bTreatOKasSusp = 1;
+ pThis->iResumeOKinRow = 0;
} else {
bTreatOKasSusp = 0;
}
diff --git a/configure.ac b/configure.ac
index bfcd3f0d..9e0aad5c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([rsyslog],[5.5.5],[rsyslog@lists.adiscon.com])
+AC_INIT([rsyslog],[5.5.7],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
@@ -779,6 +779,18 @@ AC_ARG_ENABLE(imsolaris,
)
AM_CONDITIONAL(ENABLE_IMSOLARIS, test x$enable_imsolaris = xyes)
+# settings for the ptcp input module
+AC_ARG_ENABLE(imptcp,
+ [AS_HELP_STRING([--enable-imptcp],[plain tcp input module enabled @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_imptcp="yes" ;;
+ no) enable_imptcp="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-imptcp) ;;
+ esac],
+ [enable_imptcp=no]
+)
+AM_CONDITIONAL(ENABLE_IMPTCP, test x$enable_imptcp = xyes)
+
# settings for the omprog output module
AC_ARG_ENABLE(omprog,
@@ -909,6 +921,20 @@ AM_CONDITIONAL(ENABLE_GUI, test x$enable_gui = xyes)
AC_SUBST(RELP_CFLAGS)
AC_SUBST(RELP_LIBS)
+
+# settings for omuxsock
+AC_ARG_ENABLE(omuxsock,
+ [AS_HELP_STRING([--enable-omuxsock],[Compiles stdout module @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_omuxsock="yes" ;;
+ no) enable_omuxsock="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-omuxsock) ;;
+ esac],
+ [enable_omuxsock=no]
+)
+AM_CONDITIONAL(ENABLE_OMUXSOCK, test x$enable_omuxsock = xyes)
+
+
# 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.
@@ -983,8 +1009,10 @@ AC_CONFIG_FILES([Makefile \
plugins/pmlastmsg/Makefile \
plugins/omruleset/Makefile \
plugins/omdbalerting/Makefile \
+ plugins/omuxsock/Makefile \
plugins/imfile/Makefile \
plugins/imsolaris/Makefile \
+ plugins/imptcp/Makefile \
plugins/imrelp/Makefile \
plugins/imdiag/Makefile \
plugins/omtesting/Makefile \
@@ -1017,6 +1045,7 @@ echo " Unlimited select() support enabled: $enable_unlimited_select"
echo
echo "---{ input plugins }---"
echo " Klog functionality enabled: $enable_klog ($os_type)"
+echo " plain tcp input module enabled: $enable_imptcp"
echo " imdiag enabled: $enable_imdiag"
echo " file input module enabled: $enable_imfile"
echo " Solaris input module enabled: $enable_imsolaris"
@@ -1029,6 +1058,7 @@ echo " omstdout module will be compiled: $enable_omstdout"
echo " omruleset module will be compiled: $enable_omruleset"
echo " omdbalerting module will be compiled: $enable_omdbalerting"
echo " omudpspoof module will be compiled: $enable_omudpspoof"
+echo " omuxsock module will be compiled: $enable_omuxsock"
echo " output template module will be compiled: $enable_omtemplate"
echo
echo "---{ parser modules }---"
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 253fe998..d4df740a 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -40,13 +40,13 @@ html_files = \
omlibdbi.html \
imfile.html \
imtcp.html \
+ imptcp.html \
imgssapi.html \
imrelp.html \
imsolaris.html \
imuxsock.html \
imklog.html \
pmlastmsg.html \
- professional_support.html \
queues.html \
src/queueWorkerLogic.dia \
queueWorkerLogic.jpg \
@@ -109,6 +109,7 @@ html_files = \
gssapi.html \
licensing.html \
ommail.html \
+ omuxsock.html \
omrelp.html \
syslog_parsing.html \
troubleshoot.html \
diff --git a/doc/imptcp.html b/doc/imptcp.html
new file mode 100644
index 00000000..d4228185
--- /dev/null
+++ b/doc/imptcp.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head>
+<meta http-equiv="Content-Language" content="en">
+<title>Plain TCP Syslog Input Module (imptcp)</title></head>
+<body>
+<a href="rsyslog_conf_modules.html">back</a>
+
+<h1>Plain TCP Syslog Input Module</h1>
+<p><b>Module Name:&nbsp;&nbsp;&nbsp; imptcp</b></p>
+<p><b>Available since: </b>4.7.3+, 5.5.8+
+<p><b>Author: </b>Rainer Gerhards
+&lt;rgerhards@adiscon.com&gt;</p>
+<p><b>Description</b>:</p>
+<p>Provides the ability to receive syslog messages via plain TCP syslog.
+This is a specialised input plugin tailored for high performance on Linux. It will
+probably not run on any other platform. Also, it does no provide TLS services.
+Encryption can be provided by using <a href="rsyslog_stunnel.html">stunnel</a>.
+<p>This module has no limit on the number of listeners and sessions that can be used.
+<p>Multiple receivers may be configured by
+specifying $InputPTCPServerRun multiple times.
+</p>
+<p><b>Configuration Directives</b>:</p>
+<p>This plugin has config directives similar named as imtcp, but they all have <b>P</b>TCP in
+their name instead of just TCP. Note that only a subset of the parameters are supported.
+<ul>
+<li>$InputPTCPServerAddtlFrameDelimiter &lt;Delimiter&gt;<br>
+This directive permits to specify an additional frame delimiter for plain tcp syslog.
+The industry-standard specifies using the LF character as frame delimiter. Some vendors,
+notable Juniper in their NetScreen products, use an invalid frame delimiter, in Juniper's
+case the NUL character. This directive permits to specify the ASCII value of the delimiter
+in question. Please note that this does not guarantee that all wrong implementations can
+be cured with this directive. It is not even a sure fix with all versions of NetScreen,
+as I suggest the NUL character is the effect of a (common) coding error and thus will
+probably go away at some time in the future. But for the time being, the value 0 can
+probably be used to make rsyslog handle NetScreen's invalid syslog/tcp framing.
+For additional information, see this
+<a href="http://kb.monitorware.com/problem-with-netscreen-log-t1652.html">forum thread</a>.
+<br><b>If this doesn't work for you, please do not blame the rsyslog team. Instead file
+a bug report with Juniper!</b>
+<br>Note that a similar, but worse, issue exists with Cisco's IOS implementation. They do
+not use any framing at all. This is confirmed from Cisco's side, but there seems to be
+very limited interest in fixing this issue. This directive <b>can not</b> fix the Cisco bug.
+That would require much more code changes, which I was unable to do so far. Full details
+can be found at the <a href="http://www.rsyslog.com/Article321.phtml">Cisco tcp syslog anomaly</a>
+page.
+<li>$InputPTCPServerNotifyOnConnectionClose [on/<b>off</b>]<br>
+instructs imptcp to emit a message if the remote peer closes a connection.<br>
+<li>$InputPTCPServerRun &lt;port&gt;<br>
+Starts a TCP server on selected port</li>
+<li>$InputPTCPServerInputName &lt;name&gt;<br>
+Sets a name for the inputname property. If no name is set "imptcp" is used by default. Setting a
+name is not strictly necessary, but can be useful to apply filtering based on which input
+the message was received from.
+<li>$InputPTCPServerBindRuleset &lt;name&gt;<br>
+Binds specified ruleset to next server defined.
+<li>$InputPTCPServerListenIP &lt;name&gt;<br>
+On multi-homed machines, specifies to which local address the next listerner should
+be bound.
+</ul>
+<b>Caveats/Known Bugs:</b>
+<ul>
+<li>module always binds to all interfaces</li>
+</ul>
+<p><b>Sample:</b></p>
+<p>This sets up a TCP server on port 514:<br>
+</p>
+<textarea rows="15" cols="60">$ModLoad imptcp #
+needs to be done just once
+$InputPTCPServerRun 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; 2010 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 15c365a6..381374d2 100644
--- a/doc/imuxsock.html
+++ b/doc/imuxsock.html
@@ -100,7 +100,7 @@ $InputUnixListenSocketHostName /var/run/sshd/dev/log
<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
+Copyright &copy; 2008-2010 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>
diff --git a/doc/index.html b/doc/index.html
index b3b336a7..d753e2ed 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -13,7 +13,7 @@ installed documentation which exactly matches the version you have installed.
It is highly suggested to at least briefly look over these files.
<li>The <a href="http://www.rsyslog.com">rsyslog web site</a> which offers
probably every information you'll ever need (ok, just kidding...).
-<li>The <a href="http://www.rsyslog.com/doc-status.html">project status page</a> provides
+<li>The <a href="http://www.rsyslog.com/status">project status page</a> provides
information on current releases
<li>and the <a href="troubleshoot.html">troubleshooting guide</a> hopefully helps if
things do not immediately work out
diff --git a/doc/manual.html b/doc/manual.html
index b9085daf..882af031 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -14,13 +14,13 @@ replacement. Its <a href="features.html">
advanced features</a> make it suitable for enterprise-class, <a href="rsyslog_tls.html">encryption protected syslog</a>
relay chains while at the same time being very easy to setup for the
novice user. And as we know what enterprise users really need, there is
-also <a href="professional_support.html">professional
+also <a href="http://www.rsyslog.com/professional-services">professional
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.5.5 (devel branch) of rsyslog.</b>
-Visit the <i><a href="http://www.rsyslog.com/doc-status.html">rsyslog status page</a></i></b>
+<p><b>This documentation is for version 5.5.7 (beta branch) of rsyslog.</b>
+Visit the <i><a href="http://www.rsyslog.com/status">rsyslog status page</a></i></b>
to obtain current version information and project status.
</p><p><b>If you like rsyslog, you might
want to lend us a helping hand. </b>It doesn't require a lot of
diff --git a/doc/omudpspoof.html b/doc/omudpspoof.html
index 64f83752..16cb9b13 100644
--- a/doc/omudpspoof.html
+++ b/doc/omudpspoof.html
@@ -17,10 +17,15 @@ source ports.
<p><b>Configuration Directives</b>:</p>
<ul>
<li><b>$ActionOMUDPSpoofSourceNameTemplate</b> &lt;templatename&gt;<br>
-This MUST be specified. It is the name of the template that contains a
+This is the name of the template that contains a
numerical IP address that is to be used as the source system IP address.
While it may often be a constant value, it can be generated as usual via the
-property replacer, as long as it is a valid IPv4 address.
+property replacer, as long as it is a valid IPv4 address. If not specified, the
+build-in default template RSYSLOG_omudpspoofDfltSourceTpl is used. This template is defined
+as follows:<br>
+$template RSYSLOG_omudpspoofDfltSourceTpl,"%fromhost-ip%"<br>
+So in essence, the default template spoofs the address of the system the message
+was received from. This is considered the most important use case.
<li><b>$ActionOMUDPSpoofTargetHost</b> &lt;hostname&gt;<br>
Host that the messages shall be sent to.
<li><b>$ActionUDPSpoofTargetPort</b> &lt;port&gt;<br>
@@ -42,8 +47,18 @@ equal to the start value. Default is 42000.
know via the rsyslog mailing list.
</ul>
<p><b>Sample:</b></p>
+<p>The following sample forwards all syslog messages in standard form to the
+remote server server.example.com. The original sender's address is used. We do not
+care about the source port. This example is considered the typical use case for
+omudpspoof.
+</p>
+<textarea rows="5" cols="80">$ModLoad omudpspoof
+$ActionUDPSpoofTargetHost server.example.com
+*.*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :omudpspoof:
+</textarea>
+
<p>The following sample forwards all syslog messages in unmodified form to the
-remote server server.example.com. The sender address 192.0.2.1 with the fixed
+remote server server.example.com. The sender address 192.0.2.1 with fixed
source port 514 is used.
</p>
<textarea rows="8" cols="80">$ModLoad omudpspoof
@@ -55,7 +70,7 @@ $ActionUDPSpoofSourcePortStart 514
$ActionUDPSpoofSourcePortEnd 514
*.*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :omudpspoof:;spooftemplate
</textarea>
-<p>The following sample is similar to the first, but uses as many defaults as possible.
+<p>The following sample is similar to the previous, but uses as many defaults as possible.
In that sample, a source port in the range 32000..42000 is used. The message is formatted
according to rsyslog's canned default forwarding format. Note that if any parameters
have been changed, the previously set defaults will be used!
diff --git a/doc/omuxsock.html b/doc/omuxsock.html
new file mode 100644
index 00000000..5fa569eb
--- /dev/null
+++ b/doc/omuxsock.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><title>Unix sockets output module (omuxsock) - sending syslog messages to local socket</title>
+<a href="features.html">back</a>
+</head>
+<body>
+<h1>Unix sockets Output Module (omuxsock)</h1>
+<p><b>Module Name:&nbsp;&nbsp;&nbsp; omuxsock</b></p>
+<p><b>Available since:&nbsp;&nbsp;&nbsp;</b> 4.7.3, 5.5.7</p>
+<p><b>Author: </b>Rainer Gerhards &lt;rgerhards@adiscon.com&gt;</p>
+<p><b>Description</b>:</p>
+<p>This module supports sending syslog messages to local Unix sockets.
+Thus it provided a fast message-passing interface between different rsyslog
+instances. The counterpart to omuxsock is <a href="imuxsock.html">imuxsock</a>.
+Note that the template used together with omuxsock must be suitable to be
+processed by the receiver.
+<p><b>Configuration Directives</b>:</p>
+<ul>
+<li><b>$OMUxSockSocket</b><br>
+Name of the socket to send data to. This has no default and <b>must</b>
+be set.
+</li>
+<li><b>$OMUxSockDefaultTemplate</b><br>
+This can be used to override the default template to be used together
+with omuxsock. This is primarily useful if there are many forwarding
+actions and each of them should use the same template.</li>
+</ul>
+<b>Caveats/Known Bugs:</b>
+<p>Currently, only datagram sockets are supported.
+<p><b>Sample:</b></p>
+<p>The following sample writes all messages to the "/tmp/socksample" socket.
+</p>
+<textarea rows="4" cols="80">$ModLoad omucsock
+$OMUxSockSocket /tmp/socksample
+*.* :omuxsock:
+</textarea>
+[<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; 2010 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/pmlastmsg.html b/doc/pmlastmsg.html
index 397016df..2abeac6a 100644
--- a/doc/pmlastmsg.html
+++ b/doc/pmlastmsg.html
@@ -36,10 +36,10 @@ should be used. Note that when a parser is specified, the default parser chain
is removed, so we need to specify all three parsers. We use this together with the
default ruleset.
</p>
-<textarea rows="15" cols="80">$ModLoad pmlastline # this parser is NOT a built-in module
+<textarea rows="15" cols="80">$ModLoad pmlastmsg # this parser is NOT a built-in module
# note that parser are tried in the
-# order they appear in rsyslog.conf, so put pmlastline first
+# order they appear in rsyslog.conf, so put pmlastmsg first
$RulesetParser rsyslog.lastline
# as we have removed the default parser chain, we
# need to add the default parsers as well.
diff --git a/doc/professional_support.html b/doc/professional_support.html
deleted file mode 100644
index de3ac800..00000000
--- a/doc/professional_support.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<meta http-equiv="Content-Language" content="en">
-<title>Professional Support for Rsyslog</title>
-</head>
-
-<body>
-<h1><a href="http://www.rsyslog.com/Article412.phtml">Professional Services for Rsyslog</a></h1>
-<p>Professional services are being offered by <a href="http://www.adiscon.com">Adiscon</a>, the company
-that sponsors rsyslog development. For details, please contact <a href="mailto:info%40adiscon.com">Adiscon Sales</a>.</p>
-
-<p>In an effort to keep the documentation set clean and enable Adiscon to enhance the
-professional offerings, the actual
-<a href="http://www.rsyslog.com/Article412.phtml">rsyslog service offering</a>
-has been moved to a
-<a href="http://www.rsyslog.com/Article412.phtml">separate page</a>.
-Please follow that link for details.
-
-<p>[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
-<p><font size="2">This documentation is part of the <a href="http://www.rsyslog.com/">rsyslog</a>
-project.<br>
-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>
diff --git a/doc/rsconf1_rulesetparser.html b/doc/rsconf1_rulesetparser.html
index 84350431..ef29c2a8 100644
--- a/doc/rsconf1_rulesetparser.html
+++ b/doc/rsconf1_rulesetparser.html
@@ -9,7 +9,7 @@
<p><b>Type:</b> ruleset-specific configuration directive</p>
<p><b>Parameter Values:</b> string</p>
<p><b>Available since:</b> 5.3.4+</p>
-<p><b>Default:</b> rsyslog.rfc5424;rsyslog.rfc5425</p>
+<p><b>Default:</b> rsyslog.rfc5424 followed by rsyslog.rfc5425</p>
<p><b>Description:</b></p>
<p>
This directive permits to specify which
@@ -37,7 +37,7 @@ messages that are malformed in various ways. The route to take then is
<li>make sure you find a custom parser for that device; if there is no one, you
may consider writing one yourself (it is not that hard) or getting one written
as part of
-<a href="http://www.rsyslog.com/professional-servcies">Adiscon's professional services
+<a href="http://www.rsyslog.com/professional-services">Adiscon's professional services
for rsyslog</a>.
<li>load your custom parsers via $ModLoad
<li>create a ruleset for each malformed format; assign the custom parser to it
@@ -104,6 +104,10 @@ $UDPServerRun 10514
$InputUDPServerBindRuleset maldev2
$UDPServerRun 10515
</textarea>
+
+<p>For an example of how multiple parser can be chained (and an actual use case), please see
+the example section on the <a href="pmlastmsg.html">pmlastmsg</a> parser
+module.
<p>Note the positions of the directives. With the current config language,
<b>sequence of statements is very important</b>. This is ugly, but unfortunately
the way it currently works.
diff --git a/doc/rsyslog_conf_modules.html b/doc/rsyslog_conf_modules.html
index ef83d2ec..2a64461d 100644
--- a/doc/rsyslog_conf_modules.html
+++ b/doc/rsyslog_conf_modules.html
@@ -36,7 +36,8 @@ to message generators.
<li><a href="imfile.html">imfile</a> -&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="imtcp.html">imtcp</a> - input plugin for plain tcp syslog</li>
+<li><a href="imtcp.html">imtcp</a> - input plugin for tcp syslog</li>
+<li><a href="imptcp.html">imptcp</a> - input plugin for plain tcp syslog (no TLS but faster)</li>
<li><a href="imgssapi.html">imgssapi</a> - input plugin for plain tcp and GSS-enabled syslog</li>
<li>immark - support for mark messages</li>
<li><a href="imklog.html">imklog</a> - kernel logging</li>
@@ -63,6 +64,7 @@ SQLLite, Ingres, Oracle, mSQL)</li>
permits rsyslog to alert folks by mail if something important happens</li>
<li><a href="omoracle.html">omoracle</a> - output module for Oracle (native OCI interface)</li>
<li><a href="omudpspoof.html">omudpspoof</a> - output module sending UDP syslog messages with a spoofed address</li>
+<li><a href="omuxsock.html">omuxsock</a> - output module Unix domain sockets</li>
</ul>
<a name="pm"></a><h2>Parser Modules</h2>
diff --git a/doc/status.html b/doc/status.html
deleted file mode 100644
index 6c183868..00000000
--- a/doc/status.html
+++ /dev/null
@@ -1,70 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html><head><title>rsyslog status page</title></head>
-<body>
-<h2>rsyslog status page</h2>
-<p>This page reflects the status as of 2010-05-20.</p>
-<h2>Current Releases</h2>
-
-<p><b>development:</b> 5.5.5 [2010-05-20] -
-<a href="http://www.rsyslog.com/Article461.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-204.phtml">download</a>
-<br>
-<b>v4 development:</b> 4.7.2 [2010-05-03] -
-<a href="http://www.rsyslog.com/Article457.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-202.phtml">download</a></p>
-
-<!-- not at the moment!
-<p><b>beta:</b> 5.3.7 [2010-01-27] -
-<a href="http://www.rsyslog.com/Article437.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-192.phtml">download</a></p>
--->
-
-<p><b>v5 stable:</b> 5.4.0 [2010-03-08] -
-<a href="http://www.rsyslog.com/Article447.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-197.phtml">download</a>
-
-<br><b>v4 stable:</b> 4.6.2 [2010-03-26] -
-<a href="http://www.rsyslog.com/Article449.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-198.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> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-163.phtml">download</a>
-
-<br>v2 stable: 2.0.7 [2009-04-14] - <a href="http://www.rsyslog.com/Article362.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-154.phtml">download</a>
-<br>v0 to v2 are deprecated and no longer supported. If you absolutely do not like to
-upgrade, you may consider purchasing a
-<a href="professional_support.html">commercial rsyslog support package</a>. Just let us point
-out that it is really not a good idea to still run a v0 version.
-
-<p><a href="v3compatibility.html">If you updgrade from version 2, be sure to read the rsyslog v3
-compatibility document.</a> There are no additional compatibility concerns at this time for
-upgrading from v3 to v4. If some occur, we will post an additional compatiblity document.</p>
-<p>(<a href="version_naming.html">How are versions named?</a>)</p>
-
-<h2>Platforms</h2>
-<p>Thankfully, a number of folks have begin to build packages and
-help port rsyslog to other platforms. As such,
-<a href="http://wiki.rsyslog.com/index.php/Platforms">the
-platform list is now maintained inside the rsyslog wiki</a>.
-Platform maintainers perhaps have posted extra information there. If
-you do platform-specific work, feel free to add information to the wiki.</p>
-<p>Rsyslog is the default syslogd on almost all modern Linuxes.
-It is also available under BSD and Sun Solaris.</p>
-<h2>Additional information</h2>
-<p><b>Currently supported features are listed on the <a href="features.html">rsyslog features page</a>.</b></p>
-<ul>
-<li>The rsyslog home page is <a href="http://www.rsyslog.com">www.rsyslog.com</a>.</li>
-<li>Mailing list info can be found at <a href="http://lists.adiscon.net/mailman/listinfo/rsyslog">http://lists.adiscon.com/rsyslog</a>.</li>
-<li>The change log can be found at <a href="http://www.rsyslog.com/Topic4.phtml">
-http://www.rsyslog.com/Topic4.phtml</a>. </li>
-<li>Online documentation is available at <a href="http://www.rsyslog.com/doc">http://www.rsyslog.com/doc</a>.</li>
-<li>You may also find <a href="http://rgerhards.blogspot.com/">Rainer's blog</a>
-an interesting read.</li>
-</ul>
-<p>The project was initiated in 2003 and seriouosly begun in 2004 by
-<a href="http://www.gerhards.net/rainer">Rainer Gerhards</a>
-and is currently being maintained by him. See the <a href="history.html">history page</a> for more
-background information.</p>
-</body></html>
diff --git a/plugins/imptcp/Makefile.am b/plugins/imptcp/Makefile.am
new file mode 100644
index 00000000..bfacc884
--- /dev/null
+++ b/plugins/imptcp/Makefile.am
@@ -0,0 +1,6 @@
+pkglib_LTLIBRARIES = imptcp.la
+
+imptcp_la_SOURCES = imptcp.c
+imptcp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+imptcp_la_LDFLAGS = -module -avoid-version
+imptcp_la_LIBADD =
diff --git a/plugins/imptcp/imptcp.c b/plugins/imptcp/imptcp.c
new file mode 100644
index 00000000..9b24dbc2
--- /dev/null
+++ b/plugins/imptcp/imptcp.c
@@ -0,0 +1,1174 @@
+/* imptcp.c
+ * This is a native implementation of plain tcp. It is intentionally
+ * duplicate work (imtcp). The intent is to gain very fast and simple
+ * native ptcp support, utilizing the best interfaces Linux (no cross-
+ * platform intended!) has to offer.
+ *
+ * Note that in this module we try out some new naming conventions,
+ * so it may look a bit "different" from the other modules. We are
+ * investigating if removing prefixes can help make code more readable.
+ *
+ * File begun on 2010-08-10 by RGerhards
+ *
+ * Copyright 2007-2010 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include "rsyslog.h"
+#include "cfsysline.h"
+#include "prop.h"
+#include "dirty.h"
+#include "module-template.h"
+#include "unicode-helper.h"
+#include "glbl.h"
+#include "prop.h"
+#include "errmsg.h"
+#include "srUtils.h"
+#include "datetime.h"
+#include "ruleset.h"
+#include "msg.h"
+#include "net.h" /* for permittedPeers, may be removed when this is removed */
+
+/* the define is from tcpsrv.h, we need to find a new (but easier!!!) abstraction layer some time ... */
+#define TCPSRV_NO_ADDTL_DELIMITER -1 /* specifies that no additional delimiter is to be used in TCP framing */
+
+
+MODULE_TYPE_INPUT
+
+/* static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(glbl)
+DEFobjCurrIf(net)
+DEFobjCurrIf(prop)
+DEFobjCurrIf(datetime)
+DEFobjCurrIf(errmsg)
+DEFobjCurrIf(ruleset)
+
+
+
+/* config settings */
+typedef struct configSettings_s {
+ int bEmitMsgOnClose; /* emit an informational message on close by remote peer */
+ int iAddtlFrameDelim; /* addtl frame delimiter, e.g. for netscreen, default none */
+ uchar *pszInputName; /* value for inputname property, NULL is OK and handled by core engine */
+ uchar *lstnIP; /* which IP we should listen on? */
+ ruleset_t *pRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+} configSettings_t;
+
+static configSettings_t cs;
+
+/* data elements describing our running config */
+typedef struct ptcpsrv_s ptcpsrv_t;
+typedef struct ptcplstn_s ptcplstn_t;
+typedef struct ptcpsess_s ptcpsess_t;
+typedef struct epolld_s epolld_t;
+
+/* the ptcp server (listener) object
+ * Note that the object contains support for forming a linked list
+ * of them. It does not make sense to do this seperately.
+ */
+struct ptcpsrv_s {
+ ptcpsrv_t *pNext; /* linked list maintenance */
+ uchar *port; /* Port to listen to */
+ uchar *lstnIP; /* which IP we should listen on? */
+ int bEmitMsgOnClose;
+ int iAddtlFrameDelim;
+ uchar *pszInputName;
+ prop_t *pInputName; /* InputName in (fast to process) property format */
+ ruleset_t *pRuleset;
+ ptcplstn_t *pLstn; /* root of our listeners */
+ ptcpsess_t *pSess; /* root of our sessions */
+};
+
+/* the ptcp session object. Describes a single active session.
+ * includes support for doubly-linked list.
+ */
+struct ptcpsess_s {
+ ptcpsrv_t *pSrv; /* our server */
+ ptcpsess_t *prev, *next;
+ int sock;
+ epolld_t *epd;
+//--- from tcps_sess.h
+ int iMsg; /* index of next char to store in msg */
+ int bAtStrtOfFram; /* are we at the very beginning of a new frame? */
+ enum {
+ eAtStrtFram,
+ eInOctetCnt,
+ eInMsg
+ } inputState; /* our current state */
+ int iOctetsRemain; /* Number of Octets remaining in message */
+ TCPFRAMINGMODE eFraming;
+ uchar *pMsg; /* message (fragment) received */
+ prop_t *peerName; /* host name we received messages from */
+ prop_t *peerIP;
+//--- END from tcps_sess.h
+};
+
+
+/* the ptcp listener object. Describes a single active listener.
+ */
+struct ptcplstn_s {
+ ptcpsrv_t *pSrv; /* our server */
+ ptcplstn_t *prev, *next;
+ int sock;
+ epolld_t *epd;
+};
+
+
+/* type of object stored in epoll descriptor */
+typedef enum {
+ epolld_lstn,
+ epolld_sess
+} epolld_type_t;
+
+/* an epoll descriptor. contains all information necessary to process
+ * the result of epoll.
+ */
+struct epolld_s {
+ epolld_type_t typ;
+ void *ptr;
+ struct epoll_event ev;
+};
+
+
+/* global data */
+//static permittedPeers_t *pPermPeersRoot = NULL;
+static ptcpsrv_t *pSrvRoot = NULL;
+static int epollfd = -1; /* (sole) descriptor for epoll */
+static int iMaxLine; /* maximum size of a single message */
+/* we use a single static receive buffer, as this module is not multi-threaded. Keeping
+ * the buffer in the data segment is probably a little bit more efficient than on the stack
+ * (but at least I can't believe it will ever be less efficient ;) -- rgerhards, 2010-08-10
+ * Note that we do NOT (yet?) provide a config setting to set the buffer size. For usual
+ * syslog traffic, it should be large enough. Also keep in mind that we run under a virtual
+ * memory system, so if we do not use large parts of the buffer, that's no issue at
+ * all -- it'll just use up address space. On the other hand, it would be silly to page in
+ * or page out some data just to get space for the IO buffer.
+ */
+static char rcvBuf[128*1024];
+
+/* forward definitions */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+static rsRetVal addLstn(ptcpsrv_t *pSrv, int sock);
+
+
+/* some simple constructors/destructors */
+static void
+destructSess(ptcpsess_t *pSess)
+{
+ free(pSess->pMsg);
+ free(pSess->epd);
+ prop.Destruct(&pSess->peerName);
+ prop.Destruct(&pSess->peerIP);
+ /* TODO: make these inits compile-time switch depending: */
+ pSess->pMsg = NULL;
+ pSess->epd = NULL;
+ free(pSess);
+}
+
+static void
+destructSrv(ptcpsrv_t *pSrv)
+{
+ prop.Destruct(&pSrv->pInputName);
+ free(pSrv->port);
+ free(pSrv);
+}
+
+/****************************************** TCP SUPPORT FUNCTIONS ***********************************/
+/* We may later think about moving this into a helper library again. But the whole point
+ * so far was to keep everything related close togehter. -- rgerhards, 2010-08-10
+ */
+
+
+/* Start up a server. That means all of its listeners are created.
+ * Does NOT yet accept/process any incoming data (but binds ports). Hint: this
+ * code is to be executed before dropping privileges.
+ */
+static rsRetVal
+startupSrv(ptcpsrv_t *pSrv)
+{
+ DEFiRet;
+ int error, maxs, on = 1;
+ int sock = -1;
+ int numSocks;
+ int sockflags;
+ struct addrinfo hints, *res = NULL, *r;
+ uchar *lstnIP;
+
+ lstnIP = pSrv->lstnIP == NULL ? UCHAR_CONSTANT("") : pSrv->lstnIP;
+
+ DBGPRINTF("imptcp creating listen socket on server '%s', port %s\n", lstnIP, pSrv->port);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = glbl.GetDefPFFamily();
+ hints.ai_socktype = SOCK_STREAM;
+
+ error = getaddrinfo((char*)pSrv->lstnIP, (char*) pSrv->port, &hints, &res);
+ if(error) {
+ DBGPRINTF("error %d querying server '%s', port '%s'\n", error, pSrv->lstnIP, pSrv->port);
+ ABORT_FINALIZE(RS_RET_INVALID_PORT);
+ }
+
+ /* Count max number of sockets we may open */
+ for(maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++)
+ /* EMPTY */;
+
+ numSocks = 0; /* num of sockets counter at start of array */
+ for(r = res; r != NULL ; r = r->ai_next) {
+ sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+ if(sock < 0) {
+ if(!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT))
+ DBGPRINTF("error %d creating tcp listen socket", errno);
+ /* it is debatable if PF_INET with EAFNOSUPPORT should
+ * also be ignored...
+ */
+ continue;
+ }
+
+#ifdef IPV6_V6ONLY
+ if(r->ai_family == AF_INET6) {
+ int iOn = 1;
+ if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&iOn, sizeof (iOn)) < 0) {
+ close(sock);
+ sock = -1;
+ continue;
+ }
+ }
+#endif
+ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0 ) {
+ DBGPRINTF("error %d setting tcp socket option\n", errno);
+ close(sock);
+ sock = -1;
+ continue;
+ }
+
+ /* We use non-blocking IO! */
+ if((sockflags = fcntl(sock, F_GETFL)) != -1) {
+ sockflags |= O_NONBLOCK;
+ /* SETFL could fail too, so get it caught by the subsequent
+ * error check.
+ */
+ sockflags = fcntl(sock, F_SETFL, sockflags);
+ }
+ if(sockflags == -1) {
+ DBGPRINTF("error %d setting fcntl(O_NONBLOCK) on tcp socket", errno);
+ close(sock);
+ sock = -1;
+ continue;
+ }
+
+
+
+ /* We need to enable BSD compatibility. Otherwise an attacker
+ * could flood our log files by sending us tons of ICMP errors.
+ */
+#ifndef BSD
+ if(net.should_use_so_bsdcompat()) {
+ if (setsockopt(sock, SOL_SOCKET, SO_BSDCOMPAT,
+ (char *) &on, sizeof(on)) < 0) {
+ errmsg.LogError(errno, NO_ERRCODE, "TCP setsockopt(BSDCOMPAT)");
+ close(sock);
+ sock = -1;
+ continue;
+ }
+ }
+#endif
+
+ if( (bind(sock, r->ai_addr, r->ai_addrlen) < 0)
+#ifndef IPV6_V6ONLY
+ && (errno != EADDRINUSE)
+#endif
+ ) {
+ /* TODO: check if *we* bound the socket - else we *have* an error! */
+ DBGPRINTF("error %d while binding tcp socket", errno);
+ close(sock);
+ sock = -1;
+ continue;
+ }
+
+ if(listen(sock, 511) < 0) {
+ DBGPRINTF("tcp listen error %d, suspending\n", errno);
+ close(sock);
+ sock = -1;
+ continue;
+ }
+
+ /* if we reach this point, we were able to obtain a valid socket, so we can
+ * create our listener object. -- rgerhards, 2010-08-10
+ */
+ CHKiRet(addLstn(pSrv, sock));
+ ++numSocks;
+ }
+
+ if(numSocks != maxs)
+ DBGPRINTF("We could initialize %d TCP listen sockets out of %d we received "
+ "- this may or may not be an error indication.\n", numSocks, maxs);
+
+ if(numSocks == 0) {
+ DBGPRINTF("No TCP listen sockets could successfully be initialized");
+ ABORT_FINALIZE(RS_RET_COULD_NOT_BIND);
+ }
+
+finalize_it:
+ if(res != NULL)
+ freeaddrinfo(res);
+
+ if(iRet != RS_RET_OK) {
+ if(sock != -1)
+ close(sock);
+ }
+
+ RETiRet;
+}
+
+
+/* Set pRemHost based on the address provided. This is to be called upon accept()ing
+ * a connection request. It must be provided by the socket we received the
+ * message on as well as a NI_MAXHOST size large character buffer for the FQDN.
+ * Please see http://www.hmug.org/man/3/getnameinfo.php (under Caveats)
+ * for some explanation of the code found below. If we detect a malicious
+ * hostname, we return RS_RET_MALICIOUS_HNAME and let the caller decide
+ * on how to deal with that.
+ * rgerhards, 2008-03-31
+ */
+static rsRetVal
+getPeerNames(prop_t **peerName, prop_t **peerIP, struct sockaddr *pAddr)
+{
+ int error;
+ uchar szIP[NI_MAXHOST] = "";
+ uchar szHname[NI_MAXHOST] = "";
+ struct addrinfo hints, *res;
+
+ DEFiRet;
+
+ error = getnameinfo(pAddr, SALEN(pAddr), (char*)szIP, sizeof(szIP), NULL, 0, NI_NUMERICHOST);
+
+ if(error) {
+ DBGPRINTF("Malformed from address %s\n", gai_strerror(error));
+ strcpy((char*)szHname, "???");
+ strcpy((char*)szIP, "???");
+ ABORT_FINALIZE(RS_RET_INVALID_HNAME);
+ }
+
+ if(!glbl.GetDisableDNS()) {
+ error = getnameinfo(pAddr, SALEN(pAddr), (char*)szHname, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
+ if(error == 0) {
+ memset (&hints, 0, sizeof (struct addrinfo));
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_socktype = SOCK_STREAM;
+ /* we now do a lookup once again. This one should fail,
+ * because we should not have obtained a non-numeric address. If
+ * we got a numeric one, someone messed with DNS!
+ */
+ if(getaddrinfo((char*)szHname, NULL, &hints, &res) == 0) {
+ freeaddrinfo (res);
+ /* OK, we know we have evil, so let's indicate this to our caller */
+ snprintf((char*)szHname, NI_MAXHOST, "[MALICIOUS:IP=%s]", szIP);
+ DBGPRINTF("Malicious PTR record, IP = \"%s\" HOST = \"%s\"", szIP, szHname);
+ iRet = RS_RET_MALICIOUS_HNAME;
+ }
+ } else {
+ strcpy((char*)szHname, (char*)szIP);
+ }
+ } else {
+ strcpy((char*)szHname, (char*)szIP);
+ }
+
+ /* We now have the names, so now let's allocate memory and store them permanently. */
+ CHKiRet(prop.Construct(peerName));
+ CHKiRet(prop.SetString(*peerName, szHname, ustrlen(szHname)));
+ CHKiRet(prop.ConstructFinalize(*peerName));
+ CHKiRet(prop.Construct(peerIP));
+ CHKiRet(prop.SetString(*peerIP, szIP, ustrlen(szIP)));
+ CHKiRet(prop.ConstructFinalize(*peerIP));
+
+finalize_it:
+ RETiRet;
+}
+
+
+
+/* accept an incoming connection request
+ * rgerhards, 2008-04-22
+ */
+static rsRetVal
+AcceptConnReq(int sock, int *newSock, prop_t **peerName, prop_t **peerIP)
+{
+ int sockflags;
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof(addr);
+ int iNewSock = -1;
+
+ DEFiRet;
+
+ iNewSock = accept(sock, (struct sockaddr*) &addr, &addrlen);
+ if(iNewSock < 0) {
+ if(errno == EAGAIN || errno == EWOULDBLOCK)
+ ABORT_FINALIZE(RS_RET_NO_MORE_DATA);
+ ABORT_FINALIZE(RS_RET_ACCEPT_ERR);
+ }
+
+ CHKiRet(getPeerNames(peerName, peerIP, (struct sockaddr*) &addr));
+
+ /* set the new socket to non-blocking IO */
+ if((sockflags = fcntl(iNewSock, F_GETFL)) != -1) {
+ sockflags |= O_NONBLOCK;
+ /* SETFL could fail too, so get it caught by the subsequent
+ * error check.
+ */
+ sockflags = fcntl(iNewSock, F_SETFL, sockflags);
+ }
+ if(sockflags == -1) {
+ DBGPRINTF("error %d setting fcntl(O_NONBLOCK) on tcp socket %d", errno, iNewSock);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+
+ *newSock = iNewSock;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ /* the close may be redundant, but that doesn't hurt... */
+ if(iNewSock != -1)
+ close(iNewSock);
+ }
+
+ RETiRet;
+}
+
+
+/* This is a helper for submitting the message to the rsyslog core.
+ * It does some common processing, including resetting the various
+ * state variables to a "processed" state.
+ * Note that this function is also called if we had a buffer overflow
+ * due to a too-long message. So far, there is no indication this
+ * happened and it may be worth thinking about different handling
+ * of this case (what obviously would require a change to this
+ * function or some related code).
+ * rgerhards, 2009-04-23
+ * EXTRACT from tcps_sess.c
+ */
+static rsRetVal
+doSubmitMsg(ptcpsess_t *pThis, struct syslogTime *stTime, time_t ttGenTime, multi_submit_t *pMultiSub)
+{
+ msg_t *pMsg;
+ DEFiRet;
+
+ if(pThis->iMsg == 0) {
+ DBGPRINTF("discarding zero-sized message\n");
+ FINALIZE;
+ }
+
+ /* we now create our own message object and submit it to the queue */
+ CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime));
+ MsgSetRawMsg(pMsg, (char*)pThis->pMsg, pThis->iMsg);
+ MsgSetInputName(pMsg, pThis->pSrv->pInputName);
+ MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
+ pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
+ MsgSetRcvFrom(pMsg, pThis->peerName);
+ CHKiRet(MsgSetRcvFromIP(pMsg, pThis->peerIP));
+ MsgSetRuleset(pMsg, pThis->pSrv->pRuleset);
+
+ if(pMultiSub == NULL) {
+ CHKiRet(submitMsg(pMsg));
+ } else {
+ pMultiSub->ppMsgs[pMultiSub->nElem++] = pMsg;
+ if(pMultiSub->nElem == pMultiSub->maxElem)
+ CHKiRet(multiSubmitMsg(pMultiSub));
+ }
+
+
+finalize_it:
+ /* reset status variables */
+ pThis->bAtStrtOfFram = 1;
+ pThis->iMsg = 0;
+
+ RETiRet;
+}
+
+
+/* process the data received. As TCP is stream based, we need to process the
+ * data inside a state machine. The actual data received is passed in byte-by-byte
+ * from DataRcvd, and this function here compiles messages from them and submits
+ * the end result to the queue. Introducing this function fixes a long-term bug ;)
+ * rgerhards, 2008-03-14
+ * EXTRACT from tcps_sess.c
+ */
+static inline rsRetVal
+processDataRcvd(ptcpsess_t *pThis, char c, struct syslogTime *stTime, time_t ttGenTime, multi_submit_t *pMultiSub)
+{
+ DEFiRet;
+
+ if(pThis->inputState == eAtStrtFram) {
+ if(isdigit((int) c)) {
+ pThis->inputState = eInOctetCnt;
+ pThis->iOctetsRemain = 0;
+ pThis->eFraming = TCP_FRAMING_OCTET_COUNTING;
+ } else {
+ pThis->inputState = eInMsg;
+ pThis->eFraming = TCP_FRAMING_OCTET_STUFFING;
+ }
+ }
+
+ if(pThis->inputState == eInOctetCnt) {
+ if(isdigit(c)) {
+ pThis->iOctetsRemain = pThis->iOctetsRemain * 10 + c - '0';
+ } else { /* done with the octet count, so this must be the SP terminator */
+ DBGPRINTF("TCP Message with octet-counter, size %d.\n", pThis->iOctetsRemain);
+ if(c != ' ') {
+ errmsg.LogError(0, NO_ERRCODE, "Framing Error in received TCP message: "
+ "delimiter is not SP but has ASCII value %d.\n", c);
+ }
+ if(pThis->iOctetsRemain < 1) {
+ /* TODO: handle the case where the octet count is 0! */
+ DBGPRINTF("Framing Error: invalid octet count\n");
+ errmsg.LogError(0, NO_ERRCODE, "Framing Error in received TCP message: "
+ "invalid octet count %d.\n", pThis->iOctetsRemain);
+ } else if(pThis->iOctetsRemain > iMaxLine) {
+ /* while we can not do anything against it, we can at least log an indication
+ * that something went wrong) -- rgerhards, 2008-03-14
+ */
+ DBGPRINTF("truncating message with %d octets - max msg size is %d\n",
+ pThis->iOctetsRemain, iMaxLine);
+ errmsg.LogError(0, NO_ERRCODE, "received oversize message: size is %d bytes, "
+ "max msg size is %d, truncating...\n", pThis->iOctetsRemain, iMaxLine);
+ }
+ pThis->inputState = eInMsg;
+ }
+ } else {
+ assert(pThis->inputState == eInMsg);
+ if(pThis->iMsg >= iMaxLine) {
+ /* emergency, we now need to flush, no matter if we are at end of message or not... */
+ DBGPRINTF("error: message received is larger than max msg size, we split it\n");
+ doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
+ /* we might think if it is better to ignore the rest of the
+ * message than to treat it as a new one. Maybe this is a good
+ * candidate for a configuration parameter...
+ * rgerhards, 2006-12-04
+ */
+ }
+
+ if(( (c == '\n')
+ || ((pThis->pSrv->iAddtlFrameDelim != TCPSRV_NO_ADDTL_DELIMITER) && (c == pThis->pSrv->iAddtlFrameDelim))
+ ) && pThis->eFraming == TCP_FRAMING_OCTET_STUFFING) { /* record delimiter? */
+ doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
+ pThis->inputState = eAtStrtFram;
+ } else {
+ /* IMPORTANT: here we copy the actual frame content to the message - for BOTH framing modes!
+ * If we have a message that is larger than the max msg size, we truncate it. This is the best
+ * we can do in light of what the engine supports. -- rgerhards, 2008-03-14
+ */
+ if(pThis->iMsg < iMaxLine) {
+ *(pThis->pMsg + pThis->iMsg++) = c;
+ }
+ }
+
+ if(pThis->eFraming == TCP_FRAMING_OCTET_COUNTING) {
+ /* do we need to find end-of-frame via octet counting? */
+ pThis->iOctetsRemain--;
+ if(pThis->iOctetsRemain < 1) {
+ /* we have end of frame! */
+ doSubmitMsg(pThis, stTime, ttGenTime, pMultiSub);
+ pThis->inputState = eAtStrtFram;
+ }
+ }
+ }
+
+ RETiRet;
+}
+
+
+/* Processes the data received via a TCP session. If there
+ * is no other way to handle it, data is discarded.
+ * Input parameter data is the data received, iLen is its
+ * len as returned from recv(). iLen must be 1 or more (that
+ * is errors must be handled by caller!). iTCPSess must be
+ * the index of the TCP session that received the data.
+ * rgerhards 2005-07-04
+ * And another change while generalizing. We now return either
+ * RS_RET_OK, which means the session should be kept open
+ * or anything else, which means it must be closed.
+ * rgerhards, 2008-03-01
+ * As a performance optimization, we pick up the timestamp here. Acutally,
+ * this *is* the *correct* reception step for all the data we received, because
+ * we have just received a bunch of data! -- rgerhards, 2009-06-16
+ * EXTRACT from tcps_sess.c
+ */
+#define NUM_MULTISUB 1024
+static rsRetVal
+DataRcvd(ptcpsess_t *pThis, char *pData, size_t iLen)
+{
+ multi_submit_t multiSub;
+ msg_t *pMsgs[NUM_MULTISUB];
+ struct syslogTime stTime;
+ time_t ttGenTime;
+ char *pEnd;
+ DEFiRet;
+
+ assert(pData != NULL);
+ assert(iLen > 0);
+
+ datetime.getCurrTime(&stTime, &ttGenTime);
+ multiSub.ppMsgs = pMsgs;
+ multiSub.maxElem = NUM_MULTISUB;
+ multiSub.nElem = 0;
+
+ /* We now copy the message to the session buffer. */
+ pEnd = pData + iLen; /* this is one off, which is intensional */
+
+ while(pData < pEnd) {
+ CHKiRet(processDataRcvd(pThis, *pData++, &stTime, ttGenTime, &multiSub));
+ }
+
+ if(multiSub.nElem > 0) {
+ /* submit anything that was not yet submitted */
+ CHKiRet(multiSubmitMsg(&multiSub));
+ }
+
+finalize_it:
+ RETiRet;
+}
+#undef NUM_MULTISUB
+
+
+/****************************************** --END-- TCP SUPPORT FUNCTIONS ***********************************/
+
+
+static inline void
+initConfigSettings(void)
+{
+ cs.bEmitMsgOnClose = 0;
+ cs.iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
+ cs.pszInputName = NULL;
+ cs.pRuleset = NULL;
+ cs.lstnIP = NULL;
+}
+
+
+/* add socket to the epoll set
+ */
+static inline rsRetVal
+addEPollSock(epolld_type_t typ, void *ptr, int sock, epolld_t **pEpd)
+{
+ DEFiRet;
+ epolld_t *epd = NULL;
+
+ CHKmalloc(epd = malloc(sizeof(epolld_t)));
+ epd->typ = typ;
+ epd->ptr = ptr;
+ *pEpd = epd;
+ epd->ev.events = EPOLLIN|EPOLLET;
+ epd->ev.data.ptr = (void*) epd;
+
+ if(epoll_ctl(epollfd, EPOLL_CTL_ADD, sock, &(epd->ev)) != 0) {
+ char errStr[1024];
+ int eno = errno;
+ errmsg.LogError(0, RS_RET_EPOLL_CTL_FAILED, "os error (%d) during epoll ADD: %s",
+ eno, rs_strerror_r(eno, errStr, sizeof(errStr)));
+ ABORT_FINALIZE(RS_RET_EPOLL_CTL_FAILED);
+ }
+
+ DBGPRINTF("imptcp: added socket %d to epoll[%d] set\n", sock, epollfd);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ free(epd);
+ }
+ RETiRet;
+}
+
+
+/* remove a socket from the epoll set. Note that the epd parameter
+ * is not really required -- it is used to satisfy older kernels where
+ * epoll_ctl() required a non-NULL pointer even though the ptr is never used.
+ * For simplicity, we supply the same pointer we had when we created the
+ * event (it's simple because we have it at hand).
+ */
+static inline rsRetVal
+removeEPollSock(int sock, epolld_t *epd)
+{
+ DEFiRet;
+
+ DBGPRINTF("imptcp: removing socket %d from epoll[%d] set\n", sock, epollfd);
+
+ if(epoll_ctl(epollfd, EPOLL_CTL_DEL, sock, &(epd->ev)) != 0) {
+ char errStr[1024];
+ int eno = errno;
+ errmsg.LogError(0, RS_RET_EPOLL_CTL_FAILED, "os error (%d) during epoll DEL: %s",
+ eno, rs_strerror_r(eno, errStr, sizeof(errStr)));
+ ABORT_FINALIZE(RS_RET_EPOLL_CTL_FAILED);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* add a listener to the server
+ */
+static rsRetVal
+addLstn(ptcpsrv_t *pSrv, int sock)
+{
+ DEFiRet;
+ ptcplstn_t *pLstn;
+
+ CHKmalloc(pLstn = malloc(sizeof(ptcplstn_t)));
+ pLstn->pSrv = pSrv;
+ pLstn->sock = sock;
+
+ /* add to start of server's listener list */
+ pLstn->prev = NULL;
+ pLstn->next = pSrv->pLstn;
+ if(pSrv->pLstn != NULL)
+ pSrv->pLstn->prev = pLstn;
+ pSrv->pLstn = pLstn;
+
+ iRet = addEPollSock(epolld_lstn, pLstn, sock, &pLstn->epd);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* add a session to the server
+ */
+static rsRetVal
+addSess(ptcpsrv_t *pSrv, int sock, prop_t *peerName, prop_t *peerIP)
+{
+ DEFiRet;
+ ptcpsess_t *pSess = NULL;
+
+ CHKmalloc(pSess = malloc(sizeof(ptcpsess_t)));
+ CHKmalloc(pSess->pMsg = malloc(iMaxLine * sizeof(uchar)));
+ pSess->pSrv = pSrv;
+ pSess->sock = sock;
+ pSess->inputState = eAtStrtFram;
+ pSess->iMsg = 0;
+ pSess->bAtStrtOfFram = 1;
+ pSess->peerName = peerName;
+ pSess->peerIP = peerIP;
+
+ /* add to start of server's listener list */
+ pSess->prev = NULL;
+ pSess->next = pSrv->pSess;
+ if(pSrv->pSess != NULL)
+ pSrv->pSess->prev = pSess;
+ pSrv->pSess = pSess;
+
+ iRet = addEPollSock(epolld_sess, pSess, sock, &pSess->epd);
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* close/remove a session
+ * NOTE: we must first remove the fd from the epoll set and then close it -- else we
+ * get an error "bad file descriptor" from epoll.
+ */
+static rsRetVal
+closeSess(ptcpsess_t *pSess)
+{
+ int sock;
+ DEFiRet;
+
+ sock = pSess->sock;
+ CHKiRet(removeEPollSock(sock, pSess->epd));
+ close(sock);
+
+ /* finally unlink session from structures */
+//fprintf(stderr, "closing session %d next %p, prev %p\n", pSess->sock, pSess->next, pSess->prev);
+//DBGPRINTF("imptcp: pSess->next %p\n", pSess->next);
+//DBGPRINTF("imptcp: pSess->prev %p\n", pSess->prev);
+ if(pSess->next != NULL)
+ pSess->next->prev = pSess->prev;
+ if(pSess->prev == NULL) {
+ /* need to update root! */
+ pSess->pSrv->pSess = pSess->next;
+ } else {
+ pSess->prev->next = pSess->next;
+ }
+
+ /* unlinked, now remove structure */
+ destructSess(pSess);
+
+finalize_it:
+ DBGPRINTF("imtcp: session on socket %d closed with iRet %d.\n", sock, iRet);
+ RETiRet;
+}
+
+
+#if 0
+/* set permitted peer -- rgerhards, 2008-05-19
+ */
+static rsRetVal
+setPermittedPeer(void __attribute__((unused)) *pVal, uchar *pszID)
+{
+ DEFiRet;
+ CHKiRet(net.AddPermittedPeer(&pPermPeersRoot, pszID));
+ free(pszID); /* no longer needed, but we need to free as of interface def */
+finalize_it:
+ RETiRet;
+}
+#endif
+
+
+/* accept a new ruleset to bind. Checks if it exists and complains, if not */
+static rsRetVal setRuleset(void __attribute__((unused)) *pVal, uchar *pszName)
+{
+ ruleset_t *pRuleset;
+ rsRetVal localRet;
+ DEFiRet;
+
+ localRet = ruleset.GetRuleset(&pRuleset, pszName);
+ if(localRet == RS_RET_NOT_FOUND) {
+ errmsg.LogError(0, NO_ERRCODE, "error: ruleset '%s' not found - ignored", pszName);
+ }
+ CHKiRet(localRet);
+ cs.pRuleset = pRuleset;
+ DBGPRINTF("imptcp current bind ruleset %p: '%s'\n", pRuleset, pszName);
+
+finalize_it:
+ free(pszName); /* no longer needed */
+ RETiRet;
+}
+
+
+static rsRetVal addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVal)
+{
+ DEFiRet;
+ ptcpsrv_t *pSrv;
+
+ CHKmalloc(pSrv = malloc(sizeof(ptcpsrv_t)));
+ pSrv->pSess = NULL;
+ pSrv->pLstn = NULL;
+ pSrv->bEmitMsgOnClose = cs.bEmitMsgOnClose;
+ pSrv->port = pNewVal;
+ pSrv->iAddtlFrameDelim = cs.iAddtlFrameDelim;
+ cs.pszInputName = NULL; /* moved over to pSrv, we do not own */
+ pSrv->lstnIP = cs.lstnIP;
+ cs.lstnIP = NULL; /* moved over to pSrv, we do not own */
+ pSrv->pRuleset = cs.pRuleset;
+ pSrv->pszInputName = (cs.pszInputName == NULL) ? UCHAR_CONSTANT("imptcp") : cs.pszInputName;
+ CHKiRet(prop.Construct(&pSrv->pInputName));
+ CHKiRet(prop.SetString(pSrv->pInputName, pSrv->pszInputName, ustrlen(pSrv->pszInputName)));
+ CHKiRet(prop.ConstructFinalize(pSrv->pInputName));
+
+ /* add to linked list */
+ pSrv->pNext = pSrvRoot;
+ pSrvRoot = pSrv;
+
+ /* all config vars are auto-reset -- this also is very useful with the
+ * new config format effort (v6).
+ */
+ resetConfigVariables(NULL, NULL);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ errmsg.LogError(0, NO_ERRCODE, "error %d trying to add listener", iRet);
+ }
+ RETiRet;
+}
+
+
+/* start up all listeners
+ * This is a one-time stop once the module is set to start.
+ */
+static inline rsRetVal
+startupServers()
+{
+ DEFiRet;
+ ptcpsrv_t *pSrv;
+
+ pSrv = pSrvRoot;
+ while(pSrv != NULL) {
+ DBGPRINTF("Starting up ptcp server for port %s, name '%s'\n", pSrv->port, pSrv->pszInputName);
+ startupSrv(pSrv);
+ pSrv = pSrv->pNext;
+ }
+
+ RETiRet;
+}
+
+
+/* process new activity on listener. This means we need to accept a new
+ * connection.
+ */
+static inline rsRetVal
+lstnActivity(ptcplstn_t *pLstn)
+{
+ int newSock;
+ prop_t *peerName;
+ prop_t *peerIP;
+ rsRetVal localRet;
+ DEFiRet;
+
+ DBGPRINTF("imptcp: new connection on listen socket %d\n", pLstn->sock);
+ while(1) {
+ localRet = AcceptConnReq(pLstn->sock, &newSock, &peerName, &peerIP);
+ if(localRet == RS_RET_NO_MORE_DATA)
+ break;
+ CHKiRet(localRet);
+ CHKiRet(addSess(pLstn->pSrv, newSock, peerName, peerIP));
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* process new activity on session. This means we need to accept data
+ * or close the session.
+ */
+static inline rsRetVal
+sessActivity(ptcpsess_t *pSess)
+{
+ int lenRcv;
+ int lenBuf;
+ DEFiRet;
+
+ DBGPRINTF("imptcp: new activity on session socket %d\n", pSess->sock);
+
+ while(1) {
+ lenBuf = sizeof(rcvBuf);
+ lenRcv = recv(pSess->sock, rcvBuf, lenBuf, 0);
+
+ if(lenRcv > 0) {
+ /* have data, process it */
+ DBGPRINTF("imtcp: data(%d) on socket %d: %s\n", lenBuf, pSess->sock, rcvBuf);
+ CHKiRet(DataRcvd(pSess, rcvBuf, lenRcv));
+ } else if (lenRcv == 0) {
+ /* session was closed, do clean-up */
+ if(pSess->pSrv->bEmitMsgOnClose) {
+ uchar *peerName;
+ int lenPeer;
+ prop.GetString(pSess->peerName, &peerName, &lenPeer);
+ errmsg.LogError(0, RS_RET_PEER_CLOSED_CONN, "imptcp session %d closed by remote peer %s.\n",
+ pSess->sock, peerName);
+ }
+ CHKiRet(closeSess(pSess));
+ break;
+ } else {
+ if(errno == EAGAIN || errno == EWOULDBLOCK)
+ break;
+ DBGPRINTF("imtcp: error on session socket %d - closed.\n", pSess->sock);
+ closeSess(pSess); /* try clean-up by dropping session */
+ break;
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* This function is called to gather input.
+ */
+BEGINrunInput
+ int i;
+ int nfds;
+ struct epoll_event events[1];
+ epolld_t *epd;
+CODESTARTrunInput
+ DBGPRINTF("imptcp now beginning to process input data\n");
+ /* v5 TODO: consentual termination mode */
+ while(1) {
+ DBGPRINTF("imptcp going on epoll_wait\n");
+ nfds = epoll_wait(epollfd, events, sizeof(events)/sizeof(struct epoll_event), -1);
+ for(i = 0 ; i < nfds ; ++i) { /* support for larger batches (later, TODO) */
+ epd = (epolld_t*) events[i].data.ptr;
+ switch(epd->typ) {
+ case epolld_lstn:
+ lstnActivity((ptcplstn_t *) epd->ptr);
+ break;
+ case epolld_sess:
+ sessActivity((ptcpsess_t *) epd->ptr);
+ break;
+ default:
+ errmsg.LogError(0, RS_RET_INTERNAL_ERROR,
+ "error: invalid epolld_type_t %d after epoll", epd->typ);
+ break;
+ }
+ }
+ }
+ENDrunInput
+
+
+/* initialize and return if will run or not */
+BEGINwillRun
+CODESTARTwillRun
+ /* first apply some config settings */
+ //net.PrintAllowedSenders(2); /* TCP */
+ iMaxLine = glbl.GetMaxLine(); /* get maximum size we currently support */
+
+ if(pSrvRoot == NULL) {
+ errmsg.LogError(0, RS_RET_NO_LSTN_DEFINED, "error: no ptcp server defined, module can not run.");
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ }
+
+ if((epollfd = epoll_create1(EPOLL_CLOEXEC)) < 0) {
+ errmsg.LogError(0, RS_RET_EPOLL_CR_FAILED, "error: epoll_create() failed");
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ }
+
+ /* start up servers, but do not yet read input data */
+ CHKiRet(startupServers());
+ DBGPRINTF("imptcp started up, but not yet receiving data\n");
+finalize_it:
+ENDwillRun
+
+
+/* completely shut down a server, that means closing all of its
+ * listeners and sessions.
+ */
+static inline void
+shutdownSrv(ptcpsrv_t *pSrv)
+{
+ ptcplstn_t *pLstn, *lstnDel;
+ ptcpsess_t *pSess, *sessDel;
+
+ /* listeners */
+ pLstn = pSrv->pLstn;
+ while(pLstn != NULL) {
+ close(pLstn->sock);
+ lstnDel = pLstn;
+ pLstn = pLstn->next;
+ DBGPRINTF("imptcp shutdown listen socket %d\n", lstnDel->sock);
+ free(lstnDel->epd);
+ free(lstnDel);
+ }
+
+ /* sessions */
+ pSess = pSrv->pSess;
+ while(pSess != NULL) {
+ close(pSess->sock);
+ sessDel = pSess;
+ pSess = pSess->next;
+ DBGPRINTF("imptcp shutdown session socket %d\n", sessDel->sock);
+ destructSess(sessDel);
+ }
+}
+
+
+BEGINafterRun
+ ptcpsrv_t *pSrv, *srvDel;
+CODESTARTafterRun
+ /* do cleanup here */
+ //net.clearAllowedSenders(UCHAR_CONSTANT("TCP"));
+ /* we need to close everything that is still open */
+ pSrv = pSrvRoot;
+ while(pSrv != NULL) {
+ srvDel = pSrv;
+ pSrv = pSrv->pNext;
+ shutdownSrv(srvDel);
+ destructSrv(srvDel);
+ }
+
+ close(epollfd);
+ENDafterRun
+
+
+BEGINmodExit
+CODESTARTmodExit
+#if 0
+ if(pPermPeersRoot != NULL) {
+ net.DestructPermittedPeers(&pPermPeersRoot);
+ }
+#endif
+
+ /* release objects we used */
+ objRelease(glbl, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(datetime, CORE_COMPONENT);
+ objRelease(errmsg, CORE_COMPONENT);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+
+static rsRetVal
+resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ cs.bEmitMsgOnClose = 0;
+ cs.iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
+ free(cs.pszInputName);
+ cs.pszInputName = NULL;
+ free(cs.lstnIP);
+ cs.lstnIP = NULL;
+ return RS_RET_OK;
+}
+
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ initConfigSettings();
+ /* request objects we use */
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+ CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ /* register config file handlers */
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserverrun"), 0, eCmdHdlrGetWord,
+ addTCPListener, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpservernotifyonconnectionclose"), 0,
+ eCmdHdlrBinary, NULL, &cs.bEmitMsgOnClose, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserveraddtlframedelimiter"), 0, eCmdHdlrInt,
+ NULL, &cs.iAddtlFrameDelim, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserverinputname"), 0,
+ eCmdHdlrGetWord, NULL, &cs.pszInputName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserverlistenip"), 0,
+ eCmdHdlrGetWord, NULL, &cs.lstnIP, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputptcpserverbindruleset"), 0,
+ eCmdHdlrGetWord, setRuleset, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("resetconfigvariables"), 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+
+/* vim:set ai:
+ */
diff --git a/plugins/omudpspoof/omudpspoof.c b/plugins/omudpspoof/omudpspoof.c
index 50bc6c9a..3ead5447 100644
--- a/plugins/omudpspoof/omudpspoof.c
+++ b/plugins/omudpspoof/omudpspoof.c
@@ -381,6 +381,7 @@ ENDdoAction
BEGINparseSelectorAct
+ uchar *sourceTpl;
CODESTARTparseSelectorAct
CODE_STD_STRING_REQUESTparseSelectorAct(2)
/* first check if this config line is actually for us */
@@ -392,10 +393,8 @@ CODE_STD_STRING_REQUESTparseSelectorAct(2)
p += sizeof(":omudpspoof:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
CHKiRet(createInstance(&pData));
- if(pszSourceNameTemplate == NULL) {
- errmsg.LogError(0, NO_ERRCODE, "No $ActionOMUDPSpoofSourceNameTemplate given, can not continue with this action.");
- ABORT_FINALIZE(RS_RET_NO_SRCNAME_TPL);
- }
+ sourceTpl = (pszSourceNameTemplate == NULL) ? UCHAR_CONSTANT("RSYSLOG_omudpspoofDfltSourceTpl")
+ : pszSourceNameTemplate;
if(pszTargetHost == NULL) {
errmsg.LogError(0, NO_ERRCODE, "No $ActionOMUDPSpoofTargetHost given, can not continue with this action.");
@@ -408,7 +407,7 @@ CODE_STD_STRING_REQUESTparseSelectorAct(2)
pData->port = NULL;
else
CHKmalloc(pData->port = ustrdup(pszTargetPort));
- CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pszSourceNameTemplate), OMSR_NO_RQD_TPL_OPTS));
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(sourceTpl), OMSR_NO_RQD_TPL_OPTS));
pData->compressionLevel = iCompressionLevel;
pData->sourcePort = pData->sourcePortStart = iSourcePortStart;
pData->sourcePortEnd = iSourcePortEnd;
diff --git a/plugins/omuxsock/Makefile.am b/plugins/omuxsock/Makefile.am
new file mode 100644
index 00000000..997232d9
--- /dev/null
+++ b/plugins/omuxsock/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = omuxsock.la
+
+omuxsock_la_SOURCES = omuxsock.c
+omuxsock_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS)
+omuxsock_la_LDFLAGS = -module -avoid-version
+omuxsock_la_LIBADD =
+
+EXTRA_DIST =
diff --git a/plugins/omuxsock/omuxsock.c b/plugins/omuxsock/omuxsock.c
new file mode 100644
index 00000000..c66e63aa
--- /dev/null
+++ b/plugins/omuxsock/omuxsock.c
@@ -0,0 +1,315 @@
+/* omuxsock.c
+ * This is the implementation of datgram unix domain socket forwarding.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" message code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Copyright 2010 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include "conf.h"
+#include "srUtils.h"
+#include "template.h"
+#include "msg.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "glbl.h"
+#include "errmsg.h"
+#include "unicode-helper.h"
+
+MODULE_TYPE_OUTPUT
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+DEFobjCurrIf(errmsg)
+DEFobjCurrIf(glbl)
+
+#define INVLD_SOCK -1
+
+typedef struct _instanceData {
+ permittedPeers_t *pPermPeers;
+ uchar *sockName;
+ int sock;
+ int bIsConnected; /* are we connected to remote host? 0 - no, 1 - yes, UDP means addr resolved */
+ struct sockaddr_un addr;
+} instanceData;
+
+/* config data */
+static uchar *tplName = NULL; /* name of the default template to use */
+static uchar *sockName = NULL; /* name of the default template to use */
+
+static rsRetVal doTryResume(instanceData *pData);
+
+/* Close socket.
+ */
+static inline rsRetVal
+closeSocket(instanceData *pData)
+{
+ DEFiRet;
+ if(pData->sock != INVLD_SOCK) {
+ close(pData->sock);
+ pData->sock = INVLD_SOCK;
+ }
+pData->bIsConnected = 0; // TODO: remove this variable altogether
+ RETiRet;
+}
+
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ pData->sock = INVLD_SOCK;
+ENDcreateInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ /* final cleanup */
+ closeSocket(pData);
+ free(pData->sockName);
+ENDfreeInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ DBGPRINTF("%s", pData->sockName);
+ENDdbgPrintInstInfo
+
+
+/* Send a message via UDP
+ * rgehards, 2007-12-20
+ */
+static rsRetVal sendMsg(instanceData *pData, char *msg, size_t len)
+{
+ DEFiRet;
+ unsigned lenSent = 0;
+
+ if(pData->sock == INVLD_SOCK) {
+ CHKiRet(doTryResume(pData));
+ }
+
+ if(pData->sock != INVLD_SOCK) {
+ /* we need to track if we have success sending to the remote
+ * peer. Success is indicated by at least one sendto() call
+ * succeeding. We track this be bSendSuccess. We can not simply
+ * rely on lsent, as a call might initially work, but a later
+ * call fails. Then, lsent has the error status, even though
+ * the sendto() succeeded. -- rgerhards, 2007-06-22
+ */
+ lenSent = sendto(pData->sock, msg, len, 0, &pData->addr, sizeof(pData->addr));
+ if(lenSent == len) {
+ int eno = errno;
+ char errStr[1024];
+ DBGPRINTF("omuxsock suspending: sendto(), socket %d, error: %d = %s.\n",
+ pData->sock, eno, rs_strerror_r(eno, errStr, sizeof(errStr)));
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* open socket to remote system
+ */
+static inline rsRetVal
+openSocket(instanceData *pData)
+{
+ DEFiRet;
+ assert(pData->sock == INVLD_SOCK);
+
+ if((pData->sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
+ char errStr[1024];
+ int eno = errno;
+ DBGPRINTF("error %d creating AF_UNIX/SOCK_DGRAM: %s.\n",
+ eno, rs_strerror_r(eno, errStr, sizeof(errStr)));
+ pData->sock = INVLD_SOCK;
+ ABORT_FINALIZE(RS_RET_NO_SOCKET);
+
+ }
+
+ /* set up server address structure */
+ memset(&pData->addr, 0, sizeof(pData->addr));
+ pData->addr.sun_family = AF_UNIX;
+ strcpy(pData->addr.sun_path, (char*)pData->sockName);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ closeSocket(pData);
+ }
+ RETiRet;
+}
+
+
+
+/* try to resume connection if it is not ready
+ */
+static rsRetVal doTryResume(instanceData *pData)
+{
+ DEFiRet;
+
+ DBGPRINTF("omuxsock trying to resume\n");
+ closeSocket(pData);
+ iRet = openSocket(pData);
+
+ if(iRet != RS_RET_OK) {
+ iRet = RS_RET_SUSPENDED;
+ }
+
+ RETiRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ iRet = doTryResume(pData);
+ENDtryResume
+
+BEGINdoAction
+ char *psz = NULL; /* temporary buffering */
+ register unsigned l;
+ int iMaxLine;
+CODESTARTdoAction
+ CHKiRet(doTryResume(pData));
+
+ iMaxLine = glbl.GetMaxLine();
+
+ DBGPRINTF(" omuxsock:%s\n", pData->sockName);
+
+ psz = (char*) ppString[0];
+ l = strlen((char*) psz);
+ if((int) l > iMaxLine)
+ l = iMaxLine;
+
+ CHKiRet(sendMsg(pData, psz, l));
+
+finalize_it:
+ENDdoAction
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+
+ /* first check if this config line is actually for us */
+ if(strncmp((char*) p, ":omuxsock:", sizeof(":omuxsock:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ p += sizeof(":omuxsock:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ CHKiRet(createInstance(&pData));
+
+ /* check if a non-standard template is to be applied */
+ if(*(p-1) == ';')
+ --p;
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, 0, tplName == NULL ? UCHAR_CONSTANT("RSYSLOG_TraditionalForwardFormat")
+ : tplName ));
+
+ if(sockName == NULL) {
+ errmsg.LogError(0, RS_RET_NO_SOCK_CONFIGURED, "No output socket configured for omuxsock\n");
+ ABORT_FINALIZE(RS_RET_NO_SOCK_CONFIGURED);
+ }
+
+ pData->sockName = sockName;
+ sockName = NULL; /* pData is now owner and will fee it */
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+/* a common function to free our configuration variables - used both on exit
+ * and on $ResetConfig processing. -- rgerhards, 2008-05-16
+ */
+static inline void
+freeConfigVars(void)
+{
+ free(tplName);
+ tplName = NULL;
+ free(sockName);
+ sockName = NULL;
+}
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release what we no longer need */
+ objRelease(errmsg, CORE_COMPONENT);
+ objRelease(glbl, CORE_COMPONENT);
+
+ freeConfigVars();
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+/* Reset config variables for this module to default values.
+ * rgerhards, 2008-03-28
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ freeConfigVars();
+ return RS_RET_OK;
+}
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(errmsg, CORE_COMPONENT));
+
+ CHKiRet(regCfSysLineHdlr((uchar *)"omuxsockdefaulttemplate", 0, eCmdHdlrGetWord, NULL, &tplName, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"omuxsocksocket", 0, eCmdHdlrGetWord, NULL, &sockName, NULL));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+/* vim:set ai:
+ */
diff --git a/plugins/pmlastmsg/pmlastmsg.c b/plugins/pmlastmsg/pmlastmsg.c
index 67a742c9..275f1c1f 100644
--- a/plugins/pmlastmsg/pmlastmsg.c
+++ b/plugins/pmlastmsg/pmlastmsg.c
@@ -35,7 +35,6 @@
#include <string.h>
#include <assert.h>
#include <ctype.h>
-#include "syslogd.h"
#include "conf.h"
#include "syslogd-types.h"
#include "template.h"
diff --git a/plugins/pmrfc3164sd/pmrfc3164sd.c b/plugins/pmrfc3164sd/pmrfc3164sd.c
index bc439f3f..5598c025 100644
--- a/plugins/pmrfc3164sd/pmrfc3164sd.c
+++ b/plugins/pmrfc3164sd/pmrfc3164sd.c
@@ -1,4 +1,4 @@
-/* pmrfc3164.c
+/* pmrfc3164sd.c
* This is a parser module for RFC3164(legacy syslog)-formatted messages.
*
* NOTE: read comments in module-template.h to understand how this file
@@ -45,7 +45,7 @@
#include "unicode-helper.h"
MODULE_TYPE_PARSER
-PARSER_NAME("rsyslog.rfc3164sd")
+PARSER_NAME("contrib.rfc3164sd")
/* internal structures
*/
@@ -293,8 +293,10 @@ CODESTARTparse
CHKmalloc(pBuf = MALLOC(sizeof(uchar) * (lenMsg + 1)));
/* STRUCTURED-DATA */
- parseRFCStructuredData(&p2parse, pBuf, &lenMsg);
- MsgSetStructuredData(pMsg, (char*)pBuf);
+ if (parseRFCStructuredData(&p2parse, pBuf, &lenMsg) == 0)
+ MsgSetStructuredData(pMsg, (char*)pBuf);
+ else
+ MsgSetStructuredData(pMsg, "-");
/* The rest is the actual MSG */
MsgSetMSGoffs(pMsg, p2parse - pMsg->pszRawMsg);
diff --git a/runtime/conf.c b/runtime/conf.c
index 96d9dcab..d41f2950 100644
--- a/runtime/conf.c
+++ b/runtime/conf.c
@@ -1014,7 +1014,7 @@ static rsRetVal cflineProcessTagSelector(uchar **pline)
if(**pline != '\0' && **pline == '*' && *(*pline+1) == '\0') {
dbgprintf("resetting programname filter\n");
if(pDfltProgNameCmp != NULL) {
- CHKiRet(rsCStrSetSzStr(pDfltProgNameCmp, NULL));
+ rsCStrDestruct(&pDfltProgNameCmp);
}
} else {
dbgprintf("setting programname filter to '%s'\n", *pline);
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index a8b5d401..34eaedca 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -449,6 +449,11 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_ERR_EPOLL_CTL = -2163, /**< epol_ctll() returned with an unexpected error code */
RS_RET_TIMEOUT = -2164, /**< timeout occured during operation */
RS_RET_RCV_ERR = -2165, /**< error occured during socket rcv operation */
+ RS_RET_NO_SOCK_CONFIGURED = -2166, /**< no socket (name) was configured where one is required */
+ RS_RET_NO_LSTN_DEFINED = -2172, /**< no listener defined (e.g. inside an input module) */
+ RS_RET_EPOLL_CR_FAILED = -2173, /**< epoll_create() failed */
+ RS_RET_EPOLL_CTL_FAILED = -2174, /**< epoll_ctl() failed */
+ RS_RET_INTERNAL_ERROR = -2175, /**< rsyslogd internal error, unexpected code path reached */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
diff --git a/tcps_sess.c b/tcps_sess.c
index 1ae065fa..99af0cb8 100644
--- a/tcps_sess.c
+++ b/tcps_sess.c
@@ -239,6 +239,11 @@ defaultDoSubmitMessage(tcps_sess_t *pThis, struct syslogTime *stTime, time_t ttG
ISOBJ_TYPE_assert(pThis, tcps_sess);
+ if(pThis->iMsg == 0) {
+ DBGPRINTF("discarding zero-sized message\n");
+ FINALIZE;
+ }
+
if(pThis->DoSubmitMessage != NULL) {
pThis->DoSubmitMessage(pThis, pThis->pMsg, pThis->iMsg);
FINALIZE;
@@ -477,8 +482,10 @@ DataRcvd(tcps_sess_t *pThis, char *pData, size_t iLen)
CHKiRet(processDataRcvd(pThis, *pData++, &stTime, ttGenTime, &multiSub));
}
- /* submit anything that was not yet submitted */
- CHKiRet(multiSubmitMsg(&multiSub));
+ if(multiSub.nElem > 0) {
+ /* submit anything that was not yet submitted */
+ CHKiRet(multiSubmitMsg(&multiSub));
+ }
finalize_it:
RETiRet;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7f9d8cd5..8538140e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,6 +1,6 @@
if ENABLE_TESTBENCH
TESTRUNS = rt_init rscript
-check_PROGRAMS = $(TESTRUNS) ourtail nettester tcpflood chkseq msleep randomgen diagtalker
+check_PROGRAMS = $(TESTRUNS) ourtail nettester tcpflood chkseq msleep randomgen diagtalker uxsockrcvr
TESTS = $(TESTRUNS) cfg.sh \
arrayqueue.sh \
linkedlistqueue.sh \
@@ -13,6 +13,12 @@ TESTS = $(TESTRUNS) cfg.sh \
rulesetmultiqueue.sh \
manytcp.sh \
rsf_getenv.sh \
+ manyptcp.sh \
+ imptcp_large.sh \
+ imptcp_addtlframedelim.sh \
+ imptcp_conndrop.sh \
+ imtcp_conndrop.sh \
+ imtcp_addtlframedelim.sh \
sndrcv.sh \
sndrcv_gzip.sh \
sndrcv_udp.sh \
@@ -34,6 +40,7 @@ TESTS = $(TESTRUNS) cfg.sh \
complex1.sh \
queue-persist.sh \
pipeaction.sh \
+ uxsock_simple.sh \
execonlyonce.sh \
execonlywhenprevsuspended.sh \
execonlywhenprevsuspended2.sh \
@@ -181,6 +188,18 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \
testsuites/imtcp-multiport.conf \
manytcp.sh \
testsuites/manytcp.conf \
+ manyptcp.sh \
+ testsuites/manyptcp.conf \
+ imptcp_large.sh \
+ testsuites/imptcp_large.conf \
+ imptcp_addtlframedelim.sh \
+ testsuites/imptcp_addtlframedelim.conf \
+ imptcp_conndrop.sh \
+ testsuites/imptcp_conndrop.conf \
+ imtcp_conndrop.sh \
+ testsuites/imtcp_conndrop.conf \
+ imtcp_addtlframedelim.sh \
+ testsuites/imtcp_addtlframedelim.conf \
inputname.sh \
testsuites/inputname_imtcp.conf \
testsuites/1.inputname_imtcp_12514 \
@@ -224,6 +243,8 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \
testsuites/pipeaction.conf \
pipe_noreader.sh \
testsuites/pipe_noreader.conf \
+ uxsock_simple.sh \
+ testsuites/uxsock_simple.conf \
asynwr_simple.sh \
testsuites/asynwr_simple.conf \
asynwr_timeout.sh \
@@ -293,6 +314,7 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \
testsuites/dircreate_off.conf \
cfg.sh
+uxsockrcvr_SOURCES = uxsockrcvr.c
ourtail_SOURCES = ourtail.c
msleep_SOURCES = msleep.c
chkseq_SOURCES = chkseq.c
diff --git a/tests/complex1.sh b/tests/complex1.sh
index b3e31b30..e138bff5 100755
--- a/tests/complex1.sh
+++ b/tests/complex1.sh
@@ -12,7 +12,7 @@ source $srcdir/diag.sh init
source $srcdir/diag.sh startup complex1.conf
# send 40,000 messages of 400 bytes plus header max, via three dest ports
source $srcdir/diag.sh tcpflood -m40000 -rd400 -P129 -f5 -n3 -c15 -i1
-sleep 2 # due to large messages, we need this time for the tcp receiver to settle...
+sleep 4 # due to large messages, we need this time for the tcp receiver to settle...
source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
source $srcdir/diag.sh wait-shutdown # and wait for it to terminate
ls rsyslog.out.*.log
diff --git a/tests/diag.sh b/tests/diag.sh
index 3d072880..2f307750 100755
--- a/tests/diag.sh
+++ b/tests/diag.sh
@@ -121,6 +121,7 @@ case $1 in
echo "sequence error detected"
exit 1
fi
+ rm -f work2
;;
'gzip-seq-check') # do the usual sequence check, but for gzip files
rm -f work
diff --git a/tests/imptcp_addtlframedelim.sh b/tests/imptcp_addtlframedelim.sh
new file mode 100755
index 00000000..b26fc85b
--- /dev/null
+++ b/tests/imptcp_addtlframedelim.sh
@@ -0,0 +1,14 @@
+# added 2010-08-11 by Rgerhards
+#
+# This file is part of the rsyslog project, released under GPLv3
+echo ====================================================================================
+echo TEST: \[imptcp_addtlframedelim.sh\]: test imptcp additional frame delimiter
+cat rsyslog.action.1.include
+source $srcdir/diag.sh init
+source $srcdir/diag.sh startup imptcp_addtlframedelim.conf
+source $srcdir/diag.sh tcpflood -m20000 -F0 -P129
+#sleep 2 # due to large messages, we need this time for the tcp receiver to settle...
+source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
+source $srcdir/diag.sh wait-shutdown # and wait for it to terminate
+source $srcdir/diag.sh seq-check 0 19999
+source $srcdir/diag.sh exit
diff --git a/tests/imptcp_conndrop.sh b/tests/imptcp_conndrop.sh
new file mode 100755
index 00000000..684de6b5
--- /dev/null
+++ b/tests/imptcp_conndrop.sh
@@ -0,0 +1,16 @@
+# Test imptcp with many dropping connections
+# added 2010-08-10 by Rgerhards
+#
+# This file is part of the rsyslog project, released under GPLv3
+echo ====================================================================================
+echo TEST: \[imptcp_conndrop.sh\]: test imptcp with random connection drops
+cat rsyslog.action.1.include
+source $srcdir/diag.sh init
+source $srcdir/diag.sh startup imptcp_large.conf
+# 100 byte messages to gain more practical data use
+source $srcdir/diag.sh tcpflood -c20 -m50000 -r -d100 -P129 -D
+sleep 4 # due to large messages, we need this time for the tcp receiver to settle...
+source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
+source $srcdir/diag.sh wait-shutdown # and wait for it to terminate
+source $srcdir/diag.sh seq-check 0 49999 -E
+source $srcdir/diag.sh exit
diff --git a/tests/imptcp_large.sh b/tests/imptcp_large.sh
new file mode 100755
index 00000000..b4d130bb
--- /dev/null
+++ b/tests/imptcp_large.sh
@@ -0,0 +1,16 @@
+# Test imptcp with large messages
+# added 2010-08-10 by Rgerhards
+#
+# This file is part of the rsyslog project, released under GPLv3
+echo ====================================================================================
+echo TEST: \[imptcp_large.sh\]: test imptcp with large-size messages
+cat rsyslog.action.1.include
+source $srcdir/diag.sh init
+source $srcdir/diag.sh startup imptcp_large.conf
+# send 4000 messages of 10.000bytes plus header max, randomized
+source $srcdir/diag.sh tcpflood -c5 -m20000 -r -d10000 -P129
+sleep 2 # due to large messages, we need this time for the tcp receiver to settle...
+source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
+source $srcdir/diag.sh wait-shutdown # and wait for it to terminate
+source $srcdir/diag.sh seq-check 0 19999 -E
+source $srcdir/diag.sh exit
diff --git a/tests/imtcp_addtlframedelim.sh b/tests/imtcp_addtlframedelim.sh
new file mode 100755
index 00000000..8de7ca58
--- /dev/null
+++ b/tests/imtcp_addtlframedelim.sh
@@ -0,0 +1,14 @@
+# added 2010-08-11 by Rgerhards
+#
+# This file is part of the rsyslog project, released under GPLv3
+echo ====================================================================================
+echo TEST: \[imtcp_addtlframedelim.sh\]: test imtcp additional frame delimiter
+cat rsyslog.action.1.include
+source $srcdir/diag.sh init
+source $srcdir/diag.sh startup imtcp_addtlframedelim.conf
+source $srcdir/diag.sh tcpflood -m20000 -F0 -P129
+#sleep 2 # due to large messages, we need this time for the tcp receiver to settle...
+source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
+source $srcdir/diag.sh wait-shutdown # and wait for it to terminate
+source $srcdir/diag.sh seq-check 0 19999
+source $srcdir/diag.sh exit
diff --git a/tests/imtcp_conndrop.sh b/tests/imtcp_conndrop.sh
new file mode 100755
index 00000000..2caa0ce2
--- /dev/null
+++ b/tests/imtcp_conndrop.sh
@@ -0,0 +1,16 @@
+# Test imtcp with many dropping connections
+# added 2010-08-10 by Rgerhards
+#
+# This file is part of the rsyslog project, released under GPLv3
+echo ====================================================================================
+echo TEST: \[imtcp_conndrop.sh\]: test imtcp with random connection drops
+cat rsyslog.action.1.include
+source $srcdir/diag.sh init
+source $srcdir/diag.sh startup imptcp_large.conf
+# 100 byte messages to gain more practical data use
+source $srcdir/diag.sh tcpflood -c20 -m50000 -r -d100 -P129 -D
+sleep 4 # due to large messages, we need this time for the tcp receiver to settle...
+source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
+source $srcdir/diag.sh wait-shutdown # and wait for it to terminate
+source $srcdir/diag.sh seq-check 0 49999 -E
+source $srcdir/diag.sh exit
diff --git a/tests/tcpflood.c b/tests/tcpflood.c
index 9ed2dac9..a37845a3 100644
--- a/tests/tcpflood.c
+++ b/tests/tcpflood.c
@@ -29,6 +29,9 @@
* delemiters into account.
* -C when input from a file is read, this file is transmitted -C times
* (C like cycle, running out of meaningful option switches ;))
+ * -D randomly drop and re-establish connections. Useful for stress-testing
+ * the TCP receiver.
+ * -F USASCII value for frame delimiter (in octet-stuffing mode), default LF
*
* Part of the testbench for rsyslog.
*
@@ -84,11 +87,14 @@ static int numConnections = 1; /* number of connections to create */
static int *sockArray; /* array of sockets to use */
static int msgNum = 0; /* initial message number to start with */
static int bShowProgress = 1; /* show progress messages */
+static int bRandConnDrop = 0; /* randomly drop connections? */
static char *MsgToSend = NULL; /* if non-null, this is the actual message to send */
static int bBinaryFile = 0; /* is -I file binary */
static char *dataFile = NULL; /* name of data file, if NULL, generate own data */
static int numFileIterations = 1;/* how often is file data to be sent? */
+static char frameDelim = '\n'; /* default frame delimiter */
FILE *dataFP = NULL; /* file pointer for data file, if used */
+static long nConnDrops = 0; /* counter: number of time connection was dropped (-D option) */
/* open a single tcp connection
@@ -155,8 +161,6 @@ int openConnections(void)
if(i % 10 == 0) {
if(bShowProgress)
printf("\r%5.5d", i);
- //lenMsg = sprintf(msgBuf, "\r%5.5d", i);
- //write(1, msgBuf, lenMsg);
}
if(openConn(&(sockArray[i])) != 0) {
printf("error in trying to open connection i=%d\n", i);
@@ -181,6 +185,7 @@ void closeConnections(void)
{
int i;
size_t lenMsg;
+ struct linger ling;
char msgBuf[128];
if(bShowProgress)
@@ -192,7 +197,15 @@ void closeConnections(void)
write(1, msgBuf, lenMsg);
}
}
- close(sockArray[i]);
+ if(sockArray[i] != -1) {
+ /* we try to not overrun the receiver by trying to flush buffers
+ * *during* close(). -- rgerhards, 2010-08-10
+ */
+ ling.l_onoff = 1;
+ ling.l_linger = 1;
+ setsockopt(sockArray[i], SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
+ close(sockArray[i]);
+ }
}
lenMsg = sprintf(msgBuf, "\r%5.5d close connections\n", i);
write(1, msgBuf, lenMsg);
@@ -233,8 +246,8 @@ genMsg(char *buf, size_t maxBuf, int *pLenBuf)
snprintf(dynFileIDBuf, maxBuf, "%d:", rand() % dynFileIDs);
}
if(extraDataLen == 0) {
- *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 172.20.245.8 tag msgnum:%s%8.8d:\n",
- msgPRI, dynFileIDBuf, msgNum);
+ *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 172.20.245.8 tag msgnum:%s%8.8d:%c",
+ msgPRI, dynFileIDBuf, msgNum, frameDelim);
} else {
if(bRandomizeExtraData)
edLen = ((long) rand() + extraDataLen) % extraDataLen + 1;
@@ -242,8 +255,8 @@ genMsg(char *buf, size_t maxBuf, int *pLenBuf)
edLen = extraDataLen;
memset(extraData, 'X', edLen);
extraData[edLen] = '\0';
- *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 172.20.245.8 tag msgnum:%s%8.8d:%d:%s\n",
- msgPRI, dynFileIDBuf, msgNum, edLen, extraData);
+ *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 172.20.245.8 tag msgnum:%s%8.8d:%d:%s%c",
+ msgPRI, dynFileIDBuf, msgNum, edLen, extraData, frameDelim);
}
} else {
/* use fixed message format from command line */
@@ -289,12 +302,18 @@ int sendMessages(void)
socknum = i - (numMsgsToSend - numConnections);
else {
int rnd = rand();
- //socknum = rand() % numConnections;
socknum = rnd % numConnections;
}
genMsg(buf, sizeof(buf), &lenBuf); /* generate the message to send according to params */
if(lenBuf == 0)
break; /* end of processing! */
+ if(sockArray[socknum] == -1) {
+ /* connection was dropped, need to re-establish */
+ if(openConn(&(sockArray[socknum])) != 0) {
+ printf("error in trying to re-open connection %d\n", socknum);
+ exit(1);
+ }
+ }
lenSend = send(sockArray[socknum], buf, lenBuf, 0);
if(lenSend != lenBuf) {
printf("\r%5.5d\n", i);
@@ -309,6 +328,16 @@ int sendMessages(void)
if(bShowProgress)
printf("\r%8.8d", i);
}
+ if(bRandConnDrop) {
+ /* if we need to randomly drop connections, see if we
+ * are a victim
+ */
+ if(rand() > (int) (RAND_MAX * 0.95)) {
+ ++nConnDrops;
+ close(sockArray[socknum]);
+ sockArray[socknum] = -1;
+ }
+ }
++msgNum;
++i;
}
@@ -318,59 +347,6 @@ int sendMessages(void)
}
-/* send a message via TCP
- * We open the connection on the initial send, and never close it
- * (let the OS do that). If a conneciton breaks, we do NOT try to
- * recover, so all test after that one will fail (and the test
- * driver probably hang. returns 0 if ok, something else otherwise.
- * We use traditional framing '\n' at EOR for this tester. It may be
- * worth considering additional framing modes.
- * rgerhards, 2009-04-08
- */
-int
-tcpSend(char *buf, int lenBuf)
-{
- static int sock = INVALID_SOCKET;
- struct sockaddr_in addr;
-
- if(sock == INVALID_SOCKET) {
- /* first time, need to connect to target */
- if((sock=socket(AF_INET, SOCK_STREAM, 0))==-1) {
- perror("socket()");
- return(1);
- }
-
- memset((char *) &addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(13514);
- if(inet_aton("127.0.0.1", &addr.sin_addr)==0) {
- fprintf(stderr, "inet_aton() failed\n");
- return(1);
- }
- if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
- fprintf(stderr, "connect() failed\n");
- return(1);
- }
- }
-
- /* send test data */
- if(send(sock, buf, lenBuf, 0) != lenBuf) {
- perror("send test data");
- fprintf(stderr, "send() failed\n");
- return(1);
- }
-
- /* send record terminator */
- if(send(sock, "\n", 1, 0) != 1) {
- perror("send record terminator");
- fprintf(stderr, "send() failed\n");
- return(1);
- }
-
- return 0;
-}
-
-
/* Run the test.
* rgerhards, 2009-04-03
*/
@@ -396,7 +372,7 @@ int main(int argc, char *argv[])
if(!isatty(1))
bShowProgress = 0;
- while((opt = getopt(argc, argv, "f:t:p:c:C:m:i:I:P:d:n:M:rB")) != -1) {
+ while((opt = getopt(argc, argv, "f:F:t:p:c:C:m:i:I:P:d:Dn:M:rB")) != -1) {
switch (opt) {
case 't': targetIP = optarg;
break;
@@ -421,10 +397,14 @@ int main(int argc, char *argv[])
exit(1);
}
break;
+ case 'D': bRandConnDrop = 1;
+ break;
case 'r': bRandomizeExtraData = 1;
break;
case 'f': dynFileIDs = atoi(optarg);
break;
+ case 'F': frameDelim = atoi(optarg);
+ break;
case 'M': MsgToSend = optarg;
break;
case 'I': dataFile = optarg;
@@ -472,7 +452,10 @@ int main(int argc, char *argv[])
exit(1);
}
- closeConnections();
+ closeConnections(); /* this is important so that we do not finish too early! */
+
+ if(nConnDrops > 0)
+ printf("-D option initiated %ld connection closures\n", nConnDrops);
printf("End of tcpflood Run\n");
diff --git a/tests/testsuites/imptcp_addtlframedelim.conf b/tests/testsuites/imptcp_addtlframedelim.conf
new file mode 100644
index 00000000..eb7ed0c4
--- /dev/null
+++ b/tests/testsuites/imptcp_addtlframedelim.conf
@@ -0,0 +1,13 @@
+$IncludeConfig diag-common.conf
+
+$ModLoad ../plugins/imptcp/.libs/imptcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputPTCPServerAddtlFrameDelimiter 0
+$InputPTCPServerRun 13514
+
+$template outfmt,"%msg:F,58:2%\n"
+$OMFileFlushOnTXEnd off
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 256k
+$IncludeConfig rsyslog.action.1.include
+local0.* ./rsyslog.out.log;outfmt
diff --git a/tests/testsuites/imptcp_conndrop.conf b/tests/testsuites/imptcp_conndrop.conf
new file mode 100644
index 00000000..677e33f6
--- /dev/null
+++ b/tests/testsuites/imptcp_conndrop.conf
@@ -0,0 +1,16 @@
+# simple async writing test
+# rgerhards, 2010-03-09
+$MaxMessageSize 10k
+$IncludeConfig diag-common.conf
+
+$ModLoad ../plugins/imptcp/.libs/imptcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputPTCPServerRun 13514
+
+$template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n"
+$template dynfile,"rsyslog.out.log" # trick to use relative path names!
+$OMFileFlushOnTXEnd off
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 256k
+$IncludeConfig rsyslog.action.1.include
+local0.* ?dynfile;outfmt
diff --git a/tests/testsuites/imptcp_large.conf b/tests/testsuites/imptcp_large.conf
new file mode 100644
index 00000000..677e33f6
--- /dev/null
+++ b/tests/testsuites/imptcp_large.conf
@@ -0,0 +1,16 @@
+# simple async writing test
+# rgerhards, 2010-03-09
+$MaxMessageSize 10k
+$IncludeConfig diag-common.conf
+
+$ModLoad ../plugins/imptcp/.libs/imptcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputPTCPServerRun 13514
+
+$template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n"
+$template dynfile,"rsyslog.out.log" # trick to use relative path names!
+$OMFileFlushOnTXEnd off
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 256k
+$IncludeConfig rsyslog.action.1.include
+local0.* ?dynfile;outfmt
diff --git a/tests/testsuites/imtcp_addtlframedelim.conf b/tests/testsuites/imtcp_addtlframedelim.conf
new file mode 100644
index 00000000..3b4759c5
--- /dev/null
+++ b/tests/testsuites/imtcp_addtlframedelim.conf
@@ -0,0 +1,13 @@
+$IncludeConfig diag-common.conf
+
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputTCPServerAddtlFrameDelimiter 0
+$InputTCPServerRun 13514
+
+$template outfmt,"%msg:F,58:2%\n"
+$OMFileFlushOnTXEnd off
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 256k
+$IncludeConfig rsyslog.action.1.include
+local0.* ./rsyslog.out.log;outfmt
diff --git a/tests/testsuites/imtcp_conndrop.conf b/tests/testsuites/imtcp_conndrop.conf
new file mode 100644
index 00000000..b64f132b
--- /dev/null
+++ b/tests/testsuites/imtcp_conndrop.conf
@@ -0,0 +1,16 @@
+# simple async writing test
+# rgerhards, 2010-03-09
+$MaxMessageSize 10k
+$IncludeConfig diag-common.conf
+
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputTCPServerRun 13514
+
+$template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n"
+$template dynfile,"rsyslog.out.log" # trick to use relative path names!
+$OMFileFlushOnTXEnd off
+$OMFileFlushInterval 2
+$OMFileIOBufferSize 256k
+$IncludeConfig rsyslog.action.1.include
+local0.* ?dynfile;outfmt
diff --git a/tests/testsuites/uxsock_simple.conf b/tests/testsuites/uxsock_simple.conf
new file mode 100644
index 00000000..efffdd90
--- /dev/null
+++ b/tests/testsuites/uxsock_simple.conf
@@ -0,0 +1,10 @@
+# Test for pipe output action (see .sh file for details)
+# rgerhards, 2009-11-05
+$IncludeConfig diag-common.conf
+
+$MainMsgQueueTimeoutShutdown 10000
+
+$ModLoad ../plugins/omuxsock/.libs/omuxsock
+$template outfmt,"%msg:F,58:2%\n"
+$OMUXSockSocket rsyslog-testbench-dgram-uxsock
+:msg, contains, "msgnum:" :omuxsock:;outfmt
diff --git a/tests/uxsock_simple.sh b/tests/uxsock_simple.sh
new file mode 100755
index 00000000..7f00f4bc
--- /dev/null
+++ b/tests/uxsock_simple.sh
@@ -0,0 +1,31 @@
+# This tests basic omuxsock functionality. A socket receiver is started which sends
+# all data to an output file, then a rsyslog instance is started which generates
+# messages and sends them to the unix socket. Datagram sockets are being used.
+# added 2010-08-06 by Rgerhards
+echo ===============================================================================
+echo \[uxsock_simple.sh\]: simple tests for omuxsock functionality
+
+# create the pipe and start a background process that copies data from
+# it to the "regular" work file
+source $srcdir/diag.sh init
+./uxsockrcvr -srsyslog-testbench-dgram-uxsock -orsyslog.out.log &
+BGPROCESS=$!
+echo background uxsockrcvr process id is $BGPROCESS
+
+# now do the usual run
+source $srcdir/diag.sh startup uxsock_simple.conf
+# 10000 messages should be enough
+source $srcdir/diag.sh injectmsg 0 10000
+source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
+source $srcdir/diag.sh wait-shutdown
+
+# wait for the cp process to finish, do pipe-specific cleanup
+echo shutting down uxsockrcvr...
+# TODO: we should do this more reliable in the long run! (message counter? timeout?)
+kill $BGPROCESS
+wait $BGPROCESS
+echo background process has terminated, continue test...
+
+# and continue the usual checks
+source $srcdir/diag.sh seq-check 0 9999
+source $srcdir/diag.sh exit
diff --git a/tests/uxsockrcvr.c b/tests/uxsockrcvr.c
new file mode 100644
index 00000000..551f0ef3
--- /dev/null
+++ b/tests/uxsockrcvr.c
@@ -0,0 +1,157 @@
+/* receives messages from a specified unix sockets and writes
+ * output to specfied file.
+ *
+ * Command line options:
+ * -s name of socket (required)
+ * -o name of output file (stdout if not given)
+ * -l add newline after each message received (default: do not add anything)
+ *
+ * Part of the testbench for rsyslog.
+ *
+ * Copyright 2010 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Rsyslog is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Rsyslog is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <getopt.h>
+#include <sys/un.h>
+#include <netdb.h>
+
+char *sockName = NULL;
+int sock;
+int addNL = 0;
+
+
+/* called to clean up on exit
+ */
+void
+cleanup(void)
+{
+ unlink(sockName);
+ close(sock);
+}
+
+
+void
+doTerm(int __attribute__((unused)) signum)
+{
+ exit(1);
+}
+
+
+void
+usage(void)
+{
+ fprintf(stderr, "usage: uxsockrcvr -s /socket/name -o /output/file -l\n"
+ "-l adds newline after each message received\n"
+ "-s MUST be specified\n"
+ "if -o ist not specified, stdout is used\n");
+ exit(1);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ int opt;
+ int rlen;
+ FILE *fp = stdout;
+ unsigned char data[128*1024];
+ struct sockaddr_un addr; /* address of server */
+ struct sockaddr from;
+ socklen_t fromlen;
+
+ if(argc < 2) {
+ fprintf(stderr, "error: too few arguments!\n");
+ usage();
+ }
+
+ while((opt = getopt(argc, argv, "s:o:l")) != EOF) {
+ switch((char)opt) {
+ case 'l':
+ addNL = 1;
+ break;
+ case 's':
+ sockName = optarg;
+ break;
+ case 'o':
+ if((fp = fopen(optarg, "w")) == NULL) {
+ perror(optarg);
+ exit(1);
+ }
+ break;
+ default:usage();
+ }
+ }
+
+ if(sockName == NULL) {
+ fprintf(stderr, "error: -s /socket/name must be specified!\n");
+ exit(1);
+ }
+
+ if(signal(SIGTERM, doTerm) == SIG_ERR) {
+ perror("signal(SIGTERM, ...)");
+ exit(1);
+ }
+ if(signal(SIGINT, doTerm) == SIG_ERR) {
+ perror("signal(SIGINT, ...)");
+ exit(1);
+ }
+
+ /* Create a UNIX datagram socket for server */
+ if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
+ perror("server: socket");
+ exit(1);
+ }
+
+ atexit(cleanup);
+
+ /* Set up address structure for server socket */
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, sockName);
+
+ if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
+ close(sock);
+ perror("server: bind");
+ exit(1);
+ }
+
+ /* we now run in an endless loop. We do not check who sends us
+ * data. This should be no problem for our testbench use.
+ */
+ while(1) {
+ fromlen = sizeof(from);
+ rlen = recvfrom(sock, data, 2000, 0, &from, &fromlen);
+ if(rlen == -1) {
+ perror("uxsockrcvr : recv\n");
+ exit(1);
+ } else {
+ fwrite(data, 1, rlen, fp);
+ if(addNL)
+ fputc('\n', fp);
+ }
+ }
+
+ return 0;
+}
diff --git a/tools/syslogd.c b/tools/syslogd.c
index a7f76313..56000e08 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -324,7 +324,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
/* hardcoded standard templates (used for defaults) */
-static uchar template_DebugFormat[] = "\"Debug line with all properties:\nFROMHOST: '%FROMHOST%', fromhost-ip: '%fromhost-ip%', HOSTNAME: '%HOSTNAME%', PRI: %PRI%,\nsyslogtag '%syslogtag%', programname: '%programname%', APP-NAME: '%APP-NAME%', PROCID: '%PROCID%', MSGID: '%MSGID%',\nTIMESTAMP: '%TIMESTAMP%', STRUCTURED-DATA: '%STRUCTURED-DATA%',\nmsg: '%msg%'\nescaped msg: '%msg:::drop-cc%'\nrawmsg: '%rawmsg%'\n\n\"";
+static uchar template_DebugFormat[] = "\"Debug line with all properties:\nFROMHOST: '%FROMHOST%', fromhost-ip: '%fromhost-ip%', HOSTNAME: '%HOSTNAME%', PRI: %PRI%,\nsyslogtag '%syslogtag%', programname: '%programname%', APP-NAME: '%APP-NAME%', PROCID: '%PROCID%', MSGID: '%MSGID%',\nTIMESTAMP: '%TIMESTAMP%', STRUCTURED-DATA: '%STRUCTURED-DATA%',\nmsg: '%msg%'\nescaped msg: '%msg:::drop-cc%'\ninputname: %inputname% rawmsg: '%rawmsg%'\n\n\"";
static uchar template_SyslogProtocol23Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n\"";
static uchar template_TraditionalFileFormat[] = "=RSYSLOG_TraditionalFileFormat";
static uchar template_FileFormat[] = "=RSYSLOG_FileFormat";
@@ -334,6 +334,7 @@ static uchar template_WallFmt[] = "\"\r\n\7Message from syslogd@%HOSTNAME% at %t
static uchar template_StdUsrMsgFmt[] = "\" %syslogtag%%msg%\n\r\"";
static uchar template_StdDBFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')\",SQL";
static uchar template_StdPgSQLFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-pgsql%', '%timegenerated:::date-pgsql%', %iut%, '%syslogtag%')\",STDSQL";
+static uchar template_spoofadr[] = "\"%fromhost-ip%\"";
/* end templates */
@@ -2169,6 +2170,8 @@ static rsRetVal mainThread()
tplAddLine(" StdDBFmt", &pTmp);
pTmp = template_StdPgSQLFmt;
tplLastStaticInit(tplAddLine(" StdPgSQLFmt", &pTmp));
+ pTmp = template_spoofadr;
+ tplLastStaticInit(tplAddLine("RSYSLOG_omudpspoofDfltSourceTpl", &pTmp));
CHKiRet(init());