From 279896ebda98804c89899c53f857ca189ab24f45 Mon Sep 17 00:00:00 2001 From: Ronny Egner Date: Sat, 27 Jun 2009 12:36:34 +0200 Subject: improved omoracle documentation Signed-off-by: Rainer Gerhards --- doc/omoracle.html | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/doc/omoracle.html b/doc/omoracle.html index 40f6360f..cfcf277f 100644 --- a/doc/omoracle.html +++ b/doc/omoracle.html @@ -67,6 +67,128 @@ it is suggested to post questions to the need to define the properties on the template in the correct order you want them passed to the statement! +

Some additional documentation contributed by Ronny Egner: +

+REQUIREMENTS:
+--------------
+
+- Oracle Instantclient 10g (NOT 11g) Base + Devel
+  (if you´re on 64-bit linux you should choose the 64-bit libs!) 
+- JDK 1.6 (not neccessary for oracle plugin but "make" didd not finsished successfully without it)
+
+- "oracle-instantclient-config" script 
+  (seems to shipped with instantclient 10g Release 1 but i was unable to find it for 10g Release 2 so here it is)
+
+  
+======================  /usr/local/bin/oracle-instantclient-config =====================
+#!/bin/sh
+#
+# Oracle InstantClient SDK config file
+# Jean-Christophe Duberga - Bordeaux 2 University
+#
+
+# just adapt it to your environment
+incdirs="-I/usr/include/oracle/10.2.0.4/client64"
+libdirs="-L/usr/lib/oracle/10.2.0.4/client64/lib"
+
+usage="\
+Usage: oracle-instantclient-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--cflags] [--libs] [--static-libs]"
+
+if test $# -eq 0; then
+      echo "${usage}" 1>&2
+      exit 1
+fi
+
+while test $# -gt 0; do
+  case "$1" in
+  -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  case $1 in
+    --prefix=*)
+      prefix=$optarg
+      if test $exec_prefix_set = no ; then
+        exec_prefix=$optarg
+      fi
+      ;;
+    --prefix)
+      echo $prefix
+      ;;
+    --exec-prefix=*)
+      exec_prefix=$optarg
+      exec_prefix_set=yes
+      ;;
+    --exec-prefix)
+      echo ${exec_prefix}
+      ;;
+    --version)
+      echo ${version}
+      ;;
+    --cflags)
+      echo ${incdirs}
+      ;;
+    --libs)
+      echo $libdirs -lclntsh -lnnz10 -locci -lociei -locijdbc10
+      ;;
+    --static-libs)
+      echo "No static libs" 1>&2
+      exit 1
+      ;;
+    *)
+      echo "${usage}" 1>&2
+      exit 1
+      ;;
+  esac
+  shift
+done
+
+===============   END ==============
+
+
+
+
+COMPILING RSYSLOGD
+-------------------
+
+
+./configure --enable-oracle
+
+
+
+
+RUNNING
+-------
+
+- make sure rsyslogd is able to locate the oracle libs (either via LD_LIBRARY_PATH or /etc/ld.so.conf)
+- set TNS_ADMIN to point to your tnsnames.ora
+- create a tnsnames.ora and test you are able to connect to the database
+
+- create user in oracle as shown in the following example:
+		create user syslog identified by syslog default tablespace users quota unlimited on users;
+		grant create session to syslog;
+		create role syslog_role;
+		grant syslog_role to syslog;
+		grant create table to syslog_role;
+		grant create sequence to syslog_role;
+		
+- create tables as needed
+
+- configure rsyslog as shown in the following example
+		$ModLoad omoracle
+
+		$OmoracleDBUser syslog
+		$OmoracleDBPassword syslog
+		$OmoracleDB syslog
+		$OmoracleBatchSize 1
+		$OmoracleBatchItemSize 4096
+
+		$OmoracleStatementTemplate OmoracleStatement
+		$template OmoracleStatement,"insert into foo(hostname,message) values (:host,:message)"
+		$template TestStmt,"%hostname%%msg%"
+		*.*                     :omoracle:;TestStmt
+	(you guess it: username = password = database = "syslog".... see $rsyslogd_source/plugins/omoracle/omoracle.c for me info)
+

[rsyslog.conf overview] [manual index] [rsyslog site]

