summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-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
17 files changed, 569 insertions, 197 deletions
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;