summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog47
-rw-r--r--action.c44
-rw-r--r--configure.ac8
-rw-r--r--doc/manual.html2
-rw-r--r--doc/omrelp.html41
-rw-r--r--grammar/rainerscript.c186
-rw-r--r--grammar/rainerscript.h2
-rw-r--r--plugins/imuxsock/imuxsock.c11
-rw-r--r--plugins/omrelp/omrelp.c146
-rw-r--r--plugins/omudpspoof/omudpspoof.c2
-rw-r--r--runtime/module-template.h22
-rw-r--r--runtime/modules.c4
-rw-r--r--runtime/modules.h1
-rw-r--r--runtime/nsd_gtls.c79
-rw-r--r--runtime/queue.c7
-rw-r--r--runtime/ratelimit.c14
-rw-r--r--runtime/ratelimit.h2
-rw-r--r--runtime/rsyslog.h4
-rw-r--r--runtime/ruleset.c23
-rw-r--r--runtime/stringbuf.c72
-rw-r--r--runtime/stringbuf.h7
-rwxr-xr-xtests/queue-persist-drvr.sh7
-rw-r--r--tools/syslogd.c1
23 files changed, 548 insertions, 184 deletions
diff --git a/ChangeLog b/ChangeLog
index b8027636..4c0698de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,13 +1,36 @@
---------------------------------------------------------------------------
-Version 7.3.10 [devel] 2013-04-??
-- added RainerScript re_extract() function
-- templates now permit substring extraction relative to end-of-string
+Version 7.3.11 [devel] 2013-04-??
- added support for encrypting log files
-- bugfix: imuxsock aborted under some conditions
- regression from ratelimiting enhancements
- bugfix: $PreserveFQDN is not properly working
Thanks to Louis Bouchard for the patch
closes: http://bugzilla.adiscon.com/show_bug.cgi?id=426
+- bugfix: imuxsock aborted due to problem in ratelimiting code
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: imuxsock aborted under some conditions
+ regression from ratelimiting enhancements - this was a different one
+ to the one Tomas Heinrich patched.
+---------------------------------------------------------------------------
+Version 7.3.10 [devel] 2013-04-10
+- added RainerScript re_extract() function
+- omrelp: added support for RainerScript-based configuration
+- omrelp: added ability to specify session timeout
+- templates now permit substring extraction relative to end-of-string
+- bugfix: failover/action suspend did not work correctly
+ This was experienced if the retry action took more than one second
+ to complete. For suspending, a cached timestamp was used, and if the
+ retry took longer, that timestamp was already in the past. As a
+ result, the action never was kept in suspended state, and as such
+ no failover happened. The suspend functionalit now does no longer use
+ the cached timestamp (should not have any performance implication, as
+ action suspend occurs very infrequently).
+- bugfix: gnutls RFC5425 driver had some undersized buffers
+ Thanks to Tomas Heinrich for the patch.
+- bugfix: nested if/prifilt conditions did not work properly
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=415
+- bugfix: imuxsock aborted under some conditions
+ regression from ratelimiting enhancements
+- bugfix: build problems on Solaris
+ Thanks to Martin Carpenter for the patches.
---------------------------------------------------------------------------
Version 7.3.9 [devel] 2013-03-27
- support for signing logs added
@@ -225,6 +248,16 @@ Version 7.2.7 [v7-stable] 2013-03-??
The rsyslog debug log file is now continued to be written across the
fork.
- updated systemd files to match current systemd source
+- bugfix: failover/action suspend did not work correctly
+ This was experienced if the retry action took more than one second
+ to complete. For suspending, a cached timestamp was used, and if the
+ retry took longer, that timestamp was already in the past. As a
+ result, the action never was kept in suspended state, and as such
+ no failover happened. The suspend functionalit now does no longer use
+ the cached timestamp (should not have any performance implication, as
+ action suspend occurs very infrequently).
+- bugfix: nested if/prifilt conditions did not work properly
+ closes: http://bugzilla.adiscon.com/show_bug.cgi?id=415
- bugfix: script == comparison did not work properly on JSON objects
[backport from 7.3 branch]
- bugfix: imudp scheduling parameters did affect main thread, not imudp
@@ -250,6 +283,10 @@ Version 7.2.7 [v7-stable] 2013-03-??
To use that functionality, legacy rsyslog.conf syntax had to be used.
Also, the doc was missing information on the "ParseTrusted" set of
config directives.
+- bugfix: parameter action.execOnlyWhenPreviousIsSuspended was accidently
+ of integer-type. For obvious reasons, it needs to be boolean. Note
+ that this change can break existing configurations if they circumvented
+ the problem by using 0/1 values.
- doc bugfix: rsyslog.conf man page had invalid file format info
closes: http://bugzilla.adiscon.com/show_bug.cgi?id=418
----------------------------------------------------------------------------
diff --git a/action.c b/action.c
index 89282389..49ab4839 100644
--- a/action.c
+++ b/action.c
@@ -188,7 +188,7 @@ static struct cnfparamdescr cnfparamdescr[] = {
{ "action.execonlyeverynthtime", eCmdHdlrInt, 0 }, /* legacy: actionexeconlyeverynthtime */
{ "action.execonlyeverynthtimetimeout", eCmdHdlrInt, 0 }, /* legacy: actionexeconlyeverynthtimetimeout */
{ "action.execonlyonceeveryinterval", eCmdHdlrInt, 0 }, /* legacy: actionexeconlyonceeveryinterval */
- { "action.execonlywhenpreviousissuspended", eCmdHdlrInt, 0 }, /* legacy: actionexeconlywhenpreviousissuspended */
+ { "action.execonlywhenpreviousissuspended", eCmdHdlrBinary, 0 }, /* legacy: actionexeconlywhenpreviousissuspended */
{ "action.repeatedmsgcontainsoriginalmsg", eCmdHdlrBinary, 0 }, /* legacy: repeatedmsgcontainsoriginalmsg */
{ "action.resumeretrycount", eCmdHdlrInt, 0 }, /* legacy: actionresumeretrycount */
{ "action.resumeinterval", eCmdHdlrInt, 0 }
@@ -605,13 +605,17 @@ static void actionDisable(action_t *pThis)
* CPU time. TODO: maybe a config option for that?
* rgerhards, 2007-08-02
*/
-static inline void actionSuspend(action_t *pThis, time_t ttNow)
+static inline void actionSuspend(action_t *pThis)
{
- if(ttNow == NO_TIME_PROVIDED)
- datetime.GetTime(&ttNow);
+ time_t ttNow;
+
+ /* note: we can NOT use a cached timestamp, as time may have evolved
+ * since caching, and this would break logic (and it actually did so!)
+ */
+ datetime.GetTime(&ttNow);
pThis->ttResumeRtry = ttNow + pThis->iResumeInterval * (pThis->iNbrResRtry / 10 + 1);
actionSetState(pThis, ACT_STATE_SUSP);
- DBGPRINTF("earliest retry=%d\n", (int) pThis->ttResumeRtry);
+ DBGPRINTF("action suspended, earliest retry=%d\n", (int) pThis->ttResumeRtry);
}
@@ -631,7 +635,7 @@ static inline void actionSuspend(action_t *pThis, time_t ttNow)
* of its inability to recover. -- rgerhards, 2010-04-26.
*/
static inline rsRetVal
-actionDoRetry(action_t *pThis, time_t ttNow, int *pbShutdownImmediate)
+actionDoRetry(action_t *pThis, int *pbShutdownImmediate)
{
int iRetries;
int iSleepPeriod;
@@ -642,7 +646,9 @@ actionDoRetry(action_t *pThis, time_t ttNow, int *pbShutdownImmediate)
iRetries = 0;
while((*pbShutdownImmediate == 0) && pThis->eState == ACT_STATE_RTRY) {
+ DBGPRINTF("actionDoRetry: enter loop, iRetries=%d\n", iRetries);
iRet = pThis->pMod->tryResume(pThis->pModData);
+ DBGPRINTF("actionDoRetry: action->tryResume returned %d\n", iRet);
if((pThis->iResumeOKinRow > 9) && (pThis->iResumeOKinRow % 10 == 0)) {
bTreatOKasSusp = 1;
pThis->iResumeOKinRow = 0;
@@ -650,16 +656,18 @@ actionDoRetry(action_t *pThis, time_t ttNow, int *pbShutdownImmediate)
bTreatOKasSusp = 0;
}
if((iRet == RS_RET_OK) && (!bTreatOKasSusp)) {
+ DBGPRINTF("actionDoRetry: had success RDY again (iRet=%d)\n", iRet);
actionSetState(pThis, ACT_STATE_RDY);
} else if(iRet == RS_RET_SUSPENDED || bTreatOKasSusp) {
/* max retries reached? */
+ DBGPRINTF("actionDoRetry: check for max retries, iResumeRetryCount %d, iRetries %d\n",
+ pThis->iResumeRetryCount, iRetries);
if((pThis->iResumeRetryCount != -1 && iRetries >= pThis->iResumeRetryCount)) {
- actionSuspend(pThis, ttNow);
+ actionSuspend(pThis);
} else {
++pThis->iNbrResRtry;
++iRetries;
iSleepPeriod = pThis->iResumeInterval;
- ttNow += iSleepPeriod; /* not truly exact, but sufficiently... */
srSleep(iSleepPeriod, 0);
if(*pbShutdownImmediate) {
ABORT_FINALIZE(RS_RET_FORCE_TERM);
@@ -706,7 +714,7 @@ static rsRetVal actionTryResume(action_t *pThis, int *pbShutdownImmediate)
if(pThis->eState == ACT_STATE_RTRY) {
if(ttNow == NO_TIME_PROVIDED) /* use cached result if we have it */
datetime.GetTime(&ttNow);
- CHKiRet(actionDoRetry(pThis, ttNow, pbShutdownImmediate));
+ CHKiRet(actionDoRetry(pThis, pbShutdownImmediate));
}
if(Debug && (pThis->eState == ACT_STATE_RTRY ||pThis->eState == ACT_STATE_SUSP)) {
@@ -953,6 +961,8 @@ actionProcessMessage(action_t *pThis, msg_t *pMsg, void *actParams, int *pbShutd
ISOBJ_TYPE_assert(pMsg, msg);
CHKiRet(actionPrepare(pThis, pbShutdownImmediate));
+ if(pThis->pMod->mod.om.SetShutdownImmdtPtr != NULL)
+ pThis->pMod->mod.om.SetShutdownImmdtPtr(pThis->pModData, pbShutdownImmediate);
if(pThis->eState == ACT_STATE_ITX)
CHKiRet(actionCallDoAction(pThis, pMsg, actParams));
@@ -1111,6 +1121,7 @@ submitBatch(action_t *pAction, batch_t *pBatch, int nElem)
assert(pBatch != NULL);
+ DBGPRINTF("submitBatch: enter, nElem %d\n", nElem);
wasDoneTo = pBatch->iDoneUpTo;
bDone = 0;
do {
@@ -1132,7 +1143,8 @@ submitBatch(action_t *pAction, batch_t *pBatch, int nElem)
|| localRet == RS_RET_DEFER_COMMIT) {
bDone = 1;
} else if(localRet == RS_RET_SUSPENDED) {
- ; /* do nothing, this will retry the full batch */
+ DBGPRINTF("action ret RS_RET_SUSPENDED - retry full batch\n");
+ /* do nothing, this will retry the full batch */
} else if(localRet == RS_RET_ACTION_FAILED) {
/* in this case, everything not yet committed is BAD */
for(i = pBatch->iDoneUpTo ; i < wasDoneTo + nElem ; ++i) {
@@ -1262,8 +1274,11 @@ processBatchMain(action_t *pAction, batch_t *pBatch, int *pbShutdownImmediate)
assert(pBatch != NULL);
- pbShutdownImmdtSave = pBatch->pbShutdownImmediate;
- pBatch->pbShutdownImmediate = pbShutdownImmediate;
+ if(pbShutdownImmediate != NULL) {
+ pbShutdownImmdtSave = pBatch->pbShutdownImmediate;
+ pBatch->pbShutdownImmediate = pbShutdownImmediate;
+dbgprintf("DDDD: processBatchMain ShutdownImmediate is %p, was %p\n", pBatch->pbShutdownImmediate, pbShutdownImmdtSave);
+ }
CHKiRet(prepareBatch(pAction, pBatch, &activeSave, &bMustRestoreActivePtr));
/* We now must guard the output module against execution by multiple threads. The
@@ -1294,7 +1309,8 @@ processBatchMain(action_t *pAction, batch_t *pBatch, int *pbShutdownImmediate)
}
finalize_it:
- pBatch->pbShutdownImmediate = pbShutdownImmdtSave;
+ if(pbShutdownImmediate != NULL)
+ pBatch->pbShutdownImmediate = pbShutdownImmdtSave;
RETiRet;
}
#pragma GCC diagnostic warning "-Wempty-body"
@@ -1864,7 +1880,7 @@ addAction(action_t **ppAction, modInfo_t *pMod, void *pModData,
pAction->eState = ACT_STATE_RDY; /* action is enabled */
if(bSuspended)
- actionSuspend(pAction, datetime.GetTime(NULL)); /* "good" time call, only during init and unavoidable */
+ actionSuspend(pAction);
CHKiRet(actionConstructFinalize(pAction, queueParams));
diff --git a/configure.ac b/configure.ac
index 0ec29f0d..3c5a1002 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([rsyslog],[7.3.9],[rsyslog@lists.adiscon.com])
+AC_INIT([rsyslog],[7.3.10],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
@@ -56,6 +56,10 @@ case "${host}" in
AC_DEFINE([OS_SOLARIS], [1], [Indicator for a Solaris OS])
AC_DEFINE([_POSIX_PTHREAD_SEMANTICS], [1], [Use POSIX pthread semantics])
SOL_LIBS="-lsocket -lnsl"
+ # Solaris libuuid does not ship with a pkgconfig file so override the appropriate
+ # variables (but only if they have not been set by the user).
+ LIBUUID_CFLAGS=${LIBUUID_CFLAGS:= }
+ LIBUUID_LIBS=${LIBUUID_LIBS:=-luuid}
AC_SUBST(SOL_LIBS)
;;
esac
@@ -960,7 +964,7 @@ AC_ARG_ENABLE(relp,
[enable_relp=no]
)
if test "x$enable_relp" = "xyes"; then
- PKG_CHECK_MODULES(RELP, relp >= 1.0.2)
+ PKG_CHECK_MODULES(RELP, relp >= 1.0.3)
fi
AM_CONDITIONAL(ENABLE_RELP, test x$enable_relp = xyes)
diff --git a/doc/manual.html b/doc/manual.html
index 6fba9a05..a1e39c9d 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -19,7 +19,7 @@ professional services</a> available directly from the source!</p>
<p><b>Please visit the <a href="http://www.rsyslog.com/sponsors">rsyslog sponsor's page</a>
to honor the project sponsors or become one yourself!</b> We are very grateful for any help towards the
project goals.</p>
-<p><b>This documentation is for version 7.3.9 (devel branch) of rsyslog.</b>
+<p><b>This documentation is for version 7.3.10 (devel branch) of rsyslog.</b>
Visit the <i><a href="http://www.rsyslog.com/status">rsyslog status page</a></i></b>
to obtain current version information and project status.
</p><p><b>If you like rsyslog, you might
diff --git a/doc/omrelp.html b/doc/omrelp.html
index 22e6845f..8858f884 100644
--- a/doc/omrelp.html
+++ b/doc/omrelp.html
@@ -16,10 +16,34 @@ RELP protocol. For RELP's advantages over plain tcp syslog, please see
the documentation for <a href="imrelp.html">imrelp</a>
(the server counterpart).&nbsp;</p>
<span style="font-weight: bold;">Setup</span>
-<p>Please note the <a href="http://www.librelp.com">librelp</a>
+<p>Please note that <a href="http://www.librelp.com">librelp</a>
is required for imrelp (it provides the core relp protocol
implementation).</p>
-<p><b>Configuration Directives</b>:</p>
+<p><b>Action Configuration Parameters</b>:</p>
+<p>This module supports RainerScript configuration starting with
+rsyslog 7.3.10. For older versions, legacy configuration directives
+must be used.
+<ul>
+ <li><b>target </b>(mandatory)<br>
+ The target server to connect to.
+ </li>
+ <li><b>template </b>(not mandatory, default "RSYSLOG_ForwardFormat")<br>
+ Defines the template to be used for the output.
+ </li>
+ <li><b>timeout </b>(not mandatory, default 90)<br>
+ Timeout for relp sessions. If set too low, valid sessions
+ may be considered dead and tried to recover.
+ </li>
+</ul>
+<p><b>Sample:</b></p>
+<p>The following sample sends all messages to the central server
+"centralserv" at port 2514 (note that that server must run imrelp on
+port 2514).
+</p>
+<textarea rows="3" cols="60">module(load="omrelp")
+action(type="omrelp" target="centralserv" port="2514")
+</textarea>
+<p><b>Legacy Configuration Directives</b>:</p>
<p>This module uses old-style action configuration to keep
consistent with the forwarding rule. So far, no additional
configuration directives can be specified. To send a message via RELP,
@@ -33,18 +57,15 @@ use</p>
<b>Caveats/Known Bugs:</b>
<p>See <a href="imrelp.html">imrelp</a>,
which documents them.&nbsp;</p>
-<p><b>Sample:</b></p>
+<p><b>Legacy Sample:</b></p>
<p>The following sample sends all messages to the central server
"centralserv" at port 2514 (note that that server must run imrelp on
-port 2514). Rsyslog's high-precision timestamp format is used, thus the
-special "RSYSLOG_ForwardFormat" (case sensitive!) template is used.<br>
+port 2514).
</p>
-<textarea rows="15" cols="60">$ModLoad omrelp
-# forward messages to the remote server "myserv" on
-# port 2514
-*.* :omrelp:centralserv:2514;RSYSLOG_ForwardFormat
+<textarea rows="3" cols="60">$ModLoad omrelp
+*.* :omrelp:centralserv:2514
</textarea>
-Note: to use IPv6 addresses, encode them in [::1] format.
+<p>Note: to use IPv6 addresses, encode them in [::1] format.
<p>[<a href="rsyslog_conf.html">rsyslog.conf overview</a>]
[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>
<p><font size="2">This documentation is part of the
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index 00e1e835..89cf946c 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -2,7 +2,7 @@
*
* Module begun 2011-07-01 by Rainer Gerhards
*
- * Copyright 2011-2012 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2011-2013 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -2252,31 +2252,33 @@ cnfexprPrint(struct cnfexpr *expr, int indent)
break;
}
}
+/* print only the given stmt
+ * if "subtree" equals 1, the full statement subtree is printed, else
+ * really only the statement.
+ */
void
-cnfstmtPrint(struct cnfstmt *root, int indent)
+cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree)
{
- struct cnfstmt *stmt;
char *cstr;
- //dbgprintf("stmt %p, indent %d, type '%c'\n", expr, indent, expr->nodetype);
- for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
- switch(stmt->nodetype) {
- case S_NOP:
- doIndent(indent); dbgprintf("NOP\n");
- break;
- case S_STOP:
- doIndent(indent); dbgprintf("STOP\n");
- break;
- case S_CALL:
- cstr = es_str2cstr(stmt->d.s_call.name, NULL);
- doIndent(indent); dbgprintf("CALL [%s]\n", cstr);
- free(cstr);
- break;
- case S_ACT:
- doIndent(indent); dbgprintf("ACTION %p [%s]\n", stmt->d.act, stmt->printable);
- break;
- case S_IF:
- doIndent(indent); dbgprintf("IF\n");
- cnfexprPrint(stmt->d.s_if.expr, indent+1);
+ switch(stmt->nodetype) {
+ case S_NOP:
+ doIndent(indent); dbgprintf("NOP\n");
+ break;
+ case S_STOP:
+ doIndent(indent); dbgprintf("STOP\n");
+ break;
+ case S_CALL:
+ cstr = es_str2cstr(stmt->d.s_call.name, NULL);
+ doIndent(indent); dbgprintf("CALL [%s]\n", cstr);
+ free(cstr);
+ break;
+ case S_ACT:
+ doIndent(indent); dbgprintf("ACTION %p [%s]\n", stmt->d.act, stmt->printable);
+ break;
+ case S_IF:
+ doIndent(indent); dbgprintf("IF\n");
+ cnfexprPrint(stmt->d.s_if.expr, indent+1);
+ if(subtree) {
doIndent(indent); dbgprintf("THEN\n");
cnfstmtPrint(stmt->d.s_if.t_then, indent+1);
if(stmt->d.s_if.t_else != NULL) {
@@ -2284,54 +2286,67 @@ cnfstmtPrint(struct cnfstmt *root, int indent)
cnfstmtPrint(stmt->d.s_if.t_else, indent+1);
}
doIndent(indent); dbgprintf("END IF\n");
- break;
- case S_SET:
- doIndent(indent); dbgprintf("SET %s =\n",
- stmt->d.s_set.varname);
- cnfexprPrint(stmt->d.s_set.expr, indent+1);
- doIndent(indent); dbgprintf("END SET\n");
- break;
- case S_UNSET:
- doIndent(indent); dbgprintf("UNSET %s\n",
- stmt->d.s_unset.varname);
- break;
- case S_PRIFILT:
- doIndent(indent); dbgprintf("PRIFILT '%s'\n", stmt->printable);
- pmaskPrint(stmt->d.s_prifilt.pmask, indent);
+ }
+ break;
+ case S_SET:
+ doIndent(indent); dbgprintf("SET %s =\n",
+ stmt->d.s_set.varname);
+ cnfexprPrint(stmt->d.s_set.expr, indent+1);
+ doIndent(indent); dbgprintf("END SET\n");
+ break;
+ case S_UNSET:
+ doIndent(indent); dbgprintf("UNSET %s\n",
+ stmt->d.s_unset.varname);
+ break;
+ case S_PRIFILT:
+ doIndent(indent); dbgprintf("PRIFILT '%s'\n", stmt->printable);
+ pmaskPrint(stmt->d.s_prifilt.pmask, indent);
+ if(subtree) {
cnfstmtPrint(stmt->d.s_prifilt.t_then, indent+1);
if(stmt->d.s_prifilt.t_else != NULL) {
doIndent(indent); dbgprintf("ELSE\n");
cnfstmtPrint(stmt->d.s_prifilt.t_else, indent+1);
}
doIndent(indent); dbgprintf("END PRIFILT\n");
- break;
- case S_PROPFILT:
- doIndent(indent); dbgprintf("PROPFILT\n");
- doIndent(indent); dbgprintf("\tProperty.: '%s'\n",
- propIDToName(stmt->d.s_propfilt.propID));
- if(stmt->d.s_propfilt.propName != NULL) {
- cstr = es_str2cstr(stmt->d.s_propfilt.propName, NULL);
- doIndent(indent);
- dbgprintf("\tCEE-Prop.: '%s'\n", cstr);
- free(cstr);
- }
- doIndent(indent); dbgprintf("\tOperation: ");
- if(stmt->d.s_propfilt.isNegated)
- dbgprintf("NOT ");
- dbgprintf("'%s'\n", getFIOPName(stmt->d.s_propfilt.operation));
- if(stmt->d.s_propfilt.pCSCompValue != NULL) {
- doIndent(indent); dbgprintf("\tValue....: '%s'\n",
- rsCStrGetSzStrNoNULL(stmt->d.s_propfilt.pCSCompValue));
- }
+ }
+ break;
+ case S_PROPFILT:
+ doIndent(indent); dbgprintf("PROPFILT\n");
+ doIndent(indent); dbgprintf("\tProperty.: '%s'\n",
+ propIDToName(stmt->d.s_propfilt.propID));
+ if(stmt->d.s_propfilt.propName != NULL) {
+ cstr = es_str2cstr(stmt->d.s_propfilt.propName, NULL);
+ doIndent(indent);
+ dbgprintf("\tCEE-Prop.: '%s'\n", cstr);
+ free(cstr);
+ }
+ doIndent(indent); dbgprintf("\tOperation: ");
+ if(stmt->d.s_propfilt.isNegated)
+ dbgprintf("NOT ");
+ dbgprintf("'%s'\n", getFIOPName(stmt->d.s_propfilt.operation));
+ if(stmt->d.s_propfilt.pCSCompValue != NULL) {
+ doIndent(indent); dbgprintf("\tValue....: '%s'\n",
+ rsCStrGetSzStrNoNULL(stmt->d.s_propfilt.pCSCompValue));
+ }
+ if(subtree) {
doIndent(indent); dbgprintf("THEN\n");
cnfstmtPrint(stmt->d.s_propfilt.t_then, indent+1);
doIndent(indent); dbgprintf("END PROPFILT\n");
- break;
- default:
- dbgprintf("error: unknown stmt type %u\n",
- (unsigned) stmt->nodetype);
- break;
}
+ break;
+ default:
+ dbgprintf("error: unknown stmt type %u\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+}
+void
+cnfstmtPrint(struct cnfstmt *root, int indent)
+{
+ struct cnfstmt *stmt;
+ //dbgprintf("stmt %p, indent %d, type '%c'\n", expr, indent, expr->nodetype);
+ for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
+ cnfstmtPrintOnly(stmt, indent, 1);
}
}
@@ -3621,3 +3636,52 @@ unescapeStr(uchar *s, int len)
s[iDst] = '\0';
}
}
+
+char *
+tokenval2str(int tok)
+{
+ if(tok < 256) return "";
+ switch(tok) {
+ case NAME: return "NAME";
+ case FUNC: return "FUNC";
+ case BEGINOBJ: return "BEGINOBJ";
+ case ENDOBJ: return "ENDOBJ";
+ case BEGIN_ACTION: return "BEGIN_ACTION";
+ case BEGIN_PROPERTY: return "BEGIN_PROPERTY";
+ case BEGIN_CONSTANT: return "BEGIN_CONSTANT";
+ case BEGIN_TPL: return "BEGIN_TPL";
+ case BEGIN_RULESET: return "BEGIN_RULESET";
+ case STOP: return "STOP";
+ case SET: return "SET";
+ case UNSET: return "UNSET";
+ case CONTINUE: return "CONTINUE";
+ case CALL: return "CALL";
+ case LEGACY_ACTION: return "LEGACY_ACTION";
+ case LEGACY_RULESET: return "LEGACY_RULESET";
+ case PRIFILT: return "PRIFILT";
+ case PROPFILT: return "PROPFILT";
+ case BSD_TAG_SELECTOR: return "BSD_TAG_SELECTOR";
+ case BSD_HOST_SELECTOR: return "BSD_HOST_SELECTOR";
+ case IF: return "IF";
+ case THEN: return "THEN";
+ case ELSE: return "ELSE";
+ case OR: return "OR";
+ case AND: return "AND";
+ case NOT: return "NOT";
+ case VAR: return "VAR";
+ case STRING: return "STRING";
+ case NUMBER: return "NUMBER";
+ case CMP_EQ: return "CMP_EQ";
+ case CMP_NE: return "CMP_NE";
+ case CMP_LE: return "CMP_LE";
+ case CMP_GE: return "CMP_GE";
+ case CMP_LT: return "CMP_LT";
+ case CMP_GT: return "CMP_GT";
+ case CMP_CONTAINS: return "CMP_CONTAINS";
+ case CMP_CONTAINSI: return "CMP_CONTAINSI";
+ case CMP_STARTSWITH: return "CMP_STARTSWITH";
+ case CMP_STARTSWITHI: return "CMP_STARTSWITHI";
+ case UMINUS: return "UMINUS";
+ default: return "UNKNOWN TOKEN";
+ }
+}
diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h
index 4816951b..31b2eb93 100644
--- a/grammar/rainerscript.h
+++ b/grammar/rainerscript.h
@@ -318,6 +318,7 @@ int cnfparamvalsIsSet(struct cnfparamblk *params, struct cnfparamvals *vals);
void varDelete(struct var *v);
void cnfparamvalsDestruct(struct cnfparamvals *paramvals, struct cnfparamblk *blk);
struct cnfstmt * cnfstmtNew(unsigned s_type);
+void cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree);
void cnfstmtPrint(struct cnfstmt *stmt, int indent);
struct cnfstmt* scriptAddStmt(struct cnfstmt *root, struct cnfstmt *s);
struct objlst* objlstAdd(struct objlst *root, struct cnfobj *o);
@@ -339,6 +340,7 @@ void cnfarrayContentDestruct(struct cnfarray *ar);
char* getFIOPName(unsigned iFIOP);
rsRetVal initRainerscript(void);
void unescapeStr(uchar *s, int len);
+char * tokenval2str(int tok);
/* debug helper */
void cstrPrint(char *text, es_str_t *estr);
diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c
index 0f4ded1d..c503852c 100644
--- a/plugins/imuxsock/imuxsock.c
+++ b/plugins/imuxsock/imuxsock.c
@@ -290,7 +290,7 @@ createInstance(instanceConf_t **pinst)
inst->sockName = NULL;
inst->pLogHostName = NULL;
inst->ratelimitInterval = DFLT_ratelimitInterval;
- inst->ratelimitBurst = DFLT_ratelimitSeverity;
+ inst->ratelimitBurst = DFLT_ratelimitBurst;
inst->ratelimitSeverity = DFLT_ratelimitSeverity;
inst->bUseFlowCtl = 0;
inst->bIgnoreTimestamp = 1;
@@ -412,6 +412,8 @@ addListner(instanceConf_t *inst)
ratelimitSetLinuxLike(listeners[nfd].dflt_ratelimiter,
listeners[nfd].ratelimitInterval,
listeners[nfd].ratelimitBurst);
+ ratelimitSetSeverity(listeners[nfd].dflt_ratelimiter,
+ listeners[nfd].ratelimitSev);
nfd++;
} else {
errmsg.LogError(0, NO_ERRCODE, "Out of unix socket name descriptors, ignoring %s\n",
@@ -586,6 +588,7 @@ findRatelimiter(lstn_t *pLstn, struct ucred *cred, ratelimit_t **prl)
pidbuf[sizeof(pidbuf)-1] = '\0'; /* to be on safe side */
CHKiRet(ratelimitNew(&rl, "imuxsock", pidbuf));
ratelimitSetLinuxLike(rl, pLstn->ratelimitInterval, pLstn->ratelimitBurst);
+ ratelimitSetSeverity(rl, pLstn->ratelimitSev);
CHKmalloc(keybuf = malloc(sizeof(pid_t)));
*keybuf = cred->pid;
r = hashtable_insert(pLstn->ht, keybuf, rl);
@@ -775,10 +778,7 @@ SubmitMsg(uchar *pRcv, int lenRcv, lstn_t *pLstn, struct ucred *cred, struct tim
facil = LOG_FAC(pri);
sever = LOG_PRI(pri);
- if(sever >= pLstn->ratelimitSev) {
- /* note: if cred == NULL, then ratelimiter == NULL as well! */
- findRatelimiter(pLstn, cred, &ratelimiter); /* ignore error, better so than others... */
- }
+ findRatelimiter(pLstn, cred, &ratelimiter); /* ignore error, better so than others... */
if(ts == NULL) {
datetime.getCurrTime(&st, &tt);
@@ -1075,6 +1075,7 @@ activateListeners()
ratelimitSetLinuxLike(listeners[0].dflt_ratelimiter,
listeners[0].ratelimitInterval,
listeners[0].ratelimitBurst);
+ ratelimitSetSeverity(listeners[0].dflt_ratelimiter,listeners[0].ratelimitSev);
sd_fds = sd_listen_fds(0);
if(sd_fds < 0) {
diff --git a/plugins/omrelp/omrelp.c b/plugins/omrelp/omrelp.c
index e55836c5..c9e32444 100644
--- a/plugins/omrelp/omrelp.c
+++ b/plugins/omrelp/omrelp.c
@@ -7,7 +7,7 @@
*
* File begun on 2008-03-13 by RGerhards
*
- * Copyright 2008-2012 Adiscon GmbH.
+ * Copyright 2008-2013 Adiscon GmbH.
*
* This file is part of rsyslog.
*
@@ -43,6 +43,7 @@
#include "glbl.h"
#include "errmsg.h"
#include "debug.h"
+#include "unicode-helper.h"
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
@@ -57,12 +58,14 @@ DEFobjCurrIf(glbl)
static relpEngine_t *pRelpEngine; /* our relp engine */
typedef struct _instanceData {
- char *f_hname;
+ uchar *target;
int compressionLevel; /* 0 - no compression, else level for zlib */
- char *port;
+ uchar *port;
int bInitialConnect; /* is this the initial connection request of our module? (0-no, 1-yes) */
int bIsConnected; /* currently connected to server? 0 - no, 1 - yes */
- relpClt_t *pRelpClt; /* relp client for this instance */
+ unsigned timeout;
+ relpClt_t *pRelpClt; /* relp client for this instance */
+ uchar *tplName;
} instanceData;
typedef struct configSettings_s {
@@ -70,30 +73,114 @@ typedef struct configSettings_s {
} configSettings_t;
static configSettings_t __attribute__((unused)) cs;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "target", eCmdHdlrGetWord, 1 },
+ { "port", eCmdHdlrGetWord, 0 },
+ { "timeout", eCmdHdlrInt, 0 },
+ { "template", eCmdHdlrGetWord, 1 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
BEGINinitConfVars /* (re)set config variables to default values */
CODESTARTinitConfVars
ENDinitConfVars
-/* get the syslog forward port from selector_t. The passed in
- * struct must be one that is setup for forwarding.
- * rgerhards, 2007-06-28
- * We may change the implementation to try to lookup the port
- * if it is unspecified. So far, we use the IANA default auf 514.
+/* We may change the implementation to try to lookup the port
+ * if it is unspecified. So far, we use 514 as default (what probably
+ * is not a really bright idea, but kept for backward compatibility).
*/
-static char *getRelpPt(instanceData *pData)
+static uchar *getRelpPt(instanceData *pData)
{
assert(pData != NULL);
if(pData->port == NULL)
- return("514");
+ return((uchar*)"514");
else
return(pData->port);
}
+static inline rsRetVal
+doCreateRelpClient(instanceData *pData)
+{
+ DEFiRet;
+ if(relpEngineCltConstruct(pRelpEngine, &pData->pRelpClt) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+ if(relpCltSetTimeout(pData->pRelpClt, pData->timeout) != RELP_RET_OK)
+ ABORT_FINALIZE(RS_RET_RELP_ERR);
+finalize_it:
+ RETiRet;
+}
+
+
BEGINcreateInstance
CODESTARTcreateInstance
pData->bInitialConnect = 1;
ENDcreateInstance
+BEGINfreeInstance
+CODESTARTfreeInstance
+ if(pData->pRelpClt != NULL)
+ relpEngineCltDestruct(pRelpEngine, &pData->pRelpClt);
+ free(pData->target);
+ free(pData->port);
+ free(pData->tplName);
+ENDfreeInstance
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->target = NULL;
+ pData->port = NULL;
+ pData->tplName = NULL;
+ pData->timeout = 90;
+}
+
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "target")) {
+ pData->target = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "port")) {
+ pData->port = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "timeout")) {
+ pData->timeout = (unsigned) pvals[i].val.d.n;
+ } else {
+ dbgprintf("omrelp: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ CODE_STD_STRING_REQUESTnewActInst(1)
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ?
+ "RSYSLOG_ForwardFormat" : (char*)pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+
+ CHKiRet(doCreateRelpClient(pData));
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
BEGINisCompatibleWithFeature
CODESTARTisCompatibleWithFeature
@@ -101,25 +188,16 @@ CODESTARTisCompatibleWithFeature
iRet = RS_RET_OK;
ENDisCompatibleWithFeature
-
-BEGINfreeInstance
-CODESTARTfreeInstance
- if(pData->port != NULL)
- free(pData->port);
-
- /* final cleanup */
- if(pData->pRelpClt != NULL)
- relpEngineCltDestruct(pRelpEngine, &pData->pRelpClt);
-
- if(pData->f_hname != NULL)
- free(pData->f_hname);
-
-ENDfreeInstance
+BEGINSetShutdownImmdtPtr
+CODESTARTSetShutdownImmdtPtr
+ relpEngineSetShutdownImmdtPtr(pRelpEngine, pPtr);
+ DBGPRINTF("omrelp: shutdownImmediate ptr now is %p\n", pPtr);
+ENDSetShutdownImmdtPtr
BEGINdbgPrintInstInfo
CODESTARTdbgPrintInstInfo
- printf("RELP/%s", pData->f_hname);
+ dbgprintf("RELP/%s", pData->target);
ENDdbgPrintInstInfo
@@ -131,7 +209,7 @@ static rsRetVal doConnect(instanceData *pData)
DEFiRet;
if(pData->bInitialConnect) {
- iRet = relpCltConnect(pData->pRelpClt, glbl.GetDefPFFamily(), (uchar*) pData->port, (uchar*) pData->f_hname);
+ iRet = relpCltConnect(pData->pRelpClt, glbl.GetDefPFFamily(), pData->port, pData->target);
if(iRet == RELP_RET_OK)
pData->bInitialConnect = 0;
} else {
@@ -160,7 +238,7 @@ BEGINdoAction
size_t lenMsg;
relpRetVal ret;
CODESTARTdoAction
- dbgprintf(" %s:%s/RELP\n", pData->f_hname, getRelpPt(pData));
+ dbgprintf(" %s:%s/RELP\n", pData->target, getRelpPt(pData));
if(!pData->bIsConnected) {
CHKiRet(doConnect(pData));
@@ -309,21 +387,17 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* TODO: make this if go away! */
if(*p == ';') {
*p = '\0'; /* trick to obtain hostname (later)! */
- CHKmalloc(pData->f_hname = strdup((char*) q));
+ CHKmalloc(pData->target = ustrdup(q));
*p = ';';
} else {
- CHKmalloc(pData->f_hname = strdup((char*) q));
+ CHKmalloc(pData->target = ustrdup(q));
}
/* process template */
CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) "RSYSLOG_ForwardFormat"));
- /* create our relp client */
- CHKiRet(relpEngineCltConstruct(pRelpEngine, &pData->pRelpClt)); /* we use CHKiRet as librelp has a similar return value range */
+ CHKiRet(doCreateRelpClient(pData));
- /* TODO: do we need to call freeInstance if we failed - this is a general question for
- * all output modules. I'll address it later as the interface evolves. rgerhards, 2007-07-25
- */
CODE_STD_FINALIZERparseSelectorAct
ENDparseSelectorAct
@@ -342,6 +416,8 @@ BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_OMOD_QUERIES
CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_SetShutdownImmdtPtr
ENDqueryEtryPt
diff --git a/plugins/omudpspoof/omudpspoof.c b/plugins/omudpspoof/omudpspoof.c
index 4f37fd8c..9c4c80ba 100644
--- a/plugins/omudpspoof/omudpspoof.c
+++ b/plugins/omudpspoof/omudpspoof.c
@@ -481,7 +481,7 @@ UDPSend(instanceData *pData, uchar *pszSourcename, char *msg, size_t len)
0, /* checksum */
source_ip.sin_addr.s_addr,
tempaddr->sin_addr.s_addr,
- (u_int8_t*)(msg+msgOffs), /* payload */
+ (uint8_t*)(msg+msgOffs), /* payload */
pktLen, /* payload size */
pData->libnet_handle, /* libnet handle */
ip); /* libnet id */
diff --git a/runtime/module-template.h b/runtime/module-template.h
index fe74bac9..8a958f90 100644
--- a/runtime/module-template.h
+++ b/runtime/module-template.h
@@ -938,6 +938,28 @@ static rsRetVal doHUP(instanceData __attribute__((unused)) *pData)\
}
+/* SetShutdownImmdtPtr()
+ * This function is optional. If defined by an output plugin, it is called
+ * each time the action is invoked to set the "ShutdownImmediate" pointer,
+ * which is used during termination to indicate the action should shutdown
+ * as quickly as possible.
+ */
+#define CODEqueryEtryPt_SetShutdownImmdtPtr \
+ else if(!strcmp((char*) name, "SetShutdownImmdtPtr")) {\
+ *pEtryPoint = SetShutdownImmdtPtr;\
+ }
+#define BEGINSetShutdownImmdtPtr \
+static rsRetVal SetShutdownImmdtPtr(instanceData __attribute__((unused)) *pData, int *pPtr)\
+{\
+ DEFiRet;
+
+#define CODESTARTSetShutdownImmdtPtr
+
+#define ENDSetShutdownImmdtPtr \
+ RETiRet;\
+}
+
+
/* parse() - main entry point of parser modules
*/
#define BEGINparse \
diff --git a/runtime/modules.c b/runtime/modules.c
index 9f7ff31c..e9d8d959 100644
--- a/runtime/modules.c
+++ b/runtime/modules.c
@@ -657,6 +657,10 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
if(localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND)
ABORT_FINALIZE(localRet);
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"SetShutdownImmdtPtr", &pNew->mod.om.SetShutdownImmdtPtr);
+ if(localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND)
+ ABORT_FINALIZE(localRet);
+
localRet = (*pNew->modQueryEtryPt)((uchar*)"beginTransaction", &pNew->mod.om.beginTransaction);
if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND)
pNew->mod.om.beginTransaction = dummyBeginTransaction;
diff --git a/runtime/modules.h b/runtime/modules.h
index e42d19e1..64644be2 100644
--- a/runtime/modules.h
+++ b/runtime/modules.h
@@ -142,6 +142,7 @@ struct modInfo_s {
rsRetVal (*endTransaction)(void*);
rsRetVal (*parseSelectorAct)(uchar**, void**,omodStringRequest_t**);
rsRetVal (*newActInst)(uchar *modName, struct nvlst *lst, void **, omodStringRequest_t **);
+ rsRetVal (*SetShutdownImmdtPtr)(void *pData, void *pPtr);
} om;
struct { /* data for library modules */
char dummy;
diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c
index 0f66c766..6ef4feba 100644
--- a/runtime/nsd_gtls.c
+++ b/runtime/nsd_gtls.c
@@ -259,9 +259,9 @@ gtlsClientCertCallback(gnutls_session session,
static rsRetVal
gtlsGetCertInfo(nsd_gtls_t *pThis, cstr_t **ppStr)
{
- char dn[128];
- uchar lnBuf[256];
- size_t size;
+ uchar szBufA[1024];
+ uchar *szBuf = szBufA;
+ size_t szBufLen = sizeof(szBufA), tmp;
unsigned int algo, bits;
time_t expiration_time, activation_time;
const gnutls_datum *cert_list;
@@ -271,8 +271,6 @@ gtlsGetCertInfo(nsd_gtls_t *pThis, cstr_t **ppStr)
int gnuRet;
DEFiRet;
unsigned iAltName;
- size_t szAltNameLen;
- char szAltName[1024]; /* this is sufficient for the DNSNAME... */
assert(ppStr != NULL);
ISOBJ_TYPE_assert(pThis, nsd_gtls);
@@ -281,61 +279,62 @@ gtlsGetCertInfo(nsd_gtls_t *pThis, cstr_t **ppStr)
return RS_RET_TLS_CERT_ERR;
cert_list = gnutls_certificate_get_peers(pThis->sess, &cert_list_size);
-
- CHKiRet(rsCStrConstruct(&pStr));
-
- snprintf((char*)lnBuf, sizeof(lnBuf), "peer provided %d certificate(s). ", cert_list_size);
- CHKiRet(rsCStrAppendStr(pStr, lnBuf));
+ CHKiRet(rsCStrConstructFromszStrf(&pStr, "peer provided %d certificate(s). ", cert_list_size));
if(cert_list_size > 0) {
/* we only print information about the first certificate */
CHKgnutls(gnutls_x509_crt_init(&cert));
CHKgnutls(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER));
- CHKiRet(rsCStrAppendStr(pStr, (uchar*)"Certificate 1 info: "));
-
expiration_time = gnutls_x509_crt_get_expiration_time(cert);
activation_time = gnutls_x509_crt_get_activation_time(cert);
- ctime_r(&activation_time, dn);
- dn[strlen(dn) - 1] = '\0'; /* strip linefeed */
- snprintf((char*)lnBuf, sizeof(lnBuf), "certificate valid from %s ", dn);
- CHKiRet(rsCStrAppendStr(pStr, lnBuf));
-
- ctime_r(&expiration_time, dn);
- dn[strlen(dn) - 1] = '\0'; /* strip linefeed */
- snprintf((char*)lnBuf, sizeof(lnBuf), "to %s; ", dn);
- CHKiRet(rsCStrAppendStr(pStr, lnBuf));
+ ctime_r(&activation_time, szBuf);
+ szBuf[strlen(szBuf) - 1] = '\0'; /* strip linefeed */
+ CHKiRet(rsCStrAppendStrf(pStr, (uchar*)"Certificate 1 info: "
+ "certificate valid from %s ", szBuf));
+ ctime_r(&expiration_time, szBuf);
+ szBuf[strlen(szBuf) - 1] = '\0'; /* strip linefeed */
+ CHKiRet(rsCStrAppendStrf(pStr, "to %s; ", szBuf));
/* Extract some of the public key algorithm's parameters */
algo = gnutls_x509_crt_get_pk_algorithm(cert, &bits);
-
- snprintf((char*)lnBuf, sizeof(lnBuf), "Certificate public key: %s; ",
- gnutls_pk_algorithm_get_name(algo));
- CHKiRet(rsCStrAppendStr(pStr, lnBuf));
+ CHKiRet(rsCStrAppendStrf(pStr, "Certificate public key: %s; ",
+ gnutls_pk_algorithm_get_name(algo)));
/* names */
- size = sizeof(dn);
- gnutls_x509_crt_get_dn(cert, dn, &size);
- snprintf((char*)lnBuf, sizeof(lnBuf), "DN: %s; ", dn);
- CHKiRet(rsCStrAppendStr(pStr, lnBuf));
-
- size = sizeof(dn);
- gnutls_x509_crt_get_issuer_dn(cert, dn, &size);
- snprintf((char*)lnBuf, sizeof(lnBuf), "Issuer DN: %s; ", dn);
- CHKiRet(rsCStrAppendStr(pStr, lnBuf));
+ tmp = szBufLen;
+ if(gnutls_x509_crt_get_dn(cert, szBuf, &tmp)
+ == GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ szBufLen = tmp;
+ szBuf = malloc(tmp);
+ gnutls_x509_crt_get_dn(cert, szBuf, &tmp);
+ }
+ CHKiRet(rsCStrAppendStrf(pStr, "DN: %s; ", szBuf));
+
+ tmp = szBufLen;
+ if(gnutls_x509_crt_get_issuer_dn(cert, szBuf, &tmp)
+ == GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ szBufLen = tmp;
+ szBuf = realloc((szBuf == szBufA) ? NULL : szBuf, tmp);
+ gnutls_x509_crt_get_issuer_dn(cert, szBuf, &tmp);
+ }
+ CHKiRet(rsCStrAppendStrf(pStr, "Issuer DN: %s; ", szBuf));
/* dNSName alt name */
iAltName = 0;
while(1) { /* loop broken below */
- szAltNameLen = sizeof(szAltName);
+ tmp = szBufLen;
gnuRet = gnutls_x509_crt_get_subject_alt_name(cert, iAltName,
- szAltName, &szAltNameLen, NULL);
- if(gnuRet < 0)
+ szBuf, &tmp, NULL);
+ if(gnuRet == GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ szBufLen = tmp;
+ szBuf = realloc((szBuf == szBufA) ? NULL : szBuf, tmp);
+ continue;
+ } else if(gnuRet < 0)
break;
else if(gnuRet == GNUTLS_SAN_DNSNAME) {
/* we found it! */
- snprintf((char*)lnBuf, sizeof(lnBuf), "SAN:DNSname: %s; ", szAltName);
- CHKiRet(rsCStrAppendStr(pStr, lnBuf));
+ CHKiRet(rsCStrAppendStrf(pStr, "SAN:DNSname: %s; ", szBuf));
/* do NOT break, because there may be multiple dNSName's! */
}
++iAltName;
@@ -352,6 +351,8 @@ finalize_it:
if(pStr != NULL)
rsCStrDestruct(&pStr);
}
+ if(szBuf != szBufA)
+ free(szBuf);
RETiRet;
}
diff --git a/runtime/queue.c b/runtime/queue.c
index 4c8d3ac5..74090a4d 100644
--- a/runtime/queue.c
+++ b/runtime/queue.c
@@ -991,7 +991,7 @@ rsRetVal qqueueEnqObjDirectBatch(qqueue_t *pThis, batch_t *pBatch)
* We use our knowledge about the batch_t structure below, but without that, we
* pay a too-large performance toll... -- rgerhards, 2009-04-22
*/
- iRet = pThis->pConsumer(pThis->pAction, pBatch, &pThis->bShutdownImmediate);
+ iRet = pThis->pConsumer(pThis->pAction, pBatch, NULL);
RETiRet;
}
@@ -1150,6 +1150,7 @@ tryShutdownWorkersWithinActionTimeout(qqueue_t *pThis)
DBGOPRINT((obj_t*) pThis, "trying to shutdown workers within Action Timeout");
DBGOPRINT((obj_t*) pThis, "setting EnqOnly mode\n");
pThis->bEnqOnly = 1;
+dbgprintf("DDDD: setting shutdownImmediate mode, ptr %p!\n", &pThis->bShutdownImmediate);
pThis->bShutdownImmediate = 1;
/* now DA queue */
if(pThis->bIsDA) {
@@ -1291,8 +1292,6 @@ finalize_it:
RETiRet;
}
-
-
/* Constructor for the queue object
* This constructs the data structure, but does not yet start the queue. That
* is done by queueStart(). The reason is that we want to give the caller a chance
@@ -1856,6 +1855,8 @@ ConsumerReg(qqueue_t *pThis, wti_t *pWti)
/* at this spot, we may be cancelled */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &iCancelStateSave);
+
+dbgprintf("DDDD: calling consumer with shutdownImmeditate ptr %p\n", &pThis->bShutdownImmediate);
CHKiRet(pThis->pConsumer(pThis->pAction, &pWti->batch, &pThis->bShutdownImmediate));
/* we now need to check if we should deliberately delay processing a bit
diff --git a/runtime/ratelimit.c b/runtime/ratelimit.c
index 4b618fb5..d83da2dd 100644
--- a/runtime/ratelimit.c
+++ b/runtime/ratelimit.c
@@ -202,7 +202,9 @@ ratelimitMsg(ratelimit_t *ratelimit, msg_t *pMsg, msg_t **ppRepMsg)
DEFiRet;
*ppRepMsg = NULL;
- if(ratelimit->interval) {
+ /* Only the messages having severity level at or below the
+ * treshold (the value is >=) are subject to ratelimiting. */
+ if(ratelimit->interval && (pMsg->iSeverity >= ratelimit->severity)) {
if(withinRatelimit(ratelimit, pMsg->ttGenTime) == 0) {
msgDestruct(&pMsg);
ABORT_FINALIZE(RS_RET_DISCARDMSG);
@@ -284,6 +286,7 @@ ratelimitNew(ratelimit_t **ppThis, char *modname, char *dynname)
namebuf[sizeof(namebuf)-1] = '\0'; /* to be on safe side */
pThis->name = strdup(namebuf);
}
+ /* pThis->severity == 0 - all messages are ratelimited */
pThis->bReduceRepeatMsgs = loadConf->globals.bReduceRepeatMsgs;
*ppThis = pThis;
finalize_it:
@@ -316,6 +319,15 @@ ratelimitSetThreadSafe(ratelimit_t *ratelimit)
pthread_mutex_init(&ratelimit->mut, NULL);
}
+/* Severity level determines which messages are subject to
+ * ratelimiting. Default (no value set) is all messages.
+ */
+void
+ratelimitSetSeverity(ratelimit_t *ratelimit, intTiny severity)
+{
+ ratelimit->severity = severity;
+}
+
void
ratelimitDestruct(ratelimit_t *ratelimit)
{
diff --git a/runtime/ratelimit.h b/runtime/ratelimit.h
index 820817bc..a058b069 100644
--- a/runtime/ratelimit.h
+++ b/runtime/ratelimit.h
@@ -26,6 +26,7 @@ struct ratelimit_s {
/* support for Linux kernel-type ratelimiting */
unsigned short interval;
unsigned short burst;
+ intTiny severity; /**< ratelimit only equal or lower severity levels (eq or higher values) */
unsigned done;
unsigned missed;
time_t begin;
@@ -41,6 +42,7 @@ struct ratelimit_s {
rsRetVal ratelimitNew(ratelimit_t **ppThis, char *modname, char *dynname);
void ratelimitSetThreadSafe(ratelimit_t *ratelimit);
void ratelimitSetLinuxLike(ratelimit_t *ratelimit, unsigned short interval, unsigned short burst);
+void ratelimitSetSeverity(ratelimit_t *ratelimit, intTiny severity);
rsRetVal ratelimitMsg(ratelimit_t *ratelimit, msg_t *pMsg, msg_t **ppRep);
rsRetVal ratelimitAddMsg(ratelimit_t *ratelimit, multi_submit_t *pMultiSub, msg_t *pMsg);
void ratelimitDestruct(ratelimit_t *pThis);
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 4cdd1c1e..9fdf2b0f 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -387,7 +387,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_MOD_NO_INPUT_STMT = -2224, /**< (input) module does not support input() statement */
RS_RET_NO_CEE_MSG = -2225, /**< the message being processed is NOT CEE-enhanced */
- /**** up to 2300 is reserved for v6 use ****/
+ /**** up to 2290 is reserved for v6 use ****/
+ RS_RET_RELP_ERR = -2291, /**<< error in RELP processing */
+ /**** up to 3000 is reserved for c7 use ****/
RS_RET_JNAME_NO_ROOT = -2301, /**< root element is missing in JSON path */
RS_RET_JNAME_INVALID = -2302, /**< JSON path is invalid */
RS_RET_JSON_PARSE_ERR = -2303, /**< we had a problem parsing JSON (or extra data) */
diff --git a/runtime/ruleset.c b/runtime/ruleset.c
index 66b38fc9..e3348938 100644
--- a/runtime/ruleset.c
+++ b/runtime/ruleset.c
@@ -11,7 +11,7 @@
*
* Module begun 2009-06-10 by Rainer Gerhards
*
- * Copyright 2009-2012 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2009-2013 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -297,6 +297,7 @@ execIf(struct cnfstmt *stmt, batch_t *pBatch, sbool *active)
sbool *newAct;
int i;
sbool bRet;
+ sbool allInactive = 1;
DEFiRet;
newAct = newActive(pBatch);
for(i = 0 ; i < batchNumMsgs(pBatch) ; ++i) {
@@ -306,12 +307,19 @@ execIf(struct cnfstmt *stmt, batch_t *pBatch, sbool *active)
continue; /* will be ignored in any case */
if(active == NULL || active[i]) {
bRet = cnfexprEvalBool(stmt->d.s_if.expr, pBatch->pElem[i].pMsg);
+ allInactive = 0;
} else
bRet = 0;
newAct[i] = bRet;
DBGPRINTF("batch: item %d: expr eval: %d\n", i, bRet);
}
+ if(allInactive) {
+ DBGPRINTF("execIf: all batch elements are inactive, holding execution\n");
+ freeActive(newAct);
+ FINALIZE;
+ }
+
if(stmt->d.s_if.t_then != NULL) {
scriptExec(stmt->d.s_if.t_then, pBatch, newAct);
}
@@ -319,7 +327,8 @@ execIf(struct cnfstmt *stmt, batch_t *pBatch, sbool *active)
for(i = 0 ; i < batchNumMsgs(pBatch) ; ++i) {
if(*(pBatch->pbShutdownImmediate))
FINALIZE;
- if(pBatch->eltState[i] != BATCH_STATE_DISC)
+ if(pBatch->eltState[i] != BATCH_STATE_DISC
+ && (active == NULL || active[i]))
newAct[i] = !newAct[i];
}
scriptExec(stmt->d.s_if.t_else, pBatch, newAct);
@@ -364,7 +373,8 @@ execPRIFILT(struct cnfstmt *stmt, batch_t *pBatch, sbool *active)
for(i = 0 ; i < batchNumMsgs(pBatch) ; ++i) {
if(*(pBatch->pbShutdownImmediate))
return;
- if(pBatch->eltState[i] != BATCH_STATE_DISC)
+ if(pBatch->eltState[i] != BATCH_STATE_DISC
+ && (active == NULL || active[i]))
newAct[i] = !newAct[i];
}
scriptExec(stmt->d.s_prifilt.t_else, pBatch, newAct);
@@ -504,7 +514,11 @@ scriptExec(struct cnfstmt *root, batch_t *pBatch, sbool *active)
struct cnfstmt *stmt;
for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
-dbgprintf("RRRR: scriptExec: batch of %d elements, active %p, stmt %p, nodetype %u\n", batchNumMsgs(pBatch), active, stmt, stmt->nodetype);
+ if(Debug) {
+ dbgprintf("scriptExec: batch of %d elements, active %p, active[0]:%d\n",
+ batchNumMsgs(pBatch), active, (active == NULL ? 1 : active[0]));
+ cnfstmtPrintOnly(stmt, 2, 0);
+ }
switch(stmt->nodetype) {
case S_NOP:
break;
@@ -521,7 +535,6 @@ dbgprintf("RRRR: scriptExec: batch of %d elements, active %p, stmt %p, nodetype
execUnset(stmt, pBatch, active);
break;
case S_CALL:
- DBGPRINTF("calling ruleset\n"); // TODO: add Name
scriptExec(stmt->d.s_call.stmt, pBatch, active);
break;
case S_IF:
diff --git a/runtime/stringbuf.c b/runtime/stringbuf.c
index d9f80231..75d2eac4 100644
--- a/runtime/stringbuf.c
+++ b/runtime/stringbuf.c
@@ -32,6 +32,7 @@
#include <assert.h>
#include <string.h>
#include <ctype.h>
+#include <stdarg.h>
#include <sys/types.h>
#include <libestr.h>
#include "rsyslog.h"
@@ -104,6 +105,56 @@ finalize_it:
}
+/* a helper function for rsCStr*Strf()
+ */
+static rsRetVal rsCStrConstructFromszStrv(cstr_t **ppThis, uchar *fmt, va_list ap)
+{
+ DEFiRet;
+ cstr_t *pThis;
+ va_list ap2;
+ uchar *sz;
+ int len;
+
+ assert(ppThis != NULL);
+
+ va_copy(ap2, ap);
+ len = vsnprintf(NULL, 0, fmt, ap2);
+ va_end(ap2);
+
+ if(len < 0)
+ ABORT_FINALIZE(RS_RET_ERR);
+
+ CHKiRet(rsCStrConstruct(&pThis));
+
+ pThis->iBufSize = pThis->iStrLen = len;
+ len++; /* account for the \0 written by vsnprintf */
+ if((pThis->pBuf = (uchar*) MALLOC(sizeof(uchar) * len)) == NULL) {
+ RSFREEOBJ(pThis);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ vsnprintf(pThis->pBuf, len, fmt, ap);
+ *ppThis = pThis;
+finalize_it:
+ RETiRet;
+}
+
+
+/* construct from a printf-style formated string
+ */
+rsRetVal rsCStrConstructFromszStrf(cstr_t **ppThis, uchar *fmt, ...)
+{
+ DEFiRet;
+ va_list ap;
+
+ va_start(ap, fmt);
+ iRet = rsCStrConstructFromszStrv(ppThis, fmt, ap);
+ va_end(ap);
+
+ RETiRet;
+}
+
+
/* construct from es_str_t string
* rgerhards 2010-12-03
*/
@@ -256,6 +307,27 @@ rsRetVal cstrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend)
}
+/* append a printf-style formated string
+ */
+rsRetVal rsCStrAppendStrf(cstr_t *pThis, uchar *fmt, ...)
+{
+ DEFiRet;
+ va_list ap;
+ cstr_t *pStr;
+
+ va_start(ap, fmt);
+ iRet = rsCStrConstructFromszStrv(&pStr, fmt, ap);
+ va_end(ap);
+
+ CHKiRet(iRet);
+
+ iRet = cstrAppendCStr(pThis, pStr);
+ rsCStrDestruct(pStr);
+finalize_it:
+ RETiRet;
+}
+
+
rsRetVal rsCStrAppendInt(cstr_t *pThis, long i)
{
DEFiRet;
diff --git a/runtime/stringbuf.h b/runtime/stringbuf.h
index bba004a0..b301f4b9 100644
--- a/runtime/stringbuf.h
+++ b/runtime/stringbuf.h
@@ -58,6 +58,7 @@ rsRetVal cstrConstruct(cstr_t **ppThis);
rsRetVal cstrConstructFromESStr(cstr_t **ppThis, es_str_t *str);
rsRetVal rsCStrConstructFromszStr(cstr_t **ppThis, uchar *sz);
rsRetVal rsCStrConstructFromCStr(cstr_t **ppThis, cstr_t *pFrom);
+rsRetVal rsCStrConstructFromszStrf(cstr_t **ppThis, uchar *fmt, ...);
/**
* Destruct the string buffer object.
@@ -173,6 +174,12 @@ rsRetVal rsCStrAppendStr(cstr_t *pThis, uchar* psz);
*/
rsRetVal rsCStrAppendStrWithLen(cstr_t *pThis, uchar* psz, size_t iStrLen);
+/**
+ * Append a printf-style formated string to the buffer.
+ *
+ * \param fmt pointer to the format string (see man 3 printf for details). Must not be NULL.
+ */
+rsRetVal rsCStrAppendStrf(cstr_t *pThis, uchar *fmt, ...);
/**
* Append an integer to the string. No special formatting is
diff --git a/tests/queue-persist-drvr.sh b/tests/queue-persist-drvr.sh
index de597308..823fed6c 100755
--- a/tests/queue-persist-drvr.sh
+++ b/tests/queue-persist-drvr.sh
@@ -26,5 +26,10 @@ source $srcdir/diag.sh startup queue-persist.conf
source $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
./msleep 500
$srcdir/diag.sh wait-shutdown
-source $srcdir/diag.sh seq-check 0 4999
+# note: we need to permit duplicate messages, as due to the forced
+# shutdown some messages may be flagged as "unprocessed" while they
+# actually were processed. This is inline with rsyslog's philosophy
+# to better duplicate than loose messages. Duplicate messages are
+# permitted by the -d seq-check option.
+source $srcdir/diag.sh seq-check 0 4999 -d
source $srcdir/diag.sh exit
diff --git a/tools/syslogd.c b/tools/syslogd.c
index fe1205dd..77adb2cb 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -567,6 +567,7 @@ msgConsumer(void __attribute__((unused)) *notNeeded, batch_t *pBatch, int *pbShu
assert(pBatch != NULL);
pBatch->pbShutdownImmediate = pbShutdownImmediate; /* TODO: move this to batch creation! */
preprocessBatch(pBatch);
+dbgprintf("DDDD: batches ShutdownImmediate is %p\n", pBatch->pbShutdownImmediate);
ruleset.ProcessBatch(pBatch);
//TODO: the BATCH_STATE_COMM must be set somewhere down the road, but we
//do not have this yet and so we emulate -- 2010-06-10