This documentation is part of the -- cgit From ba4806a70439dd24dc98bd707893b1319dd5e3ef Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Thu, 18 Jun 2009 13:51:17 -0400 Subject: add support for KLogPath --- plugins/imklog/bsd.c | 9 +++++++-- plugins/imklog/imklog.c | 9 +++++++++ plugins/imklog/imklog.h | 1 + plugins/imklog/linux.c | 11 ++++++++--- tools/syslogd.c | 4 ++-- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c index 090c4e9b..6d7b6c98 100644 --- a/plugins/imklog/bsd.c +++ b/plugins/imklog/bsd.c @@ -83,6 +83,11 @@ static int fklog = -1; /* /dev/klog */ # define _PATH_KLOG "/dev/klog" #endif +static uchar *GetPath(void) +{ + return pszPath ? pszPath : _PATH_KLOG; +} + /* open the kernel log - will be called inside the willRun() imklog * entry point. -- rgerhards, 2008-04-09 */ @@ -91,9 +96,9 @@ klogWillRun(void) { DEFiRet; - fklog = open(_PATH_KLOG, O_RDONLY, 0); + fklog = open(GetPath(), O_RDONLY, 0); if (fklog < 0) { - dbgprintf("can't open %s (%d)\n", _PATH_KLOG, errno); + dbgprintf("can't open %s (%d)\n", GetPath(), errno); iRet = RS_RET_ERR; // TODO: better error code } diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index f63d60ac..ab806183 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "dirty.h" #include "cfsysline.h" @@ -69,6 +70,7 @@ int use_syscall = 0; int symbol_lookup = 0; /* on recent kernels > 2.6, the kernel does this */ int bPermitNonKernel = 0; /* permit logging of messages not having LOG_KERN facility */ int iFacilIntMsg; /* the facility to use for internal messages (set by driver) */ +uchar *pszPath = NULL; /* TODO: configuration for the following directives must be implemented. It * was not done yet because we either do not yet have a config handler for * that type or I thought it was acceptable to push it to a later stage when @@ -243,6 +245,8 @@ CODESTARTmodExit /* release objects we used */ objRelease(glbl, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); + if(pszPath != NULL) + free(pszPath); ENDmodExit @@ -259,6 +263,10 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a symfile = NULL; symbol_lookup = 0; bPermitNonKernel = 0; + if(pszPath != NULL) { + free(pszPath); + pszPath = NULL; + } iFacilIntMsg = klogFacilIntMsg(); return RS_RET_OK; } @@ -273,6 +281,7 @@ CODEmodInit_QueryRegCFSLineHdlr iFacilIntMsg = klogFacilIntMsg(); CHKiRet(omsdRegCFSLineHdlr((uchar *)"debugprintkernelsymbols", 0, eCmdHdlrBinary, NULL, &dbgPrintSymbols, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogpath", 0, eCmdHdlrGetWord, NULL, &pszPath, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbollookup", 0, eCmdHdlrBinary, NULL, &symbol_lookup, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbolstwice", 0, eCmdHdlrBinary, NULL, &symbols_twice, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogusesyscallinterface", 0, eCmdHdlrBinary, NULL, &use_syscall, STD_LOADABLE_MODULE_ID)); diff --git a/plugins/imklog/imklog.h b/plugins/imklog/imklog.h index 37bd58b0..c183026d 100644 --- a/plugins/imklog/imklog.h +++ b/plugins/imklog/imklog.h @@ -52,6 +52,7 @@ extern int symbol_lookup; extern char *symfile; extern int console_log_level; extern int dbgPrintSymbols; +extern uchar *pszPath; /* the functions below may be called by the drivers */ rsRetVal imklogLogIntMsg(int priority, char *fmt, ...) __attribute__((format(printf,2, 3))); diff --git a/plugins/imklog/linux.c b/plugins/imklog/linux.c index 0dd4320d..fcd9d6cd 100644 --- a/plugins/imklog/linux.c +++ b/plugins/imklog/linux.c @@ -84,6 +84,11 @@ static enum LOGSRC {none, proc, kernel} logsrc; extern int ksyslog(int type, char *buf, int len); +static uchar *GetPath(void) +{ + return pszPath ? pszPath : _PATH_KLOG; +} + static void CloseLogSrc(void) { /* Turn on logging of messages to console, but only if we had the -c @@ -135,7 +140,7 @@ static enum LOGSRC GetKernelLogSrc(void) * file system is available to get kernel messages from. */ if ( use_syscall || - ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) ) + ((stat(GetPath(), &sb) < 0) && (errno == ENOENT)) ) { /* Initialize kernel logging. */ ksyslog(1, NULL, 0); @@ -144,14 +149,14 @@ static enum LOGSRC GetKernelLogSrc(void) return(kernel); } - if ( (kmsg = open(_PATH_KLOG, O_RDONLY|O_CLOEXEC)) < 0 ) + if ( (kmsg = open(GetPath(), O_RDONLY|O_CLOEXEC)) < 0 ) { imklogLogIntMsg(LOG_ERR, "imklog: Cannot open proc file system, %d.\n", errno); ksyslog(7, NULL, 0); /* TODO: check this, implement more */ return(none); } - imklogLogIntMsg(LOG_INFO, "imklog %s, log source = %s started.", VERSION, _PATH_KLOG); + imklogLogIntMsg(LOG_INFO, "imklog %s, log source = %s started.", VERSION, GetPath()); return(proc); } diff --git a/tools/syslogd.c b/tools/syslogd.c index 8bc4939f..f6f4b469 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -2750,8 +2750,6 @@ static rsRetVal mainThread() pTmp = template_StdPgSQLFmt; tplLastStaticInit(tplAddLine(" StdPgSQLFmt", &pTmp)); - CHKiRet(init()); - if(Debug && debugging_on) { DBGPRINTF("Debugging enabled, SIGUSR1 to turn off debugging.\n"); } @@ -2779,6 +2777,8 @@ static rsRetVal mainThread() } + CHKiRet(init()); + /* END OF INTIALIZATION * ... but keep in mind that we might do a restart and thus init() might * be called again. If that happens, we must shut down the worker thread, -- cgit From e747478051f4f81a872c791710933881c9564d64 Mon Sep 17 00:00:00 2001 From: Michael Terry Date: Mon, 29 Jun 2009 11:18:55 +0200 Subject: separate willRun and runInput calls for input modules Signed-off-by: Rainer Gerhards --- runtime/modules.c | 1 + runtime/modules.h | 1 + tools/syslogd.c | 46 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/runtime/modules.c b/runtime/modules.c index 32ae659f..bd201252 100644 --- a/runtime/modules.c +++ b/runtime/modules.c @@ -399,6 +399,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 372529ee..4d874019 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/tools/syslogd.c b/tools/syslogd.c index f6f4b469..6ccacf5f 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -2081,6 +2081,29 @@ static void dbgPrintInitInfo(void) } +/* Actually run the input modules. This happens after privileges are dropped, + * if that is requested. + */ +static rsRetVal +runInputModules(void) +{ + modInfo_t *pMod; + + /* loop through all modules and activate them (brr...) */ + pMod = module.GetNxtType(NULL, eMOD_IN); + while(pMod != NULL) { + if(pMod->mod.im.bCanRun) { + /* activate here */ + thrdCreate(pMod->mod.im.runInput, pMod->mod.im.afterRun); + } + pMod = module.GetNxtType(pMod, eMOD_IN); + } + + ENDfunc + return RS_RET_OK; /* intentional: we do not care about module errors */ +} + + /* Start the input modules. This function will probably undergo big changes * while we implement the input module interface. For now, it does the most * important thing to get at least my poor initial input modules up and @@ -2088,7 +2111,7 @@ static void dbgPrintInitInfo(void) * rgerhards, 2007-12-14 */ static rsRetVal -startInputModules(void) +startInputModules(int bRunInputModules) { DEFiRet; modInfo_t *pMod; @@ -2096,15 +2119,18 @@ startInputModules(void) /* loop through all modules and activate them (brr...) */ pMod = module.GetNxtType(NULL, eMOD_IN); while(pMod != NULL) { - if((iRet = pMod->mod.im.willRun()) == RS_RET_OK) { - /* activate here */ - thrdCreate(pMod->mod.im.runInput, pMod->mod.im.afterRun); - } else { + iRet = pMod->mod.im.willRun(); + pMod->mod.im.bCanRun = (iRet == RS_RET_OK); + if(!pMod->mod.im.bCanRun) { DBGPRINTF("module %lx will not run, iRet %d\n", (unsigned long) pMod, iRet); } pMod = module.GetNxtType(pMod, eMOD_IN); } + if (bRunInputModules) { + runInputModules(); + } + ENDfunc return RS_RET_OK; /* intentional: we do not care about module errors */ } @@ -2116,7 +2142,7 @@ startInputModules(void) * else happens. -- rgerhards, 2008-07-28 */ static rsRetVal -init(void) +init(int bRunInputModules) { rsRetVal localRet; int iNbrActions; @@ -2321,7 +2347,7 @@ init(void) * shuffled to down here once we have everything in input modules. * rgerhards, 2007-12-14 */ - startInputModules(); + startInputModules(bRunInputModules); if(Debug) { dbgPrintInitInfo(); @@ -2492,7 +2518,7 @@ doHUP(void) if(glbl.GetHUPisRestart()) { DBGPRINTF("Received SIGHUP, configured to be restart, reloading rsyslogd.\n"); - init(); /* main queue is stopped as part of init() */ + init(1); /* main queue is stopped as part of init() */ } else { DBGPRINTF("Received SIGHUP, configured to be a non-restart type of HUP - notifying actions.\n"); ruleset.IterateAllActions(doHUPActions, NULL); @@ -2750,6 +2776,8 @@ static rsRetVal mainThread() pTmp = template_StdPgSQLFmt; tplLastStaticInit(tplAddLine(" StdPgSQLFmt", &pTmp)); + CHKiRet(init(0)); + if(Debug && debugging_on) { DBGPRINTF("Debugging enabled, SIGUSR1 to turn off debugging.\n"); } @@ -2777,7 +2805,7 @@ static rsRetVal mainThread() } - CHKiRet(init()); + runInputModules(); /* END OF INTIALIZATION * ... but keep in mind that we might do a restart and thus init() might -- cgit From 6a29afc83f16c57d243b39b8e8d47f2ed909bae0 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 29 Jun 2009 11:26:18 +0200 Subject: some cleanup --- tools/syslogd.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tools/syslogd.c b/tools/syslogd.c index 6ccacf5f..10d07c95 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -2111,7 +2111,7 @@ runInputModules(void) * rgerhards, 2007-12-14 */ static rsRetVal -startInputModules(int bRunInputModules) +startInputModules(void) { DEFiRet; modInfo_t *pMod; @@ -2127,10 +2127,6 @@ startInputModules(int bRunInputModules) pMod = module.GetNxtType(pMod, eMOD_IN); } - if (bRunInputModules) { - runInputModules(); - } - ENDfunc return RS_RET_OK; /* intentional: we do not care about module errors */ } @@ -2142,7 +2138,7 @@ startInputModules(int bRunInputModules) * else happens. -- rgerhards, 2008-07-28 */ static rsRetVal -init(int bRunInputModules) +init() { rsRetVal localRet; int iNbrActions; @@ -2343,11 +2339,14 @@ init(int bRunInputModules) DBGPRINTF("Main processing queue is initialized and running\n"); /* the output part and the queue is now ready to run. So it is a good time - * to start the inputs. Please note that the net code above should be + * to initialize the inputs. Please note that the net code above should be * shuffled to down here once we have everything in input modules. * rgerhards, 2007-12-14 + * NOTE: as of 2009-06-29, the input modules are initialized, but not yet run. + * Keep in mind. though, that the outputs already run if the queue was + * persisted to disk. -- rgerhards */ - startInputModules(bRunInputModules); + startInputModules(); if(Debug) { dbgPrintInitInfo(); @@ -2518,7 +2517,8 @@ doHUP(void) if(glbl.GetHUPisRestart()) { DBGPRINTF("Received SIGHUP, configured to be restart, reloading rsyslogd.\n"); - init(1); /* main queue is stopped as part of init() */ + init(); /* main queue is stopped as part of init() */ + runInputModules(); } else { DBGPRINTF("Received SIGHUP, configured to be a non-restart type of HUP - notifying actions.\n"); ruleset.IterateAllActions(doHUPActions, NULL); @@ -2776,11 +2776,12 @@ static rsRetVal mainThread() pTmp = template_StdPgSQLFmt; tplLastStaticInit(tplAddLine(" StdPgSQLFmt", &pTmp)); - CHKiRet(init(0)); + CHKiRet(init()); if(Debug && debugging_on) { DBGPRINTF("Debugging enabled, SIGUSR1 to turn off debugging.\n"); } + /* Send a signal to the parent so it can terminate. */ if(myPid != ppid) @@ -2788,7 +2789,7 @@ static rsRetVal mainThread() /* If instructed to do so, we now drop privileges. Note that this is not 100% secure, - * because inputs and outputs are already running at this time. However, we can implement + * because outputs are already running at this time. However, we can implement * dropping of privileges rather quickly and it will work in many cases. While it is not * the ultimate solution, the current one is still much better than not being able to * drop privileges at all. Doing it correctly, requires a change in architecture, which @@ -2805,13 +2806,12 @@ static rsRetVal mainThread() } + /* finally let the inputs run... */ runInputModules(); /* END OF INTIALIZATION * ... but keep in mind that we might do a restart and thus init() might - * be called again. If that happens, we must shut down the worker thread, - * do the init() and then restart things. - * rgerhards, 2005-10-24 + * be called again. -- rgerhards, 2005-10-24 */ DBGPRINTF("initialization completed, transitioning to regular run mode\n"); -- cgit From 4822715a6e1ecc48d50a5450f93f02f785b8745a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 29 Jun 2009 11:37:29 +0200 Subject: updated testbench to new init() behavior the deferred activation of input modules broke part of the testbench - but this was a testbench issue, not one of the patch --- ChangeLog | 2 ++ tests/nettester.c | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index d7c6e408..2c4d1145 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ --------------------------------------------------------------------------- Version 4.5.0 [DEVEL] (rgerhards), 2009-??-?? +- activation order of inputs changed, they are now activated only after + privileges are dropped. Thanks to Michael Terry for the patch. - greatly improved performance - greatly reduced memory requirements of msg object to around half of the previous demand. This means that more messages can diff --git a/tests/nettester.c b/tests/nettester.c index b8816b7c..c9a978c5 100644 --- a/tests/nettester.c +++ b/tests/nettester.c @@ -107,6 +107,7 @@ tcpSend(char *buf, int lenBuf) { static int sock = INVALID_SOCKET; struct sockaddr_in addr; + int retries; if(sock == INVALID_SOCKET) { /* first time, need to connect to target */ @@ -122,10 +123,19 @@ tcpSend(char *buf, int lenBuf) fprintf(stderr, "inet_aton() failed\n"); return(1); } - if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) { - fprintf(stderr, "connect() failed\n"); - return(1); - } + retries = 0; + while(1) { /* loop broken inside */ + if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) { + break; + } else { + if(retries++ == 3) { + fprintf(stderr, "connect() failed\n"); + return(1); + } else { + sleep(1); + } + } + } } /* send test data */ -- cgit From 6511278082a7e1e9602385cd24cdb5e363cb702f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 29 Jun 2009 12:40:41 +0200 Subject: bugfix: ssh session hangs after rsyslgod is started from it stderr/stdout were not closed to be able to emit error messages, but this caused ssh sessions to hang. Now we close them after the initial initialization. See forum thread: http://kb.monitorware.com/controlling-terminal-issues-t9875.html --- ChangeLog | 6 ++++++ tools/syslogd.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6ee2e6ba..66836317 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,10 @@ --------------------------------------------------------------------------- +Version 4.2.1 [v4-stable] (rgerhards), 2009-0?-?? +- bugfix: stderr/stdout were not closed to be able to emit error messages, + but this caused ssh sessions to hang. Now we close them after the + initial initialization. See forum thread: + http://kb.monitorware.com/controlling-terminal-issues-t9875.html +--------------------------------------------------------------------------- Version 4.2.0 [v4-stable] (rgerhards), 2009-06-23 - bugfix: light and full delay watermarks had invalid values, badly affecting performance for delayable inputs diff --git a/tools/syslogd.c b/tools/syslogd.c index 77273bec..45c55664 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -3015,7 +3015,6 @@ static rsRetVal mainThread() glbl.SetHUPisRestart(0); /* we can not do restart-type HUPs with dropped privs */ } - /* END OF INTIALIZATION * ... but keep in mind that we might do a restart and thus init() might * be called again. If that happens, we must shut down the worker thread, @@ -3024,6 +3023,19 @@ static rsRetVal mainThread() */ dbgprintf("initialization completed, transitioning to regular run mode\n"); + /* close stderr and stdout if they are kept open during a fork. Note that this + * may introduce subtle security issues: if we are in a jail, one may break out of + * it via these descriptors. But if I close them earlier, error messages will (once + * again) not be emitted to the user that starts the daemon. As root jail support + * is still in its infancy (and not really done), we currently accept this issue. + * rgerhards, 2009-06-29 + */ + if(!(Debug || NoFork)) { + close(1); + close(2); + bErrMsgToStderr = 0; + } + mainloop(); finalize_it: -- cgit From de84a12f8a5f140c0f7b8e00f4cac92ef13cd866 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 29 Jun 2009 16:53:26 +0200 Subject: introduced the idea of detached properties some things inside the message can be used over a large number of messages and need to to be allocated and re-written every time. I now begin to implement this as a "prop_t" object, first use for the inputName. Some input modules are already converted, some others to go. Will do a little performance check on the new method before I go further. Also, this commit has some cleanup and a few bug fixes that prevented compiliation in debug mode (I overlooked this as I did not compile for debug, what I normally do, and the automatted test also does not do that) --- plugins/imdiag/imdiag.c | 2 +- plugins/imfile/imfile.c | 2 +- plugins/imklog/imklog.c | 2 +- plugins/imklog/linux.c | 7 ++-- plugins/imudp/imudp.c | 16 ++++++++- runtime/datetime.c | 5 --- runtime/datetime.h | 2 -- runtime/msg.c | 91 +++++++++++++++++++++++++++++++++++-------------- runtime/msg.h | 11 ++++-- runtime/prop.c | 63 ++++++++++++++++++++++++++++++++++ runtime/prop.h | 11 +++++- runtime/rsyslog.c | 3 ++ runtime/rsyslog.h | 1 + runtime/stringbuf.h | 2 +- tcps_sess.c | 8 +++-- tcpsrv.c | 15 ++++++-- tcpsrv.h | 4 +-- tests/nettester.c | 5 +-- tools/syslogd.c | 5 +-- 19 files changed, 200 insertions(+), 55 deletions(-) diff --git a/plugins/imdiag/imdiag.c b/plugins/imdiag/imdiag.c index bfb4a2e5..4b004bc4 100644 --- a/plugins/imdiag/imdiag.c +++ b/plugins/imdiag/imdiag.c @@ -206,7 +206,7 @@ doInjectMsg(int iNum) /* we now create our own message object and submit it to the queue */ CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime)); MsgSetRawMsg(pMsg, (char*) szMsg, ustrlen(szMsg)); - MsgSetInputName(pMsg, UCHAR_CONSTANT("imdiag"), sizeof("imdiag")-1); + MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("imdiag"), sizeof("imdiag")-1); MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 631d02ff..fdd0c5f0 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -97,7 +97,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); - MsgSetInputName(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); + MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine), cstrLen(cstrLine)); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index ab806183..21744c4b 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -97,7 +97,7 @@ enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); - MsgSetInputName(pMsg, UCHAR_CONSTANT("imklog"), sizeof("imklog")-1); + MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("imklog"), sizeof("imklog")-1); MsgSetRawMsgWOSize(pMsg, (char*)msg); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetRcvFrom(pMsg, glbl.GetLocalHostName()); diff --git a/plugins/imklog/linux.c b/plugins/imklog/linux.c index fcd9d6cd..977395ea 100644 --- a/plugins/imklog/linux.c +++ b/plugins/imklog/linux.c @@ -37,6 +37,7 @@ #include "msg.h" #include "module-template.h" #include "imklog.h" +#include "unicode-helper.h" /* Includes. */ @@ -86,7 +87,7 @@ extern int ksyslog(int type, char *buf, int len); static uchar *GetPath(void) { - return pszPath ? pszPath : _PATH_KLOG; + return pszPath ? pszPath : UCHAR_CONSTANT(_PATH_KLOG); } static void CloseLogSrc(void) @@ -140,7 +141,7 @@ static enum LOGSRC GetKernelLogSrc(void) * file system is available to get kernel messages from. */ if ( use_syscall || - ((stat(GetPath(), &sb) < 0) && (errno == ENOENT)) ) + ((stat((char*)GetPath(), &sb) < 0) && (errno == ENOENT)) ) { /* Initialize kernel logging. */ ksyslog(1, NULL, 0); @@ -149,7 +150,7 @@ static enum LOGSRC GetKernelLogSrc(void) return(kernel); } - if ( (kmsg = open(GetPath(), O_RDONLY|O_CLOEXEC)) < 0 ) + if ( (kmsg = open((char*)GetPath(), O_RDONLY|O_CLOEXEC)) < 0 ) { imklogLogIntMsg(LOG_ERR, "imklog: Cannot open proc file system, %d.\n", errno); ksyslog(7, NULL, 0); /* TODO: check this, implement more */ diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c index 2340aac4..828b9636 100644 --- a/plugins/imudp/imudp.c +++ b/plugins/imudp/imudp.c @@ -43,6 +43,7 @@ #include "msg.h" #include "parser.h" #include "datetime.h" +#include "prop.h" #include "unicode-helper.h" MODULE_TYPE_INPUT @@ -55,6 +56,7 @@ DEFobjCurrIf(errmsg) DEFobjCurrIf(glbl) DEFobjCurrIf(net) DEFobjCurrIf(datetime) +DEFobjCurrIf(prop) static int iMaxLine; /* maximum UDP message size supported */ static time_t ttLastDiscard = 0; /* timestamp when a message from a non-permitted sender was last discarded @@ -68,6 +70,7 @@ static uchar *pRcvBuf = NULL; /* receive buffer (for a single packet). We use a * it so that we can check available memory in willRun() and request * termination if we can not get it. -- rgerhards, 2007-12-27 */ +static prop_t *pInputName = NULL; /* our inputName currently is always "imudp", and this will hold it */ // TODO: static ruleset_t *pBindRuleset = NULL; /* ruleset to bind listener to (use system default if unspecified) */ #define TIME_REQUERY_DFLT 2 static int iTimeRequery = TIME_REQUERY_DFLT;/* how often is time to be queried inside tight recv loop? 0=always */ @@ -242,7 +245,8 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted, /* we now create our own message object and submit it to the queue */ CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime)); MsgSetRawMsg(pMsg, (char*)pRcvBuf, lenRcvBuf); - MsgSetInputName(pMsg, UCHAR_CONSTANT("imudp"), sizeof("imudp")-1); + prop.AddRef(pInputName); + MsgSetInputName(pMsg, pInputName); MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; @@ -338,6 +342,12 @@ ENDrunInput /* initialize and return if will run or not */ BEGINwillRun CODESTARTwillRun + /* we need to create the inputName property (only once during our lifetime) */ + CHKiRet(prop.Construct(&pInputName)); + CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imudp"), sizeof("imudp") - 1)); + CHKiRet(prop.ConstructFinalize(pInputName)); + prop.AddRef(pInputName); + net.PrintAllowedSenders(1); /* UDP */ /* if we could not set up any listners, there is no point in running... */ @@ -365,6 +375,8 @@ CODESTARTafterRun free(pRcvBuf); pRcvBuf = NULL; } + if(pInputName != NULL) + prop.Destruct(&pInputName); ENDafterRun @@ -374,6 +386,7 @@ CODESTARTmodExit objRelease(errmsg, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); objRelease(net, LM_NET_FILENAME); ENDmodExit @@ -405,6 +418,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(net, LM_NET_FILENAME)); /* register config file handlers */ diff --git a/runtime/datetime.c b/runtime/datetime.c index e0f3f5fa..ea67eec5 100644 --- a/runtime/datetime.c +++ b/runtime/datetime.c @@ -556,7 +556,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'; @@ -582,7 +581,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'; @@ -665,7 +663,6 @@ int formatTimestamp3339(struct syslogTime *ts, char* pBuf) BEGINfunc assert(ts != NULL); assert(pBuf != NULL); - assert(iLenBuf >= 33); /* start with fixed parts */ /* year yyyy */ @@ -740,8 +737,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/msg.c b/runtime/msg.c index c4ba18df..47b4ed85 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,26 @@ 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 +} + /* 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,7 +447,6 @@ 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; @@ -444,7 +459,6 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis) pM->pszHOSTNAME = NULL; pM->pszRcvFrom = NULL; pM->pszRcvFromIP = NULL; - pM->pszInputName = NULL; pM->pszRcvdAt3164 = NULL; pM->pszRcvdAt3339 = NULL; pM->pszRcvdAt_MySQL = NULL; @@ -458,6 +472,7 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis) pM->pCSAPPNAME = NULL; pM->pCSPROCID = NULL; pM->pCSMSGID = NULL; + pM->pInputName = NULL; pM->pRuleset = NULL; memset(&pM->tRcvdAt, 0, sizeof(pM->tRcvdAt)); memset(&pM->tTIMESTAMP, 0, sizeof(pM->tTIMESTAMP)); @@ -556,7 +571,8 @@ CODESTARTobjDestruct(msg) free(pThis->pszRawMsg); freeTAG(pThis); freeHOSTNAME(pThis); - free(pThis->pszInputName); + if(pThis->pInputName != NULL) + prop.Destruct(&pThis->pInputName); free(pThis->pszRcvFrom); free(pThis->pszRcvFromIP); free(pThis->pszRcvdAt3164); @@ -719,11 +735,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,7 +764,9 @@ static rsRetVal MsgSerialize(msg_t *pThis, strm_t *pStrm) objSerializePTR(pStrm, pszRawMsg, PSZ); objSerializePTR(pStrm, pszHOSTNAME, PSZ); - objSerializePTR(pStrm, pszInputName, PSZ); + getInputName(pThis, &psz, &len); + objSerializeSCALAR_VAR(pStrm, "pszInputName", PSZ, psz); + //objSerializePTR(pStrm, pszInputName, PSZ); objSerializePTR(pStrm, pszRcvFrom, PSZ); objSerializePTR(pStrm, pszRcvFromIP, PSZ); @@ -1427,18 +1450,6 @@ char *getHOSTNAME(msg_t *pM) } -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) @@ -1598,14 +1609,31 @@ static int getAPPNAMELen(msg_t *pM, bool bLockMutex) /* rgerhards 2008-09-10: set pszInputName in msg object * 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); + + if(pThis->pInputName != NULL) + prop.Destruct(&pThis->pInputName); + pThis->pInputName = inputName; +} + +/* to be removed soon: work-around for those tht can not natively generate an + * input name. + * rgerhards, 2009-06-29 + */ +void MsgSetInputNameStr(msg_t *pThis, uchar *psz, int len) +{ + prop_t *pProp; + assert(pThis != NULL); + + /* we need to create a property */ + prop.Construct(&pProp); + prop.SetString(pProp, psz, len); + prop.ConstructFinalize(pProp); + prop.AddRef(pProp); + MsgSetInputName(pThis, pProp); + prop.Destruct(&pProp); } /* rgerhards 2004-11-16: set pszRcvFrom in msg object @@ -1875,6 +1903,7 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, short iOffs; BEGINfunc +dbgprintf("XXXX: msgGetProp for %d\n", propID); assert(pMsg != NULL); assert(pbMustBeFreed != NULL); @@ -1910,7 +1939,10 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, break; */ case PROP_INPUTNAME: - pRes = (char*) getInputName(pMsg); +RUNLOG; + getInputName(pMsg, ((uchar**) &pRes), &bufLen); +RUNLOG; +RUNLOG_VAR("%p", pRes); break; case PROP_FROMHOST: pRes = (char*) getRcvFrom(pMsg); @@ -2738,6 +2770,7 @@ 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; DEFiRet; ISOBJ_TYPE_assert(pThis, msg); @@ -2765,7 +2798,13 @@ 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)); + prop.AddRef(myProp); + MsgSetInputName(pThis, myProp); + prop.Destruct(&myProp); } else if(isProp("pszRcvFromIP")) { MsgSetRcvFromIP(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr)); } else if(isProp("pszRcvFrom")) { @@ -2790,6 +2829,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 +2873,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..a1fc535b 100644 --- a/runtime/msg.h +++ b/runtime/msg.h @@ -72,7 +72,6 @@ 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 */ @@ -86,7 +85,6 @@ struct msg { 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 +98,7 @@ struct msg { cstr_t *pCSAPPNAME; /* APP-NAME */ cstr_t *pCSPROCID; /* PROCID */ cstr_t *pCSMSGID; /* MSGID */ + prop_t *pInputName; /* input name property */ 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 +143,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); @@ -166,6 +165,12 @@ char *textpri(char *pRes, size_t pResLen, int pri); rsRetVal msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar); rsRetVal MsgEnableThreadSafety(void); + +// REMOVE: +void MsgSetInputNameStr(msg_t *pThis, uchar *psz, int len); + + + /* TODO: remove these five (so far used in action.c) */ char *getMSG(msg_t *pM); char *getHOSTNAME(msg_t *pM); diff --git a/runtime/prop.c b/runtime/prop.c index 02be315f..989657dd 100644 --- a/runtime/prop.c +++ b/runtime/prop.c @@ -36,9 +36,12 @@ #include "config.h" #include #include +#include #include "rsyslog.h" #include "obj.h" +#include "obj-types.h" +#include "atomic.h" #include "prop.h" /* static data */ @@ -48,8 +51,45 @@ DEFobjStaticHelpers /* Standard-Constructor */ BEGINobjConstruct(prop) /* be sure to specify the object type also in END macro! */ + pThis->iRefCount = 1; ENDobjConstruct(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.sz, psz, len + 1); + } + +finalize_it: + RETiRet; +} + + +/* 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,9 +103,29 @@ propConstructFinalize(prop_t __attribute__((unused)) *pThis) } +/* 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; +} + + /* 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 */ +dbgprintf("XXXXX: propDestruct: ptr %p, pThis %p, len %d\n", pThis->szVal.psz, pThis, pThis->len); + if(pThis->len >= CONF_PROP_BUFSIZE) + free(pThis->szVal.psz); + } else { + pThis = NULL; /* tell framework NOT to destructing the object! */ + } ENDobjDestruct(prop) @@ -94,6 +154,9 @@ CODESTARTobjQueryInterface(prop) pIf->ConstructFinalize = propConstructFinalize; pIf->Destruct = propDestruct; pIf->DebugPrint = propDebugPrint; + pIf->SetString = SetString; + pIf->GetString = GetString; + pIf->AddRef = AddRef; finalize_it: ENDobjQueryInterface(prop) diff --git a/runtime/prop.h b/runtime/prop.h index 7fc466b5..1d18c650 100644 --- a/runtime/prop.h +++ b/runtime/prop.h @@ -28,14 +28,23 @@ /* 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); + rsRetVal (*AddRef)(prop_t *pThis); 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..faa74427 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" @@ -150,6 +151,8 @@ rsrtInit(char **ppErrObj, obj_if_t *pObjIF) CHKiRet(glblClassInit(NULL)); if(ppErrObj != NULL) *ppErrObj = "datetime"; CHKiRet(datetimeClassInit(NULL)); + if(ppErrObj != NULL) *ppErrObj = "prop"; + CHKiRet(propClassInit(NULL)); if(ppErrObj != NULL) *ppErrObj = "msg"; CHKiRet(msgClassInit(NULL)); if(ppErrObj != NULL) *ppErrObj = "ctok_token"; diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index 4e0f6e6c..8a043dde 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/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 /** * The dynamic string buffer object. @@ -48,7 +49,6 @@ typedef struct cstr_s uchar *pszBuf; /**< pointer to the sz version of the string (after it has been created )*/ size_t iBufSize; /**< current maximum size of the string buffer */ size_t iStrLen; /**< length of the string in characters. */ - bool bIsForeignBuf; /**< is pBuf a buffer provided by someone else? */ } cstr_t; diff --git a/tcps_sess.c b/tcps_sess.c index e0bec949..4786e154 100644 --- a/tcps_sess.c +++ b/tcps_sess.c @@ -45,6 +45,7 @@ #include "netstrm.h" #include "msg.h" #include "datetime.h" +#include "prop.h" /* static data */ @@ -52,6 +53,7 @@ DEFobjStaticHelpers DEFobjCurrIf(glbl) DEFobjCurrIf(errmsg) DEFobjCurrIf(netstrm) +DEFobjCurrIf(prop) DEFobjCurrIf(datetime) static int iMaxLine; /* maximum size of a single message */ @@ -234,9 +236,9 @@ defaultDoSubmitMessage(tcps_sess_t *pThis, struct syslogTime *stTime, time_t ttG /* we now create our own message object and submit it to the queue */ CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime)); -dbgprintf("defaultDoSubmit, iMsg %d\n", pThis->iMsg); MsgSetRawMsg(pMsg, (char*)pThis->pMsg, pThis->iMsg); - MsgSetInputName(pMsg, pThis->pLstnInfo->pszInputName, pThis->pLstnInfo->lenInputName); + prop.AddRef(pThis->pLstnInfo->pInputName); + MsgSetInputName(pMsg, pThis->pLstnInfo->pInputName); MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; @@ -520,6 +522,7 @@ CODESTARTObjClassExit(tcps_sess) objRelease(errmsg, CORE_COMPONENT); objRelease(netstrm, LM_NETSTRMS_FILENAME); objRelease(datetime, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); ENDObjClassExit(tcps_sess) @@ -532,6 +535,7 @@ BEGINObjClassInit(tcps_sess, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE c CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME)); CHKiRet(objUse(datetime, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); iMaxLine = glbl.GetMaxLine(); /* get maximum size we currently support */ diff --git a/tcpsrv.c b/tcpsrv.c index 119aea91..e8ea2b98 100644 --- a/tcpsrv.c +++ b/tcpsrv.c @@ -89,6 +89,7 @@ DEFobjCurrIf(net) DEFobjCurrIf(netstrms) DEFobjCurrIf(netstrm) DEFobjCurrIf(nssel) +DEFobjCurrIf(prop) /* add new listener port to listener port list @@ -107,8 +108,11 @@ addNewLstnPort(tcpsrv_t *pThis, uchar *pszPort) pEntry->pszPort = pszPort; pEntry->pSrv = pThis; pEntry->pRuleset = pThis->pRuleset; - CHKmalloc(pEntry->pszInputName = ustrdup(pThis->pszInputName)); - pEntry->lenInputName = ustrlen(pEntry->pszInputName); + + /* we need to create a property */ + CHKiRet(prop.Construct(&pEntry->pInputName)); + CHKiRet(prop.SetString(pEntry->pInputName, pThis->pszInputName, ustrlen(pThis->pszInputName))); + CHKiRet(prop.ConstructFinalize(pEntry->pInputName)); /* and add to list */ pEntry->pNext = pThis->pLstnPorts; @@ -250,7 +254,7 @@ static void deinit_tcp_listener(tcpsrv_t *pThis) pEntry = pThis->pLstnPorts; while(pEntry != NULL) { free(pEntry->pszPort); - free(pEntry->pszInputName); + prop.Destruct(&pEntry->pInputName); pDel = pEntry; pEntry = pEntry->pNext; free(pDel); @@ -477,6 +481,7 @@ Run(tcpsrv_t *pThis) * this thread. Thus, we also need to instantiate a cancel cleanup handler * to prevent us from leaking anything. -- rgerharsd, 20080-04-24 */ +RUNLOG_STR("XXXX: tcp server runs\n"); pthread_cleanup_push(RunCancelCleanup, (void*) &pSel); while(1) { CHKiRet(nssel.Construct(&pSel)); @@ -497,6 +502,7 @@ Run(tcpsrv_t *pThis) iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess); } +RUNLOG_STR("XXXX: tcp server select\n"); /* wait for io to become ready */ CHKiRet(nssel.Wait(pSel, &nfds)); @@ -508,6 +514,7 @@ Run(tcpsrv_t *pThis) --nfds; /* indicate we have processed one */ } } +RUNLOG_STR("XXXX: tcp server post select\n"); /* now check the sessions */ iTCPSess = TCPSessGetNxtSess(pThis, -1); @@ -883,6 +890,7 @@ CODESTARTObjClassExit(tcpsrv) /* release objects we no longer need */ objRelease(tcps_sess, DONT_LOAD_LIB); objRelease(conf, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(errmsg, CORE_COMPONENT); @@ -908,6 +916,7 @@ BEGINObjClassInit(tcpsrv, 1, OBJ_IS_LOADABLE_MODULE) /* class, version - CHANGE CHKiRet(objUse(conf, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, tcpsrvDebugPrint); diff --git a/tcpsrv.h b/tcpsrv.h index e2170bef..70682398 100644 --- a/tcpsrv.h +++ b/tcpsrv.h @@ -23,6 +23,7 @@ #define INCLUDED_TCPSRV_H #include "obj.h" +#include "prop.h" #include "tcps_sess.h" /* support for framing anomalies */ @@ -36,8 +37,7 @@ typedef enum ETCPsyslogFramingAnomaly { /* list of tcp listen ports */ struct tcpLstnPortList_s { uchar *pszPort; /**< the ports the listener shall listen on */ - uchar *pszInputName; /**< value to be used as input name */ - size_t lenInputName; /**< length of inputName */ + prop_t *pInputName; tcpsrv_t *pSrv; /**< pointer to higher-level server instance */ ruleset_t *pRuleset; /**< associated ruleset */ tcpLstnPortList_t *pNext; /**< next port or NULL */ diff --git a/tests/nettester.c b/tests/nettester.c index c9a978c5..dbfb4db3 100644 --- a/tests/nettester.c +++ b/tests/nettester.c @@ -128,11 +128,12 @@ tcpSend(char *buf, int lenBuf) if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) { break; } else { - if(retries++ == 3) { + if(retries++ == 30) { + ++iFailed; fprintf(stderr, "connect() failed\n"); return(1); } else { - sleep(1); + usleep(100); } } } diff --git a/tools/syslogd.c b/tools/syslogd.c index 3204d94e..2fe949ac 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -580,7 +580,7 @@ static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int f CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime)); } if(pszInputName != NULL) - MsgSetInputName(pMsg, pszInputName, ustrlen(pszInputName)); + MsgSetInputNameStr(pMsg, pszInputName, ustrlen(pszInputName)); MsgSetFlowControlType(pMsg, flowCtlType); MsgSetRawMsgWOSize(pMsg, (char*)msg); @@ -881,7 +881,7 @@ logmsgInternal(int iErr, int pri, uchar *msg, int flags) DEFiRet; CHKiRet(msgConstruct(&pMsg)); - MsgSetInputName(pMsg, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslogd")-1); + MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslogd")-1); MsgSetRawMsgWOSize(pMsg, (char*)msg); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetRcvFrom(pMsg, glbl.GetLocalHostName()); @@ -2089,6 +2089,7 @@ runInputModules(void) { modInfo_t *pMod; + BEGINfunc /* loop through all modules and activate them (brr...) */ pMod = module.GetNxtType(NULL, eMOD_IN); while(pMod != NULL) { -- cgit From e397c34d2a6c7c1e4c116fd2363cb173e32eb2a2 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 30 Jun 2009 15:21:15 +0200 Subject: finished transition to using inputName property ... plus some celanup and adding minor missing functionality (the rule debug info again tell the property name, not just number). --- dirty.h | 2 +- plugins/imdiag/imdiag.c | 14 ++- plugins/imfile/imfile.c | 15 ++- plugins/imklog/imklog.c | 19 ++- plugins/imrelp/imrelp.c | 18 ++- plugins/imudp/imudp.c | 2 - plugins/imuxsock/imuxsock.c | 18 ++- runtime/msg.c | 273 ++++++++++++++++++++++++++++---------------- runtime/msg.h | 6 +- runtime/rule.c | 7 +- tcps_sess.c | 1 - tools/syslogd.c | 46 ++++---- 12 files changed, 278 insertions(+), 143 deletions(-) diff --git a/dirty.h b/dirty.h index 8a0cbc80..0153cb69 100644 --- a/dirty.h +++ b/dirty.h @@ -30,7 +30,7 @@ rsRetVal multiSubmitMsg(multi_submit_t *pMultiSub); rsRetVal submitMsg(msg_t *pMsg); rsRetVal logmsgInternal(int iErr, int pri, uchar *msg, int flags); -rsRetVal parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int flags, flowControl_t flowCtlTypeu, uchar *pszInputName, struct syslogTime *stTime, time_t ttGenTime); +rsRetVal parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int flags, flowControl_t flowCtlTypeu, prop_t *pInputName, struct syslogTime *stTime, time_t ttGenTime); int parseRFCSyslogMsg(msg_t *pMsg, int flags); int parseLegacySyslogMsg(msg_t *pMsg, int flags); rsRetVal diagGetMainMsgQSize(int *piSize); /* for imdiag */ diff --git a/plugins/imdiag/imdiag.c b/plugins/imdiag/imdiag.c index 4b004bc4..8d874a87 100644 --- a/plugins/imdiag/imdiag.c +++ b/plugins/imdiag/imdiag.c @@ -66,10 +66,12 @@ DEFobjCurrIf(net) DEFobjCurrIf(netstrm) DEFobjCurrIf(errmsg) DEFobjCurrIf(datetime) +DEFobjCurrIf(prop) /* Module static data */ static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change for multiple instances */ static permittedPeers_t *pPermPeersRoot = NULL; +static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */ /* config settings */ @@ -206,7 +208,7 @@ doInjectMsg(int iNum) /* we now create our own message object and submit it to the queue */ CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime)); MsgSetRawMsg(pMsg, (char*) szMsg, ustrlen(szMsg)); - MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("imdiag"), sizeof("imdiag")-1); + MsgSetInputName(pMsg, pInputName); MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; @@ -376,13 +378,19 @@ CODESTARTwillRun /* first apply some config settings */ if(pOurTcpsrv == NULL) ABORT_FINALIZE(RS_RET_NO_RUN); + /* we need to create the inputName property (only once during our lifetime) */ + CHKiRet(prop.Construct(&pInputName)); + CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imdiag"), sizeof("imdiag") - 1)); + CHKiRet(prop.ConstructFinalize(pInputName)); + finalize_it: ENDwillRun BEGINafterRun CODESTARTafterRun - /* do cleanup here */ + if(pInputName != NULL) + prop.Destruct(&pInputName); ENDafterRun @@ -402,6 +410,7 @@ CODESTARTmodExit objRelease(tcpsrv, LM_TCPSRV_FILENAME); objRelease(errmsg, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); ENDmodExit @@ -439,6 +448,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(tcpsrv, LM_TCPSRV_FILENAME)); CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); /* register config file handlers */ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("imdiagserverrun"), 0, eCmdHdlrGetWord, diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index fdd0c5f0..7c588f90 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -46,6 +46,7 @@ #include "glbl.h" #include "datetime.h" #include "unicode-helper.h" +#include "prop.h" MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ @@ -57,6 +58,7 @@ DEFobjCurrIf(errmsg) DEFobjCurrIf(glbl) DEFobjCurrIf(datetime) DEFobjCurrIf(strm) +DEFobjCurrIf(prop) typedef struct fileInfo_s { uchar *pszFileName; @@ -81,6 +83,7 @@ static int iFilPtr = 0; /* number of files to be monitored; pointer to next fre #define MAX_INPUT_FILES 100 static fileInfo_t files[MAX_INPUT_FILES]; +static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */ /* enqueue the read file line as a message. The provided string is * not freed - thuis must be done by the caller. @@ -97,7 +100,7 @@ static rsRetVal enqLine(fileInfo_t *pInfo, cstr_t *cstrLine) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); - MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("imfile"), sizeof("imfile")-1); + MsgSetInputName(pMsg, pInputName); MsgSetRawMsg(pMsg, (char*)rsCStrGetSzStr(cstrLine), cstrLen(cstrLine)); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); @@ -336,6 +339,11 @@ CODESTARTwillRun ABORT_FINALIZE(RS_RET_NO_RUN); } + /* we need to create the inputName property (only once during our lifetime) */ + CHKiRet(prop.Construct(&pInputName)); + CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imfile"), sizeof("imfile") - 1)); + CHKiRet(prop.ConstructFinalize(pInputName)); + finalize_it: ENDwillRun @@ -391,6 +399,9 @@ CODESTARTafterRun strm.Destruct(&(files[i].pStrm)); } } + + if(pInputName != NULL) + prop.Destruct(&pInputName); ENDafterRun @@ -405,6 +416,7 @@ CODESTARTmodExit objRelease(datetime, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(errmsg, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); ENDmodExit @@ -515,6 +527,7 @@ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(strm, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index 21744c4b..10cc8b14 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -18,7 +18,7 @@ * Please note that this file replaces the klogd daemon that was * also present in pre-v3 versions of rsyslog. * - * Copyright (C) 2008 by Rainer Gerhards and Adiscon GmbH + * Copyright (C) 2008, 2009 by Rainer Gerhards and Adiscon GmbH * * This file is part of rsyslog. * @@ -54,6 +54,7 @@ #include "datetime.h" #include "imklog.h" #include "glbl.h" +#include "prop.h" #include "unicode-helper.h" MODULE_TYPE_INPUT @@ -62,6 +63,7 @@ MODULE_TYPE_INPUT DEF_IMOD_STATIC_DATA DEFobjCurrIf(datetime) DEFobjCurrIf(glbl) +DEFobjCurrIf(prop) /* configuration settings */ int dbgPrintSymbols = 0; /* this one is extern so the helpers can access it! */ @@ -81,6 +83,8 @@ char *symfile = NULL; int console_log_level = -1; +static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this module */ + /* enqueue the the kernel message into the message queue. * The provided msg string is not freed - thus must be done * by the caller. @@ -97,7 +101,7 @@ enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity) CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); - MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("imklog"), sizeof("imklog")-1); + MsgSetInputName(pMsg, pInputName); MsgSetRawMsgWOSize(pMsg, (char*)msg); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetRcvFrom(pMsg, glbl.GetLocalHostName()); @@ -230,13 +234,22 @@ ENDrunInput BEGINwillRun CODESTARTwillRun + /* we need to create the inputName property (only once during our lifetime) */ + CHKiRet(prop.Construct(&pInputName)); + CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imklog"), sizeof("imklog") - 1)); + CHKiRet(prop.ConstructFinalize(pInputName)); + iRet = klogWillRun(); +finalize_it: ENDwillRun BEGINafterRun CODESTARTafterRun iRet = klogAfterRun(); + + if(pInputName != NULL) + prop.Destruct(&pInputName); ENDafterRun @@ -245,6 +258,7 @@ CODESTARTmodExit /* release objects we used */ objRelease(glbl, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); if(pszPath != NULL) free(pszPath); ENDmodExit @@ -277,6 +291,7 @@ CODESTARTmodInit CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); iFacilIntMsg = klogFacilIntMsg(); diff --git a/plugins/imrelp/imrelp.c b/plugins/imrelp/imrelp.c index 2255e643..b9e7b2f8 100644 --- a/plugins/imrelp/imrelp.c +++ b/plugins/imrelp/imrelp.c @@ -4,7 +4,7 @@ * * File begun on 2008-03-13 by RGerhards * - * Copyright 2008 Rainer Gerhards and Adiscon GmbH. + * Copyright 2008, 2009 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * @@ -43,15 +43,19 @@ #include "module-template.h" #include "net.h" #include "msg.h" +#include "unicode-helper.h" +#include "prop.h" MODULE_TYPE_INPUT /* static data */ DEF_IMOD_STATIC_DATA DEFobjCurrIf(net) +DEFobjCurrIf(prop) /* Module static data */ static relpEngine_t *pRelpEngine; /* our relp engine */ +static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this module */ /* config settings */ @@ -85,7 +89,7 @@ onSyslogRcv(uchar *pHostname, uchar __attribute__((unused)) *pIP, uchar *pMsg, s { DEFiRet; parseAndSubmitMessage(pHostname, (uchar*) "[unset]", pMsg, lenMsg, PARSE_HOSTNAME, - eFLOWCTL_LIGHT_DELAY, (uchar*)"imrelp", NULL, 0); + eFLOWCTL_LIGHT_DELAY, pInputName, NULL, 0); RETiRet; } @@ -130,6 +134,11 @@ CODESTARTwillRun //net.PrintAllowedSenders(2); /* TCP */ if(pRelpEngine == NULL) ABORT_FINALIZE(RS_RET_NO_RUN); + + /* we need to create the inputName property (only once during our lifetime) */ + CHKiRet(prop.Construct(&pInputName)); + CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imrelp"), sizeof("imrelp") - 1)); + CHKiRet(prop.ConstructFinalize(pInputName)); finalize_it: ENDwillRun @@ -143,6 +152,9 @@ CODESTARTafterRun net.pAllowedSenders_TCP = NULL; } #endif + + if(pInputName != NULL) + prop.Destruct(&pInputName); ENDafterRun @@ -152,6 +164,7 @@ CODESTARTmodExit iRet = relpEngineDestruct(&pRelpEngine); /* release objects we used */ + objRelease(prop, CORE_COMPONENT); objRelease(net, LM_NET_FILENAME); ENDmodExit @@ -177,6 +190,7 @@ CODESTARTmodInit CODEmodInit_QueryRegCFSLineHdlr pRelpEngine = NULL; /* request objects we use */ + CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(net, LM_NET_FILENAME)); /* register config file handlers */ diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c index 828b9636..dcdec1fc 100644 --- a/plugins/imudp/imudp.c +++ b/plugins/imudp/imudp.c @@ -245,7 +245,6 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted, /* we now create our own message object and submit it to the queue */ CHKiRet(msgConstructWithTime(&pMsg, &stTime, ttGenTime)); MsgSetRawMsg(pMsg, (char*)pRcvBuf, lenRcvBuf); - prop.AddRef(pInputName); MsgSetInputName(pMsg, pInputName); MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; @@ -346,7 +345,6 @@ CODESTARTwillRun CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imudp"), sizeof("imudp") - 1)); CHKiRet(prop.ConstructFinalize(pInputName)); - prop.AddRef(pInputName); net.PrintAllowedSenders(1); /* UDP */ diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c index 1d88a2b5..424d0904 100644 --- a/plugins/imuxsock/imuxsock.c +++ b/plugins/imuxsock/imuxsock.c @@ -37,12 +37,14 @@ #include #include "dirty.h" #include "cfsysline.h" +#include "unicode-helper.h" #include "module-template.h" #include "srUtils.h" #include "errmsg.h" #include "net.h" #include "glbl.h" #include "msg.h" +#include "prop.h" MODULE_TYPE_INPUT @@ -66,7 +68,9 @@ MODULE_TYPE_INPUT DEF_IMOD_STATIC_DATA DEFobjCurrIf(errmsg) DEFobjCurrIf(glbl) +DEFobjCurrIf(prop) +static prop_t *pInputName = NULL; /* our inputName currently is always "imudp", and this will hold it */ static int startIndexUxLocalSockets; /* process funix from that index on (used to * suppress local logging. rgerhards 2005-08-01 * read-only after startup @@ -223,7 +227,7 @@ static rsRetVal readSocket(int fd, int iSock) parseAndSubmitMessage(funixHName[iSock] == NULL ? glbl.GetLocalHostName() : funixHName[iSock], (uchar*)"127.0.0.1", pRcv, iRcvd, funixParseHost[iSock] ? (funixFlags[iSock] | PARSE_HOSTNAME) : funixFlags[iSock], - funixFlowCtl[iSock], (uchar*)"imuxsock", NULL, 0); + funixFlowCtl[iSock], pInputName, NULL, 0); } else if (iRcvd < 0 && errno != EINTR) { char errStr[1024]; rs_strerror_r(errno, errStr, sizeof(errStr)); @@ -306,7 +310,12 @@ CODESTARTwillRun dbgprintf("Opened UNIX socket '%s' (fd %d).\n", funixn[i], funix[i]); } - RETiRet; + /* we need to create the inputName property (only once during our lifetime) */ + CHKiRet(prop.Construct(&pInputName)); + CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imudp"), sizeof("imudp") - 1)); + CHKiRet(prop.ConstructFinalize(pInputName)); + +finalize_it: ENDwillRun @@ -332,6 +341,9 @@ CODESTARTafterRun discardFunixn(); nfunix = 1; + + if(pInputName != NULL) + prop.Destruct(&pInputName); ENDafterRun @@ -339,6 +351,7 @@ BEGINmodExit CODESTARTmodExit objRelease(glbl, CORE_COMPONENT); objRelease(errmsg, CORE_COMPONENT); + objRelease(prop, CORE_COMPONENT); ENDmodExit @@ -375,6 +388,7 @@ CODESTARTmodInit CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(errmsg, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); + CHKiRet(objUse(prop, CORE_COMPONENT)); dbgprintf("imuxsock version %s initializing\n", PACKAGE_VERSION); diff --git a/runtime/msg.c b/runtime/msg.c index 47b4ed85..fd0cbcdc 100644 --- a/runtime/msg.c +++ b/runtime/msg.c @@ -295,6 +295,175 @@ getInputName(msg_t *pM, uchar **ppsz, int *plen) ENDfunc } + +/* 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 @@ -1606,18 +1775,22 @@ 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 *pThis, prop_t *inputName) { assert(pThis != NULL); + prop.AddRef(inputName); if(pThis->pInputName != NULL) prop.Destruct(&pThis->pInputName); pThis->pInputName = inputName; } +#if 0 /* to be removed soon: work-around for those tht can not natively generate an * input name. * rgerhards, 2009-06-29 @@ -1635,6 +1808,7 @@ void MsgSetInputNameStr(msg_t *pThis, uchar *psz, int len) MsgSetInputName(pThis, pProp); prop.Destruct(&pProp); } +#endif /* rgerhards 2004-11-16: set pszRcvFrom in msg object */ @@ -1903,7 +2077,7 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, short iOffs; BEGINfunc -dbgprintf("XXXX: msgGetProp for %d\n", propID); +dbgprintf("XXXX: msgGetProp for %s\n", propIDToName(propID)); assert(pMsg != NULL); assert(pbMustBeFreed != NULL); @@ -1939,10 +2113,7 @@ dbgprintf("XXXX: msgGetProp for %d\n", propID); break; */ case PROP_INPUTNAME: -RUNLOG; getInputName(pMsg, ((uchar**) &pRes), &bufLen); -RUNLOG; -RUNLOG_VAR("%p", pRes); break; case PROP_FROMHOST: pRes = (char*) getRcvFrom(pMsg); @@ -2670,97 +2841,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 @@ -2802,7 +2882,6 @@ rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp) CHKiRet(prop.Construct(&myProp)); CHKiRet(prop.SetString(myProp, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr))); CHKiRet(prop.ConstructFinalize(myProp)); - prop.AddRef(myProp); MsgSetInputName(pThis, myProp); prop.Destruct(&myProp); } else if(isProp("pszRcvFromIP")) { diff --git a/runtime/msg.h b/runtime/msg.h index a1fc535b..7f84da35 100644 --- a/runtime/msg.h +++ b/runtime/msg.h @@ -166,11 +166,6 @@ rsRetVal msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar); rsRetVal MsgEnableThreadSafety(void); -// REMOVE: -void MsgSetInputNameStr(msg_t *pThis, uchar *psz, int len); - - - /* TODO: remove these five (so far used in action.c) */ char *getMSG(msg_t *pM); char *getHOSTNAME(msg_t *pM); @@ -184,6 +179,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/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/tcps_sess.c b/tcps_sess.c index 4786e154..23241f4f 100644 --- a/tcps_sess.c +++ b/tcps_sess.c @@ -237,7 +237,6 @@ defaultDoSubmitMessage(tcps_sess_t *pThis, struct syslogTime *stTime, time_t ttG /* we now create our own message object and submit it to the queue */ CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime)); MsgSetRawMsg(pMsg, (char*)pThis->pMsg, pThis->iMsg); - prop.AddRef(pThis->pLstnInfo->pInputName); MsgSetInputName(pMsg, pThis->pLstnInfo->pInputName); MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; diff --git a/tools/syslogd.c b/tools/syslogd.c index 2fe949ac..f1c43602 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -140,6 +140,7 @@ #include "rule.h" #include "net.h" #include "vm.h" +#include "prop.h" /* definitions for objects we access */ DEFobjCurrIf(obj) @@ -151,25 +152,13 @@ DEFobjCurrIf(module) DEFobjCurrIf(errmsg) DEFobjCurrIf(rule) DEFobjCurrIf(ruleset) +DEFobjCurrIf(prop) DEFobjCurrIf(net) /* TODO: make go away! */ /* forward definitions */ static rsRetVal GlobalClassExit(void); -/* We define our own set of syslog defintions so that we - * do not need to rely on (possibly different) implementations. - * 2007-07-19 rgerhards - */ -/* missing definitions for solaris - * 2006-02-16 Rger - */ -#ifdef __sun -# define LOG_AUTHPRIV LOG_AUTH -#endif -#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */ -#define LOG_FTP (11<<3) /* ftp daemon */ - #ifndef UTMP_FILE #ifdef UTMP_FILENAME @@ -217,14 +206,11 @@ static rsRetVal GlobalClassExit(void); # endif #endif -#ifndef _PATH_DEV -# define _PATH_DEV "/dev/" -#endif - #ifndef _PATH_TTY # define _PATH_TTY "/dev/tty" #endif +static prop_t *pInternalInputName = NULL; /* there is only one global inputName for all internally-generated messages */ static uchar *ConfFile = (uchar*) _PATH_LOGCONF; /* read-only after startup */ static char *PidFile = _PATH_LOGPID; /* read-only after startup */ @@ -566,7 +552,7 @@ void untty(void) * interface change: bParseHostname removed, now in flags */ static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int flags, flowControl_t flowCtlType, - uchar *pszInputName, struct syslogTime *stTime, time_t ttGenTime) + prop_t *pInputName, struct syslogTime *stTime, time_t ttGenTime) { DEFiRet; register uchar *p; @@ -579,8 +565,8 @@ static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int f } else { CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime)); } - if(pszInputName != NULL) - MsgSetInputNameStr(pMsg, pszInputName, ustrlen(pszInputName)); + if(pInputName != NULL) + MsgSetInputName(pMsg, pInputName); MsgSetFlowControlType(pMsg, flowCtlType); MsgSetRawMsgWOSize(pMsg, (char*)msg); @@ -675,7 +661,7 @@ finalize_it: */ rsRetVal parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int flags, flowControl_t flowCtlType, - uchar *pszInputName, struct syslogTime *stTime, time_t ttGenTime) + prop_t *pInputName, struct syslogTime *stTime, time_t ttGenTime) { DEFiRet; register int iMsg; @@ -786,7 +772,7 @@ parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int fla */ if(iMsg == iMaxLine) { *(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */ - printline(hname, hnameIP, tmpline, flags, flowCtlType, pszInputName, stTime, ttGenTime); + printline(hname, hnameIP, tmpline, flags, flowCtlType, pInputName, stTime, ttGenTime); } else { /* This case in theory never can happen. If it happens, we have * a logic error. I am checking for it, because if I would not, @@ -838,7 +824,7 @@ parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int fla *(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */ /* typically, we should end up here! */ - printline(hname, hnameIP, tmpline, flags, flowCtlType, pszInputName, stTime, ttGenTime); + printline(hname, hnameIP, tmpline, flags, flowCtlType, pInputName, stTime, ttGenTime); finalize_it: if(tmpline != NULL) @@ -881,7 +867,7 @@ logmsgInternal(int iErr, int pri, uchar *msg, int flags) DEFiRet; CHKiRet(msgConstruct(&pMsg)); - MsgSetInputNameStr(pMsg, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslogd")-1); + MsgSetInputName(pMsg, pInternalInputName); MsgSetRawMsgWOSize(pMsg, (char*)msg); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetRcvFrom(pMsg, glbl.GetLocalHostName()); @@ -1711,6 +1697,10 @@ die(int sig) legacyOptsFree(); + /* destruct our input name */ + if(pInternalInputName != NULL) + prop.Destruct(&pInternalInputName); + /* terminate the remaining classes */ GlobalClassExit(); @@ -2867,6 +2857,8 @@ InitGlobalClasses(void) CHKiRet(objUse(ruleset, CORE_COMPONENT)); pErrObj = "conf"; CHKiRet(objUse(conf, CORE_COMPONENT)); + pErrObj = "prop"; + CHKiRet(objUse(prop, CORE_COMPONENT)); /* intialize some dummy classes that are not part of the runtime */ pErrObj = "action"; @@ -2907,6 +2899,7 @@ GlobalClassExit(void) /* first, release everything we used ourself */ objRelease(net, LM_NET_FILENAME);/* TODO: the dependency on net shall go away! -- rgerhards, 2008-03-07 */ + objRelease(prop, CORE_COMPONENT); objRelease(conf, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); objRelease(rule, CORE_COMPONENT); @@ -3213,6 +3206,11 @@ int realMain(int argc, char **argv) /* doing some core initializations */ + /* we need to create the inputName property (only once during our lifetime) */ + CHKiRet(prop.Construct(&pInternalInputName)); + CHKiRet(prop.SetString(pInternalInputName, UCHAR_CONSTANT("rsyslgod"), sizeof("rsyslgod") - 1)); + CHKiRet(prop.ConstructFinalize(pInternalInputName)); + /* get our host and domain names - we need to do this early as we may emit * error log messages, which need the correct hostname. -- rgerhards, 2008-04-04 */ -- cgit From aaffc4281e0b26f419a3fc341461f2fc479080b8 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 30 Jun 2009 18:45:41 +0200 Subject: introduced a new way of handling the RcvFrom property ... plus a fix for a long-time bug in obj-types.h. That lead to the object pointer only then to become NULL 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. --- plugins/imdiag/imdiag.c | 9 ++++- plugins/imklog/imklog.c | 2 +- plugins/imudp/imudp.c | 2 +- runtime/glbl.c | 46 +++++++++++++++++++++++++ runtime/glbl.h | 7 +++- runtime/msg.c | 91 ++++++++++++++++++++++++++++--------------------- runtime/msg.h | 7 ++-- runtime/obj-types.h | 11 +++++- runtime/parser.c | 2 +- runtime/prop.c | 18 +++++++--- runtime/prop.h | 1 + runtime/rsyslog.c | 4 +-- tcps_sess.c | 18 +++++++--- tcps_sess.h | 3 +- tools/syslogd.c | 8 +++-- 15 files changed, 168 insertions(+), 61 deletions(-) diff --git a/plugins/imdiag/imdiag.c b/plugins/imdiag/imdiag.c index 8d874a87..140222e1 100644 --- a/plugins/imdiag/imdiag.c +++ b/plugins/imdiag/imdiag.c @@ -72,6 +72,7 @@ DEFobjCurrIf(prop) static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change for multiple instances */ static permittedPeers_t *pPermPeersRoot = NULL; static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */ +static prop_t *pRcvDummy = NULL; /* config settings */ @@ -212,7 +213,7 @@ doInjectMsg(int iNum) MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; - MsgSetRcvFrom(pMsg, UCHAR_CONSTANT("127.0.0.1")); /* TODO: way may use the real sender here... */ + MsgSetRcvFrom(pMsg, pRcvDummy); CHKiRet(MsgSetRcvFromIP(pMsg, UCHAR_CONSTANT("127.0.0.1"))); CHKiRet(submitMsg(pMsg)); @@ -383,6 +384,10 @@ CODESTARTwillRun CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imdiag"), sizeof("imdiag") - 1)); CHKiRet(prop.ConstructFinalize(pInputName)); + CHKiRet(prop.Construct(&pRcvDummy)); + CHKiRet(prop.SetString(pRcvDummy, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1)); + CHKiRet(prop.ConstructFinalize(pRcvDummy)); + finalize_it: ENDwillRun @@ -391,6 +396,8 @@ BEGINafterRun CODESTARTafterRun if(pInputName != NULL) prop.Destruct(&pInputName); + if(pRcvDummy != NULL) + prop.Destruct(&pRcvDummy); ENDafterRun diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index 10cc8b14..e4db03b3 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -104,7 +104,7 @@ enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity) MsgSetInputName(pMsg, pInputName); MsgSetRawMsgWOSize(pMsg, (char*)msg); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ - MsgSetRcvFrom(pMsg, glbl.GetLocalHostName()); + MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp()); MsgSetRcvFromIP(pMsg, (uchar*)"127.0.0.1"); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetTAG(pMsg, pszTag, ustrlen(pszTag)); diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c index dcdec1fc..e091c7d6 100644 --- a/plugins/imudp/imudp.c +++ b/plugins/imudp/imudp.c @@ -249,7 +249,7 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted, MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; - MsgSetRcvFrom(pMsg, fromHost); + MsgSetRcvFromStr(pMsg, fromHost, ustrlen(fromHost)); CHKiRet(MsgSetRcvFromIP(pMsg, fromHostIP)); CHKiRet(submitMsg(pMsg)); } 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/msg.c b/runtime/msg.c index fd0cbcdc..3eb41a87 100644 --- a/runtime/msg.c +++ b/runtime/msg.c @@ -622,11 +622,9 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis) 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->pszRcvdAt3164 = NULL; pM->pszRcvdAt3339 = NULL; @@ -642,6 +640,7 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis) pM->pCSPROCID = NULL; pM->pCSMSGID = NULL; pM->pInputName = NULL; + pM->pRcvFrom = NULL; pM->pRuleset = NULL; memset(&pM->tRcvdAt, 0, sizeof(pM->tRcvdAt)); memset(&pM->tTIMESTAMP, 0, sizeof(pM->tTIMESTAMP)); @@ -742,8 +741,8 @@ CODESTARTobjDestruct(msg) freeHOSTNAME(pThis); if(pThis->pInputName != NULL) prop.Destruct(&pThis->pInputName); - free(pThis->pszRcvFrom); - free(pThis->pszRcvFromIP); + if(pThis->pRcvFrom != NULL) + prop.Destruct(&pThis->pRcvFrom); free(pThis->pszRcvdAt3164); free(pThis->pszRcvdAt3339); free(pThis->pszRcvdAt_MySQL); @@ -844,6 +843,10 @@ 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->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; @@ -871,7 +874,6 @@ msg_t* MsgDup(msg_t* pOld) } else { tmpCOPYSZ(HOSTNAME); } - tmpCOPYSZ(RcvFrom); tmpCOPYCSTR(ProgName); tmpCOPYCSTR(StrucData); @@ -935,8 +937,8 @@ static rsRetVal MsgSerialize(msg_t *pThis, strm_t *pStrm) objSerializePTR(pStrm, pszHOSTNAME, PSZ); getInputName(pThis, &psz, &len); objSerializeSCALAR_VAR(pStrm, "pszInputName", PSZ, psz); - //objSerializePTR(pStrm, pszInputName, PSZ); - objSerializePTR(pStrm, pszRcvFrom, PSZ); + psz = getRcvFrom(pThis); + objSerializeSCALAR_VAR(pStrm, "pszRcvFrom", PSZ, psz); objSerializePTR(pStrm, pszRcvFromIP, PSZ); objSerializePTR(pStrm, pCSStrucData, CSTR); @@ -1601,7 +1603,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; } @@ -1612,22 +1617,33 @@ 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; + } } uchar *getRcvFrom(msg_t *pM) { - if(pM == NULL) - return UCHAR_CONSTANT(""); - else - if(pM->pszRcvFrom == NULL) - return UCHAR_CONSTANT(""); - else - return pM->pszRcvFrom; + uchar *psz; + int len; + BEGINfunc + if(pM == NULL) { + psz = UCHAR_CONSTANT(""); + } else { + prop.GetString(pM->pInputName, &psz, &len); + } + ENDfunc + return psz; } @@ -1790,12 +1806,27 @@ void MsgSetInputName(msg_t *pThis, prop_t *inputName) pThis->pInputName = inputName; } -#if 0 + +/* 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 *pThis, prop_t *new) +{ + assert(pThis != NULL); + + prop.AddRef(new); + if(pThis->pRcvFrom != NULL) + prop.Destruct(&pThis->pRcvFrom); + pThis->pRcvFrom = new; +} + /* to be removed soon: work-around for those tht can not natively generate an * input name. * rgerhards, 2009-06-29 */ -void MsgSetInputNameStr(msg_t *pThis, uchar *psz, int len) +void MsgSetRcvFromStr(msg_t *pThis, uchar *psz, int len) { prop_t *pProp; assert(pThis != NULL); @@ -1804,24 +1835,9 @@ void MsgSetInputNameStr(msg_t *pThis, uchar *psz, int len) prop.Construct(&pProp); prop.SetString(pProp, psz, len); prop.ConstructFinalize(pProp); - prop.AddRef(pProp); - MsgSetInputName(pThis, pProp); + MsgSetRcvFrom(pThis, pProp); prop.Destruct(&pProp); } -#endif - -/* rgerhards 2004-11-16: set pszRcvFrom in msg object - */ -void MsgSetRcvFrom(msg_t *pMsg, uchar* pszRcvFrom) -{ - assert(pMsg != NULL); - free(pMsg->pszRcvFrom); - - pMsg->iLenRcvFrom = ustrlen(pszRcvFrom); - if((pMsg->pszRcvFrom = malloc(pMsg->iLenRcvFrom + 1)) != NULL) { - memcpy(pMsg->pszRcvFrom, pszRcvFrom, pMsg->iLenRcvFrom + 1); - } -} /* rgerhards 2005-05-16: set pszRcvFromIP in msg object */ @@ -2077,7 +2093,6 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, short iOffs; BEGINfunc -dbgprintf("XXXX: msgGetProp for %s\n", propIDToName(propID)); assert(pMsg != NULL); assert(pbMustBeFreed != NULL); @@ -2887,7 +2902,7 @@ rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp) } else if(isProp("pszRcvFromIP")) { MsgSetRcvFromIP(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr)); } else if(isProp("pszRcvFrom")) { - MsgSetRcvFrom(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr)); + MsgSetRcvFromStr(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr)); } else if(isProp("pszHOSTNAME")) { MsgSetHOSTNAME(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr)); } else if(isProp("pCSStrucData")) { diff --git a/runtime/msg.h b/runtime/msg.h index 7f84da35..59046fc1 100644 --- a/runtime/msg.h +++ b/runtime/msg.h @@ -78,12 +78,10 @@ struct msg { 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 */ char *pszRcvdAt3164; /* time as RFC3164 formatted string (always 15 charcters) */ char *pszRcvdAt3339; /* time as RFC3164 formatted string (32 charcters at most) */ @@ -99,6 +97,7 @@ struct msg { cstr_t *pCSPROCID; /* PROCID */ cstr_t *pCSMSGID; /* MSGID */ prop_t *pInputName; /* input name property */ + prop_t *pRcvFrom; /* name 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 @@ -151,7 +150,8 @@ 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); +void MsgSetRcvFrom(msg_t *pMsg, prop_t*); +void MsgSetRcvFromStr(msg_t *pMsg, uchar* pszRcvFrom, int); rsRetVal MsgSetRcvFromIP(msg_t *pMsg, uchar* pszRcvFromIP); void MsgSetHOSTNAME(msg_t *pMsg, uchar* pszHOSTNAME, int lenHOSTNAME); rsRetVal MsgSetAfterPRIOffs(msg_t *pMsg, short offs); @@ -164,6 +164,7 @@ 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) */ 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 989657dd..96ebe212 100644 --- a/runtime/prop.c +++ b/runtime/prop.c @@ -68,7 +68,7 @@ static rsRetVal SetString(prop_t *pThis, uchar *psz, int len) memcpy(pThis->szVal.sz, psz, len + 1); } else { CHKmalloc(pThis->szVal.psz = malloc(len + 1)); - memcpy(pThis->szVal.sz, psz, len + 1); + memcpy(pThis->szVal.psz, psz, len + 1); } finalize_it: @@ -76,15 +76,25 @@ finalize_it: } +/* 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) + if(pThis->len < CONF_PROP_BUFSIZE) { *ppsz = pThis->szVal.sz; - else +RUNLOG; + } else { *ppsz = pThis->szVal.psz; +RUNLOG; + } *plen = pThis->len; ENDfunc return RS_RET_OK; @@ -120,7 +130,6 @@ CODESTARTobjDestruct(prop) currRefCount = ATOMIC_DEC_AND_FETCH(pThis->iRefCount); if(currRefCount == 0) { /* (only) in this case we need to actually destruct the object */ -dbgprintf("XXXXX: propDestruct: ptr %p, pThis %p, len %d\n", pThis->szVal.psz, pThis, pThis->len); if(pThis->len >= CONF_PROP_BUFSIZE) free(pThis->szVal.psz); } else { @@ -156,6 +165,7 @@ CODESTARTobjQueryInterface(prop) pIf->DebugPrint = propDebugPrint; pIf->SetString = SetString; pIf->GetString = GetString; + pIf->GetStringLen = GetStringLen; pIf->AddRef = AddRef; finalize_it: diff --git a/runtime/prop.h b/runtime/prop.h index 1d18c650..62c0d799 100644 --- a/runtime/prop.h +++ b/runtime/prop.h @@ -44,6 +44,7 @@ BEGINinterface(prop) /* name must also be changed in ENDinterface macro! */ 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); 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 faa74427..443d0f41 100644 --- a/runtime/rsyslog.c +++ b/runtime/rsyslog.c @@ -147,12 +147,12 @@ 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"; CHKiRet(datetimeClassInit(NULL)); - if(ppErrObj != NULL) *ppErrObj = "prop"; - CHKiRet(propClassInit(NULL)); if(ppErrObj != NULL) *ppErrObj = "msg"; CHKiRet(msgClassInit(NULL)); if(ppErrObj != NULL) *ppErrObj = "ctok_token"; diff --git a/tcps_sess.c b/tcps_sess.c index 23241f4f..c4dc4bd4 100644 --- a/tcps_sess.c +++ b/tcps_sess.c @@ -36,6 +36,7 @@ #include "rsyslog.h" #include "dirty.h" +#include "unicode-helper.h" #include "module-template.h" #include "net.h" #include "tcpsrv.h" @@ -102,7 +103,8 @@ CODESTARTobjDestruct(tcps_sess) pThis->pSrv->pOnSessDestruct(&pThis->pUsr); } /* now destruct our own properties */ - free(pThis->fromHost); + if(pThis->fromHost != NULL) + CHKiRet(prop.Destruct(&pThis->fromHost)); free(pThis->fromHostIP); free(pThis->pMsg); ENDobjDestruct(tcps_sess) @@ -126,9 +128,14 @@ SetHost(tcps_sess_t *pThis, uchar *pszHost) ISOBJ_TYPE_assert(pThis, tcps_sess); - free(pThis->fromHost); - pThis->fromHost = pszHost; + if(pThis->fromHost == NULL) { + CHKiRet(prop.Construct(&pThis->fromHost)); + } + + CHKiRet(prop.SetString(pThis->fromHost, pszHost, ustrlen(pszHost))); +finalize_it: + free(pszHost); /* we must free according to our (old) calling conventions */ RETiRet; } @@ -325,8 +332,9 @@ Close(tcps_sess_t *pThis) ISOBJ_TYPE_assert(pThis, tcps_sess); netstrm.Destruct(&pThis->pStrm); - free(pThis->fromHost); - pThis->fromHost = NULL; /* not really needed, but... */ + if(pThis->fromHost != NULL) { + prop.Destruct(&pThis->fromHost); + } free(pThis->fromHostIP); pThis->fromHostIP = NULL; /* not really needed, but... */ diff --git a/tcps_sess.h b/tcps_sess.h index 5e59aaab..2051bd1f 100644 --- a/tcps_sess.h +++ b/tcps_sess.h @@ -24,6 +24,7 @@ #define INCLUDED_TCPS_SESS_H #include "obj.h" +#include "prop.h" /* a forward-definition, we are somewhat cyclic */ struct tcpsrv_s; @@ -44,7 +45,7 @@ struct tcps_sess_s { int iOctetsRemain; /* Number of Octets remaining in message */ TCPFRAMINGMODE eFraming; uchar *pMsg; /* message (fragment) received */ - uchar *fromHost; + prop_t *fromHost; /* host name we received messages from */ uchar *fromHostIP; void *pUsr; /* a user-pointer */ rsRetVal (*DoSubmitMessage)(tcps_sess_t*, uchar*, int); /* submit message callback */ diff --git a/tools/syslogd.c b/tools/syslogd.c index f1c43602..3694c70a 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -596,7 +596,7 @@ static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int f */ if((pMsg->msgFlags & PARSE_HOSTNAME) == 0) MsgSetHOSTNAME(pMsg, hname, ustrlen(hname)); - MsgSetRcvFrom(pMsg, hname); + MsgSetRcvFromStr(pMsg, hname, ustrlen(hname)); MsgSetAfterPRIOffs(pMsg, p - msg); CHKiRet(MsgSetRcvFromIP(pMsg, hnameIP)); @@ -870,7 +870,7 @@ logmsgInternal(int iErr, int pri, uchar *msg, int flags) MsgSetInputName(pMsg, pInternalInputName); MsgSetRawMsgWOSize(pMsg, (char*)msg); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); - MsgSetRcvFrom(pMsg, glbl.GetLocalHostName()); + MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp()); MsgSetRcvFromIP(pMsg, UCHAR_CONSTANT("127.0.0.1")); /* check if we have an error code associated and, if so, * adjust the tag. -- rgerhards, 2008-06-27 @@ -3259,6 +3259,7 @@ int realMain(int argc, char **argv) */ glbl.SetLocalHostName(LocalHostName); glbl.SetLocalDomain(LocalDomain); + glbl.GenerateLocalHostNameProperty(); /* must be redone after conf processing, FQDN setting may have changed */ /* initialize the objects */ if((iRet = modInitIminternal()) != RS_RET_OK) { @@ -3455,6 +3456,9 @@ int realMain(int argc, char **argv) if(!iConfigVerify) CHKiRet(doGlblProcessInit()); + /* re-generate local host name property, as the config may have changed our FQDN settings */ + glbl.GenerateLocalHostNameProperty(); + CHKiRet(mainThread()); /* do any de-init's that need to be done AFTER this comment */ -- cgit From a0496e7bd4cba22d2559adb50cd286f75cc6a40e Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 30 Jun 2009 18:54:49 +0200 Subject: internal bugfix: object pointer was only reset to NULL when an object was actually destructed. This most likely had no effect to existing code, but it may also have caused trouble in remote cases. Similarly, the fix may also cause trouble... Due to this trouble scenario, the fix deserves its own commit. --- ChangeLog | 6 ++++++ runtime/obj-types.h | 11 ++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b9352957..294616df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,10 @@ --------------------------------------------------------------------------- +Version 4.3.3 [beta] (rgerhards), 2009-0?-?? +- internal bugfix: object pointer was only reset to NULL when an object + was actually destructed. This most likely had no effect to existing code, + but it may also have caused trouble in remote cases. Similarly, the fix + may also cause trouble... +--------------------------------------------------------------------------- Version 4.3.2 [beta] (rgerhards), 2009-06-24 - removed long-obsoleted property UxTradMsg - added a generic network stream server (in addition to rather specific diff --git a/runtime/obj-types.h b/runtime/obj-types.h index 78829f94..ff1819a9 100644 --- a/runtime/obj-types.h +++ b/runtime/obj-types.h @@ -292,6 +292,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! */ \ @@ -299,8 +308,8 @@ rsRetVal objName##ClassExit(void) \ if(pThis != NULL) { \ obj.DestructObjSelf((obj_t*) pThis); \ free(pThis); \ - *ppThis = NULL; \ } \ + *ppThis = NULL; \ pthread_setcancelstate(iCancelStateSave, NULL); \ RETiRet; \ } -- cgit From f76881fff39b46630d95a8d8308f383bec1b8be8 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 1 Jul 2009 10:34:17 +0200 Subject: removed a debugging-left-over, caused compilation failure on some platforms ... because LARGFILE macros were not defined consistenly --- runtime/stringbuf.c | 1 - 1 file changed, 1 deletion(-) 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 /* 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 -- cgit From d6faee67b413d1f257c96a14e46f15ec1868a365 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 1 Jul 2009 13:28:17 +0200 Subject: RcvFromIP now also a property This sets stage to enable use of the property-interface to speed up things (mildly), the next step to be done. I have also fixed one regression of yesterday's changes. --- plugins/imdiag/imdiag.c | 9 ++++- plugins/imklog/imklog.c | 2 +- plugins/imudp/imudp.c | 2 +- runtime/msg.c | 97 +++++++++++++++++++++++++++++++++---------------- runtime/msg.h | 6 +-- tcps_sess.c | 19 ++++++---- tcps_sess.h | 2 +- tools/syslogd.c | 15 ++++++-- 8 files changed, 102 insertions(+), 50 deletions(-) diff --git a/plugins/imdiag/imdiag.c b/plugins/imdiag/imdiag.c index 140222e1..bf972191 100644 --- a/plugins/imdiag/imdiag.c +++ b/plugins/imdiag/imdiag.c @@ -73,6 +73,7 @@ static tcpsrv_t *pOurTcpsrv = NULL; /* our TCP server(listener) TODO: change fo static permittedPeers_t *pPermPeersRoot = NULL; static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */ static prop_t *pRcvDummy = NULL; +static prop_t *pRcvIPDummy = NULL; /* config settings */ @@ -214,7 +215,7 @@ doInjectMsg(int iNum) pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; MsgSetRcvFrom(pMsg, pRcvDummy); - CHKiRet(MsgSetRcvFromIP(pMsg, UCHAR_CONSTANT("127.0.0.1"))); + CHKiRet(MsgSetRcvFromIP(pMsg, pRcvIPDummy)); CHKiRet(submitMsg(pMsg)); finalize_it: @@ -388,6 +389,10 @@ CODESTARTwillRun CHKiRet(prop.SetString(pRcvDummy, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1)); CHKiRet(prop.ConstructFinalize(pRcvDummy)); + CHKiRet(prop.Construct(&pRcvIPDummy)); + CHKiRet(prop.SetString(pRcvIPDummy, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1)); + CHKiRet(prop.ConstructFinalize(pRcvIPDummy)); + finalize_it: ENDwillRun @@ -398,6 +403,8 @@ CODESTARTafterRun prop.Destruct(&pInputName); if(pRcvDummy != NULL) prop.Destruct(&pRcvDummy); + if(pRcvIPDummy != NULL) + prop.Destruct(&pRcvIPDummy); ENDafterRun diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index e4db03b3..269cfee0 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -105,7 +105,7 @@ enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity) MsgSetRawMsgWOSize(pMsg, (char*)msg); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp()); - MsgSetRcvFromIP(pMsg, (uchar*)"127.0.0.1"); + MsgSetRcvFromIPStr(pMsg, (uchar*)"127.0.0.1", sizeof("127.0.0.1") - 1); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetTAG(pMsg, pszTag, ustrlen(pszTag)); pMsg->iFacility = LOG_FAC(iFacility); diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c index e091c7d6..31a4869f 100644 --- a/plugins/imudp/imudp.c +++ b/plugins/imudp/imudp.c @@ -250,7 +250,7 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted, pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; MsgSetRcvFromStr(pMsg, fromHost, ustrlen(fromHost)); - CHKiRet(MsgSetRcvFromIP(pMsg, fromHostIP)); + CHKiRet(MsgSetRcvFromIPStr(pMsg, fromHostIP, ustrlen(fromHostIP))); CHKiRet(submitMsg(pMsg)); } } diff --git a/runtime/msg.c b/runtime/msg.c index 3eb41a87..d3645664 100644 --- a/runtime/msg.c +++ b/runtime/msg.c @@ -296,6 +296,26 @@ getInputName(msg_t *pM, uchar **ppsz, int *plen) } +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) { @@ -622,10 +642,8 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis) pM->iLenMSG = 0; pM->iLenTAG = 0; pM->iLenHOSTNAME = 0; - pM->iLenRcvFromIP = 0; pM->pszRawMsg = NULL; pM->pszHOSTNAME = NULL; - pM->pszRcvFromIP = NULL; pM->pszRcvdAt3164 = NULL; pM->pszRcvdAt3339 = NULL; pM->pszRcvdAt_MySQL = NULL; @@ -640,6 +658,7 @@ static inline rsRetVal msgBaseConstruct(msg_t **ppThis) 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)); @@ -743,6 +762,8 @@ CODESTARTobjDestruct(msg) 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); @@ -845,6 +866,8 @@ msg_t* MsgDup(msg_t* pOld) 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 @@ -939,7 +962,8 @@ static rsRetVal MsgSerialize(msg_t *pThis, strm_t *pStrm) objSerializeSCALAR_VAR(pStrm, "pszInputName", PSZ, psz); psz = getRcvFrom(pThis); objSerializeSCALAR_VAR(pStrm, "pszRcvFrom", PSZ, psz); - objSerializePTR(pStrm, pszRcvFromIP, PSZ); + psz = getRcvFromIP(pThis); + objSerializeSCALAR_VAR(pStrm, "pszRcvFromIP", PSZ, psz); objSerializePTR(pStrm, pCSStrucData, CSTR); objSerializePTR(pStrm, pCSAPPNAME, CSTR); @@ -1640,24 +1664,16 @@ uchar *getRcvFrom(msg_t *pM) if(pM == NULL) { psz = UCHAR_CONSTANT(""); } else { - prop.GetString(pM->pInputName, &psz, &len); + if(pM->pRcvFrom == NULL) + psz = UCHAR_CONSTANT(""); + else + 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) @@ -1822,8 +1838,8 @@ void MsgSetRcvFrom(msg_t *pThis, prop_t *new) pThis->pRcvFrom = new; } -/* to be removed soon: work-around for those tht can not natively generate an - * input name. +/* to be removed soon: work-around for those tht can not natively generate a + * property. * rgerhards, 2009-06-29 */ void MsgSetRcvFromStr(msg_t *pThis, uchar *psz, int len) @@ -1840,24 +1856,43 @@ void MsgSetRcvFromStr(msg_t *pThis, uchar *psz, int len) } -/* rgerhards 2005-05-16: set pszRcvFromIP in msg object */ -rsRetVal -MsgSetRcvFromIP(msg_t *pMsg, uchar* pszRcvFromIP) +/* 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) { - DEFiRet; - assert(pMsg != NULL); - if(pMsg->pszRcvFromIP != NULL) { - free(pMsg->pszRcvFromIP); - pMsg->iLenRcvFromIP = 0; - } + assert(pThis != NULL); - CHKmalloc(pMsg->pszRcvFromIP = (uchar*)strdup((char*)pszRcvFromIP)); - pMsg->iLenRcvFromIP = strlen((char*)pszRcvFromIP); -finalize_it: - RETiRet; + BEGINfunc + prop.AddRef(new); + if(pThis->pRcvFromIP != NULL) + prop.Destruct(&pThis->pRcvFromIP); + pThis->pRcvFromIP = new; + ENDfunc + return RS_RET_OK; } +/* to be removed soon: work-around for those tht can not natively generate a + * property. + * rgerhards, 2009-06-29 + */ +rsRetVal MsgSetRcvFromIPStr(msg_t *pThis, uchar *psz, int len) +{ + prop_t *pProp; + assert(pThis != NULL); + + /* we need to create a property */ + prop.Construct(&pProp); + prop.SetString(pProp, psz, len); + prop.ConstructFinalize(pProp); + MsgSetRcvFromIP(pThis, pProp); + prop.Destruct(&pProp); + return RS_RET_OK; +} + /* rgerhards 2004-11-09: set HOSTNAME in msg object * rgerhards, 2007-06-21: * Does not return anything. If an error occurs, the hostname is @@ -2900,7 +2935,7 @@ rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp) 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)); } else if(isProp("pszRcvFrom")) { MsgSetRcvFromStr(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr)); } else if(isProp("pszHOSTNAME")) { diff --git a/runtime/msg.h b/runtime/msg.h index 59046fc1..43f24435 100644 --- a/runtime/msg.h +++ b/runtime/msg.h @@ -78,11 +78,9 @@ struct msg { int iLenMSG; /* Length of the MSG part */ int iLenTAG; /* Length of the TAG part */ int iLenHOSTNAME; /* Length of HOSTNAME */ - 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 *pszRcvFromIP; /* IP of system message was received from */ 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) */ @@ -98,6 +96,7 @@ struct msg { 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 @@ -152,7 +151,8 @@ rsRetVal MsgSetFlowControlType(msg_t *pMsg, flowControl_t eFlowCtl); rsRetVal MsgSetStructuredData(msg_t *pMsg, char* pszStrucData); void MsgSetRcvFrom(msg_t *pMsg, prop_t*); void MsgSetRcvFromStr(msg_t *pMsg, uchar* pszRcvFrom, int); -rsRetVal MsgSetRcvFromIP(msg_t *pMsg, uchar* pszRcvFromIP); +rsRetVal MsgSetRcvFromIP(msg_t *pMsg, prop_t*); +rsRetVal MsgSetRcvFromIPStr(msg_t *pMsg, uchar*, int); void MsgSetHOSTNAME(msg_t *pMsg, uchar* pszHOSTNAME, int lenHOSTNAME); rsRetVal MsgSetAfterPRIOffs(msg_t *pMsg, short offs); void MsgSetMSGoffs(msg_t *pMsg, short offs); diff --git a/tcps_sess.c b/tcps_sess.c index c4dc4bd4..f701fe57 100644 --- a/tcps_sess.c +++ b/tcps_sess.c @@ -105,7 +105,8 @@ CODESTARTobjDestruct(tcps_sess) /* now destruct our own properties */ if(pThis->fromHost != NULL) CHKiRet(prop.Destruct(&pThis->fromHost)); - free(pThis->fromHostIP); + if(pThis->fromHostIP != NULL) + CHKiRet(prop.Destruct(&pThis->fromHostIP)); free(pThis->pMsg); ENDobjDestruct(tcps_sess) @@ -128,9 +129,8 @@ SetHost(tcps_sess_t *pThis, uchar *pszHost) ISOBJ_TYPE_assert(pThis, tcps_sess); - if(pThis->fromHost == NULL) { + if(pThis->fromHost == NULL) CHKiRet(prop.Construct(&pThis->fromHost)); - } CHKiRet(prop.SetString(pThis->fromHost, pszHost, ustrlen(pszHost))); @@ -150,9 +150,12 @@ SetHostIP(tcps_sess_t *pThis, uchar *pszHostIP) ISOBJ_TYPE_assert(pThis, tcps_sess); - free(pThis->fromHostIP); - pThis->fromHostIP = pszHostIP; + if(pThis->fromHostIP == NULL) + CHKiRet(prop.Construct(&pThis->fromHostIP)); + + CHKiRet(prop.SetString(pThis->fromHostIP, pszHostIP, ustrlen(pszHostIP))); +finalize_it: RETiRet; } @@ -249,8 +252,8 @@ defaultDoSubmitMessage(tcps_sess_t *pThis, struct syslogTime *stTime, time_t ttG pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; MsgSetRcvFrom(pMsg, pThis->fromHost); - MsgSetRuleset(pMsg, pThis->pLstnInfo->pRuleset); CHKiRet(MsgSetRcvFromIP(pMsg, pThis->fromHostIP)); + MsgSetRuleset(pMsg, pThis->pLstnInfo->pRuleset); if(pMultiSub == NULL) { CHKiRet(submitMsg(pMsg)); @@ -335,8 +338,8 @@ Close(tcps_sess_t *pThis) if(pThis->fromHost != NULL) { prop.Destruct(&pThis->fromHost); } - free(pThis->fromHostIP); - pThis->fromHostIP = NULL; /* not really needed, but... */ + if(pThis->fromHostIP != NULL) + prop.Destruct(&pThis->fromHostIP); RETiRet; } diff --git a/tcps_sess.h b/tcps_sess.h index 2051bd1f..ec3a6af4 100644 --- a/tcps_sess.h +++ b/tcps_sess.h @@ -46,7 +46,7 @@ struct tcps_sess_s { TCPFRAMINGMODE eFraming; uchar *pMsg; /* message (fragment) received */ prop_t *fromHost; /* host name we received messages from */ - uchar *fromHostIP; + prop_t *fromHostIP; void *pUsr; /* a user-pointer */ rsRetVal (*DoSubmitMessage)(tcps_sess_t*, uchar*, int); /* submit message callback */ }; diff --git a/tools/syslogd.c b/tools/syslogd.c index 3694c70a..be5b5aad 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -211,6 +211,7 @@ static rsRetVal GlobalClassExit(void); #endif static prop_t *pInternalInputName = NULL; /* there is only one global inputName for all internally-generated messages */ +static prop_t *pLocalHostIP = NULL; /* there is only one global IP for all internally-generated messages */ static uchar *ConfFile = (uchar*) _PATH_LOGCONF; /* read-only after startup */ static char *PidFile = _PATH_LOGPID; /* read-only after startup */ @@ -598,7 +599,7 @@ static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int f MsgSetHOSTNAME(pMsg, hname, ustrlen(hname)); MsgSetRcvFromStr(pMsg, hname, ustrlen(hname)); MsgSetAfterPRIOffs(pMsg, p - msg); - CHKiRet(MsgSetRcvFromIP(pMsg, hnameIP)); + CHKiRet(MsgSetRcvFromIPStr(pMsg, hnameIP, ustrlen(hname))); logmsg(pMsg, flags); @@ -871,7 +872,7 @@ logmsgInternal(int iErr, int pri, uchar *msg, int flags) MsgSetRawMsgWOSize(pMsg, (char*)msg); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp()); - MsgSetRcvFromIP(pMsg, UCHAR_CONSTANT("127.0.0.1")); + MsgSetRcvFromIP(pMsg, pLocalHostIP); /* check if we have an error code associated and, if so, * adjust the tag. -- rgerhards, 2008-06-27 */ @@ -1697,9 +1698,11 @@ die(int sig) legacyOptsFree(); - /* destruct our input name */ + /* destruct our global properties */ if(pInternalInputName != NULL) prop.Destruct(&pInternalInputName); + if(pLocalHostIP != NULL) + prop.Destruct(&pLocalHostIP); /* terminate the remaining classes */ GlobalClassExit(); @@ -3208,9 +3211,13 @@ int realMain(int argc, char **argv) /* we need to create the inputName property (only once during our lifetime) */ CHKiRet(prop.Construct(&pInternalInputName)); - CHKiRet(prop.SetString(pInternalInputName, UCHAR_CONSTANT("rsyslgod"), sizeof("rsyslgod") - 1)); + CHKiRet(prop.SetString(pInternalInputName, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslgod") - 1)); CHKiRet(prop.ConstructFinalize(pInternalInputName)); + CHKiRet(prop.Construct(&pLocalHostIP)); + CHKiRet(prop.SetString(pLocalHostIP, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1)); + CHKiRet(prop.ConstructFinalize(pLocalHostIP)); + /* get our host and domain names - we need to do this early as we may emit * error log messages, which need the correct hostname. -- rgerhards, 2008-04-04 */ -- cgit From 7bfa03bdc0b73647ffdbe4b73e5c1649af665fbf Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 1 Jul 2009 14:33:19 +0200 Subject: now put the new property-based methods to good use ... hopefully reducing the number of allocs/frees as well as overall memory usage in a busy system (plus that these shared properties hopefully remain in cache longer than its single-instance counterparts...) --- plugins/imklog/imklog.c | 10 ++++--- plugins/imudp/imudp.c | 12 ++++++-- runtime/msg.c | 58 +++++++++++++++++++++---------------- runtime/msg.h | 4 +-- runtime/prop.c | 76 ++++++++++++++++++++++++++++++++++++++++--------- runtime/prop.h | 2 ++ tcps_sess.c | 1 + tools/syslogd.c | 6 ++-- 8 files changed, 120 insertions(+), 49 deletions(-) diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index 269cfee0..2a832bee 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -84,6 +84,7 @@ int console_log_level = -1; static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this module */ +static prop_t *pLocalHostIP = NULL; /* a pseudo-constant propterty for 127.0.0.1 */ /* enqueue the the kernel message into the message queue. * The provided msg string is not freed - thus must be done @@ -105,7 +106,7 @@ enqMsg(uchar *msg, uchar* pszTag, int iFacility, int iSeverity) MsgSetRawMsgWOSize(pMsg, (char*)msg); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp()); - MsgSetRcvFromIPStr(pMsg, (uchar*)"127.0.0.1", sizeof("127.0.0.1") - 1); + MsgSetRcvFromIP(pMsg, pLocalHostIP); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetTAG(pMsg, pszTag, ustrlen(pszTag)); pMsg->iFacility = LOG_FAC(iFacility); @@ -235,9 +236,8 @@ ENDrunInput BEGINwillRun CODESTARTwillRun /* we need to create the inputName property (only once during our lifetime) */ - CHKiRet(prop.Construct(&pInputName)); - CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imklog"), sizeof("imklog") - 1)); - CHKiRet(prop.ConstructFinalize(pInputName)); + CHKiRet(prop.CreateStringProp(&pInputName, UCHAR_CONSTANT("imklog"), sizeof("imklog") - 1)); + CHKiRet(prop.CreateStringProp(&pLocalHostIP, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1)); iRet = klogWillRun(); finalize_it: @@ -250,6 +250,8 @@ CODESTARTafterRun if(pInputName != NULL) prop.Destruct(&pInputName); + if(pLocalHostIP != NULL) + prop.Destruct(&pLocalHostIP); ENDafterRun diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c index 31a4869f..718c3090 100644 --- a/plugins/imudp/imudp.c +++ b/plugins/imudp/imudp.c @@ -191,6 +191,8 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted, ssize_t lenRcvBuf; struct sockaddr_storage frominet; msg_t *pMsg; + prop_t *propFromHost = NULL; + prop_t *propFromHostIP = NULL; char errStr[1024]; iNbrTimeUsed = 0; @@ -249,14 +251,18 @@ processSocket(int fd, struct sockaddr_storage *frominetPrev, int *pbIsPermitted, MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; pMsg->bParseHOSTNAME = 1; - MsgSetRcvFromStr(pMsg, fromHost, ustrlen(fromHost)); - CHKiRet(MsgSetRcvFromIPStr(pMsg, fromHostIP, ustrlen(fromHostIP))); + MsgSetRcvFromStr(pMsg, fromHost, ustrlen(fromHost), &propFromHost); + CHKiRet(MsgSetRcvFromIPStr(pMsg, fromHostIP, ustrlen(fromHostIP), &propFromHostIP)); CHKiRet(submitMsg(pMsg)); } } - finalize_it: + if(propFromHost != NULL) + prop.Destruct(&propFromHost); + if(propFromHostIP != NULL) + prop.Destruct(&propFromHostIP); + RETiRet; } diff --git a/runtime/msg.c b/runtime/msg.c index d3645664..6c272d1f 100644 --- a/runtime/msg.c +++ b/runtime/msg.c @@ -1838,21 +1838,22 @@ void MsgSetRcvFrom(msg_t *pThis, prop_t *new) pThis->pRcvFrom = new; } -/* to be removed soon: work-around for those tht can not natively generate a - * property. - * rgerhards, 2009-06-29 + +/* 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) +void MsgSetRcvFromStr(msg_t *pThis, uchar *psz, int len, prop_t **ppProp) { - prop_t *pProp; assert(pThis != NULL); + assert(ppProp != NULL); - /* we need to create a property */ - prop.Construct(&pProp); - prop.SetString(pProp, psz, len); - prop.ConstructFinalize(pProp); - MsgSetRcvFrom(pThis, pProp); - prop.Destruct(&pProp); + prop.CreateOrReuseStringProp(ppProp, psz, len); + MsgSetRcvFrom(pThis, *ppProp); } @@ -1875,24 +1876,27 @@ rsRetVal MsgSetRcvFromIP(msg_t *pThis, prop_t *new) } -/* to be removed soon: work-around for those tht can not natively generate a - * property. - * rgerhards, 2009-06-29 +/* 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) +rsRetVal MsgSetRcvFromIPStr(msg_t *pThis, uchar *psz, int len, prop_t **ppProp) { - prop_t *pProp; + DEFiRet; assert(pThis != NULL); - /* we need to create a property */ - prop.Construct(&pProp); - prop.SetString(pProp, psz, len); - prop.ConstructFinalize(pProp); - MsgSetRcvFromIP(pThis, pProp); - prop.Destruct(&pProp); - return RS_RET_OK; + CHKiRet(prop.CreateOrReuseStringProp(ppProp, psz, len)); + MsgSetRcvFrom(pThis, *ppProp); + +finalize_it: + RETiRet; } + /* rgerhards 2004-11-09: set HOSTNAME in msg object * rgerhards, 2007-06-21: * Does not return anything. If an error occurs, the hostname is @@ -2901,6 +2905,8 @@ finalize_it: 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); @@ -2935,9 +2941,11 @@ rsRetVal MsgSetProperty(msg_t *pThis, var_t *pProp) MsgSetInputName(pThis, myProp); prop.Destruct(&myProp); } else if(isProp("pszRcvFromIP")) { - MsgSetRcvFromIPStr(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr)); + MsgSetRcvFromIPStr(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr), &propRcvFromIP); + prop.Destruct(&propRcvFromIP); } else if(isProp("pszRcvFrom")) { - MsgSetRcvFromStr(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(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")) { diff --git a/runtime/msg.h b/runtime/msg.h index 43f24435..c20fb005 100644 --- a/runtime/msg.h +++ b/runtime/msg.h @@ -150,9 +150,9 @@ 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, prop_t*); -void MsgSetRcvFromStr(msg_t *pMsg, uchar* pszRcvFrom, int); +void MsgSetRcvFromStr(msg_t *pMsg, uchar* pszRcvFrom, int, prop_t **); rsRetVal MsgSetRcvFromIP(msg_t *pMsg, prop_t*); -rsRetVal MsgSetRcvFromIPStr(msg_t *pMsg, uchar*, int); +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); diff --git a/runtime/prop.c b/runtime/prop.c index 96ebe212..804f3491 100644 --- a/runtime/prop.c +++ b/runtime/prop.c @@ -41,6 +41,7 @@ #include "rsyslog.h" #include "obj.h" #include "obj-types.h" +#include "unicode-helper.h" #include "atomic.h" #include "prop.h" @@ -54,6 +55,21 @@ 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()! */ @@ -90,10 +106,8 @@ static rsRetVal GetString(prop_t *pThis, uchar **ppsz, int *plen) ISOBJ_TYPE_assert(pThis, prop); if(pThis->len < CONF_PROP_BUFSIZE) { *ppsz = pThis->szVal.sz; -RUNLOG; } else { *ppsz = pThis->szVal.psz; -RUNLOG; } *plen = pThis->len; ENDfunc @@ -123,19 +137,53 @@ static rsRetVal AddRef(prop_t *pThis) } -/* 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); +/* 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 { - pThis = NULL; /* tell framework NOT to destructing the object! */ + /* 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! */ } -ENDobjDestruct(prop) + +finalize_it: + RETiRet; +} /* debugprint for the prop object */ @@ -167,6 +215,8 @@ CODESTARTobjQueryInterface(prop) 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 62c0d799..e3519664 100644 --- a/runtime/prop.h +++ b/runtime/prop.h @@ -46,6 +46,8 @@ BEGINinterface(prop) /* name must also be changed in ENDinterface macro! */ 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/tcps_sess.c b/tcps_sess.c index f701fe57..8d307380 100644 --- a/tcps_sess.c +++ b/tcps_sess.c @@ -156,6 +156,7 @@ SetHostIP(tcps_sess_t *pThis, uchar *pszHostIP) CHKiRet(prop.SetString(pThis->fromHostIP, pszHostIP, ustrlen(pszHostIP))); finalize_it: + free(pszHostIP); RETiRet; } diff --git a/tools/syslogd.c b/tools/syslogd.c index be5b5aad..f7253a8e 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -559,6 +559,8 @@ static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int f register uchar *p; int pri; msg_t *pMsg; + prop_t *propFromHost = NULL; + prop_t *propFromHostIP = NULL; /* Now it is time to create the message object (rgerhards) */ if(stTime == NULL) { @@ -597,9 +599,9 @@ static inline rsRetVal printline(uchar *hname, uchar *hnameIP, uchar *msg, int f */ if((pMsg->msgFlags & PARSE_HOSTNAME) == 0) MsgSetHOSTNAME(pMsg, hname, ustrlen(hname)); - MsgSetRcvFromStr(pMsg, hname, ustrlen(hname)); + MsgSetRcvFromStr(pMsg, hname, ustrlen(hname), &propFromHost); + CHKiRet(MsgSetRcvFromIPStr(pMsg, hnameIP, ustrlen(hname), &propFromHostIP)); MsgSetAfterPRIOffs(pMsg, p - msg); - CHKiRet(MsgSetRcvFromIPStr(pMsg, hnameIP, ustrlen(hname))); logmsg(pMsg, flags); -- cgit