summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog78
-rw-r--r--action.c65
-rw-r--r--action.h1
-rw-r--r--configure.ac2
-rw-r--r--doc/imtcp.html10
-rw-r--r--doc/manual.html2
-rw-r--r--doc/rsyslog_conf_global.html8
-rw-r--r--doc/status.html26
-rw-r--r--plugins/imtcp/imtcp.c5
-rw-r--r--runtime/datetime.c56
-rw-r--r--runtime/modules.c8
-rw-r--r--runtime/queue.c2
-rw-r--r--runtime/rule.c2
-rw-r--r--runtime/ruleset.c11
-rw-r--r--runtime/stream.c1
-rw-r--r--runtime/stream.h4
-rw-r--r--tcpsrv.c44
-rw-r--r--tcpsrv.h7
-rw-r--r--tests/Makefile.am4
-rwxr-xr-xtests/discard.sh16
-rw-r--r--tests/rt-init.c3
-rw-r--r--tests/testsuites/4.parse14
-rw-r--r--tests/testsuites/discard.conf13
-rw-r--r--tests/testsuites/upcase-date.parse14
-rw-r--r--tools/syslogd.c2
25 files changed, 279 insertions, 99 deletions
diff --git a/ChangeLog b/ChangeLog
index f9857a75..bde56d58 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,40 @@
---------------------------------------------------------------------------
-Version 5.1.3 [DEVEL] (rgerhards), 2009-07-??
+Version 5.1.5 [DEVEL] (rgerhards), 2009-08-??
+- added new config option $ActionWriteAllMarkMessages
+ this option permites to process mark messages under all circumstances,
+ even if an action was recently called. This can be useful to use mark
+ messages as a kind of heartbeat.
+- bugfix: hostnames with dashes in them were incorrectly treated as
+ malformed, thus causing them to be treated as TAG (this was a regression
+ introduced from the "rfc3164 strict" change in 4.5.0). Testbench has been
+ updated to include a smaple message with a hostname containing a dash.
+---------------------------------------------------------------------------
+Version 5.1.4 [DEVEL] (rgerhards), 2009-08-20
+- legacy syslog parser changed so that it now accepts date stamps in
+ wrong case. Some devices seem to create them and I do not see any harm
+ in supporting that.
+- added $InputTCPMaxListeners directive - permits to specify how many
+ TCP servers shall be possible (default is 20).
+- bugfix: memory leak with some input modules. Those inputs that
+ use parseAndSubmitMsg() leak two small memory blocks with every message.
+ Typically, those process only relatively few messages, so the issue
+ does most probably not have any effect in practice.
+- bugfix: if tcp listen port could not be created, no error message was
+ emitted
+- bugfix: discard action did not work (did not discard messages)
+- bugfix: discard action caused segfault
+- bugfix: potential segfault in output file writer (omfile)
+ In async write mode, we use modular arithmetic to index the output
+ buffer array. However, the counter variables accidently were signed,
+ thus resulting in negative indizes after integer overflow. That in turn
+ could lead to segfaults, but was depending on the memory layout of
+ the instance in question (which in turn depended on a number of
+ variables, like compile settings but also configuration). The counters
+ are now unsigned (as they always should have been) and so the dangling
+ mis-indexing does no longer happen. This bug potentially affected all
+ installations, even if only some may actually have seen a segfault.
+---------------------------------------------------------------------------
+Version 5.1.3 [DEVEL] (rgerhards), 2009-07-28
- architecture change: queue now always has at least one worker thread
if not running in direct mode. Previous versions could run without
any active workers. This simplifies the code at a very small expense.
@@ -72,11 +107,31 @@ increase.
- increased ompgsql performance by adapting to new transactional
output module interface
---------------------------------------------------------------------------
-Version 4.5.2 [DEVEL] (rgerhards), 2009-07-??
+Version 4.5.2 [v4-beta] (rgerhards), 2009-08-21
+- legacy syslog parser changed so that it now accepts date stamps in
+ wrong case. Some devices seem to create them and I do not see any harm
+ in supporting that.
+- added $InputTCPMaxListeners directive - permits to specify how many
+ TCP servers shall be possible (default is 20).
- bugfix: memory leak with some input modules. Those inputs that
use parseAndSubmitMsg() leak two small memory blocks with every message.
Typically, those process only relatively few messages, so the issue
does most probably not have any effect in practice.
+- bugfix: if tcp listen port could not be created, no error message was
+ emitted
+- bugfix: potential segfault in output file writer (omfile)
+ In async write mode, we use modular arithmetic to index the output
+ buffer array. However, the counter variables accidently were signed,
+ thus resulting in negative indizes after integer overflow. That in turn
+ could lead to segfaults, but was depending on the memory layout of
+ the instance in question (which in turn depended on a number of
+ variables, like compile settings but also configuration). The counters
+ are now unsigned (as they always should have been) and so the dangling
+ mis-indexing does no longer happen. This bug potentially affected all
+ installations, even if only some may actually have seen a segfault.
+- bugfix: hostnames with dashes in them were incorrectly treated as
+ malformed, thus causing them to be treated as TAG (this was a regression
+ introduced from the "rfc3164 strict" change in 4.5.0).
---------------------------------------------------------------------------
Version 4.5.1 [DEVEL] (rgerhards), 2009-07-15
- CONFIG CHANGE: $HUPisRestart default is now "off". We are doing this
@@ -143,13 +198,14 @@ Version 4.5.0 [DEVEL] (rgerhards), 2009-07-02
This could lead to timestamps written in the wrong format, but not to
an abort
---------------------------------------------------------------------------
-Version 4.3.3 [beta] (rgerhards), 2009-0?-??
-- internal bugfix: object pointer was only reset to NULL when an object
- was actually destructed. This most likely had no effect to existing code,
- but it may also have caused trouble in remote cases. Similarly, the fix
- may also cause trouble...
+Version 4.4.0 [v4-stable] (rgerhards), 2009-08-21
+- bugfix: stderr/stdout were not closed to be able to emit error messages,
+ but this caused ssh sessions to hang. Now we close them after the
+ initial initialization. See forum thread:
+ http://kb.monitorware.com/controlling-terminal-issues-t9875.html
+- bugfix: sending syslog messages with zip compression did not work
---------------------------------------------------------------------------
-Version 4.3.2 [beta] (rgerhards), 2009-06-24
+Version 4.3.2 [v4-beta] (rgerhards), 2009-06-24
- removed long-obsoleted property UxTradMsg
- added a generic network stream server (in addition to rather specific
syslog tcp server)
@@ -204,12 +260,6 @@ Version 4.3.0 [DEVEL] (rgerhards), 2009-04-17
execution. The most probable case for such a case would be invalid
sql inside the template, and this is now much easier to diagnose.
---------------------------------------------------------------------------
-Version 4.2.1 [v4-stable] (rgerhards), 2009-0?-??
-- bugfix: stderr/stdout were not closed to be able to emit error messages,
- but this caused ssh sessions to hang. Now we close them after the
- initial initialization. See forum thread:
- http://kb.monitorware.com/controlling-terminal-issues-t9875.html
----------------------------------------------------------------------------
Version 4.2.0 [v4-stable] (rgerhards), 2009-06-23
- bugfix: light and full delay watermarks had invalid values, badly
affecting performance for delayable inputs
diff --git a/action.c b/action.c
index 8a29df2e..1e02d23e 100644
--- a/action.c
+++ b/action.c
@@ -65,8 +65,9 @@ static int glbliActionResumeInterval = 30;
int glbliActionResumeRetryCount = 0; /* how often should suspended actions be retried? */
static int bActionRepMsgHasMsg = 0; /* last messsage repeated... has msg fragment in it */
+static int bActionWriteAllMarkMsgs = FALSE; /* should all mark messages be unconditionally written? */
static uchar *pszActionName; /* short name for the action */
-/* main message queue and its configuration parameters */
+/* action queue and its configuration parameters */
static queueType_t ActionQueType = QUEUETYPE_DIRECT; /* type of the main message queue above */
static int iActionQueueSize = 1000; /* size of the main message queue above */
static int iActionQueueDeqBatchSize = 16; /* batch size for action queues */
@@ -808,41 +809,50 @@ tryDoAction(action_t *pAction, batch_t *pBatch, int *pnElem)
assert(pBatch != NULL);
assert(pnElem != NULL);
+dbgprintf("XXXX: ENTER tryDoAction elt 0 state %d\n", pBatch->pElem[0].state);
i = pBatch->iDoneUpTo; /* all messages below that index are processed */
iElemProcessed = 0;
iCommittedUpTo = i;
while(iElemProcessed <= *pnElem && i < pBatch->nElem) {
pMsg = (msg_t*) pBatch->pElem[i].pUsrp;
- dbgprintf("submitBatch: i:%d, batch size %d, to process %d, pMsg: %p\n", i, pBatch->nElem, *pnElem, pMsg);//remove later!
- localRet = actionProcessMessage(pAction, pMsg);
- dbgprintf("action call returned %d\n", localRet);
- if(localRet == RS_RET_OK) {
- /* mark messages as committed */
- while(iCommittedUpTo < i) {
- pBatch->pElem[iCommittedUpTo++].state = BATCH_STATE_COMM;
- }
- } else if(localRet == RS_RET_PREVIOUS_COMMITTED) {
- /* mark messages as committed */
- while(iCommittedUpTo < i - 1) {
- pBatch->pElem[iCommittedUpTo++].state = BATCH_STATE_COMM;
+ dbgprintf("submitBatch: i:%d, batch size %d, to process %d, pMsg: %p, state %d\n", i, pBatch->nElem, *pnElem, pMsg, pBatch->pElem[i].state);//remove later!
+ if(pBatch->pElem[i].state != BATCH_STATE_DISC) {
+ localRet = actionProcessMessage(pAction, pMsg);
+ dbgprintf("action call returned %d\n", localRet);
+ if(localRet == RS_RET_OK) {
+ /* mark messages as committed */
+ while(iCommittedUpTo < i) {
+ pBatch->pElem[iCommittedUpTo++].state = BATCH_STATE_COMM;
+ }
+ } else if(localRet == RS_RET_PREVIOUS_COMMITTED) {
+ /* mark messages as committed */
+ while(iCommittedUpTo < i - 1) {
+ pBatch->pElem[iCommittedUpTo++].state = BATCH_STATE_COMM;
+ }
+ pBatch->pElem[i].state = BATCH_STATE_SUB;
+ } else if(localRet == RS_RET_PREVIOUS_COMMITTED) {
+ pBatch->pElem[i].state = BATCH_STATE_SUB;
+ } else if(localRet == RS_RET_DISCARDMSG) {
+ pBatch->pElem[i].state = BATCH_STATE_DISC;
+dbgprintf("XXXX: discardmsg! change state to _DISC: %d\n", pBatch->pElem[i].state);
+ } else {
+ iRet = localRet;
+ FINALIZE;
}
- pBatch->pElem[i].state = BATCH_STATE_SUB;
- } else if(localRet == RS_RET_PREVIOUS_COMMITTED) {
- pBatch->pElem[i].state = BATCH_STATE_SUB;
- } else {
- iRet = localRet;
- FINALIZE;
}
++i;
++iElemProcessed;
}
finalize_it:
- if(pBatch->iDoneUpTo != iCommittedUpTo) {
+ if(pBatch->nElem == 1 && pBatch->pElem[0].state == BATCH_STATE_DISC) {
+ iRet = RS_RET_DISCARDMSG;
+ } else if(pBatch->iDoneUpTo != iCommittedUpTo) {
*pnElem += iCommittedUpTo - pBatch->iDoneUpTo;
pBatch->iDoneUpTo = iCommittedUpTo;
}
+dbgprintf("XXXX: done tryDoAction elt 0 state %d, iret %d\n", pBatch->pElem[0].state, iRet);
RETiRet;
}
@@ -865,6 +875,7 @@ submitBatch(action_t *pAction, batch_t *pBatch, int nElem)
bDone = 0;
do {
localRet = tryDoAction(pAction, pBatch, &nElem);
+dbgprintf("XXXX: submitBatch got state %d\n", localRet);
if( localRet == RS_RET_OK
|| localRet == RS_RET_PREVIOUS_COMMITTED
|| localRet == RS_RET_DEFER_COMMIT) {
@@ -874,10 +885,15 @@ submitBatch(action_t *pAction, batch_t *pBatch, int nElem)
localRet = finishBatch(pAction);
}
+dbgprintf("XXXX: submitBatch got state %d\n", localRet);
if( localRet == RS_RET_OK
|| localRet == RS_RET_PREVIOUS_COMMITTED
|| localRet == RS_RET_DEFER_COMMIT) {
bDone = 1;
+ } else if(localRet == RS_RET_DISCARDMSG) {
+ iRet = RS_RET_DISCARDMSG; /* TODO: verify this sequence -- rgerhards, 2009-07-30 */
+ bDone = 1;
+dbgprintf("XXXX: submitBatch DONE state %d\n", localRet);
} else if(localRet == RS_RET_SUSPENDED) {
; /* do nothing, this will retry the full batch */
} else if(localRet == RS_RET_ACTION_FAILED) {
@@ -897,8 +913,10 @@ submitBatch(action_t *pAction, batch_t *pBatch, int nElem)
bDone = 1;
}
}
+dbgprintf("XXXX: submitBatch pre while state %d\n", localRet);
} while(!bDone); /* do .. while()! */
+dbgprintf("XXXX: END submitBatch elt 0 state %d, iRet %d\n", pBatch->pElem[0].state, iRet);
RETiRet;
}
@@ -1134,6 +1152,7 @@ actionWriteToAction(action_t *pAction)
* So let's enqueue our message for execution. -- rgerhards, 2007-07-24
*/
iRet = qqueueEnqObj(pAction->pQueue, pAction->f_pMsg->flowCtlType, (void*) MsgAddRef(pAction->f_pMsg));
+dbgprintf("XXXX: queueEnqObj returned %d\n", iRet);
if(iRet == RS_RET_OK)
pAction->f_prevcount = 0; /* message processed, so we start a new cycle */
@@ -1168,7 +1187,8 @@ doActionCallAction(action_t *pAction, msg_t *pMsg)
pAction->tActNow = -1; /* we do not yet know our current time (clear prev. value) */
/* don't output marks to recently written outputs */
- if((pMsg->msgFlags & MARK) && (getActNow(pAction) - pAction->f_time) < MarkInterval / 2) {
+ if(pAction->bWriteAllMarkMsgs == FALSE
+ && (pMsg->msgFlags & MARK) && (getActNow(pAction) - pAction->f_time) < MarkInterval / 2) {
ABORT_FINALIZE(RS_RET_OK);
}
@@ -1260,6 +1280,7 @@ actionAddCfSysLineHdrl(void)
CHKiRet(regCfSysLineHdlr((uchar *)"actionname", 0, eCmdHdlrGetWord, NULL, &pszActionName, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuefilename", 0, eCmdHdlrGetWord, NULL, &pszActionQFName, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuesize", 0, eCmdHdlrInt, NULL, &iActionQueueSize, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionwriteallmarkmessages", 0, eCmdHdlrBinary, NULL, &bActionWriteAllMarkMsgs, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeuebatchsize", 0, eCmdHdlrInt, NULL, &iActionQueueDeqBatchSize, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuemaxdiskspace", 0, eCmdHdlrSize, NULL, &iActionQueMaxDiskSpace, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuehighwatermark", 0, eCmdHdlrInt, NULL, &iActionQHighWtrMark, NULL));
@@ -1314,6 +1335,8 @@ addAction(action_t **ppAction, modInfo_t *pMod, void *pModData, omodStringReques
pAction->pModData = pModData;
pAction->pszName = pszActionName;
pszActionName = NULL; /* free again! */
+ pAction->bWriteAllMarkMsgs = bActionWriteAllMarkMsgs;
+ bActionWriteAllMarkMsgs = FALSE; /* reset */
pAction->bExecWhenPrevSusp = bActExecWhenPrevSusp;
pAction->iSecsExecOnceInterval = iActExecOnceInterval;
pAction->iExecEveryNthOccur = iActExecEveryNthOccur;
diff --git a/action.h b/action.h
index a29936e5..cfa08db8 100644
--- a/action.h
+++ b/action.h
@@ -53,6 +53,7 @@ struct action_s {
populated on an as-needed basis. This is a performance optimization. */
time_t tLastExec; /* time this action was last executed */
bool bExecWhenPrevSusp;/* execute only when previous action is suspended? */
+ bool bWriteAllMarkMsgs;/* should all mark msgs be written (not matter how recent the action was executed)? */
int iSecsExecOnceInterval; /* if non-zero, minimum seconds to wait until action is executed again */
action_state_t eState; /* current state of action */
int bHadAutoCommit; /* did an auto-commit happen during doAction()? */
diff --git a/configure.ac b/configure.ac
index 3b17a927..e9bc9c9d 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.1.3],[rsyslog@lists.adiscon.com])
+AC_INIT([rsyslog],[5.1.4],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([ChangeLog])
AC_CONFIG_MACRO_DIR([m4])
diff --git a/doc/imtcp.html b/doc/imtcp.html
index 9ea7efa1..5217634e 100644
--- a/doc/imtcp.html
+++ b/doc/imtcp.html
@@ -43,15 +43,19 @@ can be found at the <a href="http://www.rsyslog.com/Article321.phtml">Cisco tcp
page.
<li>$InputTCPServerRun &lt;port&gt;<br>
Starts a TCP server on selected port</li>
-<li><ul><li>$InputTCPMaxSessions &lt;number&gt;</li></ul>
-Sets the maximum number of sessions supported</li><li>$InputTCPServerStreamDriverMode &lt;number&gt;<br>
+<li>$InputTCPMaxListeners &lt;number&gt;<br>
+Sets the maximum number of listeners (server ports) supported. Default is 20. This must be set before the first $InputTCPServerRun directive.</li>
+<li>$InputTCPMaxSessions &lt;number&gt;<br>
+Sets the maximum number of sessions supported. Default is 200. This must be set before the first $InputTCPServerRun directive</li>
+<li>$InputTCPServerStreamDriverMode &lt;number&gt;<br>
Sets the driver mode for the currently selected <a href="netstream.html">network stream driver</a>. &lt;number&gt; is driver specifc.</li>
<li>$InputTCPServerInputName &lt;name&gt;<br>
Sets a name for the inputname property. If no name is set "imtcp" 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>$InputTCPServerStreamDriverAuthMode &lt;mode-string&gt;<br>
-Sets the authentication mode for the currently selected <a href="netstream.html">network stream driver</a>. &lt;mode-string&gt; is driver specifc.</li><li>$InputTCPServerStreamDriverPermittedPeer &lt;id-string&gt;<br>
+Sets the authentication mode for the currently selected <a href="netstream.html">network stream driver</a>. &lt;mode-string&gt; is driver specifc.</li>
+<li>$InputTCPServerStreamDriverPermittedPeer &lt;id-string&gt;<br>
Sets permitted peer IDs. Only these peers are able to connect to the
listener. &lt;id-string&gt; semantics depend on the currently selected
AuthMode and&nbsp; <a href="netstream.html">network stream driver</a>. PermittedPeers may not be set in anonymous modes.</li>
diff --git a/doc/manual.html b/doc/manual.html
index f45a4952..b35b157a 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -19,7 +19,7 @@ rsyslog support</a> available directly from the source!</p>
<p><b>Please visit the <a href="http://www.rsyslog.com/sponsors">rsyslog sponsor's page</a>
to honor the project sponsors or become one yourself!</b> We are very grateful for any help towards the
project goals.</p>
-<p><b>This documentation is for version 5.1.3 (devel branch) of rsyslog.</b>
+<p><b>This documentation is for version 5.1.4 (devel branch) of rsyslog.</b>
Visit the <i><a href="http://www.rsyslog.com/doc-status.html">rsyslog status page</a></i></b>
to obtain current version information and project status.
</p><p><b>If you like rsyslog, you might
diff --git a/doc/rsyslog_conf_global.html b/doc/rsyslog_conf_global.html
index f37dcc5a..fa9c7eef 100644
--- a/doc/rsyslog_conf_global.html
+++ b/doc/rsyslog_conf_global.html
@@ -107,6 +107,14 @@ that it should be not be much more often than once per second).</li>
<li><b>$ActionSendUDPRebindInterval</b> nbr</a>- [available since 4.3.2] - instructs the UDP send
action to rebind the send socket every nbr of messages sent. Zero, the default, means
that no rebind is done. This directive is useful for use with load-balancers.</li>
+<li><b>$ActionWriteAllMarkMessages</b> [on/<b>off</b>]- [available since 5.1.5] - normally, mark messages
+are written to actions only if the action was not recently executed (by default, recently means within the
+past 20 minutes). If this setting is switched to &quot;on&quot;, mark messages are always sent to actions,
+no matter how recently they have been executed. In this mode, mark messages can be used as a kind of
+heartbeat. Note that this option auto-resets to &quot;off&quot;, so if you intend to use it with multiple
+actions, it must be specified in front off <b>all</b> selector lines that should provide this
+functionality.
+</li>
<li><a href="rsconf1_allowedsender.html">$AllowedSender</a></li>
<li><a href="rsconf1_controlcharacterescapeprefix.html">$ControlCharacterEscapePrefix</a></li>
<li><a href="rsconf1_debugprintcfsyslinehandlerlist.html">$DebugPrintCFSyslineHandlerList</a></li>
diff --git a/doc/status.html b/doc/status.html
index c5de1ad3..02cc0d70 100644
--- a/doc/status.html
+++ b/doc/status.html
@@ -2,24 +2,26 @@
<html><head><title>rsyslog status page</title></head>
<body>
<h2>rsyslog status page</h2>
-<p>This page reflects the status as of 2009-07-15.</p>
+<p>This page reflects the status as of 2009-08-21.</p>
<h2>Current Releases</h2>
-<p><b>v5 development:</b> 5.1.2 [2009-07-08] -
-<a href="http://www.rsyslog.com/Article386.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-166.phtml">download</a>
-
-<br><b>v4 development:</b> 4.5.1 [2009-07-15] -
+<p><b>v5 development:</b> 5.1.4 [2009-08-20] -
+<a href="http://www.rsyslog.com/Article392.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-170.phtml">download</a>
+<br>
+<!-- not at the moment!
+<b>v4 development:</b> 4.5.1 [2009-07-15] -
<a href="http://www.rsyslog.com/Article388.phtml">change log</a> -
<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-167.phtml">download</a></p>
+-->
-<br><b>beta:</b> 4.3.2 [2009-06-24] -
-<a href="http://www.rsyslog.com/Article378.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-162.phtml">download</a></p>
+<br><b>v4-beta:</b> 4.5.2 [2009-08-21] -
+<a href="http://www.rsyslog.com/Article395.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-172.phtml">download</a></p>
-<p><b>v4 stable:</b> 4.2.0 [2009-06-23] -
-<a href="http://www.rsyslog.com/Article376.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-161.phtml">download</a>
+<p><b>v4 stable:</b> 4.4.0 [2009-08-21] -
+<a href="http://www.rsyslog.com/Article394.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-171.phtml">download</a>
<br><b>v3 stable:</b> 3.22.1 [2009-07-02] -
<a href="http://www.rsyslog.com/Article381.phtml">change log</a> -
diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c
index 1f111ef3..0bd064e6 100644
--- a/plugins/imtcp/imtcp.c
+++ b/plugins/imtcp/imtcp.c
@@ -82,6 +82,7 @@ static permittedPeers_t *pPermPeersRoot = NULL;
/* config settings */
static int iTCPSessMax = 200; /* max number of sessions */
+static int iTCPLstnMax = 20; /* max number of sessions */
static int iStrmDrvrMode = 0; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
static int iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER; /* addtl frame delimiter, e.g. for netscreen, default none */
static uchar *pszStrmDrvrAuthMode = NULL; /* authentication mode to use */
@@ -188,6 +189,7 @@ static rsRetVal addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVa
if(pOurTcpsrv == NULL) {
CHKiRet(tcpsrv.Construct(&pOurTcpsrv));
CHKiRet(tcpsrv.SetSessMax(pOurTcpsrv, iTCPSessMax));
+ CHKiRet(tcpsrv.SetLstnMax(pOurTcpsrv, iTCPLstnMax));
CHKiRet(tcpsrv.SetCBIsPermittedHost(pOurTcpsrv, isPermittedHost));
CHKiRet(tcpsrv.SetCBRcvData(pOurTcpsrv, doRcvData));
CHKiRet(tcpsrv.SetCBOpenLstnSocks(pOurTcpsrv, doOpenLstnSocks));
@@ -280,6 +282,7 @@ static rsRetVal
resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
iTCPSessMax = 200;
+ iTCPLstnMax = 20;
iStrmDrvrMode = 0;
iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
free(pszInputName);
@@ -316,6 +319,8 @@ CODEmodInit_QueryRegCFSLineHdlr
addTCPListener, NULL, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpmaxsessions"), 0, eCmdHdlrInt,
NULL, &iTCPSessMax, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpmaxlisteners"), 0, eCmdHdlrInt,
+ NULL, &iTCPLstnMax, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpserverstreamdrivermode"), 0,
eCmdHdlrInt, NULL, &iStrmDrvrMode, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpserverstreamdriverauthmode"), 0,
diff --git a/runtime/datetime.c b/runtime/datetime.c
index 2db1d3c5..dfa56b4f 100644
--- a/runtime/datetime.c
+++ b/runtime/datetime.c
@@ -335,6 +335,10 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
* We will use this for parsing, as it probably is the
* fastest way to parse it.
*
+ * 2009-08-17: we now do case-insensitive comparisons, as some devices obviously do not
+ * obey to the RFC-specified case. As we need to guess in any case, we can ignore case
+ * in the first place -- rgerhards
+ *
* 2005-07-18, well sometimes it pays to be a bit more verbose, even in C...
* Fixed a bug that lead to invalid detection of the data. The issue was that
* we had an if(++pszTS == 'x') inside of some of the consturcts below. However,
@@ -346,20 +350,21 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
*/
switch(*pszTS++)
{
+ case 'j':
case 'J':
- if(*pszTS == 'a') {
+ if(*pszTS == 'a' || *pszTS == 'A') {
++pszTS;
- if(*pszTS == 'n') {
+ if(*pszTS == 'n' || *pszTS == 'N') {
++pszTS;
month = 1;
} else
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- } else if(*pszTS == 'u') {
+ } else if(*pszTS == 'u' || *pszTS == 'U') {
++pszTS;
- if(*pszTS == 'n') {
+ if(*pszTS == 'n' || *pszTS == 'N') {
++pszTS;
month = 6;
- } else if(*pszTS == 'l') {
+ } else if(*pszTS == 'l' || *pszTS == 'L') {
++pszTS;
month = 7;
} else
@@ -367,10 +372,11 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
} else
ABORT_FINALIZE(RS_RET_INVLD_TIME);
break;
+ case 'f':
case 'F':
- if(*pszTS == 'e') {
+ if(*pszTS == 'e' || *pszTS == 'E') {
++pszTS;
- if(*pszTS == 'b') {
+ if(*pszTS == 'b' || *pszTS == 'B') {
++pszTS;
month = 2;
} else
@@ -378,13 +384,14 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
} else
ABORT_FINALIZE(RS_RET_INVLD_TIME);
break;
+ case 'm':
case 'M':
- if(*pszTS == 'a') {
+ if(*pszTS == 'a' || *pszTS == 'A') {
++pszTS;
- if(*pszTS == 'r') {
+ if(*pszTS == 'r' || *pszTS == 'R') {
++pszTS;
month = 3;
- } else if(*pszTS == 'y') {
+ } else if(*pszTS == 'y' || *pszTS == 'Y') {
++pszTS;
month = 5;
} else
@@ -392,17 +399,18 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
} else
ABORT_FINALIZE(RS_RET_INVLD_TIME);
break;
+ case 'a':
case 'A':
- if(*pszTS == 'p') {
+ if(*pszTS == 'p' || *pszTS == 'P') {
++pszTS;
- if(*pszTS == 'r') {
+ if(*pszTS == 'r' || *pszTS == 'R') {
++pszTS;
month = 4;
} else
ABORT_FINALIZE(RS_RET_INVLD_TIME);
- } else if(*pszTS == 'u') {
+ } else if(*pszTS == 'u' || *pszTS == 'U') {
++pszTS;
- if(*pszTS == 'g') {
+ if(*pszTS == 'g' || *pszTS == 'G') {
++pszTS;
month = 8;
} else
@@ -410,10 +418,11 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
} else
ABORT_FINALIZE(RS_RET_INVLD_TIME);
break;
+ case 's':
case 'S':
- if(*pszTS == 'e') {
+ if(*pszTS == 'e' || *pszTS == 'E') {
++pszTS;
- if(*pszTS == 'p') {
+ if(*pszTS == 'p' || *pszTS == 'P') {
++pszTS;
month = 9;
} else
@@ -421,10 +430,11 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
} else
ABORT_FINALIZE(RS_RET_INVLD_TIME);
break;
+ case 'o':
case 'O':
- if(*pszTS == 'c') {
+ if(*pszTS == 'c' || *pszTS == 'C') {
++pszTS;
- if(*pszTS == 't') {
+ if(*pszTS == 't' || *pszTS == 'T') {
++pszTS;
month = 10;
} else
@@ -432,10 +442,11 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
} else
ABORT_FINALIZE(RS_RET_INVLD_TIME);
break;
+ case 'n':
case 'N':
- if(*pszTS == 'o') {
+ if(*pszTS == 'o' || *pszTS == 'O') {
++pszTS;
- if(*pszTS == 'v') {
+ if(*pszTS == 'v' || *pszTS == 'V') {
++pszTS;
month = 11;
} else
@@ -443,10 +454,11 @@ ParseTIMESTAMP3164(struct syslogTime *pTime, uchar** ppszTS)
} else
ABORT_FINALIZE(RS_RET_INVLD_TIME);
break;
+ case 'd':
case 'D':
- if(*pszTS == 'e') {
+ if(*pszTS == 'e' || *pszTS == 'E') {
++pszTS;
- if(*pszTS == 'c') {
+ if(*pszTS == 'c' || *pszTS == 'C') {
++pszTS;
month = 12;
} else
diff --git a/runtime/modules.c b/runtime/modules.c
index b588909e..eee3b46e 100644
--- a/runtime/modules.c
+++ b/runtime/modules.c
@@ -466,10 +466,12 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
ABORT_FINALIZE(localRet);
localRet = (*pNew->modQueryEtryPt)((uchar*)"endTransaction", &pNew->mod.om.endTransaction);
- if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND)
- pNew->mod.om.beginTransaction = dummyEndTransaction;
- else if(localRet != RS_RET_OK)
+ if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) {
+ pNew->mod.om.endTransaction = dummyEndTransaction;
+ //pNew->mod.om.beginTransaction = dummyEndTransaction;
+ } else if(localRet != RS_RET_OK) {
ABORT_FINALIZE(localRet);
+ }
break;
case eMOD_LIB:
break;
diff --git a/runtime/queue.c b/runtime/queue.c
index cb14b58d..8388d00e 100644
--- a/runtime/queue.c
+++ b/runtime/queue.c
@@ -1044,6 +1044,7 @@ static rsRetVal qAddDirect(qqueue_t *pThis, void* pUsr)
iRet = pThis->pConsumer(pThis->pUsr, &singleBatch);
objDestruct(pUsr);
+dbgprintf("XXXX: qAddDirect returns %d\n", iRet);
RETiRet;
}
@@ -2442,6 +2443,7 @@ doEnqSingleObj(qqueue_t *pThis, flowControl_t flowCtlType, void *pUsr)
CHKiRet(qqueueAdd(pThis, pUsr));
finalize_it:
+dbgprintf("XXXX: queueEnqObj returns %d\n", iRet);
RETiRet;
}
diff --git a/runtime/rule.c b/runtime/rule.c
index 182d616a..bcd82e5f 100644
--- a/runtime/rule.c
+++ b/runtime/rule.c
@@ -83,6 +83,7 @@ DEFFUNC_llExecFunc(processMsgDoActions)
}
iRetMod = actionCallAction(pAction, pDoActData->pMsg);
+dbgprintf("XXXX: processMsgDoActions returns %d\n", iRet);
if(iRetMod == RS_RET_DISCARDMSG) {
ABORT_FINALIZE(RS_RET_DISCARDMSG);
} else if(iRetMod == RS_RET_SUSPENDED) {
@@ -271,6 +272,7 @@ processMsg(rule_t *pThis, msg_t *pMsg)
}
finalize_it:
+dbgprintf("XXXX: rule.processMsg returns %d\n", iRet);
RETiRet;
}
diff --git a/runtime/ruleset.c b/runtime/ruleset.c
index d98b4217..c1b6d490 100644
--- a/runtime/ruleset.c
+++ b/runtime/ruleset.c
@@ -138,8 +138,11 @@ finalize_it:
*/
DEFFUNC_llExecFunc(processMsgDoRules)
{
+ rsRetVal iRet;
ISOBJ_TYPE_assert(pData, rule);
- return rule.ProcessMsg((rule_t*) pData, (msg_t*) pParam);
+ iRet = rule.ProcessMsg((rule_t*) pData, (msg_t*) pParam);
+dbgprintf("XXXX: pcoessMsgDoRules returns %d\n", iRet);
+ return iRet;
}
@@ -159,8 +162,10 @@ processMsg(msg_t *pMsg)
CHKiRet(llExecFunc(&pThis->llRules, processMsgDoRules, pMsg));
finalize_it:
- if(iRet == RS_RET_DISCARDMSG)
- iRet = RS_RET_OK;
+dbgprintf("XXXX: processMsg got return state %d\n", iRet);
+
+ //if(iRet == RS_RET_DISCARDMSG)
+ //iRet = RS_RET_OK;
RETiRet;
}
diff --git a/runtime/stream.c b/runtime/stream.c
index 7c96324a..b1abb27e 100644
--- a/runtime/stream.c
+++ b/runtime/stream.c
@@ -849,6 +849,7 @@ doAsyncWriteInternal(strm_t *pThis, size_t lenBuf)
if(++pThis->iCnt == 1)
pthread_cond_signal(&pThis->notEmpty);
+finalize_it:
RETiRet;
}
diff --git a/runtime/stream.h b/runtime/stream.h
index c251e5c4..9577d704 100644
--- a/runtime/stream.h
+++ b/runtime/stream.h
@@ -131,8 +131,8 @@ typedef struct strm_s {
pthread_cond_t notFull;
pthread_cond_t notEmpty;
pthread_cond_t isEmpty;
- short iEnq;
- short iDeq;
+ unsigned short iEnq; /* this MUST be unsigned as we use module arithmetic (else invalid indexing happens!) */
+ unsigned short iDeq; /* this MUST be unsigned as we use module arithmetic (else invalid indexing happens!) */
short iCnt; /* current nbr of elements in buffer */
struct {
uchar *pBuf;
diff --git a/tcpsrv.c b/tcpsrv.c
index 5c1a4ac8..3f445063 100644
--- a/tcpsrv.c
+++ b/tcpsrv.c
@@ -261,7 +261,7 @@ static void deinit_tcp_listener(tcpsrv_t *pThis)
}
/* finally close our listen streams */
- for(i = 0 ; i < pThis->iLstnMax ; ++i) {
+ for(i = 0 ; i < pThis->iLstnCurr ; ++i) {
netstrm.Destruct(pThis->ppLstn + i);
}
}
@@ -280,12 +280,12 @@ addTcpLstn(void *pUsr, netstrm_t *pLstn)
ISOBJ_TYPE_assert(pThis, tcpsrv);
ISOBJ_TYPE_assert(pLstn, netstrm);
- if(pThis->iLstnMax >= TCPLSTN_MAX_DEFAULT)
+ if(pThis->iLstnCurr >= pThis->iLstnMax)
ABORT_FINALIZE(RS_RET_MAX_LSTN_REACHED);
- pThis->ppLstn[pThis->iLstnMax] = pLstn;
- pThis->ppLstnPort[pThis->iLstnMax] = pPortList;
- ++pThis->iLstnMax;
+ pThis->ppLstn[pThis->iLstnCurr] = pLstn;
+ pThis->ppLstnPort[pThis->iLstnCurr] = pPortList;
+ ++pThis->iLstnCurr;
finalize_it:
RETiRet;
@@ -327,15 +327,19 @@ finalize_it:
static rsRetVal
create_tcp_socket(tcpsrv_t *pThis)
{
- tcpLstnPortList_t *pEntry;
DEFiRet;
+ rsRetVal localRet;
+ tcpLstnPortList_t *pEntry;
ISOBJ_TYPE_assert(pThis, tcpsrv);
/* init all configured ports */
pEntry = pThis->pLstnPorts;
while(pEntry != NULL) {
- CHKiRet(initTCPListener(pThis, pEntry));
+ localRet = initTCPListener(pThis, pEntry);
+ if(localRet != RS_RET_OK) {
+ errmsg.LogError(0, localRet, "Could not create tcp listener, ignoring port %s.", pEntry->pszPort);
+ }
pEntry = pEntry->pNext;
}
@@ -534,7 +538,7 @@ Run(tcpsrv_t *pThis)
CHKiRet(nssel.ConstructFinalize(pSel));
/* Add the TCP listen sockets to the list of read descriptors. */
- for(i = 0 ; i < pThis->iLstnMax ; ++i) {
+ for(i = 0 ; i < pThis->iLstnCurr ; ++i) {
CHKiRet(nssel.Add(pSel, pThis->ppLstn[i], NSDSEL_RD));
}
@@ -552,7 +556,7 @@ Run(tcpsrv_t *pThis)
if(glbl.GetGlobalInputTermState() == 1)
break; /* terminate input! */
- for(i = 0 ; i < pThis->iLstnMax ; ++i) {
+ for(i = 0 ; i < pThis->iLstnCurr ; ++i) {
CHKiRet(nssel.IsReady(pSel, pThis->ppLstn[i], NSDSEL_RD, &bIsReady, &nfds));
if(bIsReady) {
DBGPRINTF("New connect on NSD %p.\n", pThis->ppLstn[i]);
@@ -591,7 +595,8 @@ finalize_it: /* this is a very special case - this time only we do not exit the
/* Standard-Constructor */
BEGINobjConstruct(tcpsrv) /* be sure to specify the object type also in END macro! */
- pThis->iSessMax = TCPSESS_MAX_DEFAULT; /* TODO: useful default ;) */
+ pThis->iSessMax = TCPSESS_MAX_DEFAULT;
+ pThis->iLstnMax = TCPLSTN_MAX_DEFAULT;
pThis->addtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
pThis->OnMsgReceive = NULL;
ENDobjConstruct(tcpsrv)
@@ -615,8 +620,8 @@ tcpsrvConstructFinalize(tcpsrv_t *pThis)
CHKiRet(netstrms.ConstructFinalize(pThis->pNS));
/* set up listeners */
- CHKmalloc(pThis->ppLstn = calloc(TCPLSTN_MAX_DEFAULT, sizeof(netstrm_t*)));
- CHKmalloc(pThis->ppLstnPort = calloc(TCPLSTN_MAX_DEFAULT, sizeof(tcpLstnPortList_t*)));
+ CHKmalloc(pThis->ppLstn = calloc(pThis->iLstnMax, sizeof(netstrm_t*)));
+ CHKmalloc(pThis->ppLstnPort = calloc(pThis->iLstnMax, sizeof(tcpLstnPortList_t*)));
iRet = pThis->OpenLstnSocks(pThis);
finalize_it:
@@ -833,6 +838,20 @@ SetDrvrPermPeers(tcpsrv_t *pThis, permittedPeers_t *pPermPeers)
* -------------------------------------------------------------------------- */
+/* set max number of listeners
+ * this must be called before ConstructFinalize, or it will have no effect!
+ * rgerhards, 2009-08-17
+ */
+static rsRetVal
+SetLstnMax(tcpsrv_t *pThis, int iMax)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, tcpsrv);
+ pThis->iLstnMax = iMax;
+ RETiRet;
+}
+
+
/* set max number of sessions
* this must be called before ConstructFinalize, or it will have no effect!
* rgerhards, 2009-04-09
@@ -875,6 +894,7 @@ CODESTARTobjQueryInterface(tcpsrv)
pIf->SetInputName = SetInputName;
pIf->SetAddtlFrameDelim = SetAddtlFrameDelim;
pIf->SetSessMax = SetSessMax;
+ pIf->SetLstnMax = SetLstnMax;
pIf->SetDrvrMode = SetDrvrMode;
pIf->SetDrvrAuthMode = SetDrvrAuthMode;
pIf->SetDrvrPermPeers = SetDrvrPermPeers;
diff --git a/tcpsrv.h b/tcpsrv.h
index 70682398..64065aab 100644
--- a/tcpsrv.h
+++ b/tcpsrv.h
@@ -54,9 +54,10 @@ struct tcpsrv_s {
uchar *pszInputName; /**< value to be used as input name */
ruleset_t *pRuleset; /**< ruleset to bind to */
permittedPeers_t *pPermPeers;/**< driver's permitted peers */
- int iLstnMax; /**< max nbr of listeners currently supported */
+ int iLstnCurr; /**< max nbr of listeners currently supported */
netstrm_t **ppLstn; /**< our netstream listners */
tcpLstnPortList_t **ppLstnPort; /**< pointer to relevant listen port description */
+ int iLstnMax; /**< max number of listners supported */
int iSessMax; /**< max number of sessions supported */
tcpLstnPortList_t *pLstnPorts; /**< head pointer for listen ports */
int addtlFrameDelim; /**< additional frame delimiter for plain TCP syslog framing (e.g. to handle NetScreen) */
@@ -111,8 +112,10 @@ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */
/* added v6 */
rsRetVal (*SetOnMsgReceive)(tcpsrv_t *pThis, rsRetVal (*OnMsgReceive)(tcps_sess_t*, uchar*, int)); /* 2009-05-24 */
rsRetVal (*SetRuleset)(tcpsrv_t *pThis, ruleset_t*); /* 2009-06-12 */
+ /* added v7 */
+ rsRetVal (*SetLstnMax)(tcpsrv_t *pThis, int iMaxLstn); /* 2009-08-17 */
ENDinterface(tcpsrv)
-#define tcpsrvCURR_IF_VERSION 6 /* increment whenever you change the interface structure! */
+#define tcpsrvCURR_IF_VERSION 7 /* increment whenever you change the interface structure! */
/* change for v4:
* - SetAddtlFrameDelim() added -- rgerhards, 2008-12-10
* - SetInputName() added -- rgerhards, 2008-12-10
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4ea641f0..c31e9eaa 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -21,6 +21,7 @@ TESTS += omod-if-array.sh \
inputname.sh \
threadingmq.sh \
threadingmqaq.sh \
+ discard.sh \
fieldtest.sh
endif
@@ -77,6 +78,7 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \
testsuites/1.parse1 \
testsuites/2.parse1 \
testsuites/3.parse1 \
+ testsuites/4.parse1 \
testsuites/oversizeTag-1.parse1 \
testsuites/date1.parse1 \
testsuites/date2.parse1 \
@@ -114,6 +116,8 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \
testsuites/1.inputname_imtcp_12515 \
testsuites/1.inputname_imtcp_12516 \
omod-if-array.sh \
+ discard.sh \
+ testsuites/discard.conf \
diag.sh \
testsuites/diag-common.conf \
daqueue-persist.sh \
diff --git a/tests/discard.sh b/tests/discard.sh
new file mode 100755
index 00000000..0fafc7d9
--- /dev/null
+++ b/tests/discard.sh
@@ -0,0 +1,16 @@
+# Test for discard functionality
+# This test checks if discard works. It is not a perfect test but
+# will find at least segfaults and obviously not discarded messages.
+# added 2009-07-30 by Rgerhards
+# This file is part of the rsyslog project, released under GPLv3
+# uncomment for debugging support:
+echo TEST discard.sh: testing discard functionality
+source $srcdir/diag.sh init
+source $srcdir/diag.sh startup discard.conf
+# 20000 messages should be enough - the disk test is slow enough ;)
+sleep 4
+source $srcdir/diag.sh tcpflood 127.0.0.1 13514 1 10 1
+source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
+source $srcdir/diag.sh wait-shutdown
+source $srcdir/diag.sh seq-check 10 -s2
+source $srcdir/diag.sh exit
diff --git a/tests/rt-init.c b/tests/rt-init.c
index aaac7ed1..b9c4ce2e 100644
--- a/tests/rt-init.c
+++ b/tests/rt-init.c
@@ -21,10 +21,9 @@
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
*/
-#include <stdio.h>
-
#include "rsyslog.h"
#include "testbench.h"
+#include <stdio.h> /* must be last, else we get a zlib compile error on some platforms */
MODULE_TYPE_TESTBENCH
diff --git a/tests/testsuites/4.parse1 b/tests/testsuites/4.parse1
new file mode 100644
index 00000000..07e2445a
--- /dev/null
+++ b/tests/testsuites/4.parse1
@@ -0,0 +1,4 @@
+<29>Jul 31 21:39:21 example-b example-gw[10538]: disconnect host=/192.0.2.1 destination=192.0.2.2/11282 in=3274 out=1448 duration=0
+29,daemon,notice,Jul 31 21:39:21,example-b,example-gw,example-gw[10538]:, disconnect host=/192.0.2.1 destination=192.0.2.2/11282 in=3274 out=1448 duration=0
+# yet another real-life sample where we had some issues with - the important
+# part is the dash inside the hostname!
diff --git a/tests/testsuites/discard.conf b/tests/testsuites/discard.conf
new file mode 100644
index 00000000..bbe2fe77
--- /dev/null
+++ b/tests/testsuites/discard.conf
@@ -0,0 +1,13 @@
+# Test for discard functionality
+# rgerhards, 2009-07-30
+$IncludeConfig diag-common.conf
+
+$ModLoad ../plugins/imtcp/.libs/imtcp
+$MainMsgQueueTimeoutShutdown 10000
+$InputTCPServerRun 13514
+
+:msg, contains, "00000001" ~
+
+$template outfmt,"%msg:F,58:2%\n"
+$template dynfile,"rsyslog.out.log" # trick to use relative path names!
+:msg, contains, "msgnum:" ?dynfile;outfmt
diff --git a/tests/testsuites/upcase-date.parse1 b/tests/testsuites/upcase-date.parse1
new file mode 100644
index 00000000..2d21222a
--- /dev/null
+++ b/tests/testsuites/upcase-date.parse1
@@ -0,0 +1,4 @@
+<6>AUG 10 22:18:24 2009 netips-warden2-p [audit] user=[*SMS] src=192.168.11.11 iface=5 access=9 Update State Reset
+6,kern,info,Aug 10 22:18:24,2009,,, netips-warden2-p [audit] user=[*SMS] src=192.168.11.11 iface=5 access=9 Update State Reset
+#Example from RFC3164, section 5.4
+#Only the first two lines are important, you may place anything behind them!
diff --git a/tools/syslogd.c b/tools/syslogd.c
index 40e9e92c..ff671138 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -1225,7 +1225,7 @@ int parseLegacySyslogMsg(msg_t *pMsg, int flags)
if(flags & PARSE_HOSTNAME) {
i = 0;
while((isalnum(p2parse[i]) || p2parse[i] == '.' || p2parse[i] == '.'
- || p2parse[i] == '_') && i < CONF_TAG_MAXSIZE) {
+ || p2parse[i] == '_' || p2parse[i] == '-') && i < CONF_TAG_MAXSIZE) {
bufParseHOSTNAME[i] = p2parse[i];
++i;
}