summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile.am10
-rw-r--r--tools/omdiscard.c2
-rw-r--r--tools/omfile.c359
-rw-r--r--tools/omfwd.c447
-rw-r--r--tools/ompipe.c102
-rw-r--r--tools/omshell.c8
-rw-r--r--tools/omusrmsg.c177
-rw-r--r--tools/pmrfc3164.c2
-rw-r--r--tools/pmrfc5424.c4
-rw-r--r--tools/syslogd.c1131
-rw-r--r--tools/syslogd.h1
11 files changed, 947 insertions, 1296 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 962ae507..4e457426 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -34,9 +34,13 @@ rsyslogd_SOURCES = \
pidfile.c \
pidfile.h \
\
- ../dirty.h
-rsyslogd_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
-rsyslogd_LDADD = $(ZLIB_LIBS) $(PTHREADS_LIBS) $(RSRT_LIBS) $(SOL_LIBS)
+ ../dirty.h \
+ ../runtime/librsyslog.la
+rsyslogd_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(CNF_LIBS)
+# note: it looks like librsyslog.la must be explicitely given on LDDADD,
+# otherwise dependencies are not properly calculated (resulting in a
+# potentially incomplete build, a problem we had several times...)
+rsyslogd_LDADD = $(ZLIB_LIBS) $(PTHREADS_LIBS) $(RSRT_LIBS) $(SOL_LIBS) $(LIBEE_LIBS) $(LIBLOGNORM_LIBS) $(CNF_LIBS) ../grammar/libgrammar.la ../runtime/librsyslog.la
rsyslogd_LDFLAGS = -export-dynamic
if ENABLE_DIAGTOOLS
diff --git a/tools/omdiscard.c b/tools/omdiscard.c
index 02896d45..182c4b63 100644
--- a/tools/omdiscard.c
+++ b/tools/omdiscard.c
@@ -44,7 +44,7 @@ MODULE_TYPE_NOKEEP
DEF_OMOD_STATIC_DATA
typedef struct _instanceData {
- char dummy;
+ EMPTY_STRUCT
} instanceData;
/* we do not need a createInstance()!
diff --git a/tools/omfile.c b/tools/omfile.c
index b94acc6d..68222883 100644
--- a/tools/omfile.c
+++ b/tools/omfile.c
@@ -71,6 +71,10 @@
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omfile")
+
+/* forward definitions */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
/* internal structures
*/
@@ -122,30 +126,11 @@ typedef struct s_dynaFileCacheEntry dynaFileCacheEntry;
#define USE_ASYNCWRITER_DFLT 0 /* default buffer use async writer */
#define FLUSHONTX_DFLT 1 /* default for flush on TX end */
-/* globals for default values */
-static int iDynaFileCacheSize = 10; /* max cache for dynamic files */
-static int fCreateMode = 0644; /* mode to use when creating files */
-static int fDirCreateMode = 0700; /* mode to use when creating files */
-static int bFailOnChown; /* fail if chown fails? */
-static uid_t fileUID; /* UID to be used for newly created files */
-static uid_t fileGID; /* GID to be used for newly created files */
-static uid_t dirUID; /* UID to be used for newly created directories */
-static uid_t dirGID; /* GID to be used for newly created directories */
-static int bCreateDirs = 1;/* auto-create directories for dynaFiles: 0 - no, 1 - yes */
-static int bEnableSync = 0;/* enable syncing of files (no dash in front of pathname in conf): 0 - no, 1 - yes */
-static int iZipLevel = 0; /* zip compression mode (0..9 as usual) */
-static sbool bFlushOnTXEnd = FLUSHONTX_DFLT;/* flush write buffers when transaction has ended? */
-static int64 iIOBufSize = IOBUF_DFLT_SIZE; /* size of an io buffer */
-static int iFlushInterval = FLUSH_INTRVL_DFLT; /* how often flush the output buffer on inactivity? */
-static int bUseAsyncWriter = USE_ASYNCWRITER_DFLT; /* should we enable asynchronous writing? */
-uchar *pszFileDfltTplName = NULL; /* name of the default template to use */
-/* end globals for default values */
-
typedef struct _instanceData {
- uchar f_fname[MAXFNAME];/* file or template name (display only) */
+ uchar *f_fname; /* file or template name (display only) */
+ uchar *tplName; /* name of assigned template */
strm_t *pStrm; /* our output stream */
- strmType_t strmType; /* stream type, used for named pipes */
char bDynamicName; /* 0 - static name, 1 - dynamic name (with properties) */
int fCreateMode; /* file creation mode for open() */
int fDirCreateMode; /* creation mode for mkdir() */
@@ -174,6 +159,63 @@ typedef struct _instanceData {
} instanceData;
+typedef struct configSettings_s {
+ int iDynaFileCacheSize; /* max cache for dynamic files */
+ int fCreateMode; /* mode to use when creating files */
+ int fDirCreateMode; /* mode to use when creating files */
+ int bFailOnChown; /* fail if chown fails? */
+ uid_t fileUID; /* UID to be used for newly created files */
+ uid_t fileGID; /* GID to be used for newly created files */
+ uid_t dirUID; /* UID to be used for newly created directories */
+ uid_t dirGID; /* GID to be used for newly created directories */
+ int bCreateDirs;/* auto-create directories for dynaFiles: 0 - no, 1 - yes */
+ int bEnableSync;/* enable syncing of files (no dash in front of pathname in conf): 0 - no, 1 - yes */
+ int iZipLevel; /* zip compression mode (0..9 as usual) */
+ sbool bFlushOnTXEnd;/* flush write buffers when transaction has ended? */
+ int64 iIOBufSize; /* size of an io buffer */
+ int iFlushInterval; /* how often flush the output buffer on inactivity? */
+ int bUseAsyncWriter; /* should we enable asynchronous writing? */
+ EMPTY_STRUCT
+} configSettings_t;
+static configSettings_t cs;
+uchar *pszFileDfltTplName; /* name of the default template to use */
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "dynafilecachesize", eCmdHdlrInt, 0 }, /* legacy: dynafilecachesize */
+ { "ziplevel", eCmdHdlrInt, 0 }, /* legacy: omfileziplevel */
+ { "flushinterval", eCmdHdlrInt, 0 }, /* legacy: omfileflushinterval */
+ { "asyncwriting", eCmdHdlrBinary, 0 }, /* legacy: omfileasyncwriting */
+ { "flushontxend", eCmdHdlrBinary, 0 }, /* legacy: omfileflushontxend */
+ { "iobuffersize", eCmdHdlrSize, 0 }, /* legacy: omfileiobuffersize */
+ { "dirowner", eCmdHdlrUID, 0 }, /* legacy: dirowner */
+ { "dirgroup", eCmdHdlrGID, 0 }, /* legacy: dirgroup */
+ { "fileowner", eCmdHdlrUID, 0 }, /* legacy: fileowner */
+ { "filegroup", eCmdHdlrGID, 0 }, /* legacy: filegroup */
+ { "dircreatemode", eCmdHdlrFileCreateMode, 0 }, /* legacy: dircreatemode */
+ { "filecreatemode", eCmdHdlrFileCreateMode, 0 }, /* legacy: filecreatemode */
+ { "failonchownfailure", eCmdHdlrBinary, 0 }, /* legacy: failonchownfailure */
+ { "createdirs", eCmdHdlrBinary, 0 }, /* legacy: createdirs */
+ { "sync", eCmdHdlrBinary, 0 }, /* legacy: actionfileenablesync */
+ { "file", eCmdHdlrString, 0 }, /* either "file" or ... */
+ { "dynafile", eCmdHdlrString, 0 }, /* "dynafile" MUST be present */
+ { "template", eCmdHdlrGetWord, 0 },
+ //{ "", eCmdHdlrGetWord, 0 }, /* legacy: */
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ pszFileDfltTplName = NULL; /* make sure this can be free'ed! */
+ iRet = resetConfigVariables(NULL, NULL); /* params are dummies */
+ENDinitConfVars
+
BEGINisCompatibleWithFeature
CODESTARTisCompatibleWithFeature
if(eFeat == sFEATURERepeatedMsgReduction)
@@ -228,21 +270,13 @@ rsRetVal setDynaFileCacheSize(void __attribute__((unused)) *pVal, int iNewVal)
iNewVal = 1000;
}
- iDynaFileCacheSize = iNewVal;
+ cs.iDynaFileCacheSize = iNewVal;
DBGPRINTF("DynaFileCacheSize changed to %d.\n", iNewVal);
RETiRet;
}
-rsRetVal goneAway(void __attribute__((unused)) *pVal,
- int __attribute__((unused)) iNewVal)
-{
- errmsg.LogError(0, RS_RET_ERR, "directive $omfileForceChown is no longer supported");
- return RS_RET_ERR;
-}
-
-
/* Helper to cfline(). Parses a output channel name up until the first
* comma and then looks for the template specifier. Tries
* to find that template. Maps the output channel to the
@@ -292,7 +326,7 @@ static rsRetVal cflineParseOutchannel(instanceData *pData, uchar* p, omodStringR
}
/* OK, we finally got a correct template. So let's use it... */
- ustrncpy(pData->f_fname, pOch->pszFileTemplate, MAXFNAME);
+ pData->f_fname = ustrdup(pOch->pszFileTemplate);
pData->iSizeLimit = pOch->uSizeLimit;
/* WARNING: It is dangerous "just" to pass the pointer. As we
* never rebuild the output channel description, this is acceptable here.
@@ -448,9 +482,9 @@ prepareFile(instanceData *pData, uchar *newFileName)
CHKiRet(strm.SetiZipLevel(pData->pStrm, pData->iZipLevel));
CHKiRet(strm.SetsIOBufSize(pData->pStrm, (size_t) pData->iIOBufSize));
CHKiRet(strm.SettOperationsMode(pData->pStrm, STREAMMODE_WRITE_APPEND));
- CHKiRet(strm.SettOpenMode(pData->pStrm, fCreateMode));
+ CHKiRet(strm.SettOpenMode(pData->pStrm, cs.fCreateMode));
CHKiRet(strm.SetbSync(pData->pStrm, pData->bSyncFile));
- CHKiRet(strm.SetsType(pData->pStrm, pData->strmType));
+ CHKiRet(strm.SetsType(pData->pStrm, STREAMTYPE_FILE_SINGLE));
CHKiRet(strm.SetiSizeLimit(pData->pStrm, pData->iSizeLimit));
/* set the flush interval only if we actually use it - otherwise it will activate
* async processing, which is a real performance waste if we do not do buffered
@@ -652,11 +686,6 @@ writeFile(uchar **ppString, unsigned iMsgOpts, instanceData *pData)
CHKiRet(doWrite(pData, ppString[0], strlen(CHAR_CONVERT(ppString[0]))));
finalize_it:
- if(iRet != RS_RET_OK) {
- /* in v5, we shall return different states for message-caused failure (but only there!) */
- if(pData->strmType == STREAMTYPE_NAMED_PIPE)
- iRet = RS_RET_DISABLE_ACTION; /* this is the traditional semantic -- rgerhards, 2010-01-15 */
- }
RETiRet;
}
@@ -669,6 +698,7 @@ ENDcreateInstance
BEGINfreeInstance
CODESTARTfreeInstance
+ free(pData->f_fname);
if(pData->bDynamicName) {
dynaFileFreeCache(pData);
} else if(pData->pStrm != NULL)
@@ -709,7 +739,128 @@ finalize_it:
ENDdoAction
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->f_fname = NULL;
+ pData->tplName = NULL;
+ pData->fileUID = -1;
+ pData->fileGID = -1;
+ pData->dirUID = -1;
+ pData->dirGID = -1;
+ pData->bFailOnChown = 1;
+ pData->iDynaFileCacheSize = 10;
+ pData->fCreateMode = 0644;
+ pData->fDirCreateMode = 0700;
+ pData->bCreateDirs = 1;
+ pData->bSyncFile = 0;
+ pData->iZipLevel = 0;
+ pData->bFlushOnTXEnd = FLUSHONTX_DFLT;
+ pData->iIOBufSize = IOBUF_DFLT_SIZE;
+ pData->iFlushInterval = FLUSH_INTRVL_DFLT;
+ pData->bUseAsyncWriter = USE_ASYNCWRITER_DFLT;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (omfile)\n");
+
+ pvals = nvlstGetParams(lst, &actpblk, NULL);
+ if(pvals == NULL) {
+ errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "omfile: either the \"file\" or "
+ "\"dynfile\" parameter must be given");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("action param blk in omfile:\n");
+ cnfparamsPrint(&actpblk, pvals);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "dynafilecachesize")) {
+ pData->iDynaFileCacheSize = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "ziplevel")) {
+ pData->iZipLevel = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "flushinterval")) {
+ pData->iFlushInterval = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "asyncwriting")) {
+ pData->bUseAsyncWriter = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "flushontxend")) {
+ pData->bFlushOnTXEnd = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "iobuffersize")) {
+ pData->iIOBufSize = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dirowner")) {
+ pData->dirUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dirgroup")) {
+ pData->dirGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "fileowner")) {
+ pData->fileUID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "filegroup")) {
+ pData->fileGID = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "dircreatemode")) {
+ pData->fDirCreateMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "filecreatemode")) {
+ pData->fCreateMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "failonchownfailure")) {
+ pData->bFailOnChown = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "sync")) {
+ pData->bSyncFile = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "createdirs")) {
+ pData->bCreateDirs = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "file")) {
+ pData->f_fname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ CODE_STD_STRING_REQUESTnewActInst(1)
+ pData->bDynamicName = 0;
+ } else if(!strcmp(actpblk.descr[i].name, "dynafile")) {
+ pData->f_fname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ CODE_STD_STRING_REQUESTnewActInst(2)
+ pData->bDynamicName = 1;
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("omfile: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->f_fname == NULL) {
+ errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "omfile: either the \"file\" or "
+ "\"dynfile\" parameter must be given");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, ustrdup((pData->tplName == NULL) ?
+ (uchar*)"RSYSLOG_FileFormat" : pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+
+ if(pData->bDynamicName) {
+ /* "filename" is actually a template name, we need this as string 1. So let's add it
+ * to the pOMSR. -- rgerhards, 2007-07-27
+ */
+ CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->f_fname), OMSR_NO_RQD_TPL_OPTS));
+ // TODO: create unified code for this (legacy+v6 system)
+ /* we now allocate the cache table */
+ CHKmalloc(pData->dynCache = (dynaFileCacheEntry**)
+ calloc(cs.iDynaFileCacheSize, sizeof(dynaFileCacheEntry*)));
+ pData->iCurrElt = -1; /* no current element */
+ }
+// TODO: add pData->iSizeLimit = 0; /* default value, use outchannels to configure! */
+
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
BEGINparseSelectorAct
+ uchar fname[MAXFNAME];
CODESTARTparseSelectorAct
/* Note: the indicator sequence permits us to use '$' to signify
* outchannel, what otherwise is not possible due to truely
@@ -718,13 +869,6 @@ CODESTARTparseSelectorAct
*/
if(!strncmp((char*) p, ":omfile:", sizeof(":omfile:") - 1)) {
p += sizeof(":omfile:") - 1;
- } else {
- if(*p == '$') {
- errmsg.LogError(0, RS_RET_OUTDATED_STMT,
- "action '%s' treated as ':omfile:%s' - please "
- "change syntax, '%s' will not be supported in "
- "rsyslog v6 and above.", p, p, p);
- }
}
if(!(*p == '$' || *p == '?' || *p == '/' || *p == '.' || *p == '-'))
ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
@@ -735,7 +879,7 @@ CODESTARTparseSelectorAct
pData->bSyncFile = 0;
p++;
} else {
- pData->bSyncFile = bEnableSync;
+ pData->bSyncFile = cs.bEnableSync;
}
pData->iSizeLimit = 0; /* default value, use outchannels to configure! */
@@ -758,39 +902,26 @@ CODESTARTparseSelectorAct
*/
CODE_STD_STRING_REQUESTparseSelectorAct(2)
++p; /* eat '?' */
- CHKiRet(cflineParseFileName(p, (uchar*) pData->f_fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
+ CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
(pszFileDfltTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pszFileDfltTplName));
+ pData->f_fname = ustrdup(fname);
+ pData->bDynamicName = 1;
+ pData->iCurrElt = -1; /* no current element */
/* "filename" is actually a template name, we need this as string 1. So let's add it
* to the pOMSR. -- rgerhards, 2007-07-27
*/
CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->f_fname), OMSR_NO_RQD_TPL_OPTS));
-
- pData->bDynamicName = 1;
- pData->iCurrElt = -1; /* no current element */
/* we now allocate the cache table */
CHKmalloc(pData->dynCache = (dynaFileCacheEntry**)
- calloc(iDynaFileCacheSize, sizeof(dynaFileCacheEntry*)));
+ calloc(cs.iDynaFileCacheSize, sizeof(dynaFileCacheEntry*)));
break;
- /* case '|': while pipe support has been removed, I leave the code in in case we
- * need high-performance pipes at a later stage (unlikely). -- rgerhards, 2010-02-28
- */
case '/':
case '.':
CODE_STD_STRING_REQUESTparseSelectorAct(1)
- /* we now have *almost* the same semantics for files and pipes, but we still need
- * to know we deal with a pipe, because we must do non-blocking opens in that case
- * (to keep consistent with traditional semantics and prevent rsyslog from hanging).
- */
- if(*p == '|') {
- ++p;
- pData->strmType = STREAMTYPE_NAMED_PIPE;
- } else {
- pData->strmType = STREAMTYPE_FILE_SINGLE;
- }
-
- CHKiRet(cflineParseFileName(p, (uchar*) pData->f_fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
+ CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
(pszFileDfltTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pszFileDfltTplName));
+ pData->f_fname = ustrdup(fname);
pData->bDynamicName = 0;
break;
default:
@@ -798,20 +929,20 @@ CODESTARTparseSelectorAct
}
/* freeze current paremeters for this action */
- pData->iDynaFileCacheSize = iDynaFileCacheSize;
- pData->fCreateMode = fCreateMode;
- pData->fDirCreateMode = fDirCreateMode;
- pData->bCreateDirs = bCreateDirs;
- pData->bFailOnChown = bFailOnChown;
- pData->fileUID = fileUID;
- pData->fileGID = fileGID;
- pData->dirUID = dirUID;
- pData->dirGID = dirGID;
- pData->iZipLevel = iZipLevel;
- pData->bFlushOnTXEnd = bFlushOnTXEnd;
- pData->iIOBufSize = (int) iIOBufSize;
- pData->iFlushInterval = iFlushInterval;
- pData->bUseAsyncWriter = bUseAsyncWriter;
+ pData->iDynaFileCacheSize = cs.iDynaFileCacheSize;
+ pData->fCreateMode = cs.fCreateMode;
+ pData->fDirCreateMode = cs.fDirCreateMode;
+ pData->bCreateDirs = cs.bCreateDirs;
+ pData->bFailOnChown = cs.bFailOnChown;
+ pData->fileUID = cs.fileUID;
+ pData->fileGID = cs.fileGID;
+ pData->dirUID = cs.dirUID;
+ pData->dirGID = cs.dirGID;
+ pData->iZipLevel = cs.iZipLevel;
+ pData->bFlushOnTXEnd = cs.bFlushOnTXEnd;
+ pData->iIOBufSize = (int) cs.iIOBufSize;
+ pData->iFlushInterval = cs.iFlushInterval;
+ pData->bUseAsyncWriter = cs.bUseAsyncWriter;
CODE_STD_FINALIZERparseSelectorAct
ENDparseSelectorAct
@@ -821,25 +952,23 @@ ENDparseSelectorAct
*/
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
- fileUID = -1;
- fileGID = -1;
- dirUID = -1;
- dirGID = -1;
- bFailOnChown = 1;
- iDynaFileCacheSize = 10;
- fCreateMode = 0644;
- fDirCreateMode = 0700;
- bCreateDirs = 1;
- bEnableSync = 0;
- iZipLevel = 0;
- bFlushOnTXEnd = FLUSHONTX_DFLT;
- iIOBufSize = IOBUF_DFLT_SIZE;
- iFlushInterval = FLUSH_INTRVL_DFLT;
- bUseAsyncWriter = USE_ASYNCWRITER_DFLT;
- if(pszFileDfltTplName != NULL) {
- free(pszFileDfltTplName);
- pszFileDfltTplName = NULL;
- }
+ cs.fileUID = -1;
+ cs.fileGID = -1;
+ cs.dirUID = -1;
+ cs.dirGID = -1;
+ cs.bFailOnChown = 1;
+ cs.iDynaFileCacheSize = 10;
+ cs.fCreateMode = 0644;
+ cs.fDirCreateMode = 0700;
+ cs.bCreateDirs = 1;
+ cs.bEnableSync = 0;
+ cs.iZipLevel = 0;
+ cs.bFlushOnTXEnd = FLUSHONTX_DFLT;
+ cs.iIOBufSize = IOBUF_DFLT_SIZE;
+ cs.iFlushInterval = FLUSH_INTRVL_DFLT;
+ cs.bUseAsyncWriter = USE_ASYNCWRITER_DFLT;
+ free(pszFileDfltTplName);
+ pszFileDfltTplName = NULL;
return RS_RET_OK;
}
@@ -870,6 +999,7 @@ ENDmodExit
BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */
CODEqueryEtryPt_doHUP
ENDqueryEtryPt
@@ -879,6 +1009,7 @@ BEGINmodInit(File)
CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
+INITLegCnfVars
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(strm, CORE_COMPONENT));
@@ -887,21 +1018,21 @@ CODEmodInit_QueryRegCFSLineHdlr
INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
DBGPRINTF("omfile: %susing transactional output interface.\n", bCoreSupportsBatching ? "" : "not ");
CHKiRet(omsdRegCFSLineHdlr((uchar *)"dynafilecachesize", 0, eCmdHdlrInt, (void*) setDynaFileCacheSize, NULL, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileziplevel", 0, eCmdHdlrInt, NULL, &iZipLevel, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushinterval", 0, eCmdHdlrInt, NULL, &iFlushInterval, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileasyncwriting", 0, eCmdHdlrBinary, NULL, &bUseAsyncWriter, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushontxend", 0, eCmdHdlrBinary, NULL, &bFlushOnTXEnd, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileiobuffersize", 0, eCmdHdlrSize, NULL, &iIOBufSize, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirowner", 0, eCmdHdlrUID, NULL, &dirUID, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirgroup", 0, eCmdHdlrGID, NULL, &dirGID, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"fileowner", 0, eCmdHdlrUID, NULL, &fileUID, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"filegroup", 0, eCmdHdlrGID, NULL, &fileGID, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"dircreatemode", 0, eCmdHdlrFileCreateMode, NULL, &fDirCreateMode, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"filecreatemode", 0, eCmdHdlrFileCreateMode, NULL, &fCreateMode, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"createdirs", 0, eCmdHdlrBinary, NULL, &bCreateDirs, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"failonchownfailure", 0, eCmdHdlrBinary, NULL, &bFailOnChown, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileforcechown", 0, eCmdHdlrBinary, goneAway, NULL, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfileenablesync", 0, eCmdHdlrBinary, NULL, &bEnableSync, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileziplevel", 0, eCmdHdlrInt, NULL, &cs.iZipLevel, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushinterval", 0, eCmdHdlrInt, NULL, &cs.iFlushInterval, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileasyncwriting", 0, eCmdHdlrBinary, NULL, &cs.bUseAsyncWriter, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushontxend", 0, eCmdHdlrBinary, NULL, &cs.bFlushOnTXEnd, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileiobuffersize", 0, eCmdHdlrSize, NULL, &cs.iIOBufSize, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirowner", 0, eCmdHdlrUID, NULL, &cs.dirUID, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirgroup", 0, eCmdHdlrGID, NULL, &cs.dirGID, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"fileowner", 0, eCmdHdlrUID, NULL, &cs.fileUID, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"filegroup", 0, eCmdHdlrGID, NULL, &cs.fileGID, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dircreatemode", 0, eCmdHdlrFileCreateMode, NULL, &cs.fDirCreateMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"filecreatemode", 0, eCmdHdlrFileCreateMode, NULL, &cs.fCreateMode, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"createdirs", 0, eCmdHdlrBinary, NULL, &cs.bCreateDirs, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"failonchownfailure", 0, eCmdHdlrBinary, NULL, &cs.bFailOnChown, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileforcechown", 0, eCmdHdlrGoneAway, NULL, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfileenablesync", 0, eCmdHdlrBinary, NULL, &cs.bEnableSync, STD_LOADABLE_MODULE_ID));
CHKiRet(regCfSysLineHdlr((uchar *)"actionfiledefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszFileDfltTplName, NULL));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
diff --git a/tools/omfwd.c b/tools/omfwd.c
index b456db17..96458941 100644
--- a/tools/omfwd.c
+++ b/tools/omfwd.c
@@ -4,9 +4,6 @@
* NOTE: read comments in module-template.h to understand how this file
* works!
*
- * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c, which
- * at the time of rsyslog fork from sysklogd was under BSD license)
- *
* Copyright 2007-2012 Adiscon GmbH.
*
* This file is part of rsyslog.
@@ -24,6 +21,9 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * TODO v6 config:
+ * - permitted peer *list*
*/
#include "config.h"
#include "rsyslog.h"
@@ -58,9 +58,11 @@
#include "module-template.h"
#include "glbl.h"
#include "errmsg.h"
+#include "unicode-helper.h"
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omfwd")
/* internal structures
*/
@@ -73,38 +75,79 @@ DEFobjCurrIf(netstrm)
DEFobjCurrIf(tcpclt)
typedef struct _instanceData {
+ uchar *tplName; /* name of assigned template */
netstrms_t *pNS; /* netstream subsystem */
netstrm_t *pNetstrm; /* our output netstream */
uchar *pszStrmDrvr;
uchar *pszStrmDrvrAuthMode;
permittedPeers_t *pPermPeers;
int iStrmDrvrMode;
- char *f_hname;
+ char *target;
int *pSockArray; /* sockets to use for UDP */
int bIsConnected; /* are we connected to remote host? 0 - no, 1 - yes, UDP means addr resolved */
struct addrinfo *f_addr;
int compressionLevel; /* 0 - no compression, else level for zlib */
char *port;
int protocol;
- int iUDPRebindInterval; /* rebind interval */
- int iTCPRebindInterval; /* rebind interval */
+ int iRebindInterval; /* rebind interval */
int nXmit; /* number of transmissions since last (re-)bind */
# define FORW_UDP 0
# define FORW_TCP 1
/* following fields for TCP-based delivery */
+ TCPFRAMINGMODE tcp_framing;
+ int bResendLastOnRecon; /* should the last message be re-sent on a successful reconnect? */
tcpclt_t *pTCPClt; /* our tcpclt object */
+ uchar sndBuf[16*1024]; /* this is intensionally fixed -- see no good reason to make configurable */
+ unsigned offsSndBuf; /* next free spot in send buffer */
} instanceData;
/* config data */
-static uchar *pszTplName = NULL; /* name of the default template to use */
-static uchar *pszStrmDrvr = NULL; /* name of the stream driver to use */
-static int iStrmDrvrMode = 0; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
-static int bResendLastOnRecon = 0; /* should the last message be re-sent on a successful reconnect? */
-static uchar *pszStrmDrvrAuthMode = NULL; /* authentication mode to use */
-static int iUDPRebindInterval = 0; /* support for automatic re-binding (load balancers!). 0 - no rebind */
-static int iTCPRebindInterval = 0; /* support for automatic re-binding (load balancers!). 0 - no rebind */
+typedef struct configSettings_s {
+ uchar *pszTplName; /* name of the default template to use */
+ uchar *pszStrmDrvr; /* name of the stream driver to use */
+ int iStrmDrvrMode; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
+ int bResendLastOnRecon; /* should the last message be re-sent on a successful reconnect? */
+ uchar *pszStrmDrvrAuthMode; /* authentication mode to use */
+ int iTCPRebindInterval; /* support for automatic re-binding (load balancers!). 0 - no rebind */
+ int iUDPRebindInterval; /* support for automatic re-binding (load balancers!). 0 - no rebind */
+ permittedPeers_t *pPermPeers;
+} configSettings_t;
+static configSettings_t cs;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "target", eCmdHdlrGetWord, 0 },
+ { "port", eCmdHdlrGetWord, 0 },
+ { "protocol", eCmdHdlrGetWord, 0 },
+ { "tcp_framing", eCmdHdlrGetWord, 0 },
+ { "ziplevel", eCmdHdlrInt, 0 },
+ { "rebindinterval", eCmdHdlrInt, 0 },
+ { "streamdriver", eCmdHdlrGetWord, 0 },
+ { "streamdrivermode", eCmdHdlrInt, 0 },
+ { "streamdriverauthmode", eCmdHdlrGetWord, 0 },
+ { "streamdriverpermittedpeers", eCmdHdlrGetWord, 0 },
+ { "resendlastmsgonreconnect", eCmdHdlrBinary, 0 },
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ cs.pszTplName = NULL; /* name of the default template to use */
+ cs.pszStrmDrvr = NULL; /* name of the stream driver to use */
+ cs.iStrmDrvrMode = 0; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
+ cs.bResendLastOnRecon = 0; /* should the last message be re-sent on a successful reconnect? */
+ cs.pszStrmDrvrAuthMode = NULL; /* authentication mode to use */
+ cs.iUDPRebindInterval = 0; /* support for automatic re-binding (load balancers!). 0 - no rebind */
+ cs.iTCPRebindInterval = 0; /* support for automatic re-binding (load balancers!). 0 - no rebind */
+ cs.pPermPeers = NULL;
+ENDinitConfVars
-static permittedPeers_t *pPermPeers = NULL;
static rsRetVal doTryResume(instanceData *pData);
@@ -131,6 +174,10 @@ pData->bIsConnected = 0; // TODO: remove this variable altogether
* This, for example, is needed after something went wrong.
* This function is void because it "can not" fail.
* rgerhards, 2008-06-04
+ * Note that we DO NOT discard the current buffer contents
+ * (if any). This permits us to save data between sessions. In
+ * the wort case, some duplication occurs, but we do not
+ * loose data.
*/
static inline void
DestructTCPInstanceData(instanceData *pData)
@@ -144,6 +191,7 @@ DestructTCPInstanceData(instanceData *pData)
BEGINcreateInstance
CODESTARTcreateInstance
+ pData->offsSndBuf = 0;
ENDcreateInstance
@@ -165,7 +213,7 @@ CODESTARTfreeInstance
}
free(pData->port);
- free(pData->f_hname);
+ free(pData->target);
free(pData->pszStrmDrvr);
free(pData->pszStrmDrvrAuthMode);
net.DestructPermittedPeers(&pData->pPermPeers);
@@ -174,7 +222,7 @@ ENDfreeInstance
BEGINdbgPrintInstInfo
CODESTARTdbgPrintInstInfo
- dbgprintf("%s", pData->f_hname);
+ dbgprintf("%s", pData->target);
ENDdbgPrintInstInfo
@@ -189,7 +237,7 @@ static rsRetVal UDPSend(instanceData *pData, char *msg, size_t len)
unsigned lsent = 0;
int bSendSuccess;
- if(pData->iUDPRebindInterval && (pData->nXmit++ % pData->iUDPRebindInterval == 0)) {
+ if(pData->iRebindInterval && (pData->nXmit++ % pData->iRebindInterval == 0)) {
dbgprintf("omfwd dropping UDP 'connection' (as configured)\n");
pData->nXmit = 1; /* else we have an addtl wrap at 2^31-1 */
CHKiRet(closeUDPSockets(pData));
@@ -242,7 +290,7 @@ static rsRetVal
setPermittedPeer(void __attribute__((unused)) *pVal, uchar *pszID)
{
DEFiRet;
- CHKiRet(net.AddPermittedPeer(&pPermPeers, pszID));
+ CHKiRet(net.AddPermittedPeer(&cs.pPermPeers, pszID));
free(pszID); /* no longer needed, but we must free it as of interface def */
finalize_it:
RETiRet;
@@ -253,30 +301,59 @@ finalize_it:
/* CODE FOR SENDING TCP MESSAGES */
-/* Send a frame via plain TCP protocol
- * rgerhards, 2007-12-28
+/* Send a buffer via TCP. Usually, this is used to send the current
+ * send buffer, but if a message is larger than the buffer, we need to
+ * have the capability to send the message buffer directly.
+ * rgerhards, 2011-04-04
*/
-static rsRetVal TCPSendFrame(void *pvData, char *msg, size_t len)
+static rsRetVal
+TCPSendBuf(instanceData *pData, uchar *buf, unsigned len)
{
DEFiRet;
+ unsigned alreadySent;
ssize_t lenSend;
- instanceData *pData = (instanceData *) pvData;
- lenSend = len;
+ alreadySent = 0;
netstrm.CheckConnection(pData->pNetstrm); /* hack for plain tcp syslog - see ptcp driver for details */
- CHKiRet(netstrm.Send(pData->pNetstrm, (uchar*)msg, &lenSend));
- dbgprintf("TCP sent %ld bytes, requested %ld\n", (long) lenSend, (long) len);
+ while(alreadySent != len) {
+ lenSend = len - alreadySent;
+ CHKiRet(netstrm.Send(pData->pNetstrm, buf+alreadySent, &lenSend));
+ DBGPRINTF("omfwd: TCP sent %ld bytes, requested %u\n", (long) lenSend, len - alreadySent);
+ alreadySent += lenSend;
+ }
- if(lenSend != (ssize_t) len) {
- /* no real error, could "just" not send everything...
- * For the time being, we ignore this...
- * rgerhards, 2005-10-25
- */
- dbgprintf("message not completely (tcp)send, ignoring %ld\n", (long) lenSend);
- usleep(1000); /* experimental - might be benefitial in this situation */
- /* TODO: we need to revisit this code -- rgerhards, 2007-12-28 */
+finalize_it:
+ RETiRet;
+}
+
+
+/* Add frame to send buffer (or send, if requried)
+ */
+static rsRetVal TCPSendFrame(void *pvData, char *msg, size_t len)
+{
+ DEFiRet;
+ instanceData *pData = (instanceData *) pvData;
+
+ DBGPRINTF("omfwd: add %u bytes to send buffer (curr offs %u)\n",
+ (unsigned) len, pData->offsSndBuf);
+ if(pData->offsSndBuf != 0 && pData->offsSndBuf + len >= sizeof(pData->sndBuf)) {
+ /* no buffer space left, need to commit previous records */
+ CHKiRet(TCPSendBuf(pData, pData->sndBuf, pData->offsSndBuf));
+ pData->offsSndBuf = 0;
+ iRet = RS_RET_PREVIOUS_COMMITTED;
+ }
+
+ /* check if the message is too large to fit into buffer */
+ if(len > sizeof(pData->sndBuf)) {
+ CHKiRet(TCPSendBuf(pData, (uchar*)msg, len));
+ ABORT_FINALIZE(RS_RET_OK); /* committed everything so far */
}
+ /* we now know the buffer has enough free space */
+ memcpy(pData->sndBuf + pData->offsSndBuf, msg, len);
+ pData->offsSndBuf += len;
+ iRet = RS_RET_DEFER_COMMIT;
+
finalize_it:
RETiRet;
}
@@ -309,7 +386,7 @@ static rsRetVal TCPSendInit(void *pvData)
if(pData->pNetstrm == NULL) {
CHKiRet(netstrms.Construct(&pData->pNS));
/* the stream driver must be set before the object is finalized! */
- CHKiRet(netstrms.SetDrvrName(pData->pNS, pszStrmDrvr));
+ CHKiRet(netstrms.SetDrvrName(pData->pNS, pData->pszStrmDrvr));
CHKiRet(netstrms.ConstructFinalize(pData->pNS));
/* now create the actual stream and connect to the server */
@@ -325,7 +402,7 @@ static rsRetVal TCPSendInit(void *pvData)
}
/* params set, now connect */
CHKiRet(netstrm.Connect(pData->pNetstrm, glbl.GetDefPFFamily(),
- (uchar*)pData->port, (uchar*)pData->f_hname));
+ (uchar*)pData->port, (uchar*)pData->target));
}
finalize_it:
@@ -351,23 +428,23 @@ static rsRetVal doTryResume(instanceData *pData)
FINALIZE;
/* The remote address is not yet known and needs to be obtained */
- dbgprintf(" %s\n", pData->f_hname);
+ dbgprintf(" %s\n", pData->target);
if(pData->protocol == FORW_UDP) {
memset(&hints, 0, sizeof(hints));
/* port must be numeric, because config file syntax requires this */
hints.ai_flags = AI_NUMERICSERV;
hints.ai_family = glbl.GetDefPFFamily();
hints.ai_socktype = SOCK_DGRAM;
- if((iErr = (getaddrinfo(pData->f_hname, pData->port, &hints, &res))) != 0) {
+ if((iErr = (getaddrinfo(pData->target, pData->port, &hints, &res))) != 0) {
dbgprintf("could not get addrinfo for hostname '%s':'%s': %d%s\n",
- pData->f_hname, pData->port, iErr, gai_strerror(iErr));
+ pData->target, pData->port, iErr, gai_strerror(iErr));
ABORT_FINALIZE(RS_RET_SUSPENDED);
}
- dbgprintf("%s found, resuming.\n", pData->f_hname);
+ dbgprintf("%s found, resuming.\n", pData->target);
pData->f_addr = res;
pData->bIsConnected = 1;
if(pData->pSockArray == NULL) {
- pData->pSockArray = net.create_udp_socket((uchar*)pData->f_hname, NULL, 0);
+ pData->pSockArray = net.create_udp_socket((uchar*)pData->target, NULL, 0);
}
} else {
CHKiRet(TCPSendInit((void*)pData));
@@ -391,6 +468,13 @@ CODESTARTtryResume
iRet = doTryResume(pData);
ENDtryResume
+
+BEGINbeginTransaction
+CODESTARTbeginTransaction
+dbgprintf("omfwd: beginTransaction\n");
+ENDbeginTransaction
+
+
BEGINdoAction
char *psz; /* temporary buffering */
register unsigned l;
@@ -403,7 +487,7 @@ CODESTARTdoAction
iMaxLine = glbl.GetMaxLine();
- dbgprintf(" %s:%s/%s\n", pData->f_hname, pData->port,
+ dbgprintf(" %s:%s/%s\n", pData->target, pData->port,
pData->protocol == FORW_UDP ? "udp" : "tcp");
psz = (char*) ppString[0];
@@ -456,9 +540,8 @@ CODESTARTdoAction
CHKiRet(UDPSend(pData, psz, l));
} else {
/* forward via TCP */
- rsRetVal ret;
- ret = tcpclt.Send(pData->pTCPClt, pData, psz, l);
- if(ret != RS_RET_OK) {
+ iRet = tcpclt.Send(pData->pTCPClt, pData, psz, l);
+ if(iRet != RS_RET_OK && iRet != RS_RET_DEFER_COMMIT && iRet != RS_RET_PREVIOUS_COMMITTED) {
/* error! */
dbgprintf("error forwarding via tcp, suspending\n");
DestructTCPInstanceData(pData);
@@ -472,6 +555,17 @@ finalize_it:
ENDdoAction
+BEGINendTransaction
+CODESTARTendTransaction
+dbgprintf("omfwd: endTransaction, offsSndBuf %u\n", pData->offsSndBuf);
+ if(pData->offsSndBuf != 0) {
+ iRet = TCPSendBuf(pData, pData->sndBuf, pData->offsSndBuf);
+ pData->offsSndBuf = 0;
+ }
+ENDendTransaction
+
+
+
/* This function loads TCP support, if not already loaded. It will be called
* during config processing. To server ressources, TCP support will only
* be loaded if it actually is used. -- rgerhard, 2008-04-17
@@ -489,6 +583,183 @@ finalize_it:
}
+/* initialize TCP structures (if necessary) after the instance has been
+ * created.
+ */
+static rsRetVal
+initTCP(instanceData *pData)
+{
+ DEFiRet;
+ if(pData->protocol == FORW_TCP) {
+ /* create our tcpclt */
+ CHKiRet(tcpclt.Construct(&pData->pTCPClt));
+ CHKiRet(tcpclt.SetResendLastOnRecon(pData->pTCPClt, pData->bResendLastOnRecon));
+ /* and set callbacks */
+ CHKiRet(tcpclt.SetSendInit(pData->pTCPClt, TCPSendInit));
+ CHKiRet(tcpclt.SetSendFrame(pData->pTCPClt, TCPSendFrame));
+ CHKiRet(tcpclt.SetSendPrepRetry(pData->pTCPClt, TCPSendPrepRetry));
+ CHKiRet(tcpclt.SetFraming(pData->pTCPClt, pData->tcp_framing));
+ CHKiRet(tcpclt.SetRebindInterval(pData->pTCPClt, pData->iRebindInterval));
+ pData->iStrmDrvrMode = cs.iStrmDrvrMode;
+ if(cs.pszStrmDrvr != NULL)
+ CHKmalloc(pData->pszStrmDrvr = (uchar*)strdup((char*)cs.pszStrmDrvr));
+ if(cs.pszStrmDrvrAuthMode != NULL)
+ CHKmalloc(pData->pszStrmDrvrAuthMode =
+ (uchar*)strdup((char*)cs.pszStrmDrvrAuthMode));
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->tplName = NULL;
+ pData->protocol = FORW_UDP;
+ pData->tcp_framing = TCP_FRAMING_OCTET_STUFFING;
+ pData->pszStrmDrvr = NULL;
+ pData->pszStrmDrvrAuthMode = NULL;
+ pData->iStrmDrvrMode = 0;
+ pData->iRebindInterval = 0;
+ pData->bResendLastOnRecon = 0;
+ pData->pPermPeers = NULL;
+ pData->compressionLevel = 0;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+ rsRetVal localRet;
+CODESTARTnewActInst
+ DBGPRINTF("newActInst (omfwd)\n");
+
+ pvals = nvlstGetParams(lst, &actpblk, NULL);
+ if(pvals == NULL) {
+ errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "omfwd: either the \"file\" or "
+ "\"dynfile\" parameter must be given");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("action param blk in omfwd:\n");
+ cnfparamsPrint(&actpblk, pvals);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "target")) {
+ pData->target = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "port")) {
+ pData->port = es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "protocol")) {
+ if(!es_strcasebufcmp(pvals[i].val.d.estr, (uchar*)"udp", 3)) {
+ pData->protocol = FORW_UDP;
+ } else if(!es_strcasebufcmp(pvals[i].val.d.estr, (uchar*)"tcp", 3)) {
+ localRet = loadTCPSupport();
+ if(localRet != RS_RET_OK) {
+ errmsg.LogError(0, localRet, "could not activate network stream modules for TCP "
+ "(internal error %d) - are modules missing?", localRet);
+ ABORT_FINALIZE(localRet);
+ }
+ pData->protocol = FORW_TCP;
+ } else {
+ uchar *str;
+ str = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ errmsg.LogError(0, RS_RET_INVLD_PROTOCOL,
+ "omfwd: invalid protocol \"%s\"", str);
+ free(str);
+ ABORT_FINALIZE(RS_RET_INVLD_PROTOCOL);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "tcp_framing")) {
+ if(!es_strcasebufcmp(pvals[i].val.d.estr, (uchar*)"traditional", 11)) {
+ pData->tcp_framing = TCP_FRAMING_OCTET_STUFFING;
+ } else if(!es_strcasebufcmp(pvals[i].val.d.estr, (uchar*)"octet-counted", 13)) {
+ pData->tcp_framing = TCP_FRAMING_OCTET_COUNTING;
+ } else {
+ uchar *str;
+ str = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ errmsg.LogError(0, RS_RET_CNF_INVLD_FRAMING,
+ "omfwd: invalid framing \"%s\"", str);
+ free(str);
+ ABORT_FINALIZE(RS_RET_CNF_INVLD_FRAMING );
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "rebindinterval")) {
+ pData->iRebindInterval = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriver")) {
+ pData->pszStrmDrvr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "streamdrivermode")) {
+ pData->iStrmDrvrMode = pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriverauthmode")) {
+ pData->pszStrmDrvrAuthMode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "streamdriverpermittedpeers")) {
+ uchar *start, *str;
+ uchar save;
+ uchar *p;
+ int lenStr;
+ str = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ start = str;
+ lenStr = ustrlen(start); /* we need length after '\0' has been dropped... */
+ while(lenStr > 0) {
+ p = start;
+ while(*p && *p != ',' && lenStr--)
+ p++;
+ if(*p == ',') {
+ *p = '\0';
+ }
+ save = *(p+1); /* we always have this, at least the \0 byte at EOS */
+ *(p+1) = '\0';
+ if(*start == '\0') {
+ DBGPRINTF("omfwd: ignoring empty permitted peer\n");
+ } else {
+ dbgprintf("omfwd: adding permitted peer: '%s'\n", start);
+ CHKiRet(net.AddPermittedPeer(&(pData->pPermPeers), start));
+ }
+ start = p+1;
+ if(lenStr)
+ --lenStr;
+ *(p+1) = save;
+ }
+ free(str);
+ } else if(!strcmp(actpblk.descr[i].name, "ziplevel")) {
+# ifdef USE_NETZIP
+ int complevel = pvals[i].val.d.n;
+ if(complevel >= 0 && complevel <= 10) {
+ pData->compressionLevel = complevel;
+ } else {
+ errmsg.LogError(0, NO_ERRCODE, "Invalid ziplevel %d specified in "
+ "forwardig action - NOT turning on compression.",
+ complevel);
+ }
+# else
+ errmsg.LogError(0, NO_ERRCODE, "Compression requested, but rsyslogd is not compiled "
+ "with compression support - request ignored.");
+# endif /* #ifdef USE_NETZIP */
+ } else if(!strcmp(actpblk.descr[i].name, "resendlastmsgonreconnect")) {
+ pData->bResendLastOnRecon = (int) pvals[i].val.d.n;
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ DBGPRINTF("omfwd: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+ CODE_STD_STRING_REQUESTnewActInst(1)
+
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, ustrdup((pData->tplName == NULL) ?
+ (uchar*)"RSYSLOG_TraditionalForwardFormat" : (uchar*)pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+
+ CHKiRet(initTCP(pData));
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
BEGINparseSelectorAct
uchar *q;
int i;
@@ -594,6 +865,7 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* JUST SKIP */;
}
+ pData->tcp_framing = tcp_framing;
pData->port = NULL;
if(*p == ':') { /* process port */
uchar * tmp;
@@ -625,42 +897,34 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
if(*p == ';' || *p == '#' || isspace(*p)) {
uchar cTmp = *p;
*p = '\0'; /* trick to obtain hostname (later)! */
- CHKmalloc(pData->f_hname = strdup((char*) q));
+ CHKmalloc(pData->target = strdup((char*) q));
*p = cTmp;
} else {
- CHKmalloc(pData->f_hname = strdup((char*) q));
+ CHKmalloc(pData->target = strdup((char*) q));
}
/* copy over config data as needed */
- pData->iUDPRebindInterval = iUDPRebindInterval;
- pData->iTCPRebindInterval = iTCPRebindInterval;
+ pData->iRebindInterval = (pData->protocol == FORW_TCP) ?
+ cs.iTCPRebindInterval : cs.iUDPRebindInterval;
/* process template */
CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
- (pszTplName == NULL) ? (uchar*)"RSYSLOG_TraditionalForwardFormat" : pszTplName));
+ (cs.pszTplName == NULL) ? (uchar*)"RSYSLOG_TraditionalForwardFormat" : cs.pszTplName));
if(pData->protocol == FORW_TCP) {
- /* create our tcpclt */
- CHKiRet(tcpclt.Construct(&pData->pTCPClt));
- CHKiRet(tcpclt.SetResendLastOnRecon(pData->pTCPClt, bResendLastOnRecon));
- /* and set callbacks */
- CHKiRet(tcpclt.SetSendInit(pData->pTCPClt, TCPSendInit));
- CHKiRet(tcpclt.SetSendFrame(pData->pTCPClt, TCPSendFrame));
- CHKiRet(tcpclt.SetSendPrepRetry(pData->pTCPClt, TCPSendPrepRetry));
- CHKiRet(tcpclt.SetFraming(pData->pTCPClt, tcp_framing));
- CHKiRet(tcpclt.SetRebindInterval(pData->pTCPClt, pData->iTCPRebindInterval));
- pData->iStrmDrvrMode = iStrmDrvrMode;
- if(pszStrmDrvr != NULL)
- CHKmalloc(pData->pszStrmDrvr = (uchar*)strdup((char*)pszStrmDrvr));
- if(pszStrmDrvrAuthMode != NULL)
+ pData->bResendLastOnRecon = cs.bResendLastOnRecon;
+ pData->iStrmDrvrMode = cs.iStrmDrvrMode;
+ if(cs.pszStrmDrvr != NULL)
+ CHKmalloc(pData->pszStrmDrvr = (uchar*)strdup((char*)cs.pszStrmDrvr));
+ if(cs.pszStrmDrvrAuthMode != NULL)
CHKmalloc(pData->pszStrmDrvrAuthMode =
- (uchar*)strdup((char*)pszStrmDrvrAuthMode));
- if(pPermPeers != NULL) {
- pData->pPermPeers = pPermPeers;
- pPermPeers = NULL;
+ (uchar*)strdup((char*)cs.pszStrmDrvrAuthMode));
+ if(cs.pPermPeers != NULL) {
+ pData->pPermPeers = cs.pPermPeers;
+ cs.pPermPeers = NULL;
}
}
-
+ CHKiRet(initTCP(pData));
CODE_STD_FINALIZERparseSelectorAct
ENDparseSelectorAct
@@ -671,21 +935,14 @@ ENDparseSelectorAct
static void
freeConfigVars(void)
{
- if(pszTplName != NULL) {
- free(pszTplName);
- pszTplName = NULL;
- }
- if(pszStrmDrvr != NULL) {
- free(pszStrmDrvr);
- pszStrmDrvr = NULL;
- }
- if(pszStrmDrvrAuthMode != NULL) {
- free(pszStrmDrvrAuthMode);
- pszStrmDrvrAuthMode = NULL;
- }
- if(pPermPeers != NULL) {
- free(pPermPeers);
- }
+ free(cs.pszTplName);
+ cs.pszTplName = NULL;
+ free(cs.pszStrmDrvr);
+ cs.pszStrmDrvr = NULL;
+ free(cs.pszStrmDrvrAuthMode);
+ cs.pszStrmDrvrAuthMode = NULL;
+ free(cs.pPermPeers);
+ cs.pPermPeers = NULL; /* TODO: fix in older builds! */
}
@@ -698,7 +955,6 @@ CODESTARTmodExit
objRelease(netstrm, LM_NETSTRMS_FILENAME);
objRelease(netstrms, LM_NETSTRMS_FILENAME);
objRelease(tcpclt, LM_TCPCLT_FILENAME);
-
freeConfigVars();
ENDmodExit
@@ -706,6 +962,8 @@ ENDmodExit
BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
+CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */
ENDqueryEtryPt
@@ -717,10 +975,10 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
freeConfigVars();
/* we now must reset all non-string values */
- iStrmDrvrMode = 0;
- bResendLastOnRecon = 0;
- iUDPRebindInterval = 0;
- iTCPRebindInterval = 0;
+ cs.iStrmDrvrMode = 0;
+ cs.bResendLastOnRecon = 0;
+ cs.iUDPRebindInterval = 0;
+ cs.iTCPRebindInterval = 0;
return RS_RET_OK;
}
@@ -728,20 +986,21 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
BEGINmodInit(Fwd)
CODESTARTmodInit
+INITLegCnfVars
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(glbl, CORE_COMPONENT));
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(net,LM_NET_FILENAME));
- CHKiRet(regCfSysLineHdlr((uchar *)"actionforwarddefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszTplName, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"actionsendtcprebindinterval", 0, eCmdHdlrInt, NULL, &iTCPRebindInterval, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"actionsendudprebindinterval", 0, eCmdHdlrInt, NULL, &iUDPRebindInterval, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriver", 0, eCmdHdlrGetWord, NULL, &pszStrmDrvr, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdrivermode", 0, eCmdHdlrInt, NULL, &iStrmDrvrMode, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriverauthmode", 0, eCmdHdlrGetWord, NULL, &pszStrmDrvrAuthMode, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionforwarddefaulttemplate", 0, eCmdHdlrGetWord, NULL, &cs.pszTplName, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendtcprebindinterval", 0, eCmdHdlrInt, NULL, &cs.iTCPRebindInterval, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendudprebindinterval", 0, eCmdHdlrInt, NULL, &cs.iUDPRebindInterval, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriver", 0, eCmdHdlrGetWord, NULL, &cs.pszStrmDrvr, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdrivermode", 0, eCmdHdlrInt, NULL, &cs.iStrmDrvrMode, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriverauthmode", 0, eCmdHdlrGetWord, NULL, &cs.pszStrmDrvrAuthMode, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriverpermittedpeer", 0, eCmdHdlrGetWord, setPermittedPeer, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"actionsendresendlastmsgonreconnect", 0, eCmdHdlrBinary, NULL, &bResendLastOnRecon, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionsendresendlastmsgonreconnect", 0, eCmdHdlrBinary, NULL, &cs.bResendLastOnRecon, NULL));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
diff --git a/tools/ompipe.c b/tools/ompipe.c
index 1a9d610f..30cb9bfc 100644
--- a/tools/ompipe.c
+++ b/tools/ompipe.c
@@ -57,6 +57,7 @@
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("ompipe")
/* internal structures
*/
@@ -69,11 +70,33 @@ DEFobjCurrIf(errmsg)
typedef struct _instanceData {
- uchar f_fname[MAXFNAME];/* pipe or template name (display only) */
- short fd; /* pipe descriptor for (current) pipe */
- sbool bHadError; /* did we already have/report an error on this pipe? */
+ uchar *pipe; /* pipe or template name (display only) */
+ uchar *tplName; /* format template to use */
+ short fd; /* pipe descriptor for (current) pipe */
+ sbool bHadError; /* did we already have/report an error on this pipe? */
} instanceData;
+typedef struct configSettings_s {
+ EMPTY_STRUCT
+} configSettings_t;
+static configSettings_t __attribute__((unused)) cs;
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "pipe", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "template", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ENDinitConfVars
+
BEGINisCompatibleWithFeature
CODESTARTisCompatibleWithFeature
@@ -84,7 +107,7 @@ ENDisCompatibleWithFeature
BEGINdbgPrintInstInfo
CODESTARTdbgPrintInstInfo
- dbgprintf("pipe %s", pData->f_fname);
+ dbgprintf("pipe %s", pData->pipe);
if (pData->fd == -1)
dbgprintf(" (unused)");
ENDdbgPrintInstInfo
@@ -100,17 +123,17 @@ static inline rsRetVal
preparePipe(instanceData *pData)
{
DEFiRet;
- pData->fd = open((char*) pData->f_fname, O_RDWR|O_NONBLOCK|O_CLOEXEC);
+ pData->fd = open((char*) pData->pipe, O_RDWR|O_NONBLOCK|O_CLOEXEC);
if(pData->fd < 0 ) {
pData->fd = -1;
if(!pData->bHadError) {
char errStr[1024];
rs_strerror_r(errno, errStr, sizeof(errStr));
errmsg.LogError(0, RS_RET_NO_FILE_ACCESS, "Could no open output pipe '%s': %s",
- pData->f_fname, errStr);
+ pData->pipe, errStr);
pData->bHadError = 1;
}
- DBGPRINTF("Error opening log pipe: %s\n", pData->f_fname);
+ DBGPRINTF("Error opening log pipe: %s\n", pData->pipe);
}
RETiRet;
}
@@ -150,7 +173,7 @@ static rsRetVal writePipe(uchar **ppString, instanceData *pData)
pData->fd = -1; /* tell that fd is no longer open! */
iRet = RS_RET_SUSPENDED;
errno = e;
- errmsg.LogError(0, NO_ERRCODE, "%s", pData->f_fname);
+ errmsg.LogError(0, NO_ERRCODE, "%s", pData->pipe);
}
finalize_it:
@@ -160,6 +183,7 @@ finalize_it:
BEGINcreateInstance
CODESTARTcreateInstance
+ pData->pipe = NULL;
pData->fd = -1;
pData->bHadError = 0;
ENDcreateInstance
@@ -167,6 +191,7 @@ ENDcreateInstance
BEGINfreeInstance
CODESTARTfreeInstance
+ free(pData->pipe);
if(pData->fd != -1)
close(pData->fd);
ENDfreeInstance
@@ -178,11 +203,54 @@ ENDtryResume
BEGINdoAction
CODESTARTdoAction
- DBGPRINTF(" (%s)\n", pData->f_fname);
+ DBGPRINTF(" (%s)\n", pData->pipe);
iRet = writePipe(ppString, pData);
ENDdoAction
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->tplName = NULL;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
+ int i;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "pipe")) {
+ pData->pipe = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("ompipe: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->tplName == NULL) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*) "RSYSLOG_FileFormat",
+ OMSR_NO_RQD_TPL_OPTS));
+ } else {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0,
+ (uchar*) strdup((char*) pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+ }
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
BEGINparseSelectorAct
CODESTARTparseSelectorAct
/* yes, the if below is redundant, but I need it now. Will go away as
@@ -202,19 +270,10 @@ CODESTARTparseSelectorAct
}
CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ CHKmalloc(pData->pipe = malloc(512));
++p;
- /* rgerhards 2004-11-17: from now, we need to have different
- * processing, because after the first comma, the template name
- * to use is specified. So we need to scan for the first coma first
- * and then look at the rest of the line.
- */
- CHKiRet(cflineParseFileName(p, (uchar*) pData->f_fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
+ CHKiRet(cflineParseFileName(p, (uchar*) pData->pipe, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS,
(pszFileDfltTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pszFileDfltTplName));
-
- /* at this stage, we ignore the return value of preparePipe, this is taken
- * care of in later steps. -- rgerhards, 2009-03-19
- */
- preparePipe(pData);
CODE_STD_FINALIZERparseSelectorAct
ENDparseSelectorAct
@@ -238,11 +297,14 @@ BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_OMOD_QUERIES
CODEqueryEtryPt_doHUP
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
ENDqueryEtryPt
BEGINmodInit(Pipe)
CODESTARTmodInit
+INITLegCnfVars
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
diff --git a/tools/omshell.c b/tools/omshell.c
index ed205a2f..ac62fa62 100644
--- a/tools/omshell.c
+++ b/tools/omshell.c
@@ -1,6 +1,13 @@
/* omshell.c
* This is the implementation of the build-in shell output module.
*
+ * ************* DO NOT EXTEND THIS MODULE **************
+ * This is pure legacy, omprog has much better and more
+ * secure functionality than this module. It is NOT
+ * recommended to base new work on it!
+ * 2012-01-19 rgerhards
+ * ******************************************************
+ *
* NOTE: read comments in module-template.h to understand how this file
* works!
*
@@ -56,7 +63,6 @@ typedef struct _instanceData {
uchar progName[MAXFNAME]; /* program to execute */
} instanceData;
-
BEGINcreateInstance
CODESTARTcreateInstance
ENDcreateInstance
diff --git a/tools/omusrmsg.c b/tools/omusrmsg.c
index 9130e403..e57d7ef9 100644
--- a/tools/omusrmsg.c
+++ b/tools/omusrmsg.c
@@ -10,17 +10,6 @@
*
* Copyright 2007-2012 Adiscon GmbH.
*
- * rgerhards, 2008-07-04 (happy Independence Day!): rsyslog inherited the
- * wall functionality from sysklogd. Sysklogd was single-threaded and could
- * not afford to spent a lot of time inside a single action. Thus, it forked
- * off a new process to do the wall. In rsyslog, however, this creates some
- * grief with the threading model. Also, we do not really need to de-couple
- * processing, because we have ample ways to do it in rsyslog. Plus, the
- * default main message queue will care for a somewhat longer execution time.
- * So in short, the real fix to the problem is an architecture change. From
- * now on, we will not fork off a new process but rather do the notification
- * within the current one. This also reduces system overhead.
- *
* This file is part of rsyslog.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -45,6 +34,7 @@
#include <string.h>
#include <assert.h>
#include <signal.h>
+#include <ctype.h>
#include <sys/param.h>
#ifdef HAVE_UTMP_H
# include <utmp.h>
@@ -84,6 +74,7 @@
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omusrmsg")
/* internal structures
*/
@@ -93,8 +84,31 @@ DEFobjCurrIf(errmsg)
typedef struct _instanceData {
int bIsWall; /* 1- is wall, 0 - individual users */
char uname[MAXUNAMES][UNAMESZ+1];
+ uchar *tplName;
} instanceData;
+typedef struct configSettings_s {
+ EMPTY_STRUCT
+} configSettings_t;
+static configSettings_t __attribute__((unused)) cs;
+
+
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "users", eCmdHdlrString, CNFPARAM_REQUIRED },
+ { "template", eCmdHdlrGetWord, 0 }
+};
+static struct cnfparamblk actpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ENDinitConfVars
+
BEGINcreateInstance
CODESTARTcreateInstance
@@ -110,7 +124,7 @@ ENDisCompatibleWithFeature
BEGINfreeInstance
CODESTARTfreeInstance
- /* TODO: free the instance pointer (currently a leak, will go away) */
+ free(pData->tplName);
ENDfreeInstance
@@ -266,22 +280,117 @@ CODESTARTdoAction
ENDdoAction
-BEGINparseSelectorAct
- uchar *q;
+static inline void
+populateUsers(instanceData *pData, es_str_t *usrs)
+{
+ int i;
+ int iDst;
+ es_size_t iUsr;
+ es_size_t len;
+ uchar *c;
+
+ len = es_strlen(usrs);
+ c = es_getBufAddr(usrs);
+ pData->bIsWall = 0; /* write to individual users */
+ iUsr = 0;
+ for(i = 0 ; i < MAXUNAMES && iUsr < len ; ++i) {
+ for( iDst = 0
+ ; iDst < UNAMESZ && iUsr < len && c[iUsr] != ','
+ ; ++iDst, ++iUsr) {
+ pData->uname[i][iDst] = c[iUsr];
+ }
+ pData->uname[i][iDst] = '\0';
+ DBGPRINTF("omusrmsg: send to user '%s'\n", pData->uname[i]);
+ if(iUsr < len && c[iUsr] != ',') {
+ errmsg.LogError(0, RS_RET_ERR, "user name '%s...' too long - "
+ "ignored", pData->uname[i]);
+ --i;
+ ++iUsr;
+ while(iUsr < len && c[iUsr] != ',')
+ ++iUsr; /* skip to next name */
+ } else if(iDst == 0) {
+ errmsg.LogError(0, RS_RET_ERR, "no user name given - "
+ "ignored");
+ --i;
+ ++iUsr;
+ while(iUsr < len && c[iUsr] != ',')
+ ++iUsr; /* skip to next name */
+ }
+ if(iUsr < len) {
+ ++iUsr; /* skip "," */
+ while(iUsr < len && isspace(c[iUsr]))
+ ++iUsr; /* skip whitespace */
+ }
+ }
+ if(i == MAXUNAMES && iUsr != len) {
+ errmsg.LogError(0, RS_RET_ERR, "omusrmsg supports only up to %d "
+ "user names in a single action - all others have been ignored",
+ MAXUNAMES);
+ }
+}
+
+
+static inline void
+setInstParamDefaults(instanceData *pData)
+{
+ pData->bIsWall = 0;
+ pData->tplName = NULL;
+}
+
+BEGINnewActInst
+ struct cnfparamvals *pvals;
int i;
- int bHadWarning = 0;
+CODESTARTnewActInst
+ if((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) {
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ CHKiRet(createInstance(&pData));
+ setInstParamDefaults(pData);
+
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ for(i = 0 ; i < actpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(actpblk.descr[i].name, "users")) {
+ if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"*", 1)) {
+ pData->bIsWall = 1;
+ } else {
+ populateUsers(pData, pvals[i].val.d.estr);
+ }
+ } else if(!strcmp(actpblk.descr[i].name, "template")) {
+ pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("omusrmsg: program error, non-handled "
+ "param '%s'\n", actpblk.descr[i].name);
+ }
+ }
+
+ if(pData->tplName == NULL) {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0,
+ (uchar*) strdup(pData->bIsWall ? " WallFmt" : " StdUsrMsgFmt"),
+ OMSR_NO_RQD_TPL_OPTS));
+ } else {
+ CHKiRet(OMSRsetEntry(*ppOMSR, 0,
+ (uchar*) strdup((char*) pData->tplName),
+ OMSR_NO_RQD_TPL_OPTS));
+ }
+CODE_STD_FINALIZERnewActInst
+ cnfparamvalsDestruct(pvals, &actpblk);
+ENDnewActInst
+
+
+BEGINparseSelectorAct
+ es_str_t *usrs;
+ int bHadWarning;
CODESTARTparseSelectorAct
CODE_STD_STRING_REQUESTparseSelectorAct(1)
- /* User names must begin with a gnu e-regex:
- * [a-zA-Z0-9_.]
- * plus '*' for wall
- */
if(!strncmp((char*) p, ":omusrmsg:", sizeof(":omusrmsg:") - 1)) {
p += sizeof(":omusrmsg:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
} else {
if(!*p || !((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z')
|| (*p >= '0' && *p <= '9') || *p == '_' || *p == '.' || *p == '*')) {
- ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
} else {
errmsg.LogError(0, RS_RET_OUTDATED_STMT,
"action '%s' treated as ':omusrmsg:%s' - please "
@@ -299,26 +408,14 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
pData->bIsWall = 1; /* write to all users */
CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) " WallFmt"));
} else {
- /* everything else beginning with the regex above
- * is currently treated as a user name -- TODO: is this portable?
- */
- dbgprintf("users: %s\n", p); /* ASP */
- pData->bIsWall = 0; /* write to individual users */
- for (i = 0; i < MAXUNAMES && *p && *p != ';'; i++) {
- for (q = p; *q && *q != ',' && *q != ';'; )
- q++;
- (void) strncpy((char*) pData->uname[i], (char*) p, UNAMESZ);
- if ((q - p) > UNAMESZ)
- pData->uname[i][UNAMESZ] = '\0';
- else
- pData->uname[i][q - p] = '\0';
- while (*q == ',' || *q == ' ')
- q++;
- p = q;
+ /* everything else is currently treated as a user name */
+ usrs = es_newStr(128);
+ while(*p && *p != ';') {
+ es_addChar(&usrs, *p);
+ ++p;
}
- /* done, on to the template
- * TODO: we need to handle the case where i >= MAXUNAME!
- */
+ populateUsers(pData, usrs);
+ es_deleteStr(usrs);
if((iRet = cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*)" StdUsrMsgFmt"))
!= RS_RET_OK)
goto finalize_it;
@@ -337,11 +434,13 @@ ENDmodExit
BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES
ENDqueryEtryPt
BEGINmodInit(UsrMsg)
CODESTARTmodInit
+INITLegCnfVars
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(objUse(errmsg, CORE_COMPONENT));
diff --git a/tools/pmrfc3164.c b/tools/pmrfc3164.c
index 6d2d22b1..2657780d 100644
--- a/tools/pmrfc3164.c
+++ b/tools/pmrfc3164.c
@@ -75,7 +75,6 @@ ENDisCompatibleWithFeature
BEGINparse
uchar *p2parse;
int lenMsg;
- int bTAGCharDetected;
int i; /* general index for parsing */
uchar bufParseTAG[CONF_TAG_MAXSIZE];
uchar bufParseHOSTNAME[CONF_HOSTNAME_MAXSIZE];
@@ -137,7 +136,6 @@ CODESTARTparse
* rgerhards, 2009-06-23: and I now have extended this logic to every character
* that is not a valid hostname.
*/
- bTAGCharDetected = 0;
if(lenMsg > 0 && pMsg->msgFlags & PARSE_HOSTNAME) {
i = 0;
while(i < lenMsg && (isalnum(p2parse[i]) || p2parse[i] == '.' || p2parse[i] == '.'
diff --git a/tools/pmrfc5424.c b/tools/pmrfc5424.c
index b06f1347..9b5c6165 100644
--- a/tools/pmrfc5424.c
+++ b/tools/pmrfc5424.c
@@ -106,7 +106,7 @@ static int parseRFCField(uchar **pp2parse, uchar *pResult, int *pLenStr)
/* set the new parse pointer */
*pp2parse = p2parse;
- return 0;
+ return iRet;
}
@@ -191,7 +191,7 @@ static int parseRFCStructuredData(uchar **pp2parse, uchar *pResult, int *pLenStr
/* set the new parse pointer */
*pp2parse = p2parse;
*pLenStr = lenStr;
- return 0;
+ return iRet;
}
/* parse a RFC5424-formatted syslog message. This function returns
diff --git a/tools/syslogd.c b/tools/syslogd.c
index 9a331a83..44e60b1c 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -108,18 +108,6 @@
#include "action.h"
#include "iminternal.h"
#include "cfsysline.h"
-#include "omshell.h"
-#include "omusrmsg.h"
-#include "omfwd.h"
-#include "omfile.h"
-#include "ompipe.h"
-#include "omdiscard.h"
-#include "pmrfc5424.h"
-#include "pmrfc3164.h"
-#include "smfile.h"
-#include "smtradfile.h"
-#include "smfwd.h"
-#include "smtradfwd.h"
#include "threads.h"
#include "wti.h"
#include "queue.h"
@@ -133,8 +121,9 @@
#include "ruleset.h"
#include "rule.h"
#include "net.h"
-#include "vm.h"
#include "prop.h"
+#include "rsconf.h"
+#include "dnscache.h"
#include "sd-daemon.h"
/* definitions for objects we access */
@@ -142,13 +131,13 @@ DEFobjCurrIf(obj)
DEFobjCurrIf(glbl)
DEFobjCurrIf(datetime) /* TODO: make go away! */
DEFobjCurrIf(conf)
-DEFobjCurrIf(expr)
DEFobjCurrIf(module)
DEFobjCurrIf(errmsg)
DEFobjCurrIf(rule)
DEFobjCurrIf(ruleset)
DEFobjCurrIf(prop)
DEFobjCurrIf(parser)
+DEFobjCurrIf(rsconf)
DEFobjCurrIf(net) /* TODO: make go away! */
@@ -199,6 +188,8 @@ static rsRetVal queryLocalHostname(void);
# define _PATH_TTY "/dev/tty"
#endif
+rsconf_t *ourConf; /* our config object */
+
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 */
@@ -211,7 +202,7 @@ static int bFinished = 0; /* used by termination signal handler, read-only excep
* is either 0 or the number of the signal that requested the
* termination.
*/
-static int iConfigVerify = 0; /* is this just a config verify run? */
+int iConfigVerify = 0; /* is this just a config verify run? */
/* Intervals at which we flush out "message repeated" messages,
* in seconds after previous message is logged. After each flush,
@@ -224,122 +215,24 @@ int repeatinterval[2] = { 30, 60 }; /* # of secs before flush */
static pid_t ppid; /* This is a quick and dirty hack used for spliting main/startup thread */
-typedef struct legacyOptsLL_s {
- uchar *line;
- struct legacyOptsLL_s *next;
-} legacyOptsLL_t;
-legacyOptsLL_t *pLegacyOptsLL = NULL;
-
/* global variables for config file state */
int iCompatibilityMode = 0; /* version we should be compatible with; 0 means sysklogd. It is
the default, so if no -c<n> option is given, we make ourselvs
as compatible to sysklogd as possible. */
-#define DFLT_bLogStatusMsgs 1
-static int bLogStatusMsgs = DFLT_bLogStatusMsgs; /* log rsyslog start/stop/HUP messages? */
-static int bDebugPrintTemplateList = 1;/* output template list in debug mode? */
-static int bDebugPrintCfSysLineHandlerList = 1;/* output cfsyslinehandler list in debug mode? */
-static int bDebugPrintModuleList = 1;/* output module list in debug mode? */
-static int bErrMsgToStderr = 1; /* print error messages to stderr (in addition to everything else)? */
-int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */
-int bAbortOnUncleanConfig = 0; /* abort run (rather than starting with partial config) if there was any issue in conf */
-int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */
/* end global config file state variables */
int MarkInterval = 20 * 60; /* interval between marks in seconds - read-only after startup */
int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */
static int NoFork = 0; /* don't fork - don't run in daemon mode - read-only after startup */
-static int bHaveMainQueue = 0;/* set to 1 if the main queue - in queueing mode - is available
+int bHaveMainQueue = 0;/* set to 1 if the main queue - in queueing mode - is available
* If the main queue is either not yet ready or not running in
* queueing mode (mode DIRECT!), then this is set to 0.
*/
-static int uidDropPriv = 0; /* user-id to which priveleges should be dropped to (AFTER init()!) */
-static int gidDropPriv = 0; /* group-id to which priveleges should be dropped to (AFTER init()!) */
extern int errno;
-static uchar *pszConfDAGFile = NULL; /* name of config DAG file, non-NULL means generate one */
/* main message queue and its configuration parameters */
qqueue_t *pMsgQueue = NULL; /* the main message queue */
-static int iMainMsgQueueSize = 10000; /* size of the main message queue above */
-static int iMainMsgQHighWtrMark = 8000; /* high water mark for disk-assisted queues */
-static int iMainMsgQLightDlyMark = -1; /* light delay mark for disk-assisted queues */
-static int iMainMsgQLowWtrMark = 2000; /* low water mark for disk-assisted queues */
-static int iMainMsgQDiscardMark = 9800; /* begin to discard messages */
-static int iMainMsgQDiscardSeverity = 8; /* by default, discard nothing to prevent unintentional loss */
-static int iMainMsgQueueNumWorkers = 1; /* number of worker threads for the mm queue above */
-static queueType_t MainMsgQueType = QUEUETYPE_FIXED_ARRAY; /* type of the main message queue above */
-static uchar *pszMainMsgQFName = NULL; /* prefix for the main message queue file */
-static int64 iMainMsgQueMaxFileSize = 1024*1024;
-static int iMainMsgQPersistUpdCnt = 0; /* persist queue info every n updates */
-static int bMainMsgQSyncQeueFiles = 0; /* sync queue files on every write? */
-static int iMainMsgQtoQShutdown = 1500; /* queue shutdown (ms) */
-static int iMainMsgQtoActShutdown = 1000; /* action shutdown (in phase 2) */
-static int iMainMsgQtoEnq = 2000; /* timeout for queue enque */
-static int iMainMsgQtoWrkShutdown = 60000; /* timeout for worker thread shutdown */
-static int iMainMsgQWrkMinMsgs = 100; /* minimum messages per worker needed to start a new one */
-static int iMainMsgQDeqSlowdown = 0; /* dequeue slowdown (simple rate limiting) */
-static int64 iMainMsgQueMaxDiskSpace = 0; /* max disk space allocated 0 ==> unlimited */
-static int64 iMainMsgQueDeqBatchSize = 32; /* dequeue batch size */
-static int bMainMsgQSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */
-static int iMainMsgQueueDeqtWinFromHr = 0; /* hour begin of time frame when queue is to be dequeued */
-static int iMainMsgQueueDeqtWinToHr = 25; /* hour begin of time frame when queue is to be dequeued */
-
-
-/* Reset config variables to default values.
- * rgerhards, 2007-07-17
- */
-static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
-{
- bLogStatusMsgs = DFLT_bLogStatusMsgs;
- bActExecWhenPrevSusp = 0;
- bDebugPrintTemplateList = 1;
- bDebugPrintCfSysLineHandlerList = 1;
- bDebugPrintModuleList = 1;
- bReduceRepeatMsgs = 0;
- bAbortOnUncleanConfig = 0;
- free(pszMainMsgQFName);
- pszMainMsgQFName = NULL;
- iMainMsgQueueSize = 10000;
- iMainMsgQHighWtrMark = 8000;
- iMainMsgQLightDlyMark = -1;
- iMainMsgQLowWtrMark = 2000;
- iMainMsgQDiscardMark = 9800;
- iMainMsgQDiscardSeverity = 8;
- iMainMsgQueMaxFileSize = 1024 * 1024;
- iMainMsgQueueNumWorkers = 1;
- iMainMsgQPersistUpdCnt = 0;
- bMainMsgQSyncQeueFiles = 0;
- iMainMsgQtoQShutdown = 1500;
- iMainMsgQtoActShutdown = 1000;
- iMainMsgQtoEnq = 2000;
- iMainMsgQtoWrkShutdown = 60000;
- iMainMsgQWrkMinMsgs = 100;
- iMainMsgQDeqSlowdown = 0;
- bMainMsgQSaveOnShutdown = 1;
- MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
- iMainMsgQueMaxDiskSpace = 0;
- iMainMsgQueDeqBatchSize = 32;
- glbliActionResumeRetryCount = 0;
-
- return RS_RET_OK;
-}
-
-
-/* hardcoded standard templates (used for defaults) */
-static uchar template_DebugFormat[] = "\"Debug line with all properties:\nFROMHOST: '%FROMHOST%', fromhost-ip: '%fromhost-ip%', HOSTNAME: '%HOSTNAME%', PRI: %PRI%,\nsyslogtag '%syslogtag%', programname: '%programname%', APP-NAME: '%APP-NAME%', PROCID: '%PROCID%', MSGID: '%MSGID%',\nTIMESTAMP: '%TIMESTAMP%', STRUCTURED-DATA: '%STRUCTURED-DATA%',\nmsg: '%msg%'\nescaped msg: '%msg:::drop-cc%'\ninputname: %inputname% rawmsg: '%rawmsg%'\n\n\"";
-static uchar template_SyslogProtocol23Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n\"";
-static uchar template_TraditionalFileFormat[] = "=RSYSLOG_TraditionalFileFormat";
-static uchar template_FileFormat[] = "=RSYSLOG_FileFormat";
-static uchar template_ForwardFormat[] = "=RSYSLOG_ForwardFormat";
-static uchar template_TraditionalForwardFormat[] = "=RSYSLOG_TraditionalForwardFormat";
-static uchar template_WallFmt[] = "\"\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n %syslogtag%%msg%\n\r\"";
-static uchar template_StdUsrMsgFmt[] = "\" %syslogtag%%msg%\n\r\"";
-static uchar template_StdDBFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')\",SQL";
-static uchar template_StdPgSQLFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-pgsql%', '%timegenerated:::date-pgsql%', %iut%, '%syslogtag%')\",STDSQL";
-static uchar template_SysklogdFileFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg%\n\"";
-static uchar template_StdJSONFmt[] = "\"{\\\"message\\\":\\\"%msg%\\\",\\\"fromhost\\\":\\\"%HOSTNAME%\\\",\\\"facility\\\":\\\"%syslogfacility-text%\\\",\\\"priority\\\":\\\"%syslogpriority-text%\\\",\\\"timereported\\\":\\\"%timereported:::date-rfc3339%\\\",\\\"timegenerated\\\":\\\"%timegenerated:::date-rfc3339%\\\"}\",JSON";
-static uchar template_spoofadr[] = "\"%fromhost-ip%\"";
-/* end templates */
/* up to the next comment, prototypes that should be removed by reordering */
@@ -497,7 +390,7 @@ void untty(void)
*/
rsRetVal
parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int flags, flowControl_t flowCtlType,
- prop_t *pInputName, struct syslogTime *stTime, time_t ttGenTime)
+ prop_t *pInputName, struct syslogTime *stTime, time_t ttGenTime, ruleset_t *pRuleset)
{
prop_t *pProp = NULL;
msg_t *pMsg;
@@ -513,6 +406,7 @@ parseAndSubmitMessage(uchar *hname, uchar *hnameIP, uchar *msg, int len, int fla
MsgSetInputName(pMsg, pInputName);
MsgSetRawMsg(pMsg, (char*)msg, len);
MsgSetFlowControlType(pMsg, flowCtlType);
+ MsgSetRuleset(pMsg, pRuleset);
pMsg->msgFlags = flags | NEEDS_PARSING;
MsgSetRcvFromStr(pMsg, hname, ustrlen(hname), &pProp);
@@ -580,7 +474,7 @@ dbgprintf("ZZZZ: pLocalHostIPIF used!\n");
* permits us to process unmodified config files which otherwise contain a
* supressor statement.
*/
- if(((Debug == DEBUG_FULL || NoFork) && bErrMsgToStderr) || iConfigVerify) {
+ if(((Debug == DEBUG_FULL || NoFork) && ourConf->globals.bErrMsgToStderr) || iConfigVerify) {
if(LOG_PRI(pri) == LOG_ERR)
fprintf(stderr, "rsyslogd: %s\n", msg);
}
@@ -802,7 +696,7 @@ DEFFUNC_llExecFunc(flushRptdMsgsActions)
assert(pAction != NULL);
BEGINfunc
- LockObj(pAction);
+ d_pthread_mutex_lock(&pAction->mutAction);
/* TODO: time() performance: the call below could be moved to
* the beginn of the llExec(). This makes it slightly less correct, but
* in an acceptable way. -- rgerhards, 2008-09-16
@@ -814,7 +708,7 @@ DEFFUNC_llExecFunc(flushRptdMsgsActions)
actionWriteToAction(pAction);
BACKOFF(pAction);
}
- UnlockObj(pAction);
+ d_pthread_mutex_unlock(&pAction->mutAction);
ENDfunc
return RS_RET_OK; /* we ignore errors, we can not do anything either way */
@@ -826,7 +720,7 @@ DEFFUNC_llExecFunc(flushRptdMsgsActions)
static void
doFlushRptdMsgs(void)
{
- ruleset.IterateAllActions(flushRptdMsgsActions, NULL);
+ ruleset.IterateAllActions(runConf, flushRptdMsgsActions, NULL);
}
@@ -863,132 +757,6 @@ static void debug_switch()
}
-void legacyOptsEnq(uchar *line)
-{
- legacyOptsLL_t *pNew;
-
- pNew = MALLOC(sizeof(legacyOptsLL_t));
- if(line == NULL)
- pNew->line = NULL;
- else
- pNew->line = (uchar *) strdup((char *) line);
- pNew->next = NULL;
-
- if(pLegacyOptsLL == NULL)
- pLegacyOptsLL = pNew;
- else {
- legacyOptsLL_t *pThis = pLegacyOptsLL;
-
- while(pThis->next != NULL)
- pThis = pThis->next;
- pThis->next = pNew;
- }
-}
-
-
-void legacyOptsFree(void)
-{
- legacyOptsLL_t *pThis = pLegacyOptsLL, *pNext;
-
- while(pThis != NULL) {
- if(pThis->line != NULL)
- free(pThis->line);
- pNext = pThis->next;
- free(pThis);
- pThis = pNext;
- }
-}
-
-
-void legacyOptsHook(void)
-{
- legacyOptsLL_t *pThis = pLegacyOptsLL;
-
- while(pThis != NULL) {
- if(pThis->line != NULL) {
- errno = 0;
- errmsg.LogError(0, NO_ERRCODE, "Warning: backward compatibility layer added to following "
- "directive to rsyslog.conf: %s", pThis->line);
- conf.cfsysline(pThis->line);
- }
- pThis = pThis->next;
- }
-}
-
-
-void legacyOptsParseTCP(char ch, char *arg)
-{
- register int i;
- register char *pArg = arg;
- static char conflict = '\0';
-
- if((conflict == 'g' && ch == 't') || (conflict == 't' && ch == 'g')) {
- fprintf(stderr, "rsyslogd: If you want to use both -g and -t, use directives instead, -%c ignored.\n", ch);
- return;
- } else
- conflict = ch;
-
- /* extract port */
- i = 0;
- while(isdigit((int) *pArg))
- i = i * 10 + *pArg++ - '0';
-
- /* number of sessions */
- if(*pArg == '\0' || *pArg == ',') {
- if(ch == 't')
- legacyOptsEnq((uchar *) "ModLoad imtcp");
- else if(ch == 'g')
- legacyOptsEnq((uchar *) "ModLoad imgssapi");
-
- if(i >= 0 && i <= 65535) {
- uchar line[30];
-
- if(ch == 't') {
- snprintf((char *) line, sizeof(line), "InputTCPServerRun %d", i);
- } else if(ch == 'g') {
- snprintf((char *) line, sizeof(line), "InputGSSServerRun %d", i);
- }
- legacyOptsEnq(line);
- } else {
- if(ch == 't') {
- fprintf(stderr, "rsyslogd: Invalid TCP listen port %d - changed to 514.\n", i);
- legacyOptsEnq((uchar *) "InputTCPServerRun 514");
- } else if(ch == 'g') {
- fprintf(stderr, "rsyslogd: Invalid GSS listen port %d - changed to 514.\n", i);
- legacyOptsEnq((uchar *) "InputGSSServerRun 514");
- }
- }
-
- if(*pArg == ',') {
- ++pArg;
- while(isspace((int) *pArg))
- ++pArg;
- i = 0;
- while(isdigit((int) *pArg)) {
- i = i * 10 + *pArg++ - '0';
- }
- if(i > 0) {
- uchar line[30];
-
- snprintf((char *) line, sizeof(line), "InputTCPMaxSessions %d", i);
- legacyOptsEnq(line);
- } else {
- if(ch == 't') {
- fprintf(stderr, "rsyslogd: TCP session max configured "
- "to %d [-t %s] - changing to 1.\n", i, arg);
- legacyOptsEnq((uchar *) "InputTCPMaxSessions 1");
- } else if (ch == 'g') {
- fprintf(stderr, "rsyslogd: GSS session max configured "
- "to %d [-g %s] - changing to 1.\n", i, arg);
- legacyOptsEnq((uchar *) "InputTCPMaxSessions 1");
- }
- }
- }
- } else
- fprintf(stderr, "rsyslogd: Invalid -t %s command line option.\n", arg);
-}
-
-
/* doDie() is a signal handler. If called, it sets the bFinished variable
* to indicate the program should terminate. However, it does not terminate
* it itself, because that causes issues with multi-threading. The actual
@@ -1026,9 +794,7 @@ static void doDie(int sig)
static void
freeAllDynMemForTermination(void)
{
- free(pszMainMsgQFName);
- free(pModDir);
- free(pszConfDAGFile);
+ free(ourConf->globals.pszConfDAGFile);
}
@@ -1037,7 +803,7 @@ freeAllDynMemForTermination(void)
static inline void
destructAllActions(void)
{
- ruleset.DestructAllActions();
+ ruleset.DestructAllActions(runConf);
bHaveMainQueue = 0; // flag that internal messages need to be temporarily stored
}
@@ -1075,7 +841,7 @@ die(int sig)
thrdTerminateAll();
/* and THEN send the termination log message (see long comment above) */
- if(sig && bLogStatusMsgs) {
+ if(sig && runConf->globals.bLogStatusMsgs) {
(void) snprintf(buf, sizeof(buf) / sizeof(char),
" [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
"\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"]" " exiting on signal %d.",
@@ -1107,7 +873,7 @@ die(int sig)
* ourselfs, this makes finding memory leaks a lot
* easier.
*/
- tplDeleteAll();
+ tplDeleteAll(runConf);
/* de-init some modules */
modExitIminternal();
@@ -1119,8 +885,6 @@ die(int sig)
*/
unregCfSysLineHdlrs();
- legacyOptsFree();
-
/* destruct our global properties */
if(pInternalInputName != NULL)
prop.Destruct(&pInternalInputName);
@@ -1156,110 +920,7 @@ static void doexit()
exit(0); /* "good" exit, only during child-creation */
}
-
-/* set the maximum message size */
-static rsRetVal setMaxMsgSize(void __attribute__((unused)) *pVal, long iNewVal)
-{
- return glbl.SetMaxLine(iNewVal);
-}
-
-
-/* set the action resume interval */
-static rsRetVal setActionResumeInterval(void __attribute__((unused)) *pVal, int iNewVal)
-{
- return actionSetGlobalResumeInterval(iNewVal);
-}
-
-
-/* set the processes max number ob files (upon configuration request)
- * 2009-04-14 rgerhards
- */
-static rsRetVal setMaxFiles(void __attribute__((unused)) *pVal, int iFiles)
-{
- struct rlimit maxFiles;
- char errStr[1024];
- DEFiRet;
-
- maxFiles.rlim_cur = iFiles;
- maxFiles.rlim_max = iFiles;
-
- if(setrlimit(RLIMIT_NOFILE, &maxFiles) < 0) {
- /* NOTE: under valgrind, we seem to be unable to extend the size! */
- rs_strerror_r(errno, errStr, sizeof(errStr));
- errmsg.LogError(0, RS_RET_ERR_RLIM_NOFILE, "could not set process file limit to %d: %s [kernel max %ld]",
- iFiles, errStr, (long) maxFiles.rlim_max);
- ABORT_FINALIZE(RS_RET_ERR_RLIM_NOFILE);
- }
-#ifdef USE_UNLIMITED_SELECT
- glbl.SetFdSetSize(howmany(iFiles, __NFDBITS) * sizeof (fd_mask));
-#endif
- DBGPRINTF("Max number of files set to %d [kernel max %ld].\n", iFiles, (long) maxFiles.rlim_max);
-
-finalize_it:
- RETiRet;
-}
-
-
-/* set the processes umask (upon configuration request) */
-static rsRetVal setUmask(void __attribute__((unused)) *pVal, int iUmask)
-{
- umask(iUmask);
- DBGPRINTF("umask set to 0%3.3o.\n", iUmask);
-
- return RS_RET_OK;
-}
-
-
-/* drop to specified group
- * if something goes wrong, the function never returns
- * Note that such an abort can cause damage to on-disk structures, so we should
- * re-design the "interface" in the long term. -- rgerhards, 2008-11-26
- */
-static void doDropPrivGid(int iGid)
-{
- int res;
- uchar szBuf[1024];
-
- res = setgroups(0, NULL); /* remove all supplementary group IDs */
- if(res) {
- perror("could not remove supplemental group IDs");
- exit(1);
- }
- DBGPRINTF("setgroups(0, NULL): %d\n", res);
- res = setgid(iGid);
- if(res) {
- /* if we can not set the userid, this is fatal, so let's unconditionally abort */
- perror("could not set requested group id");
- exit(1);
- }
- DBGPRINTF("setgid(%d): %d\n", iGid, res);
- snprintf((char*)szBuf, sizeof(szBuf)/sizeof(uchar), "rsyslogd's groupid changed to %d", iGid);
- logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, szBuf, 0);
-}
-
-
-/* drop to specified user
- * if something goes wrong, the function never returns
- * Note that such an abort can cause damage to on-disk structures, so we should
- * re-design the "interface" in the long term. -- rgerhards, 2008-11-19
- */
-static void doDropPrivUid(int iUid)
-{
- int res;
- uchar szBuf[1024];
-
- res = setuid(iUid);
- if(res) {
- /* if we can not set the userid, this is fatal, so let's unconditionally abort */
- perror("could not set requested userid");
- exit(1);
- }
- DBGPRINTF("setuid(%d): %d\n", iUid, res);
- snprintf((char*)szBuf, sizeof(szBuf)/sizeof(uchar), "rsyslogd's userid changed to %d", iUid);
- logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, szBuf, 0);
-}
-
-
+#if 0 /* TODO: re-enable, currently not used */
/* helper to generateConfigDAG, to print out all actions via
* the llExecFunc() facility.
* rgerhards, 2007-08-02
@@ -1444,105 +1105,7 @@ generateConfigDAG(uchar *pszDAGFile)
finalize_it:
RETiRet;
}
-
-
-/* print debug information as part of init(). This pretty much
- * outputs the whole config of rsyslogd. I've moved this code
- * out of init() to clean it somewhat up.
- * rgerhards, 2007-07-31
- */
-static void dbgPrintInitInfo(void)
-{
- ruleset.DebugPrintAll();
- DBGPRINTF("\n");
- if(bDebugPrintTemplateList)
- tplPrintList();
- if(bDebugPrintModuleList)
- module.PrintList();
- ochPrintList();
-
- if(bDebugPrintCfSysLineHandlerList)
- dbgPrintCfSysLineHandlers();
-
- DBGPRINTF("Messages with malicious PTR DNS Records are %sdropped.\n",
- glbl.GetDropMalPTRMsgs() ? "" : "not ");
-
- DBGPRINTF("Main queue size %d messages.\n", iMainMsgQueueSize);
- DBGPRINTF("Main queue worker threads: %d, wThread shutdown: %d, Perists every %d updates.\n",
- iMainMsgQueueNumWorkers, iMainMsgQtoWrkShutdown, iMainMsgQPersistUpdCnt);
- DBGPRINTF("Main queue timeouts: shutdown: %d, action completion shutdown: %d, enq: %d\n",
- iMainMsgQtoQShutdown, iMainMsgQtoActShutdown, iMainMsgQtoEnq);
- DBGPRINTF("Main queue watermarks: high: %d, low: %d, discard: %d, discard-severity: %d, light-delay %d\n",
- iMainMsgQHighWtrMark, iMainMsgQLowWtrMark, iMainMsgQDiscardMark, iMainMsgQDiscardSeverity, iMainMsgQLightDlyMark);
- DBGPRINTF("Main queue save on shutdown %d, max disk space allowed %lld\n",
- bMainMsgQSaveOnShutdown, iMainMsgQueMaxDiskSpace);
- /* TODO: add
- iActionRetryCount = 0;
- iActionRetryInterval = 30000;
- static int iMainMsgQtoWrkMinMsgs = 100;
- static int iMainMsgQbSaveOnShutdown = 1;
- iMainMsgQueMaxDiskSpace = 0;
- setQPROP(qqueueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", 100);
- setQPROP(qqueueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", 1);
- */
- DBGPRINTF("Work Directory: '%s'.\n", glbl.GetWorkDir());
-}
-
-
-/* Actually run the input modules. This happens after privileges are dropped,
- * if that is requested.
- */
-static rsRetVal
-runInputModules(void)
-{
- modInfo_t *pMod;
- int bNeedsCancel;
-
- BEGINfunc
- /* loop through all modules and activate them (brr...) */
- pMod = module.GetNxtType(NULL, eMOD_IN);
- while(pMod != NULL) {
- if(pMod->mod.im.bCanRun) {
- DBGPRINTF("trying to start input module '%s'\n", pMod->pszName);
- /* activate here */
- bNeedsCancel = (pMod->isCompatibleWithFeature(sFEATURENonCancelInputTermination) == RS_RET_OK) ?
- 0 : 1;
- thrdCreate(pMod->mod.im.runInput, pMod->mod.im.afterRun, bNeedsCancel);
- }
- 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
- * running. Almost no config option is taken.
- * rgerhards, 2007-12-14
- */
-static rsRetVal
-startInputModules(void)
-{
- DEFiRet;
- modInfo_t *pMod;
-
- /* loop through all modules and activate them (brr...) */
- pMod = module.GetNxtType(NULL, eMOD_IN);
- while(pMod != NULL) {
- 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);
- }
-
- ENDfunc
- return RS_RET_OK; /* intentional: we do not care about module errors */
-}
+#endif
/* create a main message queue, now also used for ruleset queues. This function
@@ -1555,12 +1118,12 @@ rsRetVal createMainQueue(qqueue_t **ppQueue, uchar *pszQueueName)
DEFiRet;
/* switch the message object to threaded operation, if necessary */
- if(MainMsgQueType == QUEUETYPE_DIRECT || iMainMsgQueueNumWorkers > 1) {
+ if(ourConf->globals.mainQ.MainMsgQueType == QUEUETYPE_DIRECT || ourConf->globals.mainQ.iMainMsgQueueNumWorkers > 1) {
MsgEnableThreadSafety();
}
/* create message queue */
- CHKiRet_Hdlr(qqueueConstruct(ppQueue, MainMsgQueType, iMainMsgQueueNumWorkers, iMainMsgQueueSize, msgConsumer)) {
+ CHKiRet_Hdlr(qqueueConstruct(ppQueue, ourConf->globals.mainQ.MainMsgQueType, ourConf->globals.mainQ.iMainMsgQueueNumWorkers, ourConf->globals.mainQ.iMainMsgQueueSize, msgConsumer)) {
/* no queue is fatal, we need to give up in that case... */
errmsg.LogError(0, iRet, "could not create (ruleset) main message queue"); \
}
@@ -1577,28 +1140,25 @@ rsRetVal createMainQueue(qqueue_t **ppQueue, uchar *pszQueueName)
errmsg.LogError(0, NO_ERRCODE, "Invalid " #directive ", error %d. Ignored, running with default setting", iRet); \
}
- setQPROP(qqueueSetMaxFileSize, "$MainMsgQueueFileSize", iMainMsgQueMaxFileSize);
- setQPROP(qqueueSetsizeOnDiskMax, "$MainMsgQueueMaxDiskSpace", iMainMsgQueMaxDiskSpace);
- setQPROP(qqueueSetiDeqBatchSize, "$MainMsgQueueDequeueBatchSize", iMainMsgQueDeqBatchSize);
- setQPROPstr(qqueueSetFilePrefix, "$MainMsgQueueFileName", pszMainMsgQFName);
- setQPROP(qqueueSetiPersistUpdCnt, "$MainMsgQueueCheckpointInterval", iMainMsgQPersistUpdCnt);
- setQPROP(qqueueSetbSyncQueueFiles, "$MainMsgQueueSyncQueueFiles", bMainMsgQSyncQeueFiles);
- setQPROP(qqueueSettoQShutdown, "$MainMsgQueueTimeoutShutdown", iMainMsgQtoQShutdown );
- setQPROP(qqueueSettoActShutdown, "$MainMsgQueueTimeoutActionCompletion", iMainMsgQtoActShutdown);
- setQPROP(qqueueSettoWrkShutdown, "$MainMsgQueueWorkerTimeoutThreadShutdown", iMainMsgQtoWrkShutdown);
- setQPROP(qqueueSettoEnq, "$MainMsgQueueTimeoutEnqueue", iMainMsgQtoEnq);
- setQPROP(qqueueSetiHighWtrMrk, "$MainMsgQueueHighWaterMark", iMainMsgQHighWtrMark);
- setQPROP(qqueueSetiLowWtrMrk, "$MainMsgQueueLowWaterMark", iMainMsgQLowWtrMark);
- setQPROP(qqueueSetiDiscardMrk, "$MainMsgQueueDiscardMark", iMainMsgQDiscardMark);
- if(iMainMsgQLightDlyMark > 0) {
- setQPROP(qqueueSetiLightDlyMrk, "$MainMsgQueueLightDelayMark", iMainMsgQLightDlyMark);
- }
- setQPROP(qqueueSetiDiscardSeverity, "$MainMsgQueueDiscardSeverity", iMainMsgQDiscardSeverity);
- setQPROP(qqueueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", iMainMsgQWrkMinMsgs);
- setQPROP(qqueueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", bMainMsgQSaveOnShutdown);
- setQPROP(qqueueSetiDeqSlowdown, "$MainMsgQueueDequeueSlowdown", iMainMsgQDeqSlowdown);
- setQPROP(qqueueSetiDeqtWinFromHr, "$MainMsgQueueDequeueTimeBegin", iMainMsgQueueDeqtWinFromHr);
- setQPROP(qqueueSetiDeqtWinToHr, "$MainMsgQueueDequeueTimeEnd", iMainMsgQueueDeqtWinToHr);
+ setQPROP(qqueueSetMaxFileSize, "$MainMsgQueueFileSize", ourConf->globals.mainQ.iMainMsgQueMaxFileSize);
+ setQPROP(qqueueSetsizeOnDiskMax, "$MainMsgQueueMaxDiskSpace", ourConf->globals.mainQ.iMainMsgQueMaxDiskSpace);
+ setQPROP(qqueueSetiDeqBatchSize, "$MainMsgQueueDequeueBatchSize", ourConf->globals.mainQ.iMainMsgQueDeqBatchSize);
+ setQPROPstr(qqueueSetFilePrefix, "$MainMsgQueueFileName", ourConf->globals.mainQ.pszMainMsgQFName);
+ setQPROP(qqueueSetiPersistUpdCnt, "$MainMsgQueueCheckpointInterval", ourConf->globals.mainQ.iMainMsgQPersistUpdCnt);
+ setQPROP(qqueueSetbSyncQueueFiles, "$MainMsgQueueSyncQueueFiles", ourConf->globals.mainQ.bMainMsgQSyncQeueFiles);
+ setQPROP(qqueueSettoQShutdown, "$MainMsgQueueTimeoutShutdown", ourConf->globals.mainQ.iMainMsgQtoQShutdown );
+ setQPROP(qqueueSettoActShutdown, "$MainMsgQueueTimeoutActionCompletion", ourConf->globals.mainQ.iMainMsgQtoActShutdown);
+ setQPROP(qqueueSettoWrkShutdown, "$MainMsgQueueWorkerTimeoutThreadShutdown", ourConf->globals.mainQ.iMainMsgQtoWrkShutdown);
+ setQPROP(qqueueSettoEnq, "$MainMsgQueueTimeoutEnqueue", ourConf->globals.mainQ.iMainMsgQtoEnq);
+ setQPROP(qqueueSetiHighWtrMrk, "$MainMsgQueueHighWaterMark", ourConf->globals.mainQ.iMainMsgQHighWtrMark);
+ setQPROP(qqueueSetiLowWtrMrk, "$MainMsgQueueLowWaterMark", ourConf->globals.mainQ.iMainMsgQLowWtrMark);
+ setQPROP(qqueueSetiDiscardMrk, "$MainMsgQueueDiscardMark", ourConf->globals.mainQ.iMainMsgQDiscardMark);
+ setQPROP(qqueueSetiDiscardSeverity, "$MainMsgQueueDiscardSeverity", ourConf->globals.mainQ.iMainMsgQDiscardSeverity);
+ setQPROP(qqueueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", ourConf->globals.mainQ.iMainMsgQWrkMinMsgs);
+ setQPROP(qqueueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", ourConf->globals.mainQ.bMainMsgQSaveOnShutdown);
+ setQPROP(qqueueSetiDeqSlowdown, "$MainMsgQueueDequeueSlowdown", ourConf->globals.mainQ.iMainMsgQDeqSlowdown);
+ setQPROP(qqueueSetiDeqtWinFromHr, "$MainMsgQueueDequeueTimeBegin", ourConf->globals.mainQ.iMainMsgQueueDeqtWinFromHr);
+ setQPROP(qqueueSetiDeqtWinToHr, "$MainMsgQueueDequeueTimeEnd", ourConf->globals.mainQ.iMainMsgQueueDeqtWinToHr);
# undef setQPROP
# undef setQPROPstr
@@ -1619,142 +1179,22 @@ rsRetVal createMainQueue(qqueue_t **ppQueue, uchar *pszQueueName)
static rsRetVal
init(void)
{
- rsRetVal localRet;
- int iNbrActions;
- int bHadConfigErr = 0;
- ruleset_t *pRuleset;
- char cbuf[BUFSIZ];
char bufStartUpMsg[512];
struct sigaction sigAct;
DEFiRet;
- DBGPRINTF("rsyslog %s - called init()\n", VERSION);
-
- /* construct the default ruleset */
- ruleset.Construct(&pRuleset);
- ruleset.SetName(pRuleset, UCHAR_CONSTANT("RSYSLOG_DefaultRuleset"));
- ruleset.ConstructFinalize(pRuleset);
-
- /* open the configuration file */
- localRet = conf.processConfFile(ConfFile);
- CHKiRet(conf.GetNbrActActions(&iNbrActions));
-
- if(localRet != RS_RET_OK) {
- errmsg.LogError(0, localRet, "CONFIG ERROR: could not interpret master config file '%s'.", ConfFile);
- bHadConfigErr = 1;
- } else if(iNbrActions == 0) {
- errmsg.LogError(0, RS_RET_NO_ACTIONS, "CONFIG ERROR: there are no active actions configured. Inputs will "
- "run, but no output whatsoever is created.");
- bHadConfigErr = 1;
- }
-
- if((localRet != RS_RET_OK && localRet != RS_RET_NONFATAL_CONFIG_ERR) || iNbrActions == 0) {
- /* rgerhards: this code is executed to set defaults when the
- * config file could not be opened. We might think about
- * abandoning the run in this case - but this, too, is not
- * very clever... So we stick with what we have.
- * We ignore any errors while doing this - we would be lost anyhow...
- */
- errmsg.LogError(0, NO_ERRCODE, "EMERGENCY CONFIGURATION ACTIVATED - fix rsyslog config file!");
-
- /* note: we previously used _POSIY_TTY_NAME_MAX+1, but this turned out to be
- * too low on linux... :-S -- rgerhards, 2008-07-28
- */
- char szTTYNameBuf[128];
- rule_t *pRule = NULL; /* initialization to NULL is *vitally* important! */
- conf.cfline(UCHAR_CONSTANT("*.ERR\t" _PATH_CONSOLE), &pRule);
- conf.cfline(UCHAR_CONSTANT("syslog.*\t" _PATH_CONSOLE), &pRule);
- conf.cfline(UCHAR_CONSTANT("*.PANIC\t*"), &pRule);
- conf.cfline(UCHAR_CONSTANT("syslog.*\troot"), &pRule);
- if(ttyname_r(0, szTTYNameBuf, sizeof(szTTYNameBuf)) == 0) {
- snprintf(cbuf,sizeof(cbuf), "*.*\t%s", szTTYNameBuf);
- conf.cfline((uchar*)cbuf, &pRule);
- } else {
- DBGPRINTF("error %d obtaining controlling terminal, not using that emergency rule\n", errno);
- }
- ruleset.AddRule(ruleset.GetCurrent(), &pRule);
- }
-
- legacyOptsHook();
-
- /* some checks */
- if(iMainMsgQueueNumWorkers < 1) {
- errmsg.LogError(0, NO_ERRCODE, "$MainMsgQueueNumWorkers must be at least 1! Set to 1.\n");
- iMainMsgQueueNumWorkers = 1;
- }
-
- if(MainMsgQueType == QUEUETYPE_DISK) {
- errno = 0; /* for logerror! */
- if(glbl.GetWorkDir() == NULL) {
- errmsg.LogError(0, NO_ERRCODE, "No $WorkDirectory specified - can not run main message queue in 'disk' mode. "
- "Using 'FixedArray' instead.\n");
- MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
- }
- if(pszMainMsgQFName == NULL) {
- errmsg.LogError(0, NO_ERRCODE, "No $MainMsgQueueFileName specified - can not run main message queue in "
- "'disk' mode. Using 'FixedArray' instead.\n");
- MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
- }
- }
-
- /* check if we need to generate a config DAG and, if so, do that */
- if(pszConfDAGFile != NULL)
- generateConfigDAG(pszConfDAGFile);
-
- /* we are done checking the config - now validate if we should actually run or not.
- * If not, terminate. -- rgerhards, 2008-07-25
- */
- if(iConfigVerify) {
- if(bHadConfigErr) {
- /* a bit dirty, but useful... */
- exit(1);
- }
- ABORT_FINALIZE(RS_RET_VALIDATION_RUN);
- }
-
- if(bAbortOnUncleanConfig && bHadConfigErr) {
- fprintf(stderr, "rsyslogd: $AbortOnUncleanConfig is set, and config is not clean.\n"
- "Check error log for details, fix errors and restart. As a last\n"
- "resort, you may want to remove $AbortOnUncleanConfig to permit a\n"
- "startup with a dirty config.\n");
- exit(2);
- }
-
- /* create message queue */
- CHKiRet_Hdlr(createMainQueue(&pMsgQueue, UCHAR_CONSTANT("main Q"))) {
- /* no queue is fatal, we need to give up in that case... */
- fprintf(stderr, "fatal error %d: could not create message queue - rsyslogd can not run!\n", iRet);
- exit(1);
- }
-
- bHaveMainQueue = (MainMsgQueType == QUEUETYPE_DIRECT) ? 0 : 1;
- 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 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();
-
- if(Debug) {
- dbgPrintInitInfo();
- }
-
memset(&sigAct, 0, sizeof (sigAct));
sigemptyset(&sigAct.sa_mask);
sigAct.sa_handler = sighup_handler;
sigaction(SIGHUP, &sigAct, NULL);
+ CHKiRet(rsconf.Activate(ourConf));
DBGPRINTF(" started.\n");
/* we now generate the startup message. It now includes everything to
* identify this instance. -- rgerhards, 2005-08-17
*/
- if(bLogStatusMsgs) {
+ if(ourConf->globals.bLogStatusMsgs) {
snprintf(bufStartUpMsg, sizeof(bufStartUpMsg)/sizeof(char),
" [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
"\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] start",
@@ -1767,100 +1207,6 @@ finalize_it:
}
-/* Switch the default ruleset (that, what servcies bind to if nothing specific
- * is specified).
- * rgerhards, 2009-06-12
- */
-static rsRetVal
-setDefaultRuleset(void __attribute__((unused)) *pVal, uchar *pszName)
-{
- DEFiRet;
-
- CHKiRet(ruleset.SetDefaultRuleset(pszName));
-
-finalize_it:
- free(pszName); /* no longer needed */
- RETiRet;
-}
-
-
-
-/* Put the rsyslog main thread to sleep for n seconds. This was introduced as
- * a quick and dirty workaround for a privilege drop race in regard to listener
- * startup, which itself was a result of the not-yet-done proper coding of
- * privilege drop code (quite some effort). It may be useful for other occasions, too.
- * is specified).
- * rgerhards, 2009-06-12
- */
-static rsRetVal
-putToSleep(void __attribute__((unused)) *pVal, int iNewVal)
-{
- DEFiRet;
- DBGPRINTF("rsyslog main thread put to sleep via $sleep %d directive...\n", iNewVal);
- srSleep(iNewVal, 0);
- DBGPRINTF("rsyslog main thread continues after $sleep %d\n", iNewVal);
- RETiRet;
-}
-
-
-/* Switch to either an already existing rule set or start a new one. The
- * named rule set becomes the new "current" rule set (what means that new
- * actions are added to it).
- * rgerhards, 2009-06-12
- */
-static rsRetVal
-setCurrRuleset(void __attribute__((unused)) *pVal, uchar *pszName)
-{
- ruleset_t *pRuleset;
- rsRetVal localRet;
- DEFiRet;
-
- localRet = ruleset.SetCurrRuleset(pszName);
-
- if(localRet == RS_RET_NOT_FOUND) {
- DBGPRINTF("begin new current rule set '%s'\n", pszName);
- CHKiRet(ruleset.Construct(&pRuleset));
- CHKiRet(ruleset.SetName(pRuleset, pszName));
- CHKiRet(ruleset.ConstructFinalize(pRuleset));
- } else {
- ABORT_FINALIZE(localRet);
- }
-
-finalize_it:
- free(pszName); /* no longer needed */
- RETiRet;
-}
-
-
-/* set the main message queue mode
- * rgerhards, 2008-01-03
- */
-static rsRetVal setMainMsgQueType(void __attribute__((unused)) *pVal, uchar *pszType)
-{
- DEFiRet;
-
- if (!strcasecmp((char *) pszType, "fixedarray")) {
- MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
- DBGPRINTF("main message queue type set to FIXED_ARRAY\n");
- } else if (!strcasecmp((char *) pszType, "linkedlist")) {
- MainMsgQueType = QUEUETYPE_LINKEDLIST;
- DBGPRINTF("main message queue type set to LINKEDLIST\n");
- } else if (!strcasecmp((char *) pszType, "disk")) {
- MainMsgQueType = QUEUETYPE_DISK;
- DBGPRINTF("main message queue type set to DISK\n");
- } else if (!strcasecmp((char *) pszType, "direct")) {
- MainMsgQueType = QUEUETYPE_DIRECT;
- DBGPRINTF("main message queue type set to DIRECT (no queueing at all)\n");
- } else {
- errmsg.LogError(0, RS_RET_INVALID_PARAMS, "unknown mainmessagequeuetype parameter: %s", (char *) pszType);
- iRet = RS_RET_INVALID_PARAMS;
- }
- free(pszType); /* no longer needed */
-
- RETiRet;
-}
-
-
/*
* The following function is resposible for handling a SIGHUP signal. Since
* we are now doing mallocs/free as part of init we had better not being
@@ -1927,7 +1273,7 @@ doHUP(void)
{
char buf[512];
- if(bLogStatusMsgs) {
+ if(ourConf->globals.bLogStatusMsgs) {
snprintf(buf, sizeof(buf) / sizeof(char),
" [origin software=\"rsyslogd\" " "swVersion=\"" VERSION
"\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] rsyslogd was HUPed",
@@ -1937,7 +1283,7 @@ doHUP(void)
}
queryLocalHostname(); /* re-read our name */
- ruleset.IterateAllActions(doHUPActions, NULL);
+ ruleset.IterateAllActions(ourConf, doHUPActions, NULL);
}
@@ -1967,7 +1313,7 @@ mainloop(void)
* powertop, for example). In that case, we primarily wait for a signal,
* but a once-a-day wakeup should be quite acceptable. -- rgerhards, 2008-06-09
*/
- tvSelectTimeout.tv_sec = (bReduceRepeatMsgs == 1) ? TIMERINTVL : 86400 /*1 day*/;
+ tvSelectTimeout.tv_sec = (runConf->globals.bReduceRepeatMsgs == 1) ? TIMERINTVL : 86400 /*1 day*/;
//tvSelectTimeout.tv_sec = TIMERINTVL; /* TODO: change this back to the above code when we have a better solution for apc */
tvSelectTimeout.tv_usec = 0;
select(1, NULL, NULL, NULL, &tvSelectTimeout);
@@ -1995,7 +1341,7 @@ mainloop(void)
* for the time being, I think the remaining risk can be accepted.
* rgerhards, 2008-01-10
*/
- if(bReduceRepeatMsgs == 1)
+ if(runConf->globals.bReduceRepeatMsgs == 1)
doFlushRptdMsgs();
if(bHadHUP) {
@@ -2008,122 +1354,6 @@ mainloop(void)
ENDfunc
}
-
-/* load build-in modules
- * very first version begun on 2007-07-23 by rgerhards
- */
-static rsRetVal loadBuildInModules(void)
-{
- DEFiRet;
-
- if((iRet = module.doModInit(modInitFile, UCHAR_CONSTANT("builtin-file"), NULL)) != RS_RET_OK) {
- RETiRet;
- }
- if((iRet = module.doModInit(modInitPipe, UCHAR_CONSTANT("builtin-pipe"), NULL)) != RS_RET_OK) {
- RETiRet;
- }
-#ifdef SYSLOG_INET
- if((iRet = module.doModInit(modInitFwd, UCHAR_CONSTANT("builtin-fwd"), NULL)) != RS_RET_OK) {
- RETiRet;
- }
-#endif
- if((iRet = module.doModInit(modInitShell, UCHAR_CONSTANT("builtin-shell"), NULL)) != RS_RET_OK) {
- RETiRet;
- }
- if((iRet = module.doModInit(modInitDiscard, UCHAR_CONSTANT("builtin-discard"), NULL)) != RS_RET_OK) {
- RETiRet;
- }
-
- /* dirty, but this must be for the time being: the usrmsg module must always be
- * loaded as last module. This is because it processes any type of action selector.
- * If we load it before other modules, these others will never have a chance of
- * working with the config file. We may change that implementation so that a user name
- * must start with an alnum, that would definitely help (but would it break backwards
- * compatibility?). * rgerhards, 2007-07-23
- * User names now must begin with:
- * [a-zA-Z0-9_.]
- */
- CHKiRet(module.doModInit(modInitUsrMsg, (uchar*) "builtin-usrmsg", NULL));
-
- /* load build-in parser modules */
- CHKiRet(module.doModInit(modInitpmrfc5424, UCHAR_CONSTANT("builtin-pmrfc5424"), NULL));
- CHKiRet(module.doModInit(modInitpmrfc3164, UCHAR_CONSTANT("builtin-pmrfc3164"), NULL));
-
- /* and set default parser modules (order is *very* important, legacy (3164) parse needs to go last! */
- CHKiRet(parser.AddDfltParser(UCHAR_CONSTANT("rsyslog.rfc5424")));
- CHKiRet(parser.AddDfltParser(UCHAR_CONSTANT("rsyslog.rfc3164")));
-
- /* load build-in strgen modules */
- CHKiRet(module.doModInit(modInitsmfile, UCHAR_CONSTANT("builtin-smfile"), NULL));
- CHKiRet(module.doModInit(modInitsmtradfile, UCHAR_CONSTANT("builtin-smtradfile"), NULL));
- CHKiRet(module.doModInit(modInitsmfwd, UCHAR_CONSTANT("builtin-smfwd"), NULL));
- CHKiRet(module.doModInit(modInitsmtradfwd, UCHAR_CONSTANT("builtin-smtradfwd"), NULL));
-
- /* ok, initialization of the command handler probably does not 100% belong right in
- * this space here. However, with the current design, this is actually quite a good
- * place to put it. We might decide to shuffle it around later, but for the time
- * being, the code has found its home here. A not-just-sideeffect of this decision
- * is that rsyslog will terminate if we can not register our built-in config commands.
- * This, I think, is the right thing to do. -- rgerhards, 2007-07-31
- */
- CHKiRet(regCfSysLineHdlr((uchar *)"logrsyslogstatusmessages", 0, eCmdHdlrBinary, NULL, &bLogStatusMsgs, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeretrycount", 0, eCmdHdlrInt, NULL, &glbliActionResumeRetryCount, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"defaultruleset", 0, eCmdHdlrGetWord, setDefaultRuleset, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"ruleset", 0, eCmdHdlrGetWord, setCurrRuleset, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"sleep", 0, eCmdHdlrInt, putToSleep, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuefilename", 0, eCmdHdlrGetWord, NULL, &pszMainMsgQFName, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesize", 0, eCmdHdlrInt, NULL, &iMainMsgQueueSize, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuehighwatermark", 0, eCmdHdlrInt, NULL, &iMainMsgQHighWtrMark, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuelowwatermark", 0, eCmdHdlrInt, NULL, &iMainMsgQLowWtrMark, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuediscardmark", 0, eCmdHdlrInt, NULL, &iMainMsgQDiscardMark, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuelightdelaymark", 0, eCmdHdlrInt, NULL, &iMainMsgQLightDlyMark, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuediscardseverity", 0, eCmdHdlrSeverity, NULL, &iMainMsgQDiscardSeverity, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuecheckpointinterval", 0, eCmdHdlrInt, NULL, &iMainMsgQPersistUpdCnt, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesyncqueuefiles", 0, eCmdHdlrBinary, NULL, &bMainMsgQSyncQeueFiles, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetype", 0, eCmdHdlrGetWord, setMainMsgQueType, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkerthreads", 0, eCmdHdlrInt, NULL, &iMainMsgQueueNumWorkers, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutshutdown", 0, eCmdHdlrInt, NULL, &iMainMsgQtoQShutdown, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutactioncompletion", 0, eCmdHdlrInt, NULL, &iMainMsgQtoActShutdown, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutenqueue", 0, eCmdHdlrInt, NULL, &iMainMsgQtoEnq, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkertimeoutthreadshutdown", 0, eCmdHdlrInt, NULL, &iMainMsgQtoWrkShutdown, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeueslowdown", 0, eCmdHdlrInt, NULL, &iMainMsgQDeqSlowdown, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkerthreadminimummessages", 0, eCmdHdlrInt, NULL, &iMainMsgQWrkMinMsgs, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxfilesize", 0, eCmdHdlrSize, NULL, &iMainMsgQueMaxFileSize, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuebatchsize", 0, eCmdHdlrSize, NULL, &iMainMsgQueDeqBatchSize, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxdiskspace", 0, eCmdHdlrSize, NULL, &iMainMsgQueMaxDiskSpace, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesaveonshutdown", 0, eCmdHdlrBinary, NULL, &bMainMsgQSaveOnShutdown, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimebegin", 0, eCmdHdlrInt, NULL, &iMainMsgQueueDeqtWinFromHr, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimeend", 0, eCmdHdlrInt, NULL, &iMainMsgQueueDeqtWinToHr, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"abortonuncleanconfig", 0, eCmdHdlrBinary, NULL, &bAbortOnUncleanConfig, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgreduction", 0, eCmdHdlrBinary, NULL, &bReduceRepeatMsgs, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlywhenpreviousissuspended", 0, eCmdHdlrBinary, NULL, &bActExecWhenPrevSusp, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt, setActionResumeInterval, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"template", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_TEMPLATE, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"outchannel", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_OUTCHANNEL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"allowedsender", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_ALLOWEDSENDER, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"modload", 0, eCmdHdlrCustomHandler, conf.doModLoad, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"includeconfig", 0, eCmdHdlrCustomHandler, conf.doIncludeLine, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"umask", 0, eCmdHdlrFileCreateMode, setUmask, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"maxopenfiles", 0, eCmdHdlrInt, setMaxFiles, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"debugprinttemplatelist", 0, eCmdHdlrBinary, NULL, &bDebugPrintTemplateList, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"debugprintmodulelist", 0, eCmdHdlrBinary, NULL, &bDebugPrintModuleList, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"debugprintcfsyslinehandlerlist", 0, eCmdHdlrBinary,
- NULL, &bDebugPrintCfSysLineHandlerList, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"moddir", 0, eCmdHdlrGetWord, NULL, &pModDir, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"generateconfiggraph", 0, eCmdHdlrGetWord, NULL, &pszConfDAGFile, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"errormessagestostderr", 0, eCmdHdlrBinary, NULL, &bErrMsgToStderr, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"maxmessagesize", 0, eCmdHdlrSize, setMaxMsgSize, NULL, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"privdroptouser", 0, eCmdHdlrUID, NULL, &uidDropPriv, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"privdroptouserid", 0, eCmdHdlrInt, NULL, &uidDropPriv, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"privdroptogroup", 0, eCmdHdlrGID, NULL, &gidDropPriv, NULL));
- CHKiRet(regCfSysLineHdlr((uchar *)"privdroptogroupid", 0, eCmdHdlrGID, NULL, &gidDropPriv, NULL));
-
-finalize_it:
- RETiRet;
-}
-
-
/* print version and compile-time setting information.
*/
static void printVersion(void)
@@ -2169,97 +1399,6 @@ static void printVersion(void)
}
-/* This function is called after initial initalization. It is used to
- * move code out of the too-long main() function.
- * rgerhards, 2007-10-17
- */
-static rsRetVal mainThread()
-{
- DEFiRet;
- uchar *pTmp;
-
- /* initialize the build-in templates */
- pTmp = template_DebugFormat;
- tplAddLine("RSYSLOG_DebugFormat", &pTmp);
- pTmp = template_SyslogProtocol23Format;
- tplAddLine("RSYSLOG_SyslogProtocol23Format", &pTmp);
- pTmp = template_FileFormat; /* new format for files with high-precision stamp */
- tplAddLine("RSYSLOG_FileFormat", &pTmp);
- pTmp = template_TraditionalFileFormat;
- tplAddLine("RSYSLOG_TraditionalFileFormat", &pTmp);
- pTmp = template_WallFmt;
- tplAddLine(" WallFmt", &pTmp);
- pTmp = template_ForwardFormat;
- tplAddLine("RSYSLOG_ForwardFormat", &pTmp);
- pTmp = template_TraditionalForwardFormat;
- tplAddLine("RSYSLOG_TraditionalForwardFormat", &pTmp);
- pTmp = template_StdUsrMsgFmt;
- tplAddLine(" StdUsrMsgFmt", &pTmp);
- pTmp = template_StdDBFmt;
- tplAddLine(" StdDBFmt", &pTmp);
- pTmp = template_SysklogdFileFormat;
- tplAddLine("RSYSLOG_SysklogdFileFormat", &pTmp);
- pTmp = template_StdPgSQLFmt;
- tplAddLine(" StdPgSQLFmt", &pTmp);
- pTmp = template_StdJSONFmt;
- tplAddLine(" StdJSONFmt", &pTmp);
- pTmp = template_spoofadr;
- tplLastStaticInit(tplAddLine("RSYSLOG_omudpspoofDfltSourceTpl", &pTmp));
-
- 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)
- kill(ppid, SIGTERM);
-
-
- /* If instructed to do so, we now drop privileges. Note that this is not 100% secure,
- * 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
- * we should do over time. TODO -- rgerhards, 2008-11-19
- */
- if(gidDropPriv != 0) {
- doDropPrivGid(gidDropPriv);
- }
-
- if(uidDropPriv != 0) {
- doDropPrivUid(uidDropPriv);
- }
-
- /* finally let the inputs run... */
- runInputModules();
-
- /* END OF INTIALIZATION
- */
- 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 == DEBUG_FULL || NoFork)) {
- close(1);
- close(2);
- bErrMsgToStderr = 0;
- }
-
- mainloop();
-
-finalize_it:
- RETiRet;
-}
-
-
/* Method to initialize all global classes and use the objects that we need.
* rgerhards, 2008-01-04
* rgerhards, 2008-04-16: the actual initialization is now carried out by the runtime
@@ -2284,8 +1423,6 @@ InitGlobalClasses(void)
CHKiRet(objUse(module, CORE_COMPONENT));
pErrObj = "datetime";
CHKiRet(objUse(datetime, CORE_COMPONENT));
- pErrObj = "expr";
- CHKiRet(objUse(expr, CORE_COMPONENT));
pErrObj = "rule";
CHKiRet(objUse(rule, CORE_COMPONENT));
pErrObj = "ruleset";
@@ -2296,6 +1433,8 @@ InitGlobalClasses(void)
CHKiRet(objUse(prop, CORE_COMPONENT));
pErrObj = "parser";
CHKiRet(objUse(parser, CORE_COMPONENT));
+ pErrObj = "rsconf";
+ CHKiRet(objUse(rsconf, CORE_COMPONENT));
/* intialize some dummy classes that are not part of the runtime */
pErrObj = "action";
@@ -2306,6 +1445,7 @@ InitGlobalClasses(void)
/* TODO: the dependency on net shall go away! -- rgerhards, 2008-03-07 */
pErrObj = "net";
CHKiRet(objUse(net, LM_NET_FILENAME));
+ dnscacheInit();
finalize_it:
if(iRet != RS_RET_OK) {
@@ -2338,9 +1478,8 @@ GlobalClassExit(void)
objRelease(conf, CORE_COMPONENT);
objRelease(ruleset, CORE_COMPONENT);
objRelease(rule, CORE_COMPONENT);
- objRelease(expr, CORE_COMPONENT);
- vmClassExit(); /* this is hack, currently core_modules do not get this automatically called */
parserClassExit(); /* this is hack, currently core_modules do not get this automatically called */
+ rsconfClassExit(); /* this is hack, currently core_modules do not get this automatically called */
objRelease(datetime, CORE_COMPONENT);
/* TODO: implement the rest of the deinit */
@@ -2353,6 +1492,7 @@ GlobalClassExit(void)
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(module, CORE_COMPONENT));
#endif
+ dnscacheDeinit();
rsrtExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */
RETiRet;
@@ -2648,18 +1788,16 @@ doGlblProcessInit(void)
*/
int realMain(int argc, char **argv)
{
- DEFiRet;
-
+ rsRetVal localRet;
int ch;
extern int optind;
extern char *optarg;
int bEOptionWasGiven = 0;
- int bImUxSockLoaded = 0; /* already generated a $ModLoad imuxsock? */
int iHelperUOpt;
int bChDirRoot = 1; /* change the current working directory to "/"? */
char *arg; /* for command line option processing */
- uchar legacyConfLine[80];
char cwdbuf[128]; /* buffer to obtain/display current working directory */
+ DEFiRet;
/* first, parse the command line options. We do not carry out any actual work, just
* see what we should do. This relieves us from certain anomalies and we can process
@@ -2697,6 +1835,9 @@ int realMain(int argc, char **argv)
case 'u': /* misc user settings */
case 'w': /* disable disallowed host warnings */
case 'x': /* disable dns for remote messages */
+ case 'g': /* enable tcp gssapi logging */
+ case 'r': /* accept remote messages */
+ case 't': /* enable tcp logging */
CHKiRet(bufOptAdd(ch, optarg));
break;
case 'c': /* compatibility mode */
@@ -2707,37 +1848,15 @@ int realMain(int argc, char **argv)
Debug = 1;
break;
case 'e': /* log every message (no repeat message supression) */
- fprintf(stderr, "note: -e option is no longer supported, every message is now logged by default\n");
bEOptionWasGiven = 1;
break;
- case 'g': /* enable tcp gssapi logging */
-#if defined(SYSLOG_INET) && defined(USE_GSSAPI)
- CHKiRet(bufOptAdd('g', optarg));
-#else
- fprintf(stderr, "rsyslogd: -g not valid - not compiled with gssapi support");
-#endif
- break;
case 'M': /* default module load path -- this MUST be carried out immediately! */
glblModPath = (uchar*) optarg;
break;
- case 'r': /* accept remote messages */
-#ifdef SYSLOG_INET
- CHKiRet(bufOptAdd(ch, optarg));
-#else
- fprintf(stderr, "rsyslogd: -r not valid - not compiled with network support\n");
-#endif
- break;
- case 't': /* enable tcp logging */
-#ifdef SYSLOG_INET
- CHKiRet(bufOptAdd(ch, optarg));
-#else
- fprintf(stderr, "rsyslogd: -t not valid - not compiled with network support\n");
-#endif
- break;
case 'v': /* MUST be carried out immediately! */
printVersion();
exit(0); /* exit for -v option - so this is a "good one" */
- case '?':
+ case '?':
default:
usage();
}
@@ -2781,11 +1900,6 @@ int realMain(int argc, char **argv)
exit(1); /* "good" exit, leaving at init for fatal error */
}
- if((iRet = loadBuildInModules()) != RS_RET_OK) {
- fprintf(stderr, "fatal error: could not activate built-in modules. Error code %d.\n",
- iRet);
- exit(1); /* "good" exit, leaving at init for fatal error */
- }
/* END core initializations - we now come back to carrying out command line options*/
@@ -2802,32 +1916,15 @@ int realMain(int argc, char **argv)
send_to_all++;
break;
case 'a':
- if(iCompatibilityMode < 3) {
- if(!bImUxSockLoaded) {
- legacyOptsEnq((uchar *) "ModLoad imuxsock");
- bImUxSockLoaded = 1;
- }
- snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "addunixlistensocket %s", arg);
- legacyOptsEnq(legacyConfLine);
- } else {
- fprintf(stderr, "error -a is no longer supported, use module imuxsock instead");
- }
+ fprintf(stderr, "rsyslogd: error -a is no longer supported, use module imuxsock instead");
break;
case 'f': /* configuration file */
ConfFile = (uchar*) arg;
break;
case 'g': /* enable tcp gssapi logging */
- if(iCompatibilityMode < 3) {
- legacyOptsParseTCP(ch, arg);
- } else
- fprintf(stderr, "-g option only supported in compatibility modes 0 to 2 - ignored\n");
- break;
+ fprintf(stderr, "rsyslogd: -g option no longer supported - ignored\n");
case 'h':
- if(iCompatibilityMode < 3) {
- errmsg.LogError(0, NO_ERRCODE, "WARNING: -h option is no longer supported - ignored");
- } else {
- usage(); /* for v3 and above, it simply is an error */
- }
+ fprintf(stderr, "rsyslogd: error -h is no longer supported - ignored");
break;
case 'i': /* pid file name */
PidFile = arg;
@@ -2840,11 +1937,7 @@ int realMain(int argc, char **argv)
}
break;
case 'm': /* mark interval */
- if(iCompatibilityMode < 3) {
- MarkInterval = atoi(arg) * 60;
- } else
- fprintf(stderr,
- "-m option only supported in compatibility modes 0 to 2 - ignored\n");
+ fprintf(stderr, "rsyslogd: error -m is no longer supported - use immark instead");
break;
case 'n': /* don't fork */
NoFork = 1;
@@ -2853,27 +1946,10 @@ int realMain(int argc, char **argv)
iConfigVerify = atoi(arg);
break;
case 'o':
- if(iCompatibilityMode < 3) {
- if(!bImUxSockLoaded) {
- legacyOptsEnq((uchar *) "ModLoad imuxsock");
- bImUxSockLoaded = 1;
- }
- legacyOptsEnq((uchar *) "OmitLocalLogging");
- } else {
- fprintf(stderr, "error -o is no longer supported, use module imuxsock instead");
- }
+ fprintf(stderr, "error -o is no longer supported, use module imuxsock instead");
break;
case 'p':
- if(iCompatibilityMode < 3) {
- if(!bImUxSockLoaded) {
- legacyOptsEnq((uchar *) "ModLoad imuxsock");
- bImUxSockLoaded = 1;
- }
- snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "SystemLogSocketName %s", arg);
- legacyOptsEnq(legacyConfLine);
- } else {
- fprintf(stderr, "error -p is no longer supported, use module imuxsock instead");
- }
+ fprintf(stderr, "error -p is no longer supported, use module imuxsock instead");
break;
case 'q': /* add hostname if DNS resolving has failed */
*(net.pACLAddHostnameOnFail) = 1;
@@ -2882,12 +1958,7 @@ int realMain(int argc, char **argv)
*(net.pACLDontResolve) = 1;
break;
case 'r': /* accept remote messages */
- if(iCompatibilityMode < 3) {
- legacyOptsEnq((uchar *) "ModLoad imudp");
- snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "UDPServerRun %s", arg);
- legacyOptsEnq(legacyConfLine);
- } else
- fprintf(stderr, "-r option only supported in compatibility modes 0 to 2 - ignored\n");
+ fprintf(stderr, "rsyslogd: error option -r is no longer supported - ignored");
break;
case 's':
if(glbl.GetStripDomains() != NULL) {
@@ -2897,10 +1968,7 @@ int realMain(int argc, char **argv)
}
break;
case 't': /* enable tcp logging */
- if(iCompatibilityMode < 3) {
- legacyOptsParseTCP(ch, arg);
- } else
- fprintf(stderr, "-t option only supported in compatibility modes 0 to 2 - ignored\n");
+ fprintf(stderr, "rsyslogd: error option -t is no longer supported - ignored");
break;
case 'T':/* chroot() immediately at program startup, but only for testing, NOT security yet */
if(chroot(arg) != 0) {
@@ -2935,32 +2003,30 @@ int realMain(int argc, char **argv)
VERSION, iConfigVerify, ConfFile);
}
+ localRet = rsconf.Load(&ourConf, ConfFile);
+ if(localRet == RS_RET_NONFATAL_CONFIG_ERR) {
+ if(loadConf->globals.bAbortOnUncleanConfig) {
+ fprintf(stderr, "rsyslogd: $AbortOnUncleanConfig is set, and config is not clean.\n"
+ "Check error log for details, fix errors and restart. As a last\n"
+ "resort, you may want to remove $AbortOnUncleanConfig to permit a\n"
+ "startup with a dirty config.\n");
+ exit(2);
+ }
+ if(iConfigVerify) {
+ /* a bit dirty, but useful... */
+ exit(1);
+ }
+ localRet = RS_RET_OK;
+ }
+ CHKiRet(localRet);
+
if(bChDirRoot) {
if(chdir("/") != 0)
fprintf(stderr, "Can not do 'cd /' - still trying to run\n");
}
-
/* process compatibility mode settings */
- if(iCompatibilityMode < 4) {
- errmsg.LogError(0, NO_ERRCODE, "WARNING: rsyslogd is running in compatibility mode. Automatically "
- "generated config directives may interfer with your rsyslog.conf settings. "
- "We suggest upgrading your config and adding -c5 as the first "
- "rsyslogd option.");
- }
-
- if(iCompatibilityMode < 3) {
- if(MarkInterval > 0) {
- legacyOptsEnq((uchar *) "ModLoad immark");
- snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "MarkMessagePeriod %d", MarkInterval);
- legacyOptsEnq(legacyConfLine);
- }
- if(!bImUxSockLoaded) {
- legacyOptsEnq((uchar *) "ModLoad imuxsock");
- }
- }
-
- if(bEOptionWasGiven && iCompatibilityMode < 3) {
+ if(bEOptionWasGiven) {
errmsg.LogError(0, NO_ERRCODE, "WARNING: \"message repeated n times\" feature MUST be turned on in "
"rsyslog.conf - CURRENTLY EVERY MESSAGE WILL BE LOGGED. Visit "
"http://www.rsyslog.com/rptdmsgreduction to learn "
@@ -2970,7 +2036,34 @@ int realMain(int argc, char **argv)
if(!iConfigVerify)
CHKiRet(doGlblProcessInit());
- CHKiRet(mainThread());
+ 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)
+ kill(ppid, SIGTERM);
+
+
+ /* END OF INTIALIZATION */
+ 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 == DEBUG_FULL || NoFork)) {
+ close(1);
+ close(2);
+ ourConf->globals.bErrMsgToStderr = 0;
+ }
+
+ mainloop();
/* do any de-init's that need to be done AFTER this comment */
@@ -2982,7 +2075,7 @@ finalize_it:
if(iRet == RS_RET_VALIDATION_RUN) {
fprintf(stderr, "rsyslogd: End of config validation run. Bye.\n");
} else if(iRet != RS_RET_OK) {
- fprintf(stderr, "rsyslogd run failed with error %d (see rsyslog.h "
+ fprintf(stderr, "rsyslogd: run failed with error %d (see rsyslog.h "
"or try http://www.rsyslog.com/e/%d to learn what that number means)\n", iRet, iRet*-1);
}
diff --git a/tools/syslogd.h b/tools/syslogd.h
index a3323d1f..88bbd5f3 100644
--- a/tools/syslogd.h
+++ b/tools/syslogd.h
@@ -26,7 +26,6 @@
#include "template.h"
#include "action.h"
#include "linkedlist.h"
-#include "expr.h"
/* the following prototypes should go away once we have an input
* module interface -- rgerhards, 2007-12-12