diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2009-07-01 14:34:56 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2009-07-01 14:34:56 +0200 |
commit | 6322343eca1084b509386a94c1bcf2ca819f1220 (patch) | |
tree | cd873a34a4df087c3411de951c40a26f64f7d0ec /runtime | |
parent | e6aeb1b995d6629ff04fd0f6068be2e9ffe9ca42 (diff) | |
parent | 7bfa03bdc0b73647ffdbe4b73e5c1649af665fbf (diff) | |
download | rsyslog-6322343eca1084b509386a94c1bcf2ca819f1220.tar.gz rsyslog-6322343eca1084b509386a94c1bcf2ca819f1220.tar.xz rsyslog-6322343eca1084b509386a94c1bcf2ca819f1220.zip |
Merge branch 'master' into v5-devel
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/datetime.c | 5 | ||||
-rw-r--r-- | runtime/datetime.h | 2 | ||||
-rw-r--r-- | runtime/glbl.c | 46 | ||||
-rw-r--r-- | runtime/glbl.h | 7 | ||||
-rw-r--r-- | runtime/modules.c | 1 | ||||
-rw-r--r-- | runtime/modules.h | 1 | ||||
-rw-r--r-- | runtime/msg.c | 512 | ||||
-rw-r--r-- | runtime/msg.h | 20 | ||||
-rw-r--r-- | runtime/obj-types.h | 11 | ||||
-rw-r--r-- | runtime/parser.c | 2 | ||||
-rw-r--r-- | runtime/prop.c | 131 | ||||
-rw-r--r-- | runtime/prop.h | 14 | ||||
-rw-r--r-- | runtime/rsyslog.c | 3 | ||||
-rw-r--r-- | runtime/rsyslog.h | 1 | ||||
-rw-r--r-- | runtime/rule.c | 7 | ||||
-rw-r--r-- | runtime/stringbuf.c | 1 | ||||
-rw-r--r-- | runtime/stringbuf.h | 2 |
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; |