summaryrefslogtreecommitdiffstats
path: root/runtime/modules.c
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/modules.c')
-rw-r--r--runtime/modules.c169
1 files changed, 151 insertions, 18 deletions
diff --git a/runtime/modules.c b/runtime/modules.c
index 39f977dd..5706685f 100644
--- a/runtime/modules.c
+++ b/runtime/modules.c
@@ -11,7 +11,7 @@
*
* File begun on 2007-07-22 by RGerhards
*
- * Copyright 2007-2011 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -75,6 +75,18 @@ static struct dlhandle_s *pHandles = NULL;
static uchar *pModDir; /* directory where loadable modules are found */
+/* tables for interfacing with the v6 config system */
+/* action (instance) parameters */
+static struct cnfparamdescr actpdescr[] = {
+ { "load", eCmdHdlrGetWord, 1 }
+};
+static struct cnfparamblk pblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(actpdescr)/sizeof(struct cnfparamdescr),
+ actpdescr
+ };
+
+
/* we provide a set of dummy functions for modules that do not support the
* some interfaces.
* On the commit feature: As the modules do not support it, they commit each message they
@@ -337,10 +349,13 @@ addModToGlblList(modInfo_t *pThis)
}
-/* Add a module to the config module list for current loadConf
+/* ready module for config processing. this includes checking if the module
+ * is already in the config, so this function may return errors. Returns a
+ * pointer to the last module inthe current config. That pointer needs to
+ * be passed to addModToCnfLst() when it is called later in the process.
*/
rsRetVal
-addModToCnfList(modInfo_t *pThis)
+readyModForCnf(modInfo_t *pThis, cfgmodules_etry_t **ppNew, cfgmodules_etry_t **ppLast)
{
cfgmodules_etry_t *pNew;
cfgmodules_etry_t *pLast;
@@ -348,8 +363,7 @@ addModToCnfList(modInfo_t *pThis)
assert(pThis != NULL);
if(loadConf == NULL) {
- /* we are in an early init state */
- FINALIZE;
+ FINALIZE; /* we are in an early init state */
}
/* check for duplicates and, as a side-activity, identify last node */
@@ -358,11 +372,16 @@ addModToCnfList(modInfo_t *pThis)
while(1) { /* loop broken inside */
if(pLast->pMod == pThis) {
DBGPRINTF("module '%s' already in this config\n", modGetName(pThis));
+ if(strncmp((char*)modGetName(pThis), "builtin:", sizeof("builtin:")-1)) {
+ errmsg.LogError(0, RS_RET_MODULE_ALREADY_IN_CONF,
+ "module '%s' already in this config, cannot be added\n", modGetName(pThis));
+ ABORT_FINALIZE(RS_RET_MODULE_ALREADY_IN_CONF);
+ }
FINALIZE;
}
if(pLast->next == NULL)
break;
- pLast = pLast -> next;
+ pLast = pLast->next;
}
}
@@ -380,6 +399,36 @@ addModToCnfList(modInfo_t *pThis)
CHKiRet(pThis->beginCnfLoad(&pNew->modCnf, loadConf));
}
+ *ppLast = pLast;
+ *ppNew = pNew;
+finalize_it:
+ RETiRet;
+}
+
+
+/* abort the creation of a module entry without adding it to the
+ * module list. Needed to prevent mem leaks.
+ */
+static inline void
+abortCnfUse(cfgmodules_etry_t *pNew)
+{
+ free(pNew);
+}
+
+
+/* Add a module to the config module list for current loadConf.
+ * Requires last pointer obtained by readyModForCnf().
+ */
+rsRetVal
+addModToCnfList(cfgmodules_etry_t *pNew, cfgmodules_etry_t *pLast)
+{
+ DEFiRet;
+ assert(pNew != NULL);
+
+ if(loadConf == NULL) {
+ FINALIZE; /* we are in an early init state */
+ }
+
if(pLast == NULL) {
loadConf->modules.root = pNew;
} else {
@@ -535,7 +584,7 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
CHKiRet((*modGetType)(&pNew->eType));
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"getKeepType", &modGetKeepType));
CHKiRet((*modGetKeepType)(&pNew->eKeepType));
- dbgprintf("module %s of type %d being loaded.\n", name, pNew->eType);
+ dbgprintf("module %s of type %d being loaded (keepType=%d).\n", name, pNew->eType, pNew->eKeepType);
/* OK, we know we can successfully work with the module. So we now fill the
* rest of the data elements. First we load the interfaces common to all
@@ -548,6 +597,11 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
pNew->isCompatibleWithFeature = dummyIsCompatibleWithFeature;
else if(localRet != RS_RET_OK)
ABORT_FINALIZE(localRet);
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"setModCnf", &pNew->setModCnf);
+ if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND)
+ pNew->setModCnf = NULL;
+ else if(localRet != RS_RET_OK)
+ ABORT_FINALIZE(localRet);
/* optional calls for new config system */
localRet = (*pNew->modQueryEtryPt)((uchar*)"getModCnfName", &getModCnfName);
@@ -584,6 +638,12 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"willRun", &pNew->mod.im.willRun));
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"afterRun", &pNew->mod.im.afterRun));
pNew->mod.im.bCanRun = 0;
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"newInpInst", &pNew->mod.im.newInpInst);
+ if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) {
+ pNew->mod.om.newActInst = NULL;
+ } else if(localRet != RS_RET_OK) {
+ ABORT_FINALIZE(localRet);
+ }
break;
case eMOD_OUT:
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"freeInstance", &pNew->freeInstance));
@@ -602,7 +662,8 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
else if(localRet != RS_RET_OK)
ABORT_FINALIZE(localRet);
- localRet = (*pNew->modQueryEtryPt)((uchar*)"endTransaction", &pNew->mod.om.endTransaction);
+ localRet = (*pNew->modQueryEtryPt)((uchar*)"endTransaction",
+ &pNew->mod.om.endTransaction);
if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) {
pNew->mod.om.endTransaction = dummyEndTransaction;
} else if(localRet != RS_RET_OK) {
@@ -754,6 +815,7 @@ static void modPrintList(void)
dbgprintf("\tdbgPrintInstInfo: 0x%lx\n", (unsigned long) pMod->dbgPrintInstInfo);
dbgprintf("\tfreeInstance: 0x%lx\n", (unsigned long) pMod->freeInstance);
dbgprintf("\tbeginCnfLoad: 0x%lx\n", (unsigned long) pMod->beginCnfLoad);
+ dbgprintf("\tSetModCnf: 0x%lx\n", (unsigned long) pMod->setModCnf);
dbgprintf("\tcheckCnf: 0x%lx\n", (unsigned long) pMod->checkCnf);
dbgprintf("\tactivateCnfPrePrivDrop: 0x%lx\n", (unsigned long) pMod->activateCnfPrePrivDrop);
dbgprintf("\tactivateCnf: 0x%lx\n", (unsigned long) pMod->activateCnf);
@@ -931,17 +993,17 @@ findModule(uchar *pModName, int iModNameLen, modInfo_t **pMod)
* the system loads a module for internal reasons, this is not directly tied to a
* configuration. We could also think if it would be useful to add only certain types
* of modules, but the current implementation at least looks simpler.
+ * Note: pvals = NULL means legacy config system
*/
static rsRetVal
-Load(uchar *pModName, sbool bConfLoad)
+Load(uchar *pModName, sbool bConfLoad, struct nvlst *lst)
{
- DEFiRet;
-
size_t iPathLen, iModNameLen;
- uchar *pModNameCmp;
int bHasExtension;
void *pModHdlr, *pModInit;
modInfo_t *pModInfo;
+ cfgmodules_etry_t *pNew;
+ cfgmodules_etry_t *pLast;
uchar *pModDirCurr, *pModDirNext;
int iLoadCnt;
struct dlhandle_s *pHandle = NULL;
@@ -952,9 +1014,11 @@ Load(uchar *pModName, sbool bConfLoad)
# endif
uchar *pPathBuf = pathBuf;
size_t lenPathBuf = sizeof(pathBuf);
+ rsRetVal localRet;
+ DEFiRet;
assert(pModName != NULL);
- dbgprintf("Requested to load module '%s'\n", pModName);
+ DBGPRINTF("Requested to load module '%s'\n", pModName);
iModNameLen = strlen((char*)pModName);
/* overhead for a full path is potentially 1 byte for a slash,
@@ -972,9 +1036,29 @@ Load(uchar *pModName, sbool bConfLoad)
CHKiRet(findModule(pModName, iModNameLen, &pModInfo));
if(pModInfo != NULL) {
- if(bConfLoad)
- addModToCnfList(pModInfo);
- dbgprintf("Module '%s' already loaded\n", pModName);
+ DBGPRINTF("Module '%s' already loaded\n", pModName);
+ if(bConfLoad) {
+ localRet = readyModForCnf(pModInfo, &pNew, &pLast);
+ if(pModInfo->setModCnf != NULL && localRet == RS_RET_OK) {
+ addModToCnfList(pNew, pLast);
+ if(!strncmp((char*)pModName, "builtin:", sizeof("builtin:")-1)) {
+ if(pModInfo->bSetModCnfCalled) {
+ errmsg.LogError(0, RS_RET_DUP_PARAM,
+ "parameters for built-in module %s already set - ignored\n",
+ pModName);
+ ABORT_FINALIZE(RS_RET_DUP_PARAM);
+ } else {
+ /* for built-in moules, we need to call setModConf,
+ * because there is no way to set parameters at load
+ * time for obvious reasons...
+ */
+ if(lst != NULL)
+ pModInfo->setModCnf(lst);
+ pModInfo->bSetModCnfCalled = 1;
+ }
+ }
+ }
+ }
FINALIZE;
}
@@ -1082,8 +1166,24 @@ Load(uchar *pModName, sbool bConfLoad)
dlclose(pModHdlr);
ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_INIT_FAILED);
}
- if(bConfLoad)
- addModToCnfList(pModInfo);
+
+ if(bConfLoad) {
+ readyModForCnf(pModInfo, &pNew, &pLast);
+ if(pModInfo->setModCnf != NULL) {
+ if(lst != NULL) {
+ localRet = pModInfo->setModCnf(lst);
+ if(localRet != RS_RET_OK) {
+ errmsg.LogError(0, localRet,
+ "module '%s', failed processing config parameters",
+ pPathBuf);
+ abortCnfUse(pNew);
+ ABORT_FINALIZE(localRet);
+ }
+ }
+ pModInfo->bSetModCnfCalled = 1;
+ }
+ addModToCnfList(pNew, pLast);
+ }
finalize_it:
if(pPathBuf != pathBuf) /* used malloc()ed memory? */
@@ -1093,6 +1193,39 @@ finalize_it:
}
+/* the v6+ way of loading modules: process a "module(...)" directive.
+ * rgerhards, 2012-06-20
+ */
+rsRetVal
+modulesProcessCnf(struct cnfobj *o)
+{
+ struct cnfparamvals *pvals;
+ uchar *cnfModName = NULL;
+ int typeIdx;
+ DEFiRet;
+
+ pvals = nvlstGetParams(o->nvlst, &pblk, NULL);
+ if(pvals == NULL) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ DBGPRINTF("modulesProcessCnf params:\n");
+ cnfparamsPrint(&pblk, pvals);
+ typeIdx = cnfparamGetIdx(&pblk, "load");
+ if(pvals[typeIdx].bUsed == 0) {
+ errmsg.LogError(0, RS_RET_CONF_RQRD_PARAM_MISSING, "module type missing");
+ ABORT_FINALIZE(RS_RET_CONF_RQRD_PARAM_MISSING);
+ }
+
+ cnfModName = (uchar*)es_str2cstr(pvals[typeIdx].val.d.estr, NULL);
+ iRet = Load(cnfModName, 1, o->nvlst);
+
+finalize_it:
+ free(cnfModName);
+ cnfparamvalsDestruct(pvals, &pblk);
+ RETiRet;
+}
+
+
/* set the default module load directory. A NULL value may be provided, in
* which case any previous value is deleted but no new one set. The caller-provided
* string is duplicated. If it needs to be freed, that's the caller's duty.