summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2009-06-26 15:33:14 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2009-06-26 15:33:14 +0200
commit876597296f27fa4a4beea81124d3e14369490acd (patch)
tree50795596d141711ad7e045041613a3041d8974fc
parentd22f240bc3525f7e112ce44aea6b9f87f8a51c8a (diff)
parent7ea63db2f9d6b375dc95696e47357d73927f2d3d (diff)
downloadrsyslog-876597296f27fa4a4beea81124d3e14369490acd.tar.gz
rsyslog-876597296f27fa4a4beea81124d3e14369490acd.tar.xz
rsyslog-876597296f27fa4a4beea81124d3e14369490acd.zip
Merge branch 'master' into v5-devel
Conflicts: runtime/rsyslog.h
-rw-r--r--runtime/conf.c10
-rw-r--r--runtime/msg.c356
-rw-r--r--runtime/msg.h5
-rw-r--r--runtime/rsyslog.h41
-rw-r--r--runtime/rule.c14
-rw-r--r--runtime/rule.h4
-rw-r--r--runtime/stringbuf.c57
-rw-r--r--runtime/stringbuf.h66
-rw-r--r--template.c16
-rw-r--r--template.h2
10 files changed, 364 insertions, 207 deletions
diff --git a/runtime/conf.c b/runtime/conf.c
index f9c37610..84178fd5 100644
--- a/runtime/conf.c
+++ b/runtime/conf.c
@@ -837,6 +837,7 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
{
rsParsObj *pPars;
cstr_t *pCSCompOp;
+ cstr_t *pCSPropName;
rsRetVal iRet;
int iOffset; /* for compare operations */
@@ -856,12 +857,19 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f)
}
/* read property */
- iRet = parsDelimCStr(pPars, &f->f_filterData.prop.pCSPropName, ',', 1, 1, 1);
+ iRet = parsDelimCStr(pPars, &pCSPropName, ',', 1, 1, 1);
if(iRet != RS_RET_OK) {
errmsg.LogError(0, iRet, "error %d parsing filter property - ignoring selector", iRet);
rsParsDestruct(pPars);
return(iRet);
}
+ iRet = propNameToID(pCSPropName, &f->f_filterData.prop.propID);
+ if(iRet != RS_RET_OK) {
+ errmsg.LogError(0, iRet, "error %d parsing filter property - ignoring selector", iRet);
+ rsParsDestruct(pPars);
+ return(iRet);
+ }
+ cstrDestruct(&pCSPropName);
/* read operation */
iRet = parsDelimCStr(pPars, &pCSCompOp, ',', 1, 1, 1);
diff --git a/runtime/msg.c b/runtime/msg.c
index 3f69dbcb..c4ba18df 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -1864,10 +1864,9 @@ static uchar *getNOW(eNOWType eNow)
* rgerhards 2005-09-15
*/
char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
- cstr_t *pCSPropName, size_t *pPropLen,
+ propid_t propID, size_t *pPropLen,
unsigned short *pbMustBeFreed)
{
- uchar *pName;
char *pRes; /* result pointer */
int bufLen = -1; /* length of string or -1, if not known */
char *pBufStart;
@@ -1876,132 +1875,155 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
short iOffs;
BEGINfunc
+ assert(pMsg != NULL);
+ assert(pbMustBeFreed != NULL);
+
#ifdef FEATURE_REGEXP
/* Variables necessary for regular expression matching */
size_t nmatch = 10;
regmatch_t pmatch[10];
#endif
- assert(pMsg != NULL);
- assert(pbMustBeFreed != NULL);
-
- if(pCSPropName == NULL) {
- assert(pTpe != NULL);
- pName = pTpe->data.field.pPropRepl;
- } else {
- pName = rsCStrGetSzStrNoNULL(pCSPropName);
- }
*pbMustBeFreed = 0;
- /* sometimes there are aliases to the original MonitoWare
- * property names. These come after || in the ifs below. */
- if(!strcmp((char*) pName, "msg")) {
- pRes = getMSG(pMsg);
- bufLen = getMSGLen(pMsg);
- } else if(!strcmp((char*) pName, "timestamp")
- || !strcmp((char*) pName, "timereported")) {
- pRes = getTimeReported(pMsg, pTpe->data.field.eDateFormat);
- } else if(!strcmp((char*) pName, "hostname") || !strcmp((char*) pName, "source")) {
- pRes = getHOSTNAME(pMsg);
- } else if(!strcmp((char*) pName, "syslogtag")) {
- pRes = getTAG(pMsg);
- } else if(!strcmp((char*) pName, "rawmsg")) {
- pRes = getRawMsg(pMsg);
- /* 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")) {
- pRes = (char*) getInputName(pMsg);
- } else if(!strcmp((char*) pName, "fromhost")) {
- pRes = (char*) getRcvFrom(pMsg);
- } else if(!strcmp((char*) pName, "fromhost-ip")) {
- pRes = (char*) getRcvFromIP(pMsg);
- } else if(!strcmp((char*) pName, "pri")) {
- pRes = getPRI(pMsg);
- } else if(!strcmp((char*) pName, "pri-text")) {
- pBuf = malloc(20 * sizeof(char));
- if(pBuf == NULL) {
- *pbMustBeFreed = 0;
- return "**OUT OF MEMORY**";
- } else {
- *pbMustBeFreed = 1;
- pRes = textpri(pBuf, 20, getPRIi(pMsg));
- }
- } else if(!strcmp((char*) pName, "iut")) {
- pRes = "1"; /* always 1 for syslog messages (a MonitorWare thing;)) */
- } else if(!strcmp((char*) pName, "syslogfacility")) {
- pRes = getFacility(pMsg);
- } else if(!strcmp((char*) pName, "syslogfacility-text")) {
- pRes = getFacilityStr(pMsg);
- } else if(!strcmp((char*) pName, "syslogseverity") || !strcmp((char*) pName, "syslogpriority")) {
- pRes = getSeverity(pMsg);
- } else if(!strcmp((char*) pName, "syslogseverity-text") || !strcmp((char*) pName, "syslogpriority-text")) {
- pRes = getSeverityStr(pMsg);
- } else if(!strcmp((char*) pName, "timegenerated")) {
- pRes = getTimeGenerated(pMsg, pTpe->data.field.eDateFormat);
- } else if(!strcmp((char*) pName, "programname")) {
- pRes = getProgramName(pMsg, LOCK_MUTEX);
- } else if(!strcmp((char*) pName, "protocol-version")) {
- pRes = getProtocolVersionString(pMsg);
- } else if(!strcmp((char*) pName, "structured-data")) {
- pRes = getStructuredData(pMsg);
- } else if(!strcmp((char*) pName, "app-name")) {
- pRes = getAPPNAME(pMsg, LOCK_MUTEX);
- } else if(!strcmp((char*) pName, "procid")) {
- pRes = getPROCID(pMsg, LOCK_MUTEX);
- } else if(!strcmp((char*) pName, "msgid")) {
- pRes = getMSGID(pMsg);
- /* here start system properties (those, that do not relate to the message itself */
- } else if(!strcmp((char*) pName, "$now")) {
- if((pRes = (char*) getNOW(NOW_NOW)) == NULL) {
- return "***OUT OF MEMORY***";
- } else
- *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$year")) {
- if((pRes = (char*) getNOW(NOW_YEAR)) == NULL) {
- return "***OUT OF MEMORY***";
- } else
- *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$month")) {
- if((pRes = (char*) getNOW(NOW_MONTH)) == NULL) {
- return "***OUT OF MEMORY***";
- } else
- *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$day")) {
- if((pRes = (char*) getNOW(NOW_DAY)) == NULL) {
- return "***OUT OF MEMORY***";
- } else
- *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$hour")) {
- if((pRes = (char*) getNOW(NOW_HOUR)) == NULL) {
- return "***OUT OF MEMORY***";
- } else
- *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$hhour")) {
- if((pRes = (char*) getNOW(NOW_HHOUR)) == NULL) {
- return "***OUT OF MEMORY***";
- } else
- *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$qhour")) {
- if((pRes = (char*) getNOW(NOW_QHOUR)) == NULL) {
- return "***OUT OF MEMORY***";
- } else
- *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$minute")) {
- if((pRes = (char*) getNOW(NOW_MINUTE)) == NULL) {
- return "***OUT OF MEMORY***";
- } else
- *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
- } else if(!strcmp((char*) pName, "$myhostname")) {
- pRes = (char*) glbl.GetLocalHostName();
- } else {
- /* there is no point in continuing, we may even otherwise render the
- * error message unreadable. rgerhards, 2007-07-10
- */
- dbgprintf("invalid property name: '%s'\n", pName);
- return "**INVALID PROPERTY NAME**";
+ switch(propID) {
+ case PROP_MSG:
+ pRes = getMSG(pMsg);
+ bufLen = getMSGLen(pMsg);
+ break;
+ case PROP_TIMESTAMP:
+ pRes = getTimeReported(pMsg, pTpe->data.field.eDateFormat);
+ break;
+ case PROP_HOSTNAME:
+ pRes = getHOSTNAME(pMsg);
+ break;
+ case PROP_SYSLOGTAG:
+ pRes = getTAG(pMsg);
+ break;
+ case PROP_RAWMSG:
+ pRes = getRawMsg(pMsg);
+ break;
+ /* 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:
+ pRes = (char*) getInputName(pMsg);
+ break;
+ case PROP_FROMHOST:
+ pRes = (char*) getRcvFrom(pMsg);
+ break;
+ case PROP_FROMHOST_IP:
+ pRes = (char*) getRcvFromIP(pMsg);
+ break;
+ case PROP_PRI:
+ pRes = getPRI(pMsg);
+ break;
+ case PROP_PRI_TEXT:
+ pBuf = malloc(20 * sizeof(char));
+ if(pBuf == NULL) {
+ *pbMustBeFreed = 0;
+ return "**OUT OF MEMORY**";
+ } else {
+ *pbMustBeFreed = 1;
+ pRes = textpri(pBuf, 20, getPRIi(pMsg));
+ }
+ break;
+ case PROP_IUT:
+ pRes = "1"; /* always 1 for syslog messages (a MonitorWare thing;)) */
+ break;
+ case PROP_SYSLOGFACILITY:
+ pRes = getFacility(pMsg);
+ break;
+ case PROP_SYSLOGFACILITY_TEXT:
+ pRes = getFacilityStr(pMsg);
+ break;
+ case PROP_SYSLOGSEVERITY:
+ pRes = getSeverity(pMsg);
+ break;
+ case PROP_SYSLOGSEVERITY_TEXT:
+ pRes = getSeverityStr(pMsg);
+ break;
+ case PROP_TIMEGENERATED:
+ pRes = getTimeGenerated(pMsg, pTpe->data.field.eDateFormat);
+ break;
+ case PROP_PROGRAMNAME:
+ pRes = getProgramName(pMsg, LOCK_MUTEX);
+ break;
+ case PROP_PROTOCOL_VERSION:
+ pRes = getProtocolVersionString(pMsg);
+ break;
+ case PROP_STRUCTURED_DATA:
+ pRes = getStructuredData(pMsg);
+ break;
+ case PROP_APP_NAME:
+ pRes = getAPPNAME(pMsg, LOCK_MUTEX);
+ break;
+ case PROP_PROCID:
+ pRes = getPROCID(pMsg, LOCK_MUTEX);
+ break;
+ case PROP_MSGID:
+ pRes = getMSGID(pMsg);
+ break;
+ case PROP_SYS_NOW:
+ if((pRes = (char*) getNOW(NOW_NOW)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ break;
+ case PROP_SYS_YEAR:
+ if((pRes = (char*) getNOW(NOW_YEAR)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ break;
+ case PROP_SYS_MONTH:
+ if((pRes = (char*) getNOW(NOW_MONTH)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ break;
+ case PROP_SYS_DAY:
+ if((pRes = (char*) getNOW(NOW_DAY)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ break;
+ case PROP_SYS_HOUR:
+ if((pRes = (char*) getNOW(NOW_HOUR)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ break;
+ case PROP_SYS_HHOUR:
+ if((pRes = (char*) getNOW(NOW_HHOUR)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ break;
+ case PROP_SYS_QHOUR:
+ if((pRes = (char*) getNOW(NOW_QHOUR)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ break;
+ case PROP_SYS_MINUTE:
+ if((pRes = (char*) getNOW(NOW_MINUTE)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ break;
+ case PROP_SYS_MYHOSTNAME:
+ pRes = (char*) glbl.GetLocalHostName();
+ break;
+ default:
+ /* there is no point in continuing, we may even otherwise render the
+ * error message unreadable. rgerhards, 2007-07-10
+ */
+ dbgprintf("invalid property id: '%d'\n", propID);
+ return "**INVALID PROPERTY NAME**";
}
/* If we did not receive a template pointer, we are already done... */
@@ -2587,6 +2609,7 @@ msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar)
size_t propLen;
uchar *pszProp = NULL;
cstr_t *pstrProp;
+ propid_t propid;
unsigned short bMustBeFreed = 0;
ISOBJ_TYPE_assert(pThis, msg);
@@ -2598,7 +2621,9 @@ msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar)
CHKiRet(var.ConstructFinalize(pVar));
/* always call MsgGetProp() without a template specifier */
- pszProp = (uchar*) MsgGetProp(pThis, NULL, pstrPropName, &propLen, &bMustBeFreed);
+ /* TODO: optimize propNameToID() call -- rgerhards, 2009-06-26 */
+ propNameToID(pstrPropName, &propid);
+ pszProp = (uchar*) MsgGetProp(pThis, NULL, propid, &propLen, &bMustBeFreed);
/* now create a string object out of it and hand that over to the var */
CHKiRet(rsCStrConstructFromszStr(&pstrProp, pszProp));
@@ -2614,6 +2639,95 @@ 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
diff --git a/runtime/msg.h b/runtime/msg.h
index 56ba5b80..e6b25e6c 100644
--- a/runtime/msg.h
+++ b/runtime/msg.h
@@ -33,6 +33,7 @@
#include "syslogd-types.h"
#include "template.h"
+
/* rgerhards 2004-11-08: The following structure represents a
* syslog message.
*
@@ -160,7 +161,7 @@ void MsgSetRawMsgWOSize(msg_t *pMsg, char* pszRawMsg);
void MsgSetRawMsg(msg_t *pMsg, char* pszRawMsg, size_t lenMsg);
rsRetVal MsgReplaceMSG(msg_t *pThis, uchar* pszMSG, int lenMSG);
char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
- cstr_t *pCSPropName, size_t *pPropLen, unsigned short *pbMustBeFreed);
+ propid_t propID, size_t *pPropLen, unsigned short *pbMustBeFreed);
char *textpri(char *pRes, size_t pResLen, int pri);
rsRetVal msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar);
rsRetVal MsgEnableThreadSafety(void);
@@ -177,6 +178,8 @@ int getHOSTNAMELen(msg_t *pM);
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);
+
/* The MsgPrepareEnqueue() function is a macro for performance reasons.
* It needs one global variable to work. This is acceptable, as it gains
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 09c3a066..3c8db169 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -81,6 +81,7 @@ typedef long long int64;
typedef long long unsigned uint64;
typedef int64 number_t; /* type to use for numbers - TODO: maybe an autoconf option? */
typedef char intTiny; /* 0..127! */
+typedef uchar uintTiny; /* 0..255! */
/* define some base data types */
typedef unsigned char uchar;/* get rid of the unhandy "unsigned char" */
@@ -170,6 +171,45 @@ struct multi_submit_s {
#define _PATH_CONSOLE "/dev/console"
#endif
+/* properties are now encoded as (tiny) integers. I do not use an enum as I would like
+ * to keep the memory footprint small (and thus cache hits high).
+ * rgerhards, 2009-06-26
+ */
+typedef uintTiny propid_t;
+#define PROP_INVALID 0
+#define PROP_MSG 1
+#define PROP_TIMESTAMP 2
+#define PROP_HOSTNAME 3
+#define PROP_SYSLOGTAG 4
+#define PROP_RAWMSG 5
+#define PROP_INPUTNAME 6
+#define PROP_FROMHOST 7
+#define PROP_FROMHOST_IP 8
+#define PROP_PRI 9
+#define PROP_PRI_TEXT 10
+#define PROP_IUT 11
+#define PROP_SYSLOGFACILITY 12
+#define PROP_SYSLOGFACILITY_TEXT 13
+#define PROP_SYSLOGSEVERITY 14
+#define PROP_SYSLOGSEVERITY_TEXT 15
+#define PROP_TIMEGENERATED 16
+#define PROP_PROGRAMNAME 17
+#define PROP_PROTOCOL_VERSION 18
+#define PROP_STRUCTURED_DATA 19
+#define PROP_APP_NAME 20
+#define PROP_PROCID 21
+#define PROP_MSGID 22
+#define PROP_SYS_NOW 150
+#define PROP_SYS_YEAR 151
+#define PROP_SYS_MONTH 152
+#define PROP_SYS_DAY 153
+#define PROP_SYS_HOUR 154
+#define PROP_SYS_HHOUR 155
+#define PROP_SYS_QHOUR 156
+#define PROP_SYS_MINUTE 157
+#define PROP_SYS_MYHOSTNAME 158
+
+
/* The error codes below are orginally "borrowed" from
* liblogging. As such, we reserve values up to -2999
* just in case we need to borrow something more ;)
@@ -339,6 +379,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_STREAM_DISABLED = -2127, /**< a file has been disabled (e.g. by size limit restriction) */
RS_RET_FILENAME_INVALID = -2140, /**< filename invalid, not found, no access, ... */
RS_RET_ZLIB_ERR = -2141, /**< error during zlib call */
+ RS_RET_VAR_NOT_FOUND = -2142, /**< variable not found */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
diff --git a/runtime/rule.c b/runtime/rule.c
index 221368e6..ce19146b 100644
--- a/runtime/rule.c
+++ b/runtime/rule.c
@@ -179,8 +179,7 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, int *bProcessMsg)
bRet = (pResult->val.num) ? 1 : 0;
} else {
assert(pRule->f_filter_type == FILTER_PROP); /* assert() just in case... */
- pszPropVal = MsgGetProp(pMsg, NULL, pRule->f_filterData.prop.pCSPropName, &propLen, &pbMustBeFreed);
- // TODO: optimize, we now have the length of the property!
+ pszPropVal = MsgGetProp(pMsg, NULL, pRule->f_filterData.prop.propID, &propLen, &pbMustBeFreed);
/* Now do the compares (short list currently ;)) */
switch(pRule->f_filterData.prop.operation ) {
@@ -220,9 +219,8 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, int *bProcessMsg)
bRet = (bRet == 1) ? 0 : 1;
if(Debug) {
- dbgprintf("Filter: check for property '%s' (value '%s') ",
- rsCStrGetSzStrNoNULL(pRule->f_filterData.prop.pCSPropName),
- pszPropVal);
+ dbgprintf("Filter: check for property '%d' (value '%s') ",
+ pRule->f_filterData.prop.propID, pszPropVal);
if(pRule->f_filterData.prop.isNegated)
dbgprintf("NOT ");
dbgprintf("%s '%s': %s\n",
@@ -308,8 +306,6 @@ CODESTARTobjDestruct(rule)
rsCStrDestruct(&pThis->pCSProgNameComp);
if(pThis->f_filter_type == FILTER_PROP) {
- if(pThis->f_filterData.prop.pCSPropName != NULL)
- rsCStrDestruct(&pThis->f_filterData.prop.pCSPropName);
if(pThis->f_filterData.prop.pCSCompValue != NULL)
rsCStrDestruct(&pThis->f_filterData.prop.pCSCompValue);
if(pThis->f_filterData.prop.regex_cache != NULL)
@@ -377,8 +373,8 @@ CODESTARTobjDebugPrint(rule)
dbgprintf("EXPRESSION-BASED Filter: can currently not be displayed");
} else {
dbgprintf("PROPERTY-BASED Filter:\n");
- dbgprintf("\tProperty.: '%s'\n",
- rsCStrGetSzStrNoNULL(pThis->f_filterData.prop.pCSPropName));
+ dbgprintf("\tProperty.: '%d'\n", pThis->f_filterData.prop.propID);
+// TODO: XXXX ADD idtostring()!
dbgprintf("\tOperation: ");
if(pThis->f_filterData.prop.isNegated)
dbgprintf("NOT ");
diff --git a/runtime/rule.h b/runtime/rule.h
index 38b11c63..99ac44e7 100644
--- a/runtime/rule.h
+++ b/runtime/rule.h
@@ -44,11 +44,11 @@ struct rule_s {
union {
u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
struct {
- cstr_t *pCSPropName;
fiop_t operation;
regex_t *regex_cache; /* cache for compiled REs, if such are used */
cstr_t *pCSCompValue; /* value to "compare" against */
- char isNegated; /* actually a boolean ;) */
+ bool isNegated;
+ propid_t propID; /* ID of the requested property */
} prop;
expr_t *f_expr; /* expression object */
} f_filterData;
diff --git a/runtime/stringbuf.c b/runtime/stringbuf.c
index f3824831..88f5a3a2 100644
--- a/runtime/stringbuf.c
+++ b/runtime/stringbuf.c
@@ -343,42 +343,6 @@ uchar* rsCStrGetSzStr(cstr_t *pThis)
}
-/* Converts the CStr object to a classical sz string and returns that.
- * Same restrictions as in cstrGetSzStr() applies (see there!). This
- * function here guarantees that a valid string is returned, even if
- * the CStr object currently holds a NULL pointer string buffer. If so,
- * "" is returned.
- * rgerhards 2005-10-19
- * WARNING: The returned pointer MUST NOT be freed, as it may be
- * obtained from that constant memory pool (in case of NULL!)
- */
-uchar* cstrGetSzStrNoNULL(cstr_t *pThis)
-{
- rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
- if(pThis->pBuf == NULL)
- return (uchar*) "";
- else
- return cstrGetSzStr(pThis);
-}
-
-/* Returns the cstr data as a classical C sz string. We use that the
- * Finalizer did properly terminate our string (but we may stil be NULL).
- * So it is vital that the finalizer is called BEFORe this function here!
- * The caller must not free or otherwise manipulate the returned string and must not
- * destroy the CStr object as long as the ascii string is used.
- * This function may return NULL, if the string is currently NULL. This
- * is a feature, not a bug. If you need non-NULL in any case, use
- * cstrGetSzStrNoNULL() instead.
- * Note that due to the new single-buffer interface this function almost does nothing!
- * rgerhards, 2006-09-16
- */
-uchar* cstrGetSzStr(cstr_t *pThis)
-{
- rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
- return(pThis->pBuf);
-}
-
-
/* Converts the CStr object to a classical zero-terminated C string,
* returns that string and destroys the CStr object. The returned string
* MUST be freed by the caller. The function might return NULL if
@@ -426,27 +390,6 @@ finalize_it:
}
-/* Finalize the string object. This must be called after all data is added to it
- * but before that data is used.
- * rgerhards, 2009-06-16
- */
-rsRetVal
-cstrFinalize(cstr_t *pThis)
-{
- DEFiRet;
- rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
-
- if(pThis->iStrLen > 0) {
- /* terminate string only if one exists */
- CHKiRet(cstrAppendChar(pThis, '\0'));
- --pThis->iStrLen; /* do NOT count the \0 byte */
- }
-
-finalize_it:
- RETiRet;
-}
-
-
/* return the length of the current string
* 2005-09-09 rgerhards
* Please note: this is only a function in a debug build.
diff --git a/runtime/stringbuf.h b/runtime/stringbuf.h
index 4fbd9a9b..400c74eb 100644
--- a/runtime/stringbuf.h
+++ b/runtime/stringbuf.h
@@ -74,9 +74,7 @@ void rsCStrDestruct(cstr_t **ppThis);
rsRetVal rsCStrExtendBuf(cstr_t *pThis, size_t iMinNeeded); /* our helper, NOT a public interface! */
static inline rsRetVal cstrAppendChar(cstr_t *pThis, uchar c)
{
- rsRetVal iRet;
-
- rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ rsRetVal iRet = RS_RET_OK;
if(pThis->iStrLen >= pThis->iBufSize) {
CHKiRet(rsCStrExtendBuf(pThis, 1)); /* need more memory! */
@@ -89,6 +87,66 @@ finalize_it:
return iRet;
}
+
+/* some inline functions for things that are really frequently called... */
+
+/* Finalize the string object. This must be called after all data is added to it
+ * but before that data is used.
+ * rgerhards, 2009-06-16
+ */
+static inline rsRetVal
+cstrFinalize(cstr_t *pThis)
+{
+ rsRetVal iRet = RS_RET_OK;
+
+ if(pThis->iStrLen > 0) {
+ /* terminate string only if one exists */
+ CHKiRet(cstrAppendChar(pThis, '\0'));
+ --pThis->iStrLen; /* do NOT count the \0 byte */
+ }
+
+finalize_it:
+ return iRet;
+}
+
+
+/* Returns the cstr data as a classical C sz string. We use that the
+ * Finalizer did properly terminate our string (but we may stil be NULL).
+ * So it is vital that the finalizer is called BEFORe this function here!
+ * The caller must not free or otherwise manipulate the returned string and must not
+ * destroy the CStr object as long as the ascii string is used.
+ * This function may return NULL, if the string is currently NULL. This
+ * is a feature, not a bug. If you need non-NULL in any case, use
+ * cstrGetSzStrNoNULL() instead.
+ * Note that due to the new single-buffer interface this function almost does nothing!
+ * rgerhards, 2006-09-16
+ */
+static inline uchar* cstrGetSzStr(cstr_t *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ return(pThis->pBuf);
+}
+
+
+/* Converts the CStr object to a classical sz string and returns that.
+ * Same restrictions as in cstrGetSzStr() applies (see there!). This
+ * function here guarantees that a valid string is returned, even if
+ * the CStr object currently holds a NULL pointer string buffer. If so,
+ * "" is returned.
+ * rgerhards 2005-10-19
+ * WARNING: The returned pointer MUST NOT be freed, as it may be
+ * obtained from that constant memory pool (in case of NULL!)
+ */
+static inline uchar* cstrGetSzStrNoNULL(cstr_t *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ if(pThis->pBuf == NULL)
+ return (uchar*) "";
+ else
+ return cstrGetSzStr(pThis);
+}
+
+
/**
* Truncate "n" number of characters from the end of the
* string. The buffer remains unchanged, just the
@@ -148,8 +206,6 @@ rsRetVal rsCStrConvertToBool(cstr_t *pStr, number_t *pBool);
/* new calling interface */
rsRetVal cstrFinalize(cstr_t *pThis);
rsRetVal cstrConvSzStrAndDestruct(cstr_t *pThis, uchar **ppSz, int bRetNULL);
-uchar* cstrGetSzStr(cstr_t *pThis);
-uchar* cstrGetSzStrNoNULL(cstr_t *pThis);
rsRetVal cstrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend);
/* now come inline-like functions */
diff --git a/template.c b/template.c
index 704f0b19..832183b0 100644
--- a/template.c
+++ b/template.c
@@ -105,7 +105,7 @@ rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *
iLenVal = pTpe->data.constant.iLenConstant;
bMustBeFreed = 0;
} else if(pTpe->eEntryType == FIELD) {
- pVal = (uchar*) MsgGetProp(pMsg, pTpe, NULL, &iLenVal, &bMustBeFreed);
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid, &iLenVal, &bMustBeFreed);
/* we now need to check if we should use SQL option. In this case,
* we must go over the generated string and escape '\'' characters.
* rgerhards, 2005-09-22: the option values below look somewhat misplaced,
@@ -173,7 +173,7 @@ rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr)
if(pTpe->eEntryType == CONSTANT) {
CHKmalloc(pArr[iArr] = (uchar*)strdup((char*) pTpe->data.constant.pConstant));
} else if(pTpe->eEntryType == FIELD) {
- pVal = (uchar*) MsgGetProp(pMsg, pTpe, NULL, &propLen, &bMustBeFreed);
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid, &propLen, &bMustBeFreed);
if(bMustBeFreed) { /* if it must be freed, it is our own private copy... */
pArr[iArr] = pVal; /* ... so we can use it! */
} else {
@@ -561,11 +561,11 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
++p; /* do NOT do this in tolower()! */
}
- /* got the name*/
+ /* got the name */
cstrFinalize(pStrB);
- if(cstrConvSzStrAndDestruct(pStrB, &pTpe->data.field.pPropRepl, 0) != RS_RET_OK)
+
+ if(propNameToID(pStrB, &pTpe->data.field.propid) != RS_RET_OK)
return 1;
-// TODO: another optimization: map name to integer id OPT
/* Check frompos, if it has an R, then topos should be a regex */
if(*p == ':') {
@@ -1004,8 +1004,6 @@ void tplDeleteAll(void)
regexp.regfree(&(pTpeDel->data.field.re));
}
}
- /*dbgprintf("(FIELD), value: '%s'", pTpeDel->data.field.pPropRepl);*/
- free(pTpeDel->data.field.pPropRepl);
break;
}
/*dbgprintf("\n");*/
@@ -1061,8 +1059,6 @@ void tplDeleteNew(void)
regexp.regfree(&(pTpeDel->data.field.re));
}
}
- /*dbgprintf("(FIELD), value: '%s'", pTpeDel->data.field.pPropRepl);*/
- free(pTpeDel->data.field.pPropRepl);
break;
}
/*dbgprintf("\n");*/
@@ -1111,7 +1107,7 @@ void tplPrintList(void)
pTpe->data.constant.pConstant);
break;
case FIELD:
- dbgprintf("(FIELD), value: '%s' ", pTpe->data.field.pPropRepl);
+ dbgprintf("(FIELD), value: '%d' ", pTpe->data.field.propid);
switch(pTpe->data.field.eDateFormat) {
case tplFmtDefault:
break;
diff --git a/template.h b/template.h
index 73ed0f84..271e8271 100644
--- a/template.h
+++ b/template.h
@@ -63,7 +63,7 @@ struct templateEntry {
int iLenConstant; /* its length */
} constant;
struct {
- uchar *pPropRepl; /* pointer to property replacer string */
+ propid_t propid; /* property to be used */
unsigned iFromPos; /* for partial strings only chars from this position ... */
unsigned iToPos; /* up to that one... */
#ifdef FEATURE_REGEXP