summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2009-07-01 14:34:56 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2009-07-01 14:34:56 +0200
commit6322343eca1084b509386a94c1bcf2ca819f1220 (patch)
treecd873a34a4df087c3411de951c40a26f64f7d0ec
parente6aeb1b995d6629ff04fd0f6068be2e9ffe9ca42 (diff)
parent7bfa03bdc0b73647ffdbe4b73e5c1649af665fbf (diff)
downloadrsyslog-6322343eca1084b509386a94c1bcf2ca819f1220.tar.gz
rsyslog-6322343eca1084b509386a94c1bcf2ca819f1220.tar.xz
rsyslog-6322343eca1084b509386a94c1bcf2ca819f1220.zip
Merge branch 'master' into v5-devel
-rw-r--r--ChangeLog18
-rw-r--r--dirty.h2
-rw-r--r--doc/omoracle.html122
-rw-r--r--plugins/imdiag/imdiag.c32
-rw-r--r--plugins/imfile/imfile.c15
-rw-r--r--plugins/imklog/bsd.c9
-rw-r--r--plugins/imklog/imklog.c34
-rw-r--r--plugins/imklog/imklog.h1
-rw-r--r--plugins/imklog/linux.c12
-rw-r--r--plugins/imrelp/imrelp.c18
-rw-r--r--plugins/imudp/imudp.c26
-rw-r--r--plugins/imuxsock/imuxsock.c18
-rw-r--r--runtime/datetime.c5
-rw-r--r--runtime/datetime.h2
-rw-r--r--runtime/glbl.c46
-rw-r--r--runtime/glbl.h7
-rw-r--r--runtime/modules.c1
-rw-r--r--runtime/modules.h1
-rw-r--r--runtime/msg.c512
-rw-r--r--runtime/msg.h20
-rw-r--r--runtime/obj-types.h11
-rw-r--r--runtime/parser.c2
-rw-r--r--runtime/prop.c131
-rw-r--r--runtime/prop.h14
-rw-r--r--runtime/rsyslog.c3
-rw-r--r--runtime/rsyslog.h1
-rw-r--r--runtime/rule.c7
-rw-r--r--runtime/stringbuf.c1
-rw-r--r--runtime/stringbuf.h2
-rw-r--r--tcps_sess.c41
-rw-r--r--tcps_sess.h5
-rw-r--r--tcpsrv.c15
-rw-r--r--tcpsrv.h4
-rw-r--r--tests/nettester.c19
-rw-r--r--tools/syslogd.c128
35 files changed, 1003 insertions, 282 deletions
diff --git a/ChangeLog b/ChangeLog
index 7c0e03ca..8e9d39de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -44,6 +44,8 @@ increase.
output module interface
---------------------------------------------------------------------------
Version 4.5.0 [DEVEL] (rgerhards), 2009-??-??
+- activation order of inputs changed, they are now activated only after
+ privileges are dropped. Thanks to Michael Terry for the patch.
- greatly improved performance
- greatly reduced memory requirements of msg object
to around half of the previous demand. This means that more messages can
@@ -73,6 +75,16 @@ Version 4.5.0 [DEVEL] (rgerhards), 2009-??-??
- set a more sensible timeout for shutdow, now 1.5 seconds to complete
processing (this also removes those cases where the shutdown message
was not written because the termination happened before it)
+- 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.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.3.2 [beta] (rgerhards), 2009-06-24
- removed long-obsoleted property UxTradMsg
@@ -129,6 +141,12 @@ 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/dirty.h b/dirty.h
index 8a0cbc80..0153cb69 100644
--- a/dirty.h
+++ b/dirty.h
@@ -30,7 +30,7 @@
rsRetVal multiSubmitMsg(multi_submit_t *pMultiSub);
rsRetVal submitMsg(msg_t *pMsg);
rsRetVal logmsgInternal(int iErr, int pri, uchar *msg, int flags);
-rsRetVal parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int flags, flowControl_t flowCtlTypeu, uchar *pszInputName, struct syslogTime *stTime, time_t ttGenTime);
+rsRetVal parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int flags, flowControl_t flowCtlTypeu, prop_t *pInputName, struct syslogTime *stTime, time_t ttGenTime);
int parseRFCSyslogMsg(msg_t *pMsg, int flags);
int parseLegacySyslogMsg(msg_t *pMsg, int flags);
rsRetVal diagGetMainMsgQSize(int *piSize); /* for imdiag */
diff --git a/doc/omoracle.html b/doc/omoracle.html
index 40f6360f..cfcf277f 100644
--- a/doc/omoracle.html
+++ b/doc/omoracle.html
@@ -67,6 +67,128 @@ it is suggested to post questions to the
need to define the properties on the template in the correct order
you want them passed to the statement!
</pre>
+<p>Some additional documentation contributed by Ronny Egner:
+<pre>
+REQUIREMENTS:
+--------------
+
+- Oracle Instantclient 10g (NOT 11g) Base + Devel
+ (if you´re on 64-bit linux you should choose the 64-bit libs!)
+- JDK 1.6 (not neccessary for oracle plugin but "make" didd not finsished successfully without it)
+
+- "oracle-instantclient-config" script
+ (seems to shipped with instantclient 10g Release 1 but i was unable to find it for 10g Release 2 so here it is)
+
+
+====================== /usr/local/bin/oracle-instantclient-config =====================
+#!/bin/sh
+#
+# Oracle InstantClient SDK config file
+# Jean-Christophe Duberga - Bordeaux 2 University
+#
+
+# just adapt it to your environment
+incdirs="-I/usr/include/oracle/10.2.0.4/client64"
+libdirs="-L/usr/lib/oracle/10.2.0.4/client64/lib"
+
+usage="\
+Usage: oracle-instantclient-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--cflags] [--libs] [--static-libs]"
+
+if test $# -eq 0; then
+ echo "${usage}" 1>&2
+ exit 1
+fi
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case $1 in
+ --prefix=*)
+ prefix=$optarg
+ if test $exec_prefix_set = no ; then
+ exec_prefix=$optarg
+ fi
+ ;;
+ --prefix)
+ echo $prefix
+ ;;
+ --exec-prefix=*)
+ exec_prefix=$optarg
+ exec_prefix_set=yes
+ ;;
+ --exec-prefix)
+ echo ${exec_prefix}
+ ;;
+ --version)
+ echo ${version}
+ ;;
+ --cflags)
+ echo ${incdirs}
+ ;;
+ --libs)
+ echo $libdirs -lclntsh -lnnz10 -locci -lociei -locijdbc10
+ ;;
+ --static-libs)
+ echo "No static libs" 1>&2
+ exit 1
+ ;;
+ *)
+ echo "${usage}" 1>&2
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+=============== END ==============
+
+
+
+
+COMPILING RSYSLOGD
+-------------------
+
+
+./configure --enable-oracle
+
+
+
+
+RUNNING
+-------
+
+- make sure rsyslogd is able to locate the oracle libs (either via LD_LIBRARY_PATH or /etc/ld.so.conf)
+- set TNS_ADMIN to point to your tnsnames.ora
+- create a tnsnames.ora and test you are able to connect to the database
+
+- create user in oracle as shown in the following example:
+ create user syslog identified by syslog default tablespace users quota unlimited on users;
+ grant create session to syslog;
+ create role syslog_role;
+ grant syslog_role to syslog;
+ grant create table to syslog_role;
+ grant create sequence to syslog_role;
+
+- create tables as needed
+
+- configure rsyslog as shown in the following example
+ $ModLoad omoracle
+
+ $OmoracleDBUser syslog
+ $OmoracleDBPassword syslog
+ $OmoracleDB syslog
+ $OmoracleBatchSize 1
+ $OmoracleBatchItemSize 4096
+
+ $OmoracleStatementTemplate OmoracleStatement
+ $template OmoracleStatement,"insert into foo(hostname,message) values (:host,:message)"
+ $template TestStmt,"%hostname%%msg%"
+ *.* :omoracle:;TestStmt
+ (you guess it: username = password = database = "syslog".... see $rsyslogd_source/plugins/omoracle/omoracle.c for me info)
+</pre>
<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/plugins/imdiag/imdiag.c b/plugins/imdiag/imdiag.c
index 6edcb8b3..7cacc44a 100644
--- a/plugins/imdiag/imdiag.c
+++ b/plugins/imdiag/imdiag.c
@@ -66,10 +66,14 @@ DEFobjCurrIf(net)
DEFobjCurrIf(netstrm)
DEFobjCurrIf(errmsg)
DEFobjCurrIf(datetime)
+DEFobjCurrIf(prop)
/* Module static data */
static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change for multiple instances */
static permittedPeers_t *pPermPeersRoot = NULL;
+static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */
+static prop_t *pRcvDummy = NULL;
+static prop_t *pRcvIPDummy = NULL;
/* config settings */
@@ -206,12 +210,12 @@ doInjectMsg(int iNum)
/* we now create our own message object and submit it to the queue */
CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime));
MsgSetRawMsg(pMsg, (char*) szMsg, ustrlen(szMsg));
- MsgSetInputName(pMsg, UCHAR_CONSTANT("imdiag"), sizeof("imdiag")-1);
+ MsgSetInputName(pMsg, pInputName);
MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);
pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
pMsg->bParseHOSTNAME = 1;
- MsgSetRcvFrom(pMsg, UCHAR_CONSTANT("127.0.0.1")); /* TODO: way may use the real sender here... */
- CHKiRet(MsgSetRcvFromIP(pMsg, UCHAR_CONSTANT("127.0.0.1")));
+ MsgSetRcvFrom(pMsg, pRcvDummy);
+ CHKiRet(MsgSetRcvFromIP(pMsg, pRcvIPDummy));
CHKiRet(submitMsg(pMsg));
finalize_it:
@@ -380,13 +384,31 @@ CODESTARTwillRun
/* first apply some config settings */
if(pOurTcpsrv == NULL)
ABORT_FINALIZE(RS_RET_NO_RUN);
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imdiag"), sizeof("imdiag") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+
+ CHKiRet(prop.Construct(&pRcvDummy));
+ CHKiRet(prop.SetString(pRcvDummy, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
+ CHKiRet(prop.ConstructFinalize(pRcvDummy));
+
+ CHKiRet(prop.Construct(&pRcvIPDummy));
+ CHKiRet(prop.SetString(pRcvIPDummy, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
+ CHKiRet(prop.ConstructFinalize(pRcvIPDummy));
+
finalize_it:
ENDwillRun
BEGINafterRun
CODESTARTafterRun
- /* do cleanup here */
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ if(pRcvDummy != NULL)
+ prop.Destruct(&pRcvDummy);
+ if(pRcvIPDummy != NULL)
+ prop.Destruct(&pRcvIPDummy);
ENDafterRun
@@ -406,6 +428,7 @@ CODESTARTmodExit
objRelease(tcpsrv, LM_TCPSRV_FILENAME);
objRelease(errmsg, CORE_COMPONENT);
objRelease(datetime, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
ENDmodExit
@@ -443,6 +466,7 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(tcpsrv, LM_TCPSRV_FILENAME));
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
/* register config file handlers */
CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("imdiagserverrun"), 0, eCmdHdlrGetWord,
diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
index 631d02ff..7c588f90 100644
--- a/plugins/imfile/imfile.c
+++ b/plugins/imfile/imfile.c
@@ -46,6 +46,7 @@
#include "glbl.h"
#include "datetime.h"
#include "unicode-helper.h"
+#include "prop.h"
MODULE_TYPE_INPUT /* must be present for input modules, do not remove */
@@ -57,6 +58,7 @@ DEFobjCurrIf(errmsg)
DEFobjCurrIf(glbl)
DEFobjCurrIf(datetime)
DEFobjCurrIf(strm)
+DEFobjCurrIf(prop)
typedef struct fileInfo_s {
uchar *pszFileName;
@@ -81,6 +83,7 @@ static int iFilPtr = 0; /* number of files to be monitored; pointer to next fre
#define MAX_INPUT_FILES 100
static fileInfo_t files[MAX_INPUT_FILES];
+static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */
/* enqueue the read file line as a message. The provided string is
* not freed - thuis must be done by the caller.
@@ -97,7 +100,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine)
CHKiRet(msgConstruct(&pMsg));
MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY);
- MsgSetInputName(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1);
+ MsgSetInputName(pMsg, pInputName);
MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine), cstrLen(cstrLine));
MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
@@ -336,6 +339,11 @@ CODESTARTwillRun
ABORT_FINALIZE(RS_RET_NO_RUN);
}
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imfile"), sizeof("imfile") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+
finalize_it:
ENDwillRun
@@ -391,6 +399,9 @@ CODESTARTafterRun
strm.Destruct(&(files[i].pStrm));
}
}
+
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
ENDafterRun
@@ -405,6 +416,7 @@ CODESTARTmodExit
objRelease(datetime, CORE_COMPONENT);
objRelease(glbl, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
ENDmodExit
@@ -515,6 +527,7 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(glbl, CORE_COMPONENT));
CHKiRet(objUse(datetime, CORE_COMPONENT));
CHKiRet(objUse(strm, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord,
NULL, &pszFileName, STD_LOADABLE_MODULE_ID));
diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c
index 090c4e9b..6d7b6c98 100644
--- a/plugins/imklog/bsd.c
+++ b/plugins/imklog/bsd.c
@@ -83,6 +83,11 @@ static int fklog = -1; /* /dev/klog */
# define _PATH_KLOG "/dev/klog"
#endif
+static uchar *GetPath(void)
+{
+ return pszPath ? pszPath : _PATH_KLOG;
+}
+
/* open the kernel log - will be called inside the willRun() imklog
* entry point. -- rgerhards, 2008-04-09
*/
@@ -91,9 +96,9 @@ klogWillRun(void)
{
DEFiRet;
- fklog = open(_PATH_KLOG, O_RDONLY, 0);
+ fklog = open(GetPath(), O_RDONLY, 0);
if (fklog < 0) {
- dbgprintf("can't open %s (%d)\n", _PATH_KLOG, errno);
+ dbgprintf("can't open %s (%d)\n", GetPath(), errno);
iRet = RS_RET_ERR; // TODO: better error code
}
diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c
index f63d60ac..2a832bee 100644
--- a/plugins/imklog/imklog.c
+++ b/plugins/imklog/imklog.c
@@ -18,7 +18,7 @@
* Please note that this file replaces the klogd daemon that was
* also present in pre-v3 versions of rsyslog.
*
- * Copyright (C) 2008 by Rainer Gerhards and Adiscon GmbH
+ * Copyright (C) 2008, 2009 by Rainer Gerhards and Adiscon GmbH
*
* This file is part of rsyslog.
*
@@ -44,6 +44,7 @@
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
+#include <stdlib.h>
#include "dirty.h"
#include "cfsysline.h"
@@ -53,6 +54,7 @@
#include "datetime.h"
#include "imklog.h"
#include "glbl.h"
+#include "prop.h"
#include "unicode-helper.h"
MODULE_TYPE_INPUT
@@ -61,6 +63,7 @@ MODULE_TYPE_INPUT
DEF_IMOD_STATIC_DATA
DEFobjCurrIf(datetime)
DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
/* configuration settings */
int dbgPrintSymbols = 0; /* this one is extern so the helpers can access it! */
@@ -69,6 +72,7 @@ int use_syscall = 0;
int symbol_lookup = 0; /* on recent kernels > 2.6, the kernel does this */
int bPermitNonKernel = 0; /* permit logging of messages not having LOG_KERN facility */
int iFacilIntMsg; /* the facility to use for internal messages (set by driver) */
+uchar *pszPath = NULL;
/* TODO: configuration for the following directives must be implemented. It
* was not done yet because we either do not yet have a config handler for
* that type or I thought it was acceptable to push it to a later stage when
@@ -79,6 +83,9 @@ char *symfile = NULL;
int console_log_level = -1;
+static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this module */
+static prop_t *pLocalHostIP = NULL; /* a pseudo-constant propterty for 127.0.0.1 */
+
/* enqueue the the kernel message into the message queue.
* The provided msg string is not freed - thus must be done
* by the caller.
@@ -95,11 +102,11 @@ enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity)
CHKiRet(msgConstruct(&pMsg));
MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
- MsgSetInputName(pMsg, UCHAR_CONSTANT("imklog"), sizeof("imklog")-1);
+ MsgSetInputName(pMsg, pInputName);
MsgSetRawMsgWOSize(pMsg, (char*)msg);
MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */
- MsgSetRcvFrom(pMsg, glbl.GetLocalHostName());
- MsgSetRcvFromIP(pMsg, (uchar*)"127.0.0.1");
+ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
+ MsgSetRcvFromIP(pMsg, pLocalHostIP);
MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
MsgSetTAG(pMsg, pszTag, ustrlen(pszTag));
pMsg->iFacility = LOG_FAC(iFacility);
@@ -228,13 +235,23 @@ ENDrunInput
BEGINwillRun
CODESTARTwillRun
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.CreateStringProp(&pInputName, UCHAR_CONSTANT("imklog"), sizeof("imklog") - 1));
+ CHKiRet(prop.CreateStringProp(&pLocalHostIP, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
+
iRet = klogWillRun();
+finalize_it:
ENDwillRun
BEGINafterRun
CODESTARTafterRun
iRet = klogAfterRun();
+
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
+ if(pLocalHostIP != NULL)
+ prop.Destruct(&pLocalHostIP);
ENDafterRun
@@ -243,6 +260,9 @@ CODESTARTmodExit
/* release objects we used */
objRelease(glbl, CORE_COMPONENT);
objRelease(datetime, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
+ if(pszPath != NULL)
+ free(pszPath);
ENDmodExit
@@ -259,6 +279,10 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
symfile = NULL;
symbol_lookup = 0;
bPermitNonKernel = 0;
+ if(pszPath != NULL) {
+ free(pszPath);
+ pszPath = NULL;
+ }
iFacilIntMsg = klogFacilIntMsg();
return RS_RET_OK;
}
@@ -269,10 +293,12 @@ CODESTARTmodInit
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(datetime, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
iFacilIntMsg = klogFacilIntMsg();
CHKiRet(omsdRegCFSLineHdlr((uchar *)"debugprintkernelsymbols", 0, eCmdHdlrBinary, NULL, &dbgPrintSymbols, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogpath", 0, eCmdHdlrGetWord, NULL, &pszPath, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbollookup", 0, eCmdHdlrBinary, NULL, &symbol_lookup, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbolstwice", 0, eCmdHdlrBinary, NULL, &symbols_twice, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogusesyscallinterface", 0, eCmdHdlrBinary, NULL, &use_syscall, STD_LOADABLE_MODULE_ID));
diff --git a/plugins/imklog/imklog.h b/plugins/imklog/imklog.h
index 37bd58b0..c183026d 100644
--- a/plugins/imklog/imklog.h
+++ b/plugins/imklog/imklog.h
@@ -52,6 +52,7 @@ extern int symbol_lookup;
extern char *symfile;
extern int console_log_level;
extern int dbgPrintSymbols;
+extern uchar *pszPath;
/* the functions below may be called by the drivers */
rsRetVal imklogLogIntMsg(int priority, char *fmt, ...) __attribute__((format(printf,2, 3)));
diff --git a/plugins/imklog/linux.c b/plugins/imklog/linux.c
index 0dd4320d..977395ea 100644
--- a/plugins/imklog/linux.c
+++ b/plugins/imklog/linux.c
@@ -37,6 +37,7 @@
#include "msg.h"
#include "module-template.h"
#include "imklog.h"
+#include "unicode-helper.h"
/* Includes. */
@@ -84,6 +85,11 @@ static enum LOGSRC {none, proc, kernel} logsrc;
extern int ksyslog(int type, char *buf, int len);
+static uchar *GetPath(void)
+{
+ return pszPath ? pszPath : UCHAR_CONSTANT(_PATH_KLOG);
+}
+
static void CloseLogSrc(void)
{
/* Turn on logging of messages to console, but only if we had the -c
@@ -135,7 +141,7 @@ static enum LOGSRC GetKernelLogSrc(void)
* file system is available to get kernel messages from.
*/
if ( use_syscall ||
- ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) )
+ ((stat((char*)GetPath(), &sb) < 0) && (errno == ENOENT)) )
{
/* Initialize kernel logging. */
ksyslog(1, NULL, 0);
@@ -144,14 +150,14 @@ static enum LOGSRC GetKernelLogSrc(void)
return(kernel);
}
- if ( (kmsg = open(_PATH_KLOG, O_RDONLY|O_CLOEXEC)) < 0 )
+ if ( (kmsg = open((char*)GetPath(), O_RDONLY|O_CLOEXEC)) < 0 )
{
imklogLogIntMsg(LOG_ERR, "imklog: Cannot open proc file system, %d.\n", errno);
ksyslog(7, NULL, 0); /* TODO: check this, implement more */
return(none);
}
- imklogLogIntMsg(LOG_INFO, "imklog %s, log source = %s started.", VERSION, _PATH_KLOG);
+ imklogLogIntMsg(LOG_INFO, "imklog %s, log source = %s started.", VERSION, GetPath());
return(proc);
}
diff --git a/plugins/imrelp/imrelp.c b/plugins/imrelp/imrelp.c
index 2255e643..b9e7b2f8 100644
--- a/plugins/imrelp/imrelp.c
+++ b/plugins/imrelp/imrelp.c
@@ -4,7 +4,7 @@
*
* File begun on 2008-03-13 by RGerhards
*
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2008, 2009 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
@@ -43,15 +43,19 @@
#include "module-template.h"
#include "net.h"
#include "msg.h"
+#include "unicode-helper.h"
+#include "prop.h"
MODULE_TYPE_INPUT
/* static data */
DEF_IMOD_STATIC_DATA
DEFobjCurrIf(net)
+DEFobjCurrIf(prop)
/* Module static data */
static relpEngine_t *pRelpEngine; /* our relp engine */
+static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this module */
/* config settings */
@@ -85,7 +89,7 @@ onSyslogRcv(uchar *pHostname, uchar __attribute__((unused)) *pIP, uchar *pMsg, s
{
DEFiRet;
parseAndSubmitMessage(pHostname, (uchar*) "[unset]", pMsg, lenMsg, PARSE_HOSTNAME,
- eFLOWCTL_LIGHT_DELAY, (uchar*)"imrelp", NULL, 0);
+ eFLOWCTL_LIGHT_DELAY, pInputName, NULL, 0);
RETiRet;
}
@@ -130,6 +134,11 @@ CODESTARTwillRun
//net.PrintAllowedSenders(2); /* TCP */
if(pRelpEngine == NULL)
ABORT_FINALIZE(RS_RET_NO_RUN);
+
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imrelp"), sizeof("imrelp") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
finalize_it:
ENDwillRun
@@ -143,6 +152,9 @@ CODESTARTafterRun
net.pAllowedSenders_TCP = NULL;
}
#endif
+
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
ENDafterRun
@@ -152,6 +164,7 @@ CODESTARTmodExit
iRet = relpEngineDestruct(&pRelpEngine);
/* release objects we used */
+ objRelease(prop, CORE_COMPONENT);
objRelease(net, LM_NET_FILENAME);
ENDmodExit
@@ -177,6 +190,7 @@ CODESTARTmodInit
CODEmodInit_QueryRegCFSLineHdlr
pRelpEngine = NULL;
/* request objects we use */
+ CHKiRet(objUse(prop, CORE_COMPONENT));
CHKiRet(objUse(net, LM_NET_FILENAME));
/* register config file handlers */
diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c
index 2340aac4..718c3090 100644
--- a/plugins/imudp/imudp.c
+++ b/plugins/imudp/imudp.c
@@ -43,6 +43,7 @@
#include "msg.h"
#include "parser.h"
#include "datetime.h"
+#include "prop.h"
#include "unicode-helper.h"
MODULE_TYPE_INPUT
@@ -55,6 +56,7 @@ DEFobjCurrIf(errmsg)
DEFobjCurrIf(glbl)
DEFobjCurrIf(net)
DEFobjCurrIf(datetime)
+DEFobjCurrIf(prop)
static int iMaxLine; /* maximum UDP message size supported */
static time_t ttLastDiscard = 0; /* timestamp when a message from a non-permitted sender was last discarded
@@ -68,6 +70,7 @@ static uchar *pRcvBuf = NULL; /* receive buffer (for a single packet). We use a
* it so that we can check available memory in willRun() and request
* termination if we can not get it. -- rgerhards, 2007-12-27
*/
+static prop_t *pInputName = NULL; /* our inputName currently is always "imudp", and this will hold it */
// TODO: static ruleset_t *pBindRuleset = NULL; /* ruleset to bind listener to (use system default if unspecified) */
#define TIME_REQUERY_DFLT 2
static int iTimeRequery = TIME_REQUERY_DFLT;/* how often is time to be queried inside tight recv loop? 0=always */
@@ -188,6 +191,8 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted,
ssize_t lenRcvBuf;
struct sockaddr_storage frominet;
msg_t *pMsg;
+ prop_t *propFromHost = NULL;
+ prop_t *propFromHostIP = NULL;
char errStr[1024];
iNbrTimeUsed = 0;
@@ -242,18 +247,22 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted,
/* we now create our own message object and submit it to the queue */
CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime));
MsgSetRawMsg(pMsg, (char*)pRcvBuf, lenRcvBuf);
- MsgSetInputName(pMsg, UCHAR_CONSTANT("imudp"), sizeof("imudp")-1);
+ MsgSetInputName(pMsg, pInputName);
MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);
pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
pMsg->bParseHOSTNAME = 1;
- MsgSetRcvFrom(pMsg, fromHost);
- CHKiRet(MsgSetRcvFromIP(pMsg, fromHostIP));
+ MsgSetRcvFromStr(pMsg, fromHost, ustrlen(fromHost), &propFromHost);
+ CHKiRet(MsgSetRcvFromIPStr(pMsg, fromHostIP, ustrlen(fromHostIP), &propFromHostIP));
CHKiRet(submitMsg(pMsg));
}
}
-
finalize_it:
+ if(propFromHost != NULL)
+ prop.Destruct(&propFromHost);
+ if(propFromHostIP != NULL)
+ prop.Destruct(&propFromHostIP);
+
RETiRet;
}
@@ -338,6 +347,11 @@ ENDrunInput
/* initialize and return if will run or not */
BEGINwillRun
CODESTARTwillRun
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imudp"), sizeof("imudp") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+
net.PrintAllowedSenders(1); /* UDP */
/* if we could not set up any listners, there is no point in running... */
@@ -365,6 +379,8 @@ CODESTARTafterRun
free(pRcvBuf);
pRcvBuf = NULL;
}
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
ENDafterRun
@@ -374,6 +390,7 @@ CODESTARTmodExit
objRelease(errmsg, CORE_COMPONENT);
objRelease(glbl, CORE_COMPONENT);
objRelease(datetime, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
objRelease(net, LM_NET_FILENAME);
ENDmodExit
@@ -405,6 +422,7 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
CHKiRet(objUse(net, LM_NET_FILENAME));
/* register config file handlers */
diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c
index 9a1e424c..6d60efaf 100644
--- a/plugins/imuxsock/imuxsock.c
+++ b/plugins/imuxsock/imuxsock.c
@@ -37,12 +37,14 @@
#include <sys/un.h>
#include "dirty.h"
#include "cfsysline.h"
+#include "unicode-helper.h"
#include "module-template.h"
#include "srUtils.h"
#include "errmsg.h"
#include "net.h"
#include "glbl.h"
#include "msg.h"
+#include "prop.h"
MODULE_TYPE_INPUT
@@ -66,7 +68,9 @@ MODULE_TYPE_INPUT
DEF_IMOD_STATIC_DATA
DEFobjCurrIf(errmsg)
DEFobjCurrIf(glbl)
+DEFobjCurrIf(prop)
+static prop_t *pInputName = NULL; /* our inputName currently is always "imudp", and this will hold it */
static int startIndexUxLocalSockets; /* process funix from that index on (used to
* suppress local logging. rgerhards 2005-08-01
* read-only after startup
@@ -223,7 +227,7 @@ static rsRetVal readSocket(int fd, int iSock)
parseAndSubmitMessage(funixHName[iSock] == NULL ? glbl.GetLocalHostName() : funixHName[iSock],
(uchar*)"127.0.0.1", pRcv,
iRcvd, funixParseHost[iSock] ? (funixFlags[iSock] | PARSE_HOSTNAME) : funixFlags[iSock],
- funixFlowCtl[iSock], (uchar*)"imuxsock", NULL, 0);
+ funixFlowCtl[iSock], pInputName, NULL, 0);
} else if (iRcvd < 0 && errno != EINTR) {
char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
@@ -306,7 +310,12 @@ CODESTARTwillRun
dbgprintf("Opened UNIX socket '%s' (fd %d).\n", funixn[i], funix[i]);
}
- RETiRet;
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInputName));
+ CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imudp"), sizeof("imudp") - 1));
+ CHKiRet(prop.ConstructFinalize(pInputName));
+
+finalize_it:
ENDwillRun
@@ -329,6 +338,9 @@ CODESTARTafterRun
discardFunixn();
nfunix = 1;
+
+ if(pInputName != NULL)
+ prop.Destruct(&pInputName);
ENDafterRun
@@ -336,6 +348,7 @@ BEGINmodExit
CODESTARTmodExit
objRelease(glbl, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
ENDmodExit
@@ -372,6 +385,7 @@ CODESTARTmodInit
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
dbgprintf("imuxsock version %s initializing\n", PACKAGE_VERSION);
diff --git a/runtime/datetime.c b/runtime/datetime.c
index 5b9f5b6d..46488433 100644
--- a/runtime/datetime.c
+++ b/runtime/datetime.c
@@ -558,7 +558,6 @@ int formatTimestampToMySQL(struct syslogTime *ts, char* pBuf)
*/
assert(ts != NULL);
assert(pBuf != NULL);
- assert(iLenDst >= 15);
pBuf[0] = (ts->year / 1000) % 10 + '0';
pBuf[1] = (ts->year / 100) % 10 + '0';
@@ -584,7 +583,6 @@ int formatTimestampToPgSQL(struct syslogTime *ts, char *pBuf)
/* see note in formatTimestampToMySQL, applies here as well */
assert(ts != NULL);
assert(pBuf != NULL);
- assert(iLenDst >= 20);
pBuf[0] = (ts->year / 1000) % 10 + '0';
pBuf[1] = (ts->year / 100) % 10 + '0';
@@ -667,7 +665,6 @@ int formatTimestamp3339(struct syslogTime *ts, char* pBuf)
BEGINfunc
assert(ts != NULL);
assert(pBuf != NULL);
- assert(iLenBuf >= 33);
/* start with fixed parts */
/* year yyyy */
@@ -742,8 +739,6 @@ int formatTimestamp3164(struct syslogTime *ts, char* pBuf)
assert(ts != NULL);
assert(pBuf != NULL);
- assert(iLenBuf >= 16);
-
pBuf[0] = monthNames[(ts->month - 1)% 12][0];
pBuf[1] = monthNames[(ts->month - 1) % 12][1];
pBuf[2] = monthNames[(ts->month - 1) % 12][2];
diff --git a/runtime/datetime.h b/runtime/datetime.h
index 79a86d05..58f368e7 100644
--- a/runtime/datetime.h
+++ b/runtime/datetime.h
@@ -23,8 +23,6 @@
#ifndef INCLUDED_DATETIME_H
#define INCLUDED_DATETIME_H
-#include "datetime.h"
-
/* TODO: define error codes */
#define NO_ERRCODE -1
diff --git a/runtime/glbl.c b/runtime/glbl.c
index 28f14320..32b85622 100644
--- a/runtime/glbl.c
+++ b/runtime/glbl.c
@@ -35,8 +35,10 @@
#include "rsyslog.h"
#include "obj.h"
+#include "unicode-helper.h"
#include "cfsysline.h"
#include "glbl.h"
+#include "prop.h"
/* some defaults */
#ifndef DFLT_NETSTRM_DRVR
@@ -45,6 +47,7 @@
/* static data */
DEFobjStaticHelpers
+DEFobjCurrIf(prop)
/* static data
* For this object, these variables are obviously what makes the "meat" of the
@@ -59,6 +62,7 @@ static int iDefPFFamily = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both)
static int bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records during DNS lookup */
static int option_DisallowWarning = 1; /* complain if message from disallowed sender is received */
static int bDisableDNS = 0; /* don't look up IP addresses of remote messages */
+static prop_t *propLocalHostName = NULL;/* our hostname as FQDN - read-only after startup */
static uchar *LocalHostName = NULL;/* our hostname - read-only after startup */
static uchar *LocalFQDNName = NULL;/* our hostname as FQDN - read-only after startup */
static uchar *LocalDomain; /* our local domain name - read-only after startup */
@@ -132,6 +136,44 @@ GetLocalHostName(void)
}
+/* generate the local hostname property. This must be done after the hostname info
+ * has been set as well as PreserveFQDN.
+ * rgerhards, 2009-06-30
+ */
+static rsRetVal
+GenerateLocalHostNameProperty(void)
+{
+ DEFiRet;
+ uchar *pszName;
+
+ if(propLocalHostName != NULL)
+ prop.Destruct(&propLocalHostName);
+
+ CHKiRet(prop.Construct(&propLocalHostName));
+ if(LocalHostName == NULL)
+ pszName = (uchar*) "[localhost]";
+ else {
+ if(GetPreserveFQDN() == 1)
+ pszName = LocalFQDNName;
+ else
+ pszName = LocalHostName;
+ }
+ CHKiRet(prop.SetString(propLocalHostName, pszName, ustrlen(pszName)));
+ CHKiRet(prop.ConstructFinalize(propLocalHostName));
+
+finalize_it:
+ RETiRet;
+}
+
+/* return our local hostname as a string property
+ */
+static prop_t*
+GetLocalHostNameProp(void)
+{
+ return(propLocalHostName);
+}
+
+
/* return the current localhost name as FQDN (requires FQDN to be set)
* TODO: we should set the FQDN ourselfs in here!
*/
@@ -197,6 +239,8 @@ CODESTARTobjQueryInterface(glbl)
* of course, also affects the "if" above).
*/
pIf->GetWorkDir = GetWorkDir;
+ pIf->GenerateLocalHostNameProperty = GenerateLocalHostNameProperty;
+ pIf->GetLocalHostNameProp = GetLocalHostNameProp;
#define SIMP_PROP(name) \
pIf->Get##name = Get##name; \
pIf->Set##name = Set##name;
@@ -262,6 +306,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
*/
BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
+ CHKiRet(objUse(prop, CORE_COMPONENT));
/* register config handlers (TODO: we need to implement a way to unregister them) */
CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, NULL, &pszWorkDir, NULL));
@@ -295,6 +340,7 @@ BEGINObjClassExit(glbl, OBJ_IS_CORE_MODULE) /* class, version */
free(LocalHostName);
if(LocalFQDNName != NULL)
free(LocalFQDNName);
+ objRelease(prop, CORE_COMPONENT);
ENDObjClassExit(glbl)
/* vi:set ai:
diff --git a/runtime/glbl.h b/runtime/glbl.h
index 5bdf4f57..dcfb6d5f 100644
--- a/runtime/glbl.h
+++ b/runtime/glbl.h
@@ -32,6 +32,8 @@
#ifndef GLBL_H_INCLUDED
#define GLBL_H_INCLUDED
+#include "prop.h"
+
#define glblGetIOBufSize() 4096 /* size of the IO buffer, e.g. for strm class */
/* interfaces */
@@ -57,9 +59,12 @@ BEGINinterface(glbl) /* name must also be changed in ENDinterface macro! */
SIMP_PROP(DfltNetstrmDrvrCAF, uchar*)
SIMP_PROP(DfltNetstrmDrvrKeyFile, uchar*)
SIMP_PROP(DfltNetstrmDrvrCertFile, uchar*)
+ /* added v3, 2009-06-30 */
+ rsRetVal (*GenerateLocalHostNameProperty)(void);
+ prop_t* (*GetLocalHostNameProp)(void);
#undef SIMP_PROP
ENDinterface(glbl)
-#define glblCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */
+#define glblCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */
/* version 2 had PreserveFQDN added - rgerhards, 2008-12-08 */
/* the remaining prototypes */
diff --git a/runtime/modules.c b/runtime/modules.c
index 9830aa45..0ec6b1ce 100644
--- a/runtime/modules.c
+++ b/runtime/modules.c
@@ -435,6 +435,7 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"runInput", &pNew->mod.im.runInput));
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"willRun", &pNew->mod.im.willRun));
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"afterRun", &pNew->mod.im.afterRun));
+ pNew->mod.im.bCanRun = 0;
break;
case eMOD_OUT:
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"freeInstance", &pNew->freeInstance));
diff --git a/runtime/modules.h b/runtime/modules.h
index e33bbbe1..71e3199c 100644
--- a/runtime/modules.h
+++ b/runtime/modules.h
@@ -106,6 +106,7 @@ typedef struct modInfo_s {
rsRetVal (*runInput)(thrdInfo_t*); /* function to gather input and submit to queue */
rsRetVal (*willRun)(void); /* function to gather input and submit to queue */
rsRetVal (*afterRun)(thrdInfo_t*); /* function to gather input and submit to queue */
+ int bCanRun; /* cached value of whether willRun() succeeded */
} im;
struct {/* data for output modules */
/* below: perform the configured action
diff --git a/runtime/msg.c b/runtime/msg.c
index c4ba18df..6c272d1f 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -48,6 +48,7 @@
#include "atomic.h"
#include "unicode-helper.h"
#include "ruleset.h"
+#include "prop.h"
/* static data */
DEFobjStaticHelpers
@@ -55,6 +56,7 @@ DEFobjCurrIf(var)
DEFobjCurrIf(datetime)
DEFobjCurrIf(glbl)
DEFobjCurrIf(regexp)
+DEFobjCurrIf(prop)
static struct {
uchar *pszName;
@@ -273,12 +275,215 @@ static char *syslog_number_names[24] = { "0", "1", "2", "3", "4", "5", "6", "7",
/* some forward declarations */
static int getAPPNAMELen(msg_t *pM, bool bLockMutex);
+
static inline int getProtocolVersion(msg_t *pM)
{
return(pM->iProtocolVersion);
}
+static inline void
+getInputName(msg_t *pM, uchar **ppsz, int *plen)
+{
+ BEGINfunc
+ if(pM == NULL) {
+ *ppsz = UCHAR_CONSTANT("");
+ *plen = 0;
+ } else {
+ prop.GetString(pM->pInputName, ppsz, plen);
+ }
+ ENDfunc
+}
+
+
+static inline uchar*
+getRcvFromIP(msg_t *pM)
+{
+ uchar *psz;
+ int len;
+ BEGINfunc
+ if(pM == NULL) {
+ psz = UCHAR_CONSTANT("");
+ } else {
+ if(pM->pRcvFromIP == NULL)
+ psz = UCHAR_CONSTANT("");
+ else
+ prop.GetString(pM->pRcvFromIP, &psz, &len);
+ }
+ ENDfunc
+ return psz;
+}
+
+
+
+/* map a property name (string) to a property ID */
+rsRetVal propNameToID(cstr_t *pCSPropName, propid_t *pPropID)
+{
+ uchar *pName;
+ DEFiRet;
+
+ assert(pCSPropName != NULL);
+ assert(pPropID != NULL);
+ pName = rsCStrGetSzStrNoNULL(pCSPropName);
+
+ /* sometimes there are aliases to the original MonitoWare
+ * property names. These come after || in the ifs below. */
+ if(!strcmp((char*) pName, "msg")) {
+ *pPropID = PROP_MSG;
+ } else if(!strcmp((char*) pName, "timestamp")
+ || !strcmp((char*) pName, "timereported")) {
+ *pPropID = PROP_TIMESTAMP;
+ } else if(!strcmp((char*) pName, "hostname") || !strcmp((char*) pName, "source")) {
+ *pPropID = PROP_HOSTNAME;
+ } else if(!strcmp((char*) pName, "syslogtag")) {
+ *pPropID = PROP_SYSLOGTAG;
+ } else if(!strcmp((char*) pName, "rawmsg")) {
+ *pPropID = PROP_RAWMSG;
+ /* enable this, if someone actually uses UxTradMsg, delete after some time has
+ * passed and nobody complained -- rgerhards, 2009-06-16
+ } else if(!strcmp((char*) pName, "uxtradmsg")) {
+ pRes = getUxTradMsg(pMsg);
+ */
+ } else if(!strcmp((char*) pName, "inputname")) {
+ *pPropID = PROP_INPUTNAME;
+ } else if(!strcmp((char*) pName, "fromhost")) {
+ *pPropID = PROP_FROMHOST;
+ } else if(!strcmp((char*) pName, "fromhost-ip")) {
+ *pPropID = PROP_FROMHOST_IP;
+ } else if(!strcmp((char*) pName, "pri")) {
+ *pPropID = PROP_PRI;
+ } else if(!strcmp((char*) pName, "pri-text")) {
+ *pPropID = PROP_PRI_TEXT;
+ } else if(!strcmp((char*) pName, "iut")) {
+ *pPropID = PROP_IUT;
+ } else if(!strcmp((char*) pName, "syslogfacility")) {
+ *pPropID = PROP_SYSLOGFACILITY;
+ } else if(!strcmp((char*) pName, "syslogfacility-text")) {
+ *pPropID = PROP_SYSLOGFACILITY_TEXT;
+ } else if(!strcmp((char*) pName, "syslogseverity") || !strcmp((char*) pName, "syslogpriority")) {
+ *pPropID = PROP_SYSLOGSEVERITY;
+ } else if(!strcmp((char*) pName, "syslogseverity-text") || !strcmp((char*) pName, "syslogpriority-text")) {
+ *pPropID = PROP_SYSLOGSEVERITY_TEXT;
+ } else if(!strcmp((char*) pName, "timegenerated")) {
+ *pPropID = PROP_TIMEGENERATED;
+ } else if(!strcmp((char*) pName, "programname")) {
+ *pPropID = PROP_PROGRAMNAME;
+ } else if(!strcmp((char*) pName, "protocol-version")) {
+ *pPropID = PROP_PROTOCOL_VERSION;
+ } else if(!strcmp((char*) pName, "structured-data")) {
+ *pPropID = PROP_STRUCTURED_DATA;
+ } else if(!strcmp((char*) pName, "app-name")) {
+ *pPropID = PROP_APP_NAME;
+ } else if(!strcmp((char*) pName, "procid")) {
+ *pPropID = PROP_PROCID;
+ } else if(!strcmp((char*) pName, "msgid")) {
+ *pPropID = PROP_MSGID;
+ /* here start system properties (those, that do not relate to the message itself */
+ } else if(!strcmp((char*) pName, "$now")) {
+ *pPropID = PROP_SYS_NOW;
+ } else if(!strcmp((char*) pName, "$year")) {
+ *pPropID = PROP_SYS_YEAR;
+ } else if(!strcmp((char*) pName, "$month")) {
+ *pPropID = PROP_SYS_MONTH;
+ } else if(!strcmp((char*) pName, "$day")) {
+ *pPropID = PROP_SYS_DAY;
+ } else if(!strcmp((char*) pName, "$hour")) {
+ *pPropID = PROP_SYS_HOUR;
+ } else if(!strcmp((char*) pName, "$hhour")) {
+ *pPropID = PROP_SYS_HHOUR;
+ } else if(!strcmp((char*) pName, "$qhour")) {
+ *pPropID = PROP_SYS_QHOUR;
+ } else if(!strcmp((char*) pName, "$minute")) {
+ *pPropID = PROP_SYS_MINUTE;
+ } else if(!strcmp((char*) pName, "$myhostname")) {
+ *pPropID = PROP_SYS_MYHOSTNAME;
+ } else {
+ *pPropID = PROP_INVALID;
+ iRet = RS_RET_VAR_NOT_FOUND;
+ }
+
+ RETiRet;
+}
+
+
+/* map a property ID to a name string (useful for displaying) */
+uchar *propIDToName(propid_t propID)
+{
+ switch(propID) {
+ case PROP_MSG:
+ return UCHAR_CONSTANT("msg");
+ case PROP_TIMESTAMP:
+ return UCHAR_CONSTANT("timestamp");
+ case PROP_HOSTNAME:
+ return UCHAR_CONSTANT("hostname");
+ case PROP_SYSLOGTAG:
+ return UCHAR_CONSTANT("syslogtag");
+ case PROP_RAWMSG:
+ return UCHAR_CONSTANT("rawmsg");
+ /* enable this, if someone actually uses UxTradMsg, delete after some time has
+ * passed and nobody complained -- rgerhards, 2009-06-16
+ case PROP_UXTRADMSG:
+ pRes = getUxTradMsg(pMsg);
+ break;
+ */
+ case PROP_INPUTNAME:
+ return UCHAR_CONSTANT("inputname");
+ case PROP_FROMHOST:
+ return UCHAR_CONSTANT("fromhost");
+ case PROP_FROMHOST_IP:
+ return UCHAR_CONSTANT("fromhost-ip");
+ case PROP_PRI:
+ return UCHAR_CONSTANT("pri");
+ case PROP_PRI_TEXT:
+ return UCHAR_CONSTANT("pri-text");
+ case PROP_IUT:
+ return UCHAR_CONSTANT("iut");
+ case PROP_SYSLOGFACILITY:
+ return UCHAR_CONSTANT("syslogfacility");
+ case PROP_SYSLOGFACILITY_TEXT:
+ return UCHAR_CONSTANT("syslogfacility-text");
+ case PROP_SYSLOGSEVERITY:
+ return UCHAR_CONSTANT("syslogseverity");
+ case PROP_SYSLOGSEVERITY_TEXT:
+ return UCHAR_CONSTANT("syslogseverity-text");
+ case PROP_TIMEGENERATED:
+ return UCHAR_CONSTANT("timegenerated");
+ case PROP_PROGRAMNAME:
+ return UCHAR_CONSTANT("programname");
+ case PROP_PROTOCOL_VERSION:
+ return UCHAR_CONSTANT("protocol-version");
+ case PROP_STRUCTURED_DATA:
+ return UCHAR_CONSTANT("structured-data");
+ case PROP_APP_NAME:
+ return UCHAR_CONSTANT("app-name");
+ case PROP_PROCID:
+ return UCHAR_CONSTANT("procid");
+ case PROP_MSGID:
+ return UCHAR_CONSTANT("msgid");
+ case PROP_SYS_NOW:
+ return UCHAR_CONSTANT("$NOW");
+ case PROP_SYS_YEAR:
+ return UCHAR_CONSTANT("$YEAR");
+ case PROP_SYS_MONTH:
+ return UCHAR_CONSTANT("$MONTH");
+ case PROP_SYS_DAY:
+ return UCHAR_CONSTANT("$DAY");
+ case PROP_SYS_HOUR:
+ return UCHAR_CONSTANT("$HOUR");
+ case PROP_SYS_HHOUR:
+ return UCHAR_CONSTANT("$HHOUR");
+ case PROP_SYS_QHOUR:
+ return UCHAR_CONSTANT("$QHOUR");
+ case PROP_SYS_MINUTE:
+ return UCHAR_CONSTANT("$MINUTE");
+ case PROP_SYS_MYHOSTNAME:
+ return UCHAR_CONSTANT("$MYHOSTNAME");
+ default:
+ return UCHAR_CONSTANT("*invalid property id*");
+ }
+}
+
+
/* The following functions will support advanced output module
* multithreading, once this is implemented. Currently, we
* include them as hooks only. The idea is that we need to guard
@@ -431,20 +636,14 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis)
pM->iFacility = -1;
pM->offAfterPRI = 0;
pM->offMSG = -1;
- pM->iLenInputName = 0;
pM->iProtocolVersion = 0;
pM->msgFlags = 0;
pM->iLenRawMsg = 0;
pM->iLenMSG = 0;
pM->iLenTAG = 0;
pM->iLenHOSTNAME = 0;
- pM->iLenRcvFrom = 0;
- pM->iLenRcvFromIP = 0;
pM->pszRawMsg = NULL;
pM->pszHOSTNAME = NULL;
- pM->pszRcvFrom = NULL;
- pM->pszRcvFromIP = NULL;
- pM->pszInputName = NULL;
pM->pszRcvdAt3164 = NULL;
pM->pszRcvdAt3339 = NULL;
pM->pszRcvdAt_MySQL = NULL;
@@ -458,6 +657,9 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis)
pM->pCSAPPNAME = NULL;
pM->pCSPROCID = NULL;
pM->pCSMSGID = NULL;
+ pM->pInputName = NULL;
+ pM->pRcvFromIP = NULL;
+ pM->pRcvFrom = NULL;
pM->pRuleset = NULL;
memset(&pM->tRcvdAt, 0, sizeof(pM->tRcvdAt));
memset(&pM->tTIMESTAMP, 0, sizeof(pM->tTIMESTAMP));
@@ -556,9 +758,12 @@ CODESTARTobjDestruct(msg)
free(pThis->pszRawMsg);
freeTAG(pThis);
freeHOSTNAME(pThis);
- free(pThis->pszInputName);
- free(pThis->pszRcvFrom);
- free(pThis->pszRcvFromIP);
+ if(pThis->pInputName != NULL)
+ prop.Destruct(&pThis->pInputName);
+ if(pThis->pRcvFrom != NULL)
+ prop.Destruct(&pThis->pRcvFrom);
+ if(pThis->pRcvFromIP != NULL)
+ prop.Destruct(&pThis->pRcvFromIP);
free(pThis->pszRcvdAt3164);
free(pThis->pszRcvdAt3339);
free(pThis->pszRcvdAt_MySQL);
@@ -659,6 +864,12 @@ msg_t* MsgDup(msg_t* pOld)
pNew->iProtocolVersion = pOld->iProtocolVersion;
pNew->ttGenTime = pOld->ttGenTime;
pNew->offMSG = pOld->offMSG;
+ pNew->pRcvFrom = pOld->pRcvFrom;
+ prop.AddRef(pNew->pRcvFrom);
+ pNew->pRcvFromIP = pOld->pRcvFromIP;
+ prop.AddRef(pNew->pRcvFromIP);
+ pNew->pInputName = pOld->pInputName;
+ prop.AddRef(pNew->pInputName);
/* enable this, if someone actually uses UxTradMsg, delete after some time has
* passed and nobody complained -- rgerhards, 2009-06-16
pNew->offAfterPRI = pOld->offAfterPRI;
@@ -686,7 +897,6 @@ msg_t* MsgDup(msg_t* pOld)
} else {
tmpCOPYSZ(HOSTNAME);
}
- tmpCOPYSZ(RcvFrom);
tmpCOPYCSTR(ProgName);
tmpCOPYCSTR(StrucData);
@@ -719,11 +929,16 @@ msg_t* MsgDup(msg_t* pOld)
*/
static rsRetVal MsgSerialize(msg_t *pThis, strm_t *pStrm)
{
+ uchar *psz;
+ int len;
DEFiRet;
assert(pThis != NULL);
assert(pStrm != NULL);
+ /* "pump" some property values into strings */
+
+ /* then serialize elements */
CHKiRet(obj.BeginSerialize(pStrm, (obj_t*) pThis));
objSerializeSCALAR(pStrm, iProtocolVersion, SHORT);
objSerializeSCALAR(pStrm, iSeverity, SHORT);
@@ -743,9 +958,12 @@ static rsRetVal MsgSerialize(msg_t *pThis, strm_t *pStrm)
objSerializePTR(pStrm, pszRawMsg, PSZ);
objSerializePTR(pStrm, pszHOSTNAME, PSZ);
- objSerializePTR(pStrm, pszInputName, PSZ);
- objSerializePTR(pStrm, pszRcvFrom, PSZ);
- objSerializePTR(pStrm, pszRcvFromIP, PSZ);
+ getInputName(pThis, &psz, &len);
+ objSerializeSCALAR_VAR(pStrm, "pszInputName", PSZ, psz);
+ psz = getRcvFrom(pThis);
+ objSerializeSCALAR_VAR(pStrm, "pszRcvFrom", PSZ, psz);
+ psz = getRcvFromIP(pThis);
+ objSerializeSCALAR_VAR(pStrm, "pszRcvFromIP", PSZ, psz);
objSerializePTR(pStrm, pCSStrucData, CSTR);
objSerializePTR(pStrm, pCSAPPNAME, CSTR);
@@ -1409,7 +1627,10 @@ int getHOSTNAMELen(msg_t *pM)
return 0;
else
if(pM->pszHOSTNAME == NULL)
- return pM->iLenRcvFrom;
+ if(pM->pRcvFrom == NULL)
+ return 0;
+ else
+ return prop.GetStringLen(pM->pRcvFrom);
else
return pM->iLenHOSTNAME;
}
@@ -1420,48 +1641,39 @@ char *getHOSTNAME(msg_t *pM)
if(pM == NULL)
return "";
else
- if(pM->pszHOSTNAME == NULL)
- return (char*) pM->pszRcvFrom;
- else
+ if(pM->pszHOSTNAME == NULL) {
+ if(pM->pRcvFrom == NULL) {
+ return "";
+ } else {
+ uchar *psz;
+ int len;
+ prop.GetString(pM->pRcvFrom, &psz, &len);
+ return (char*) psz;
+ }
+ } else {
return (char*) pM->pszHOSTNAME;
-}
-
-
-static uchar *getInputName(msg_t *pM)
-{
- if(pM == NULL)
- return (uchar*) "";
- else
- if(pM->pszInputName == NULL)
- return (uchar*) "";
- else
- return pM->pszInputName;
+ }
}
uchar *getRcvFrom(msg_t *pM)
{
- if(pM == NULL)
- return UCHAR_CONSTANT("");
- else
- if(pM->pszRcvFrom == NULL)
- return UCHAR_CONSTANT("");
+ uchar *psz;
+ int len;
+ BEGINfunc
+ if(pM == NULL) {
+ psz = UCHAR_CONSTANT("");
+ } else {
+ if(pM->pRcvFrom == NULL)
+ psz = UCHAR_CONSTANT("");
else
- return pM->pszRcvFrom;
+ prop.GetString(pM->pRcvFrom, &psz, &len);
+ }
+ ENDfunc
+ return psz;
}
-uchar *getRcvFromIP(msg_t *pM)
-{
- if(pM == NULL)
- return (uchar*) "";
- else
- if(pM->pszRcvFromIP == NULL)
- return (uchar*) "";
- else
- return pM->pszRcvFromIP;
-}
-
/* rgerhards 2004-11-24: set STRUCTURED DATA in msg object
*/
rsRetVal MsgSetStructuredData(msg_t *pMsg, char* pszStrucData)
@@ -1595,46 +1807,91 @@ static int getAPPNAMELen(msg_t *pM, bool bLockMutex)
return (pM->pCSAPPNAME == NULL) ? 0 : rsCStrLen(pM->pCSAPPNAME);
}
-/* rgerhards 2008-09-10: set pszInputName in msg object
+/* rgerhards 2008-09-10: set pszInputName in msg object. This calls AddRef()
+ * on the property, because this must be done in all current cases and there
+ * is no case expected where this may not be necessary.
* rgerhards, 2009-06-16
*/
-void MsgSetInputName(msg_t *pMsg, uchar* pszInputName, size_t lenInputName)
+void MsgSetInputName(msg_t *pThis, prop_t *inputName)
{
- assert(pMsg != NULL);
- free(pMsg->pszInputName);
- pMsg->iLenInputName = lenInputName;
- if((pMsg->pszInputName = malloc(pMsg->iLenInputName + 1)) != NULL) {
- memcpy(pMsg->pszInputName, pszInputName, pMsg->iLenInputName + 1);
- }
+ assert(pThis != NULL);
+
+ prop.AddRef(inputName);
+ if(pThis->pInputName != NULL)
+ prop.Destruct(&pThis->pInputName);
+ pThis->pInputName = inputName;
}
-/* rgerhards 2004-11-16: set pszRcvFrom in msg object
+
+/* rgerhards 2008-09-10: set RcvFrom name in msg object. This calls AddRef()
+ * on the property, because this must be done in all current cases and there
+ * is no case expected where this may not be necessary.
+ * rgerhards, 2009-06-30
*/
-void MsgSetRcvFrom(msg_t *pMsg, uchar* pszRcvFrom)
+void MsgSetRcvFrom(msg_t *pThis, prop_t *new)
{
- assert(pMsg != NULL);
- free(pMsg->pszRcvFrom);
+ assert(pThis != NULL);
- pMsg->iLenRcvFrom = ustrlen(pszRcvFrom);
- if((pMsg->pszRcvFrom = malloc(pMsg->iLenRcvFrom + 1)) != NULL) {
- memcpy(pMsg->pszRcvFrom, pszRcvFrom, pMsg->iLenRcvFrom + 1);
- }
+ prop.AddRef(new);
+ if(pThis->pRcvFrom != NULL)
+ prop.Destruct(&pThis->pRcvFrom);
+ pThis->pRcvFrom = new;
}
-/* rgerhards 2005-05-16: set pszRcvFromIP in msg object */
-rsRetVal
-MsgSetRcvFromIP(msg_t *pMsg, uchar* pszRcvFromIP)
+/* This is used to set the property via a string. This function should not be
+ * called if there is a reliable way for a caller to make sure that the
+ * same name can be used across multiple messages. However, if it can not
+ * ensure that, calling this function is the second best thing, because it
+ * will re-use the previously created property if it contained the same
+ * name (but it works only for the immediate previous).
+ * rgerhards, 2009-06-31
+ */
+void MsgSetRcvFromStr(msg_t *pThis, uchar *psz, int len, prop_t **ppProp)
+{
+ assert(pThis != NULL);
+ assert(ppProp != NULL);
+
+ prop.CreateOrReuseStringProp(ppProp, psz, len);
+ MsgSetRcvFrom(pThis, *ppProp);
+}
+
+
+/* set RcvFromIP name in msg object. This calls AddRef()
+ * on the property, because this must be done in all current cases and there
+ * is no case expected where this may not be necessary.
+ * rgerhards, 2009-06-30
+ */
+rsRetVal MsgSetRcvFromIP(msg_t *pThis, prop_t *new)
+{
+ assert(pThis != NULL);
+
+ BEGINfunc
+ prop.AddRef(new);
+ if(pThis->pRcvFromIP != NULL)
+ prop.Destruct(&pThis->pRcvFromIP);
+ pThis->pRcvFromIP = new;
+ ENDfunc
+ return RS_RET_OK;
+}
+
+
+/* This is used to set the property via a string. This function should not be
+ * called if there is a reliable way for a caller to make sure that the
+ * same name can be used across multiple messages. However, if it can not
+ * ensure that, calling this function is the second best thing, because it
+ * will re-use the previously created property if it contained the same
+ * name (but it works only for the immediate previous).
+ * rgerhards, 2009-06-31
+ */
+rsRetVal MsgSetRcvFromIPStr(msg_t *pThis, uchar *psz, int len, prop_t **ppProp)
{
DEFiRet;
- assert(pMsg != NULL);
- if(pMsg->pszRcvFromIP != NULL) {
- free(pMsg->pszRcvFromIP);
- pMsg->iLenRcvFromIP = 0;
- }
+ assert(pThis != NULL);
+
+ CHKiRet(prop.CreateOrReuseStringProp(ppProp, psz, len));
+ MsgSetRcvFrom(pThis, *ppProp);
- CHKmalloc(pMsg->pszRcvFromIP = (uchar*)strdup((char*)pszRcvFromIP));
- pMsg->iLenRcvFromIP = strlen((char*)pszRcvFromIP);
finalize_it:
RETiRet;
}
@@ -1910,7 +2167,7 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
break;
*/
case PROP_INPUTNAME:
- pRes = (char*) getInputName(pMsg);
+ getInputName(pMsg, ((uchar**) &pRes), &bufLen);
break;
case PROP_FROMHOST:
pRes = (char*) getRcvFrom(pMsg);
@@ -2638,97 +2895,6 @@ finalize_it:
RETiRet;
}
-
-/* map a property name (string) to a property ID */
-rsRetVal propNameToID(cstr_t *pCSPropName, propid_t *pPropID)
-{
- uchar *pName;
- DEFiRet;
-
- assert(pCSPropName != NULL);
- assert(pPropID != NULL);
- pName = rsCStrGetSzStrNoNULL(pCSPropName);
-
- /* sometimes there are aliases to the original MonitoWare
- * property names. These come after || in the ifs below. */
- if(!strcmp((char*) pName, "msg")) {
- *pPropID = PROP_MSG;
- } else if(!strcmp((char*) pName, "timestamp")
- || !strcmp((char*) pName, "timereported")) {
- *pPropID = PROP_TIMESTAMP;
- } else if(!strcmp((char*) pName, "hostname") || !strcmp((char*) pName, "source")) {
- *pPropID = PROP_HOSTNAME;
- } else if(!strcmp((char*) pName, "syslogtag")) {
- *pPropID = PROP_SYSLOGTAG;
- } else if(!strcmp((char*) pName, "rawmsg")) {
- *pPropID = PROP_RAWMSG;
- /* enable this, if someone actually uses UxTradMsg, delete after some time has
- * passed and nobody complained -- rgerhards, 2009-06-16
- } else if(!strcmp((char*) pName, "uxtradmsg")) {
- pRes = getUxTradMsg(pMsg);
- */
- } else if(!strcmp((char*) pName, "inputname")) {
- *pPropID = PROP_INPUTNAME;
- } else if(!strcmp((char*) pName, "fromhost")) {
- *pPropID = PROP_FROMHOST;
- } else if(!strcmp((char*) pName, "fromhost-ip")) {
- *pPropID = PROP_FROMHOST_IP;
- } else if(!strcmp((char*) pName, "pri")) {
- *pPropID = PROP_PRI;
- } else if(!strcmp((char*) pName, "pri-text")) {
- *pPropID = PROP_PRI_TEXT;
- } else if(!strcmp((char*) pName, "iut")) {
- *pPropID = PROP_IUT;
- } else if(!strcmp((char*) pName, "syslogfacility")) {
- *pPropID = PROP_SYSLOGFACILITY;
- } else if(!strcmp((char*) pName, "syslogfacility-text")) {
- *pPropID = PROP_SYSLOGFACILITY_TEXT;
- } else if(!strcmp((char*) pName, "syslogseverity") || !strcmp((char*) pName, "syslogpriority")) {
- *pPropID = PROP_SYSLOGSEVERITY;
- } else if(!strcmp((char*) pName, "syslogseverity-text") || !strcmp((char*) pName, "syslogpriority-text")) {
- *pPropID = PROP_SYSLOGSEVERITY_TEXT;
- } else if(!strcmp((char*) pName, "timegenerated")) {
- *pPropID = PROP_TIMEGENERATED;
- } else if(!strcmp((char*) pName, "programname")) {
- *pPropID = PROP_PROGRAMNAME;
- } else if(!strcmp((char*) pName, "protocol-version")) {
- *pPropID = PROP_PROTOCOL_VERSION;
- } else if(!strcmp((char*) pName, "structured-data")) {
- *pPropID = PROP_STRUCTURED_DATA;
- } else if(!strcmp((char*) pName, "app-name")) {
- *pPropID = PROP_APP_NAME;
- } else if(!strcmp((char*) pName, "procid")) {
- *pPropID = PROP_PROCID;
- } else if(!strcmp((char*) pName, "msgid")) {
- *pPropID = PROP_MSGID;
- /* here start system properties (those, that do not relate to the message itself */
- } else if(!strcmp((char*) pName, "$now")) {
- *pPropID = PROP_SYS_NOW;
- } else if(!strcmp((char*) pName, "$year")) {
- *pPropID = PROP_SYS_YEAR;
- } else if(!strcmp((char*) pName, "$month")) {
- *pPropID = PROP_SYS_MONTH;
- } else if(!strcmp((char*) pName, "$day")) {
- *pPropID = PROP_SYS_DAY;
- } else if(!strcmp((char*) pName, "$hour")) {
- *pPropID = PROP_SYS_HOUR;
- } else if(!strcmp((char*) pName, "$hhour")) {
- *pPropID = PROP_SYS_HHOUR;
- } else if(!strcmp((char*) pName, "$qhour")) {
- *pPropID = PROP_SYS_QHOUR;
- } else if(!strcmp((char*) pName, "$minute")) {
- *pPropID = PROP_SYS_MINUTE;
- } else if(!strcmp((char*) pName, "$myhostname")) {
- *pPropID = PROP_SYS_MYHOSTNAME;
- } else {
- *pPropID = PROP_INVALID;
- iRet = RS_RET_VAR_NOT_FOUND;
- }
-
- RETiRet;
-}
-
-
/* This function can be used as a generic way to set properties.
* We have to handle a lot of legacy, so our return value is not always
* 100% correct (called functions do not always provide one, should
@@ -2738,6 +2904,9 @@ rsRetVal propNameToID(cstr_t *pCSPropName, propid_t *pPropID)
#define isProp(name) !rsCStrSzStrCmp(pProp->pcsName, (uchar*) name, sizeof(name) - 1)
rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp)
{
+ prop_t *myProp;
+ prop_t *propRcvFrom = NULL;
+ prop_t *propRcvFromIP = NULL;
DEFiRet;
ISOBJ_TYPE_assert(pThis, msg);
@@ -2765,11 +2934,18 @@ rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp)
} else if(isProp("pszTAG")) {
MsgSetTAG(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), cstrLen(pProp->val.pStr));
} else if(isProp("pszInputName")) {
- MsgSetInputName(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr));
+ /* we need to create a property */
+ CHKiRet(prop.Construct(&myProp));
+ CHKiRet(prop.SetString(myProp, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr)));
+ CHKiRet(prop.ConstructFinalize(myProp));
+ MsgSetInputName(pThis, myProp);
+ prop.Destruct(&myProp);
} else if(isProp("pszRcvFromIP")) {
- MsgSetRcvFromIP(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr));
+ MsgSetRcvFromIPStr(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr), &propRcvFromIP);
+ prop.Destruct(&propRcvFromIP);
} else if(isProp("pszRcvFrom")) {
- MsgSetRcvFrom(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr));
+ MsgSetRcvFromStr(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr), &propRcvFrom);
+ prop.Destruct(&propRcvFrom);
} else if(isProp("pszHOSTNAME")) {
MsgSetHOSTNAME(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr));
} else if(isProp("pCSStrucData")) {
@@ -2790,6 +2966,7 @@ rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp)
dbgprintf("no longer supported property pszMSG silently ignored\n");
}
+finalize_it:
RETiRet;
}
#undef isProp
@@ -2833,6 +3010,7 @@ BEGINObjClassInit(msg, 1, OBJ_IS_CORE_MODULE)
CHKiRet(objUse(var, CORE_COMPONENT));
CHKiRet(objUse(datetime, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
/* set our own handlers */
OBJSetMethodHandler(objMethod_SERIALIZE, MsgSerialize);
diff --git a/runtime/msg.h b/runtime/msg.h
index e6b25e6c..c20fb005 100644
--- a/runtime/msg.h
+++ b/runtime/msg.h
@@ -72,21 +72,15 @@ struct msg {
short iFacility; /* Facility code 0 .. 23*/
short offAfterPRI; /* offset, at which raw message WITHOUT PRI part starts in pszRawMsg */
short offMSG; /* offset at which the MSG part starts in pszRawMsg */
- short iLenInputName; /* Length of pszInputName */
short iProtocolVersion;/* protocol version of message received 0 - legacy, 1 syslog-protocol) */
int msgFlags; /* flags associated with this message */
int iLenRawMsg; /* length of raw message */
int iLenMSG; /* Length of the MSG part */
int iLenTAG; /* Length of the TAG part */
int iLenHOSTNAME; /* Length of HOSTNAME */
- int iLenRcvFrom; /* Length of pszRcvFrom */
- int iLenRcvFromIP; /* Length of pszRcvFromIP */
uchar *pszRawMsg; /* message as it was received on the wire. This is important in case we
* need to preserve cryptographic verifiers. */
uchar *pszHOSTNAME; /* HOSTNAME from syslog message */
- uchar *pszRcvFrom; /* System message was received from */
- uchar *pszRcvFromIP; /* IP of system message was received from */
- uchar *pszInputName; /* name of the input module that submitted this message */
char *pszRcvdAt3164; /* time as RFC3164 formatted string (always 15 charcters) */
char *pszRcvdAt3339; /* time as RFC3164 formatted string (32 charcters at most) */
char *pszRcvdAt_MySQL; /* rcvdAt as MySQL formatted string (always 14 charcters) */
@@ -100,6 +94,9 @@ struct msg {
cstr_t *pCSAPPNAME; /* APP-NAME */
cstr_t *pCSPROCID; /* PROCID */
cstr_t *pCSMSGID; /* MSGID */
+ prop_t *pInputName; /* input name property */
+ prop_t *pRcvFrom; /* name of system message was received from */
+ prop_t *pRcvFromIP; /* IP of system message was received from */
ruleset_t *pRuleset; /* ruleset to be used for processing this message */
time_t ttGenTime; /* time msg object was generated, same as tRcvdAt, but a Unix timestamp.
While this field looks redundant, it is required because a Unix timestamp
@@ -144,7 +141,7 @@ rsRetVal msgDestruct(msg_t **ppM);
msg_t* MsgDup(msg_t* pOld);
msg_t *MsgAddRef(msg_t *pM);
void setProtocolVersion(msg_t *pM, int iNewVersion);
-void MsgSetInputName(msg_t *pMsg, uchar*, size_t);
+void MsgSetInputName(msg_t *pMsg, prop_t*);
rsRetVal MsgSetAPPNAME(msg_t *pMsg, char* pszAPPNAME);
rsRetVal MsgSetPROCID(msg_t *pMsg, char* pszPROCID);
rsRetVal MsgSetMSGID(msg_t *pMsg, char* pszMSGID);
@@ -152,8 +149,10 @@ void MsgSetTAG(msg_t *pMsg, uchar* pszBuf, size_t lenBuf);
void MsgSetRuleset(msg_t *pMsg, ruleset_t*);
rsRetVal MsgSetFlowControlType(msg_t *pMsg, flowControl_t eFlowCtl);
rsRetVal MsgSetStructuredData(msg_t *pMsg, char* pszStrucData);
-void MsgSetRcvFrom(msg_t *pMsg, uchar* pszRcvFrom);
-rsRetVal MsgSetRcvFromIP(msg_t *pMsg, uchar* pszRcvFromIP);
+void MsgSetRcvFrom(msg_t *pMsg, prop_t*);
+void MsgSetRcvFromStr(msg_t *pMsg, uchar* pszRcvFrom, int, prop_t **);
+rsRetVal MsgSetRcvFromIP(msg_t *pMsg, prop_t*);
+rsRetVal MsgSetRcvFromIPStr(msg_t *pThis, uchar *psz, int len, prop_t **ppProp);
void MsgSetHOSTNAME(msg_t *pMsg, uchar* pszHOSTNAME, int lenHOSTNAME);
rsRetVal MsgSetAfterPRIOffs(msg_t *pMsg, short offs);
void MsgSetMSGoffs(msg_t *pMsg, short offs);
@@ -165,6 +164,8 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
char *textpri(char *pRes, size_t pResLen, int pri);
rsRetVal msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar);
rsRetVal MsgEnableThreadSafety(void);
+uchar *getRcvFrom(msg_t *pM);
+
/* TODO: remove these five (so far used in action.c) */
char *getMSG(msg_t *pM);
@@ -179,6 +180,7 @@ char *getProgramName(msg_t *pM, bool bLockMutex);
int getProgramNameLen(msg_t *pM, bool bLockMutex);
uchar *getRcvFrom(msg_t *pM);
rsRetVal propNameToID(cstr_t *pCSPropName, propid_t *pPropID);
+uchar *propIDToName(propid_t propID);
/* The MsgPrepareEnqueue() function is a macro for performance reasons.
diff --git a/runtime/obj-types.h b/runtime/obj-types.h
index 6c1381ac..e1b54d4f 100644
--- a/runtime/obj-types.h
+++ b/runtime/obj-types.h
@@ -293,6 +293,15 @@ rsRetVal objName##ClassExit(void) \
ISOBJ_TYPE_assert(pThis, OBJ); \
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave);
+/* note: there was a long-time bug in the macro below that lead to *ppThis = NULL
+ * only when the object was actually destructed. I discovered this issue during
+ * introduction of the pRcvFrom property in msg_t, but it potentially had other
+ * effects, too. I am not sure if some experienced instability resulted from this
+ * bug OR if its fix will cause harm to so-far "correctly" running code. The later
+ * may very well be. Thus I will change it only for the current branch and also
+ * the beta, but not in all old builds. Let's see how things evolve.
+ * rgerhards, 2009-06-30
+ */
#define ENDobjDestruct(OBJ) \
goto finalize_it; /* prevent compiler warning ;) */ \
/* no more code here! */ \
@@ -300,8 +309,8 @@ rsRetVal objName##ClassExit(void) \
if(pThis != NULL) { \
obj.DestructObjSelf((obj_t*) pThis); \
free(pThis); \
- *ppThis = NULL; \
} \
+ *ppThis = NULL; \
pthread_setcancelstate(iCancelStateSave, NULL); \
RETiRet; \
}
diff --git a/runtime/parser.c b/runtime/parser.c
index d4ca7673..a5183105 100644
--- a/runtime/parser.c
+++ b/runtime/parser.c
@@ -261,7 +261,7 @@ rsRetVal parseMsg(msg_t *pMsg)
CHKiRet(sanitizeMessage(pMsg));
/* we needed to sanitize first, because we otherwise do not have a C-string we can print... */
- DBGPRINTF("msg parser: flags %x, from '%s', msg '%s'\n", pMsg->msgFlags, pMsg->pszRcvFrom, pMsg->pszRawMsg);
+ DBGPRINTF("msg parser: flags %x, from '%s', msg '%s'\n", pMsg->msgFlags, getRcvFrom(pMsg), pMsg->pszRawMsg);
/* pull PRI */
pri = DEFUPRI;
diff --git a/runtime/prop.c b/runtime/prop.c
index 02be315f..804f3491 100644
--- a/runtime/prop.c
+++ b/runtime/prop.c
@@ -36,9 +36,13 @@
#include "config.h"
#include <stdlib.h>
#include <assert.h>
+#include <string.h>
#include "rsyslog.h"
#include "obj.h"
+#include "obj-types.h"
+#include "unicode-helper.h"
+#include "atomic.h"
#include "prop.h"
/* static data */
@@ -48,9 +52,69 @@ DEFobjStaticHelpers
/* Standard-Constructor
*/
BEGINobjConstruct(prop) /* be sure to specify the object type also in END macro! */
+ pThis->iRefCount = 1;
ENDobjConstruct(prop)
+/* destructor for the prop object */
+BEGINobjDestruct(prop) /* be sure to specify the object type also in END and CODESTART macros! */
+ int currRefCount;
+CODESTARTobjDestruct(prop)
+ currRefCount = ATOMIC_DEC_AND_FETCH(pThis->iRefCount);
+ if(currRefCount == 0) {
+ /* (only) in this case we need to actually destruct the object */
+ if(pThis->len >= CONF_PROP_BUFSIZE)
+ free(pThis->szVal.psz);
+ } else {
+ pThis = NULL; /* tell framework NOT to destructing the object! */
+ }
+ENDobjDestruct(prop)
+
+/* set string, we make our own private copy! This MUST only be called BEFORE
+ * ConstructFinalize()!
+ */
+static rsRetVal SetString(prop_t *pThis, uchar *psz, int len)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, prop);
+ if(pThis->len >= CONF_PROP_BUFSIZE)
+ free(pThis->szVal.psz);
+ pThis->len = len;
+ if(len < CONF_PROP_BUFSIZE) {
+ memcpy(pThis->szVal.sz, psz, len + 1);
+ } else {
+ CHKmalloc(pThis->szVal.psz = malloc(len + 1));
+ memcpy(pThis->szVal.psz, psz, len + 1);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* get string length */
+static int GetStringLen(prop_t *pThis)
+{
+ return pThis->len;
+}
+
+
+/* get string */
+static rsRetVal GetString(prop_t *pThis, uchar **ppsz, int *plen)
+{
+ BEGINfunc
+ ISOBJ_TYPE_assert(pThis, prop);
+ if(pThis->len < CONF_PROP_BUFSIZE) {
+ *ppsz = pThis->szVal.sz;
+ } else {
+ *ppsz = pThis->szVal.psz;
+ }
+ *plen = pThis->len;
+ ENDfunc
+ return RS_RET_OK;
+}
+
+
/* ConstructionFinalizer
* rgerhards, 2008-01-09
*/
@@ -63,10 +127,63 @@ propConstructFinalize(prop_t __attribute__((unused)) *pThis)
}
-/* destructor for the prop object */
-BEGINobjDestruct(prop) /* be sure to specify the object type also in END and CODESTART macros! */
-CODESTARTobjDestruct(prop)
-ENDobjDestruct(prop)
+/* add a new reference. It is VERY IMPORTANT to call this function whenever
+ * the property is handed over to some entitiy that later call Destruct() on it.
+ */
+static rsRetVal AddRef(prop_t *pThis)
+{
+ ATOMIC_INC(pThis->iRefCount);
+ return RS_RET_OK;
+}
+
+
+/* this is a "do it all in one shot" function that creates a new property,
+ * assigns the provided string to it and finalizes the property. Among the
+ * convenience, it is alos (very, very) slightly faster.
+ * rgerhards, 2009-07-01
+ */
+static rsRetVal CreateStringProp(prop_t **ppThis, uchar* psz, int len)
+{
+ DEFiRet;
+ propConstruct(ppThis);
+ SetString(*ppThis, psz, len);
+ propConstructFinalize(*ppThis);
+ RETiRet;
+}
+
+/* another one-stop function, quite useful: it takes a property pointer and
+ * a string. If the string is already contained in the property, nothing happens.
+ * If the string is different (or the pointer NULL), the current property
+ * is destructed and a new one created. This can be used to get a specific
+ * name in those cases where there is a good chance that the property
+ * immediatly previously processed already contained the value we need - in
+ * which case we save us all the creation overhead by just reusing the already
+ * existing property).
+ * rgerhards, 2009-07-01
+ */
+rsRetVal CreateOrReuseStringProp(prop_t **ppThis, uchar *psz, int len)
+{
+ uchar *pszPrev;
+ int lenPrev;
+ DEFiRet;
+ assert(ppThis != NULL);
+
+ if(*ppThis == NULL) {
+ /* we need to create a property */
+ CHKiRet(CreateStringProp(ppThis, psz, len));
+ } else {
+ /* already exists, check if we can re-use it */
+ GetString(*ppThis, &pszPrev, &lenPrev);
+ if(len != lenPrev && ustrcmp(psz, pszPrev)) {
+ /* different, need to discard old & create new one */
+ propDestruct(ppThis);
+ CHKiRet(CreateStringProp(ppThis, psz, len));
+ } /* else we can re-use the existing one! */
+ }
+
+finalize_it:
+ RETiRet;
+}
/* debugprint for the prop object */
@@ -94,6 +211,12 @@ CODESTARTobjQueryInterface(prop)
pIf->ConstructFinalize = propConstructFinalize;
pIf->Destruct = propDestruct;
pIf->DebugPrint = propDebugPrint;
+ pIf->SetString = SetString;
+ pIf->GetString = GetString;
+ pIf->GetStringLen = GetStringLen;
+ pIf->AddRef = AddRef;
+ pIf->CreateStringProp = CreateStringProp;
+ pIf->CreateOrReuseStringProp = CreateOrReuseStringProp;
finalize_it:
ENDobjQueryInterface(prop)
diff --git a/runtime/prop.h b/runtime/prop.h
index 7fc466b5..e3519664 100644
--- a/runtime/prop.h
+++ b/runtime/prop.h
@@ -28,14 +28,26 @@
/* the prop object */
struct prop_s {
BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ int iRefCount; /* reference counter */
+ union {
+ uchar *psz; /* stored string */
+ uchar sz[CONF_PROP_BUFSIZE];
+ } szVal;
+ int len; /* we use int intentionally, otherwise we may get some troubles... */
};
/* interfaces */
BEGINinterface(prop) /* name must also be changed in ENDinterface macro! */
INTERFACEObjDebugPrint(prop);
rsRetVal (*Construct)(prop_t **ppThis);
- rsRetVal (*ConstructFinalize)(prop_t __attribute__((unused)) *pThis);
+ rsRetVal (*ConstructFinalize)(prop_t *pThis);
rsRetVal (*Destruct)(prop_t **ppThis);
+ rsRetVal (*SetString)(prop_t *pThis, uchar* psz, int len);
+ rsRetVal (*GetString)(prop_t *pThis, uchar** ppsz, int *plen);
+ int (*GetStringLen)(prop_t *pThis);
+ rsRetVal (*AddRef)(prop_t *pThis);
+ rsRetVal (*CreateStringProp)(prop_t **ppThis, uchar* psz, int len);
+ rsRetVal (*CreateOrReuseStringProp)(prop_t **ppThis, uchar *psz, int len);
ENDinterface(prop)
#define propCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
diff --git a/runtime/rsyslog.c b/runtime/rsyslog.c
index 6f732f0e..443d0f41 100644
--- a/runtime/rsyslog.c
+++ b/runtime/rsyslog.c
@@ -77,6 +77,7 @@
#include "conf.h"
#include "glbl.h"
#include "errmsg.h"
+#include "prop.h"
#include "rule.h"
#include "ruleset.h"
@@ -146,6 +147,8 @@ rsrtInit(char **ppErrObj, obj_if_t *pObjIF)
* class immediately after it is initialized. And, of course, we load those classes
* first that we use ourselfs... -- rgerhards, 2008-03-07
*/
+ if(ppErrObj != NULL) *ppErrObj = "prop";
+ CHKiRet(propClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "glbl";
CHKiRet(glblClassInit(NULL));
if(ppErrObj != NULL) *ppErrObj = "datetime";
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 76f320e6..c51b1272 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -39,6 +39,7 @@
#define CONF_RAWMSG_BUFSIZE 101
#define CONF_TAG_BUFSIZE 32
#define CONF_HOSTNAME_BUFSIZE 32
+#define CONF_PROP_BUFSIZE 16 /* should be close to sizeof(ptr) or lighly above it */
/* ############################################################# *
diff --git a/runtime/rule.c b/runtime/rule.c
index ce19146b..3a257a90 100644
--- a/runtime/rule.c
+++ b/runtime/rule.c
@@ -219,8 +219,8 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, int *bProcessMsg)
bRet = (bRet == 1) ? 0 : 1;
if(Debug) {
- dbgprintf("Filter: check for property '%d' (value '%s') ",
- pRule->f_filterData.prop.propID, pszPropVal);
+ dbgprintf("Filter: check for property '%s' (value '%s') ",
+ propIDToName(pRule->f_filterData.prop.propID), pszPropVal);
if(pRule->f_filterData.prop.isNegated)
dbgprintf("NOT ");
dbgprintf("%s '%s': %s\n",
@@ -373,8 +373,7 @@ CODESTARTobjDebugPrint(rule)
dbgprintf("EXPRESSION-BASED Filter: can currently not be displayed");
} else {
dbgprintf("PROPERTY-BASED Filter:\n");
- dbgprintf("\tProperty.: '%d'\n", pThis->f_filterData.prop.propID);
-// TODO: XXXX ADD idtostring()!
+ dbgprintf("\tProperty.: '%s'\n", propIDToName(pThis->f_filterData.prop.propID));
dbgprintf("\tOperation: ");
if(pThis->f_filterData.prop.isNegated)
dbgprintf("NOT ");
diff --git a/runtime/stringbuf.c b/runtime/stringbuf.c
index 88f5a3a2..93995b38 100644
--- a/runtime/stringbuf.c
+++ b/runtime/stringbuf.c
@@ -1,4 +1,3 @@
-#include <stdio.h>
/* This is the byte-counted string class for rsyslog. It is a replacement
* for classical \0 terminated string functions. We introduce it in
* the hope it will make the program more secure, obtain some performance
diff --git a/runtime/stringbuf.h b/runtime/stringbuf.h
index 400c74eb..c5130238 100644
--- a/runtime/stringbuf.h
+++ b/runtime/stringbuf.h
@@ -35,6 +35,7 @@
#ifndef _STRINGBUF_H_INCLUDED__
#define _STRINGBUF_H_INCLUDED__ 1
+#include <assert.h>
/**
* The dynamic string buffer object.
@@ -48,7 +49,6 @@ typedef struct cstr_s
uchar *pszBuf; /**< pointer to the sz version of the string (after it has been created )*/
size_t iBufSize; /**< current maximum size of the string buffer */
size_t iStrLen; /**< length of the string in characters. */
- bool bIsForeignBuf; /**< is pBuf a buffer provided by someone else? */
} cstr_t;
diff --git a/tcps_sess.c b/tcps_sess.c
index e0bec949..8d307380 100644
--- a/tcps_sess.c
+++ b/tcps_sess.c
@@ -36,6 +36,7 @@
#include "rsyslog.h"
#include "dirty.h"
+#include "unicode-helper.h"
#include "module-template.h"
#include "net.h"
#include "tcpsrv.h"
@@ -45,6 +46,7 @@
#include "netstrm.h"
#include "msg.h"
#include "datetime.h"
+#include "prop.h"
/* static data */
@@ -52,6 +54,7 @@ DEFobjStaticHelpers
DEFobjCurrIf(glbl)
DEFobjCurrIf(errmsg)
DEFobjCurrIf(netstrm)
+DEFobjCurrIf(prop)
DEFobjCurrIf(datetime)
static int iMaxLine; /* maximum size of a single message */
@@ -100,8 +103,10 @@ CODESTARTobjDestruct(tcps_sess)
pThis->pSrv->pOnSessDestruct(&pThis->pUsr);
}
/* now destruct our own properties */
- free(pThis->fromHost);
- free(pThis->fromHostIP);
+ if(pThis->fromHost != NULL)
+ CHKiRet(prop.Destruct(&pThis->fromHost));
+ if(pThis->fromHostIP != NULL)
+ CHKiRet(prop.Destruct(&pThis->fromHostIP));
free(pThis->pMsg);
ENDobjDestruct(tcps_sess)
@@ -124,9 +129,13 @@ SetHost(tcps_sess_t *pThis, uchar *pszHost)
ISOBJ_TYPE_assert(pThis, tcps_sess);
- free(pThis->fromHost);
- pThis->fromHost = pszHost;
+ if(pThis->fromHost == NULL)
+ CHKiRet(prop.Construct(&pThis->fromHost));
+ CHKiRet(prop.SetString(pThis->fromHost, pszHost, ustrlen(pszHost)));
+
+finalize_it:
+ free(pszHost); /* we must free according to our (old) calling conventions */
RETiRet;
}
@@ -141,9 +150,13 @@ SetHostIP(tcps_sess_t *pThis, uchar *pszHostIP)
ISOBJ_TYPE_assert(pThis, tcps_sess);
- free(pThis->fromHostIP);
- pThis->fromHostIP = pszHostIP;
+ if(pThis->fromHostIP == NULL)
+ CHKiRet(prop.Construct(&pThis->fromHostIP));
+ CHKiRet(prop.SetString(pThis->fromHostIP, pszHostIP, ustrlen(pszHostIP)));
+
+finalize_it:
+ free(pszHostIP);
RETiRet;
}
@@ -234,15 +247,14 @@ defaultDoSubmitMessage(tcps_sess_t *pThis, struct syslogTime *stTime, time_t ttG
/* we now create our own message object and submit it to the queue */
CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime));
-dbgprintf("defaultDoSubmit, iMsg %d\n", pThis->iMsg);
MsgSetRawMsg(pMsg, (char*)pThis->pMsg, pThis->iMsg);
- MsgSetInputName(pMsg, pThis->pLstnInfo->pszInputName, pThis->pLstnInfo->lenInputName);
+ MsgSetInputName(pMsg, pThis->pLstnInfo->pInputName);
MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME;
pMsg->bParseHOSTNAME = 1;
MsgSetRcvFrom(pMsg, pThis->fromHost);
- MsgSetRuleset(pMsg, pThis->pLstnInfo->pRuleset);
CHKiRet(MsgSetRcvFromIP(pMsg, pThis->fromHostIP));
+ MsgSetRuleset(pMsg, pThis->pLstnInfo->pRuleset);
if(pMultiSub == NULL) {
CHKiRet(submitMsg(pMsg));
@@ -324,10 +336,11 @@ Close(tcps_sess_t *pThis)
ISOBJ_TYPE_assert(pThis, tcps_sess);
netstrm.Destruct(&pThis->pStrm);
- free(pThis->fromHost);
- pThis->fromHost = NULL; /* not really needed, but... */
- free(pThis->fromHostIP);
- pThis->fromHostIP = NULL; /* not really needed, but... */
+ if(pThis->fromHost != NULL) {
+ prop.Destruct(&pThis->fromHost);
+ }
+ if(pThis->fromHostIP != NULL)
+ prop.Destruct(&pThis->fromHostIP);
RETiRet;
}
@@ -520,6 +533,7 @@ CODESTARTObjClassExit(tcps_sess)
objRelease(errmsg, CORE_COMPONENT);
objRelease(netstrm, LM_NETSTRMS_FILENAME);
objRelease(datetime, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
ENDObjClassExit(tcps_sess)
@@ -532,6 +546,7 @@ BEGINObjClassInit(tcps_sess, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE c
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME));
CHKiRet(objUse(datetime, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
iMaxLine = glbl.GetMaxLine(); /* get maximum size we currently support */
diff --git a/tcps_sess.h b/tcps_sess.h
index 5e59aaab..ec3a6af4 100644
--- a/tcps_sess.h
+++ b/tcps_sess.h
@@ -24,6 +24,7 @@
#define INCLUDED_TCPS_SESS_H
#include "obj.h"
+#include "prop.h"
/* a forward-definition, we are somewhat cyclic */
struct tcpsrv_s;
@@ -44,8 +45,8 @@ struct tcps_sess_s {
int iOctetsRemain; /* Number of Octets remaining in message */
TCPFRAMINGMODE eFraming;
uchar *pMsg; /* message (fragment) received */
- uchar *fromHost;
- uchar *fromHostIP;
+ prop_t *fromHost; /* host name we received messages from */
+ prop_t *fromHostIP;
void *pUsr; /* a user-pointer */
rsRetVal (*DoSubmitMessage)(tcps_sess_t*, uchar*, int); /* submit message callback */
};
diff --git a/tcpsrv.c b/tcpsrv.c
index 119aea91..e8ea2b98 100644
--- a/tcpsrv.c
+++ b/tcpsrv.c
@@ -89,6 +89,7 @@ DEFobjCurrIf(net)
DEFobjCurrIf(netstrms)
DEFobjCurrIf(netstrm)
DEFobjCurrIf(nssel)
+DEFobjCurrIf(prop)
/* add new listener port to listener port list
@@ -107,8 +108,11 @@ addNewLstnPort(tcpsrv_t *pThis, uchar *pszPort)
pEntry->pszPort = pszPort;
pEntry->pSrv = pThis;
pEntry->pRuleset = pThis->pRuleset;
- CHKmalloc(pEntry->pszInputName = ustrdup(pThis->pszInputName));
- pEntry->lenInputName = ustrlen(pEntry->pszInputName);
+
+ /* we need to create a property */
+ CHKiRet(prop.Construct(&pEntry->pInputName));
+ CHKiRet(prop.SetString(pEntry->pInputName, pThis->pszInputName, ustrlen(pThis->pszInputName)));
+ CHKiRet(prop.ConstructFinalize(pEntry->pInputName));
/* and add to list */
pEntry->pNext = pThis->pLstnPorts;
@@ -250,7 +254,7 @@ static void deinit_tcp_listener(tcpsrv_t *pThis)
pEntry = pThis->pLstnPorts;
while(pEntry != NULL) {
free(pEntry->pszPort);
- free(pEntry->pszInputName);
+ prop.Destruct(&pEntry->pInputName);
pDel = pEntry;
pEntry = pEntry->pNext;
free(pDel);
@@ -477,6 +481,7 @@ Run(tcpsrv_t *pThis)
* this thread. Thus, we also need to instantiate a cancel cleanup handler
* to prevent us from leaking anything. -- rgerharsd, 20080-04-24
*/
+RUNLOG_STR("XXXX: tcp server runs\n");
pthread_cleanup_push(RunCancelCleanup, (void*) &pSel);
while(1) {
CHKiRet(nssel.Construct(&pSel));
@@ -497,6 +502,7 @@ Run(tcpsrv_t *pThis)
iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess);
}
+RUNLOG_STR("XXXX: tcp server select\n");
/* wait for io to become ready */
CHKiRet(nssel.Wait(pSel, &nfds));
@@ -508,6 +514,7 @@ Run(tcpsrv_t *pThis)
--nfds; /* indicate we have processed one */
}
}
+RUNLOG_STR("XXXX: tcp server post select\n");
/* now check the sessions */
iTCPSess = TCPSessGetNxtSess(pThis, -1);
@@ -883,6 +890,7 @@ CODESTARTObjClassExit(tcpsrv)
/* release objects we no longer need */
objRelease(tcps_sess, DONT_LOAD_LIB);
objRelease(conf, CORE_COMPONENT);
+ objRelease(prop, CORE_COMPONENT);
objRelease(ruleset, CORE_COMPONENT);
objRelease(glbl, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
@@ -908,6 +916,7 @@ BEGINObjClassInit(tcpsrv, 1, OBJ_IS_LOADABLE_MODULE) /* class, version - CHANGE
CHKiRet(objUse(conf, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
CHKiRet(objUse(ruleset, CORE_COMPONENT));
+ CHKiRet(objUse(prop, CORE_COMPONENT));
/* set our own handlers */
OBJSetMethodHandler(objMethod_DEBUGPRINT, tcpsrvDebugPrint);
diff --git a/tcpsrv.h b/tcpsrv.h
index e2170bef..70682398 100644
--- a/tcpsrv.h
+++ b/tcpsrv.h
@@ -23,6 +23,7 @@
#define INCLUDED_TCPSRV_H
#include "obj.h"
+#include "prop.h"
#include "tcps_sess.h"
/* support for framing anomalies */
@@ -36,8 +37,7 @@ typedef enum ETCPsyslogFramingAnomaly {
/* list of tcp listen ports */
struct tcpLstnPortList_s {
uchar *pszPort; /**< the ports the listener shall listen on */
- uchar *pszInputName; /**< value to be used as input name */
- size_t lenInputName; /**< length of inputName */
+ prop_t *pInputName;
tcpsrv_t *pSrv; /**< pointer to higher-level server instance */
ruleset_t *pRuleset; /**< associated ruleset */
tcpLstnPortList_t *pNext; /**< next port or NULL */
diff --git a/tests/nettester.c b/tests/nettester.c
index b8816b7c..dbfb4db3 100644
--- a/tests/nettester.c
+++ b/tests/nettester.c
@@ -107,6 +107,7 @@ tcpSend(char *buf, int lenBuf)
{
static int sock = INVALID_SOCKET;
struct sockaddr_in addr;
+ int retries;
if(sock == INVALID_SOCKET) {
/* first time, need to connect to target */
@@ -122,10 +123,20 @@ tcpSend(char *buf, int lenBuf)
fprintf(stderr, "inet_aton() failed\n");
return(1);
}
- if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
- fprintf(stderr, "connect() failed\n");
- return(1);
- }
+ retries = 0;
+ while(1) { /* loop broken inside */
+ if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
+ break;
+ } else {
+ if(retries++ == 30) {
+ ++iFailed;
+ fprintf(stderr, "connect() failed\n");
+ return(1);
+ } else {
+ usleep(100);
+ }
+ }
+ }
}
/* send test data */
diff --git a/tools/syslogd.c b/tools/syslogd.c
index 72687495..e3824d9e 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -143,6 +143,7 @@
#include "rule.h"
#include "net.h"
#include "vm.h"
+#include "prop.h"
/* definitions for objects we access */
DEFobjCurrIf(obj)
@@ -154,25 +155,13 @@ DEFobjCurrIf(module)
DEFobjCurrIf(errmsg)
DEFobjCurrIf(rule)
DEFobjCurrIf(ruleset)
+DEFobjCurrIf(prop)
DEFobjCurrIf(net) /* TODO: make go away! */
/* forward definitions */
static rsRetVal GlobalClassExit(void);
-/* We define our own set of syslog defintions so that we
- * do not need to rely on (possibly different) implementations.
- * 2007-07-19 rgerhards
- */
-/* missing definitions for solaris
- * 2006-02-16 Rger
- */
-#ifdef __sun
-# define LOG_AUTHPRIV LOG_AUTH
-#endif
-#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
-#define LOG_FTP (11<<3) /* ftp daemon */
-
#ifndef UTMP_FILE
#ifdef UTMP_FILENAME
@@ -220,14 +209,12 @@ static rsRetVal GlobalClassExit(void);
# endif
#endif
-#ifndef _PATH_DEV
-# define _PATH_DEV "/dev/"
-#endif
-
#ifndef _PATH_TTY
# define _PATH_TTY "/dev/tty"
#endif
+static prop_t *pInternalInputName = NULL; /* there is only one global inputName for all internally-generated messages */
+static prop_t *pLocalHostIP = NULL; /* there is only one global IP for all internally-generated messages */
static uchar *ConfFile = (uchar*) _PATH_LOGCONF; /* read-only after startup */
static char *PidFile = _PATH_LOGPID; /* read-only after startup */
@@ -571,12 +558,14 @@ void untty(void)
* interface change: bParseHostname removed, now in flags
*/
static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int flags, flowControl_t flowCtlType,
- uchar *pszInputName, struct syslogTime *stTime, time_t ttGenTime)
+ prop_t *pInputName, struct syslogTime *stTime, time_t ttGenTime)
{
DEFiRet;
register uchar *p;
int pri;
msg_t *pMsg;
+ prop_t *propFromHost = NULL;
+ prop_t *propFromHostIP = NULL;
/* Now it is time to create the message object (rgerhards) */
if(stTime == NULL) {
@@ -584,8 +573,8 @@ static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int f
} else {
CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime));
}
- if(pszInputName != NULL)
- MsgSetInputName(pMsg, pszInputName, ustrlen(pszInputName));
+ if(pInputName != NULL)
+ MsgSetInputName(pMsg, pInputName);
MsgSetFlowControlType(pMsg, flowCtlType);
MsgSetRawMsgWOSize(pMsg, (char*)msg);
@@ -615,9 +604,9 @@ static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int f
*/
if((pMsg->msgFlags & PARSE_HOSTNAME) == 0)
MsgSetHOSTNAME(pMsg, hname, ustrlen(hname));
- MsgSetRcvFrom(pMsg, hname);
+ MsgSetRcvFromStr(pMsg, hname, ustrlen(hname), &propFromHost);
+ CHKiRet(MsgSetRcvFromIPStr(pMsg, hnameIP, ustrlen(hname), &propFromHostIP));
MsgSetAfterPRIOffs(pMsg, p - msg);
- CHKiRet(MsgSetRcvFromIP(pMsg, hnameIP));
logmsg(pMsg, flags);
@@ -680,7 +669,7 @@ finalize_it:
*/
rsRetVal
parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int flags, flowControl_t flowCtlType,
- uchar *pszInputName, struct syslogTime *stTime, time_t ttGenTime)
+ prop_t *pInputName, struct syslogTime *stTime, time_t ttGenTime)
{
DEFiRet;
register int iMsg;
@@ -791,7 +780,7 @@ parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int fla
*/
if(iMsg == iMaxLine) {
*(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
- printline(hname, hnameIP, tmpline, flags, flowCtlType, pszInputName, stTime, ttGenTime);
+ printline(hname, hnameIP, tmpline, flags, flowCtlType, pInputName, stTime, ttGenTime);
} else {
/* This case in theory never can happen. If it happens, we have
* a logic error. I am checking for it, because if I would not,
@@ -843,7 +832,7 @@ parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int fla
*(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
/* typically, we should end up here! */
- printline(hname, hnameIP, tmpline, flags, flowCtlType, pszInputName, stTime, ttGenTime);
+ printline(hname, hnameIP, tmpline, flags, flowCtlType, pInputName, stTime, ttGenTime);
finalize_it:
if(tmpline != NULL)
@@ -886,11 +875,11 @@ logmsgInternal(int iErr, int pri, uchar *msg, int flags)
DEFiRet;
CHKiRet(msgConstruct(&pMsg));
- MsgSetInputName(pMsg, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslogd")-1);
+ MsgSetInputName(pMsg, pInternalInputName);
MsgSetRawMsgWOSize(pMsg, (char*)msg);
MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName()));
- MsgSetRcvFrom(pMsg, glbl.GetLocalHostName());
- MsgSetRcvFromIP(pMsg, UCHAR_CONSTANT("127.0.0.1"));
+ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp());
+ MsgSetRcvFromIP(pMsg, pLocalHostIP);
/* check if we have an error code associated and, if so,
* adjust the tag. -- rgerhards, 2008-06-27
*/
@@ -1955,6 +1944,12 @@ die(int sig)
legacyOptsFree();
+ /* destruct our global properties */
+ if(pInternalInputName != NULL)
+ prop.Destruct(&pInternalInputName);
+ if(pLocalHostIP != NULL)
+ prop.Destruct(&pLocalHostIP);
+
/* terminate the remaining classes */
GlobalClassExit();
@@ -2325,6 +2320,30 @@ static void dbgPrintInitInfo(void)
}
+/* Actually run the input modules. This happens after privileges are dropped,
+ * if that is requested.
+ */
+static rsRetVal
+runInputModules(void)
+{
+ modInfo_t *pMod;
+
+ BEGINfunc
+ /* loop through all modules and activate them (brr...) */
+ pMod = module.GetNxtType(NULL, eMOD_IN);
+ while(pMod != NULL) {
+ if(pMod->mod.im.bCanRun) {
+ /* activate here */
+ thrdCreate(pMod->mod.im.runInput, pMod->mod.im.afterRun);
+ }
+ pMod = module.GetNxtType(pMod, eMOD_IN);
+ }
+
+ ENDfunc
+ return RS_RET_OK; /* intentional: we do not care about module errors */
+}
+
+
/* Start the input modules. This function will probably undergo big changes
* while we implement the input module interface. For now, it does the most
* important thing to get at least my poor initial input modules up and
@@ -2340,10 +2359,9 @@ startInputModules(void)
/* loop through all modules and activate them (brr...) */
pMod = module.GetNxtType(NULL, eMOD_IN);
while(pMod != NULL) {
- if((iRet = pMod->mod.im.willRun()) == RS_RET_OK) {
- /* activate here */
- thrdCreate(pMod->mod.im.runInput, pMod->mod.im.afterRun);
- } else {
+ iRet = pMod->mod.im.willRun();
+ pMod->mod.im.bCanRun = (iRet == RS_RET_OK);
+ if(!pMod->mod.im.bCanRun) {
DBGPRINTF("module %lx will not run, iRet %d\n", (unsigned long) pMod, iRet);
}
pMod = module.GetNxtType(pMod, eMOD_IN);
@@ -2360,7 +2378,7 @@ startInputModules(void)
* else happens. -- rgerhards, 2008-07-28
*/
static rsRetVal
-init(void)
+init()
{
rsRetVal localRet;
int iNbrActions;
@@ -2562,9 +2580,12 @@ init(void)
DBGPRINTF("Main processing queue is initialized and running\n");
/* the output part and the queue is now ready to run. So it is a good time
- * to start the inputs. Please note that the net code above should be
+ * to initialize the inputs. Please note that the net code above should be
* shuffled to down here once we have everything in input modules.
* rgerhards, 2007-12-14
+ * NOTE: as of 2009-06-29, the input modules are initialized, but not yet run.
+ * Keep in mind. though, that the outputs already run if the queue was
+ * persisted to disk. -- rgerhards
*/
startInputModules();
@@ -2738,6 +2759,7 @@ doHUP(void)
if(glbl.GetHUPisRestart()) {
DBGPRINTF("Received SIGHUP, configured to be restart, reloading rsyslogd.\n");
init(); /* main queue is stopped as part of init() */
+ runInputModules();
} else {
DBGPRINTF("Received SIGHUP, configured to be a non-restart type of HUP - notifying actions.\n");
ruleset.IterateAllActions(doHUPActions, NULL);
@@ -3001,6 +3023,7 @@ static rsRetVal mainThread()
if(Debug && debugging_on) {
DBGPRINTF("Debugging enabled, SIGUSR1 to turn off debugging.\n");
}
+
/* Send a signal to the parent so it can terminate.
*/
if(myPid != ppid)
@@ -3008,7 +3031,7 @@ static rsRetVal mainThread()
/* If instructed to do so, we now drop privileges. Note that this is not 100% secure,
- * because inputs and outputs are already running at this time. However, we can implement
+ * because outputs are already running at this time. However, we can implement
* dropping of privileges rather quickly and it will work in many cases. While it is not
* the ultimate solution, the current one is still much better than not being able to
* drop privileges at all. Doing it correctly, requires a change in architecture, which
@@ -3024,15 +3047,28 @@ static rsRetVal mainThread()
glbl.SetHUPisRestart(0); /* we can not do restart-type HUPs with dropped privs */
}
+ /* finally let the inputs run... */
+ runInputModules();
/* END OF INTIALIZATION
* ... but keep in mind that we might do a restart and thus init() might
- * be called again. If that happens, we must shut down the worker thread,
- * do the init() and then restart things.
- * rgerhards, 2005-10-24
+ * be called again. -- rgerhards, 2005-10-24
*/
DBGPRINTF("initialization completed, transitioning to regular run mode\n");
+ /* close stderr and stdout if they are kept open during a fork. Note that this
+ * may introduce subtle security issues: if we are in a jail, one may break out of
+ * it via these descriptors. But if I close them earlier, error messages will (once
+ * again) not be emitted to the user that starts the daemon. As root jail support
+ * is still in its infancy (and not really done), we currently accept this issue.
+ * rgerhards, 2009-06-29
+ */
+ if(!(Debug || NoFork)) {
+ close(1);
+ close(2);
+ bErrMsgToStderr = 0;
+ }
+
mainloop();
finalize_it:
@@ -3072,6 +3108,8 @@ InitGlobalClasses(void)
CHKiRet(objUse(ruleset, CORE_COMPONENT));
pErrObj = "conf";
CHKiRet(objUse(conf, CORE_COMPONENT));
+ pErrObj = "prop";
+ CHKiRet(objUse(prop, CORE_COMPONENT));
/* intialize some dummy classes that are not part of the runtime */
pErrObj = "action";
@@ -3112,6 +3150,7 @@ GlobalClassExit(void)
/* first, release everything we used ourself */
objRelease(net, LM_NET_FILENAME);/* TODO: the dependency on net shall go away! -- rgerhards, 2008-03-07 */
+ objRelease(prop, CORE_COMPONENT);
objRelease(conf, CORE_COMPONENT);
objRelease(ruleset, CORE_COMPONENT);
objRelease(rule, CORE_COMPONENT);
@@ -3418,6 +3457,15 @@ int realMain(int argc, char **argv)
/* doing some core initializations */
+ /* we need to create the inputName property (only once during our lifetime) */
+ CHKiRet(prop.Construct(&pInternalInputName));
+ CHKiRet(prop.SetString(pInternalInputName, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslgod") - 1));
+ CHKiRet(prop.ConstructFinalize(pInternalInputName));
+
+ CHKiRet(prop.Construct(&pLocalHostIP));
+ CHKiRet(prop.SetString(pLocalHostIP, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
+ CHKiRet(prop.ConstructFinalize(pLocalHostIP));
+
/* get our host and domain names - we need to do this early as we may emit
* error log messages, which need the correct hostname. -- rgerhards, 2008-04-04
*/
@@ -3466,6 +3514,7 @@ int realMain(int argc, char **argv)
*/
glbl.SetLocalHostName(LocalHostName);
glbl.SetLocalDomain(LocalDomain);
+ glbl.GenerateLocalHostNameProperty(); /* must be redone after conf processing, FQDN setting may have changed */
/* initialize the objects */
if((iRet = modInitIminternal()) != RS_RET_OK) {
@@ -3662,6 +3711,9 @@ int realMain(int argc, char **argv)
if(!iConfigVerify)
CHKiRet(doGlblProcessInit());
+ /* re-generate local host name property, as the config may have changed our FQDN settings */
+ glbl.GenerateLocalHostNameProperty();
+
CHKiRet(mainThread());
/* do any de-init's that need to be done AFTER this comment */