mirror of
https://github.com/rsyslog/rsyslog.git
synced 2026-06-16 04:12:41 +02:00
964 lines
37 KiB
C
964 lines
37 KiB
C
/* imrelp.c
|
|
*
|
|
* This is the implementation of the RELP input module.
|
|
*
|
|
* File begun on 2008-03-13 by RGerhards
|
|
*
|
|
* Copyright 2008-2019 Adiscon GmbH.
|
|
*
|
|
* This file is part of rsyslog.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
* -or-
|
|
* see COPYING.ASL20 in the source distribution
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* 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.
|
|
*/
|
|
#include "config.h"
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <stdarg.h>
|
|
#include <ctype.h>
|
|
#include <netinet/in.h>
|
|
#include <netdb.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <signal.h>
|
|
#include <librelp.h>
|
|
#include "rsyslog.h"
|
|
#include "dirty.h"
|
|
#include "errmsg.h"
|
|
#include "cfsysline.h"
|
|
#include "module-template.h"
|
|
#include "net.h"
|
|
#include "msg.h"
|
|
#include "unicode-helper.h"
|
|
#include "prop.h"
|
|
#include "ruleset.h"
|
|
#include "glbl.h"
|
|
#include "statsobj.h"
|
|
#include "srUtils.h"
|
|
#include "parserif.h"
|
|
#include "ratelimit.h"
|
|
|
|
MODULE_TYPE_INPUT;
|
|
MODULE_TYPE_NOKEEP;
|
|
MODULE_CNFNAME("imrelp")
|
|
|
|
/* static data */
|
|
DEF_IMOD_STATIC_DATA;
|
|
DEFobjCurrIf(net) DEFobjCurrIf(prop) DEFobjCurrIf(ruleset) DEFobjCurrIf(glbl) DEFobjCurrIf(statsobj)
|
|
|
|
/* forward definitions */
|
|
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal);
|
|
|
|
|
|
/* Module static data */
|
|
/* config vars for legacy config system */
|
|
static relpEngine_t *pRelpEngine; /* our relp engine */
|
|
|
|
/* config settings */
|
|
typedef struct configSettings_s {
|
|
uchar *pszBindRuleset; /* name of Ruleset to bind to */
|
|
} configSettings_t;
|
|
static configSettings_t cs;
|
|
|
|
struct instanceConf_s {
|
|
uchar *pszBindPort; /* port to bind to */
|
|
uchar *pszBindAddr; /* address to bind to */
|
|
uchar *pszBindRuleset; /* name of ruleset to bind to */
|
|
uchar *pszInputName; /* value for inputname property */
|
|
prop_t *pInputName; /* InputName in property format for fast access */
|
|
ruleset_t *pBindRuleset; /* ruleset to bind listener to */
|
|
sbool bKeepAlive; /* support keep-alive packets */
|
|
sbool bEnableTLS;
|
|
sbool bEnableTLSZip;
|
|
sbool bEnableLstn; /* flag to permit disabling of listener in error case */
|
|
int dhBits;
|
|
size_t maxDataSize;
|
|
int oversizeMode;
|
|
uchar *pristring; /* GnuTLS priority string (NULL if not to be provided) */
|
|
uchar *authmode; /* TLS auth mode */
|
|
uchar *caCertFile;
|
|
uchar *myCertFile;
|
|
uchar *myPrivKeyFile;
|
|
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
|
|
uchar *tlscfgcmd;
|
|
#endif
|
|
int iKeepAliveIntvl;
|
|
int iKeepAliveProbes;
|
|
int iKeepAliveTime;
|
|
int ratelimitInterval;
|
|
int ratelimitBurst;
|
|
uchar *pszRatelimitName;
|
|
flowControl_t flowCtlType;
|
|
struct {
|
|
int nmemb;
|
|
uchar **name;
|
|
} permittedPeers;
|
|
|
|
struct instanceConf_s *next;
|
|
/* with librelp, this module does not have any own specific session
|
|
* or listener active data item. As a "work-around", we keep some
|
|
* data items inside the configuration object. To keep things
|
|
* decently clean, we put them all into their dedicated struct. So
|
|
* it is easy to judge what is actual configuration and what is
|
|
* dynamic runtime data. -- rgerhards, 2013-06-18
|
|
*/
|
|
struct {
|
|
statsobj_t *stats; /* listener stats */
|
|
STATSCOUNTER_DEF(ctrSubmit, mutCtrSubmit)
|
|
ratelimit_t *ratelimiter;
|
|
} data;
|
|
};
|
|
|
|
|
|
struct modConfData_s {
|
|
rsconf_t *pConf; /* our overall config object */
|
|
instanceConf_t *root, *tail;
|
|
const char *tlslib;
|
|
uchar *pszBindRuleset; /* default name of Ruleset to bind to */
|
|
};
|
|
|
|
static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */
|
|
static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current load process */
|
|
|
|
/* module-global parameters */
|
|
static struct cnfparamdescr modpdescr[] = {{"ruleset", eCmdHdlrGetWord, 0}, {"tls.tlslib", eCmdHdlrString, 0}};
|
|
static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr};
|
|
|
|
/* input instance parameters */
|
|
static struct cnfparamdescr inppdescr[] = {{"port", eCmdHdlrString, CNFPARAM_REQUIRED},
|
|
{"address", eCmdHdlrString, 0},
|
|
{"name", eCmdHdlrString, 0},
|
|
{"ruleset", eCmdHdlrString, 0},
|
|
{"keepalive", eCmdHdlrBinary, 0},
|
|
{"keepalive.probes", eCmdHdlrInt, 0},
|
|
{"keepalive.time", eCmdHdlrInt, 0},
|
|
{"keepalive.interval", eCmdHdlrInt, 0},
|
|
{"maxdatasize", eCmdHdlrSize, 0},
|
|
{"oversizemode", eCmdHdlrString, 0},
|
|
{"flowcontrol", eCmdHdlrGetWord, 0},
|
|
{"ratelimit.interval", eCmdHdlrInt, 0},
|
|
{"ratelimit.burst", eCmdHdlrInt, 0},
|
|
{"ratelimit.name", eCmdHdlrString, 0},
|
|
{"tls", eCmdHdlrBinary, 0},
|
|
{"tls.permittedpeer", eCmdHdlrArray, 0},
|
|
{"tls.authmode", eCmdHdlrString, 0},
|
|
{"tls.dhbits", eCmdHdlrInt, 0},
|
|
{"tls.prioritystring", eCmdHdlrString, 0},
|
|
{"tls.cacert", eCmdHdlrString, 0},
|
|
{"tls.mycert", eCmdHdlrString, 0},
|
|
{"tls.myprivkey", eCmdHdlrString, 0},
|
|
{"tls.tlscfgcmd", eCmdHdlrString, 0},
|
|
{"tls.compression", eCmdHdlrBinary, 0}};
|
|
static struct cnfparamblk inppblk = {CNFPARAMBLK_VERSION, sizeof(inppdescr) / sizeof(struct cnfparamdescr), inppdescr};
|
|
|
|
#include "im-helper.h" /* must be included AFTER the type definitions! */
|
|
static int bLegacyCnfModGlobalsPermitted; /* are legacy module-global config parameters permitted? */
|
|
|
|
/* ------------------------------ callbacks ------------------------------ */
|
|
|
|
PRAGMA_DIAGNOSTIC_PUSH
|
|
PRAGMA_IGNORE_Wformat_nonliteral static void __attribute__((format(printf, 1, 2))) imrelp_dbgprintf(const char *fmt,
|
|
...) {
|
|
va_list ap;
|
|
char pszWriteBuf[32 * 1024 + 1]; // this function has to be able to
|
|
/*generate a buffer longer than that of r_dbgprintf, so
|
|
r_dbgprintf can properly truncate*/
|
|
|
|
if (!(Debug && debugging_on)) {
|
|
return;
|
|
}
|
|
|
|
va_start(ap, fmt);
|
|
vsnprintf(pszWriteBuf, sizeof(pszWriteBuf), fmt, ap);
|
|
va_end(ap);
|
|
r_dbgprintf("imrelp.c", "%s", pszWriteBuf);
|
|
}
|
|
PRAGMA_DIAGNOSTIC_POP
|
|
|
|
static void onErr(void *pUsr, char *objinfo, char *errmesg, __attribute__((unused)) relpRetVal errcode) {
|
|
instanceConf_t *inst = (instanceConf_t *)pUsr;
|
|
LogError(0, RS_RET_RELP_AUTH_FAIL,
|
|
"imrelp[%s]: error '%s', object "
|
|
" '%s' - input may not work as intended",
|
|
inst->pszBindPort, errmesg, objinfo);
|
|
}
|
|
|
|
static void onGenericErr(char *objinfo, char *errmesg, __attribute__((unused)) relpRetVal errcode) {
|
|
LogError(0, RS_RET_RELP_ERR,
|
|
"imrelp: librelp error '%s', object "
|
|
" '%s' - input may not work as intended",
|
|
errmesg, objinfo);
|
|
}
|
|
|
|
static void onAuthErr(void *pUsr, char *authinfo, char *errmesg, __attribute__((unused)) relpRetVal errcode) {
|
|
instanceConf_t *inst = (instanceConf_t *)pUsr;
|
|
LogError(0, RS_RET_RELP_AUTH_FAIL,
|
|
"imrelp[%s]: authentication error '%s', peer "
|
|
"is '%s'",
|
|
inst->pszBindPort, errmesg, authinfo);
|
|
}
|
|
|
|
/* callback for receiving syslog messages. This function is invoked from the
|
|
* RELP engine when a syslog message arrived. It must return a relpRetVal,
|
|
* with anything else but RELP_RET_OK terminating the relp session. Please note
|
|
* that RELP_RET_OK is equal to RS_RET_OK and the other libRELP error codes
|
|
* are different from our rsRetVal. So we can simply use our own iRet system
|
|
* to fulfill the requirement.
|
|
* rgerhards, 2008-03-21
|
|
* Note: librelp 1.0.0 is required in order to receive the IP address, otherwise
|
|
* we will only see the hostname (twice). -- rgerhards, 2009-10-14
|
|
*/
|
|
static relpRetVal onSyslogRcv(void *pUsr, uchar *pHostname, uchar *pIP, uchar *msg, size_t lenMsg) {
|
|
prop_t *pProp = NULL;
|
|
smsg_t *pMsg;
|
|
instanceConf_t *inst = (instanceConf_t *)pUsr;
|
|
DEFiRet;
|
|
|
|
CHKiRet(msgConstruct(&pMsg));
|
|
MsgSetInputName(pMsg, inst->pInputName);
|
|
MsgSetRawMsg(pMsg, (char *)msg, lenMsg);
|
|
MsgSetFlowControlType(pMsg, inst->flowCtlType);
|
|
MsgSetRuleset(pMsg, inst->pBindRuleset);
|
|
pMsg->msgFlags = PARSE_HOSTNAME | NEEDS_PARSING;
|
|
|
|
/* TODO: optimize this, we can store it inside the session */
|
|
MsgSetRcvFromStr(pMsg, pHostname, ustrlen(pHostname), &pProp);
|
|
CHKiRet(prop.Destruct(&pProp));
|
|
CHKiRet(MsgSetRcvFromIPStr(pMsg, pIP, ustrlen(pIP), &pProp));
|
|
CHKiRet(prop.Destruct(&pProp));
|
|
if (inst->data.ratelimiter != NULL) {
|
|
CHKiRet(ratelimitAddMsg(inst->data.ratelimiter, NULL, pMsg));
|
|
} else {
|
|
CHKiRet(submitMsg2(pMsg));
|
|
}
|
|
STATSCOUNTER_INC(inst->data.ctrSubmit, inst->data.mutCtrSubmit);
|
|
|
|
finalize_it:
|
|
|
|
RETiRet;
|
|
}
|
|
|
|
|
|
/* ------------------------------ end callbacks ------------------------------ */
|
|
|
|
/* create input instance, set default parameters, and
|
|
* add it to the list of instances.
|
|
*/
|
|
static rsRetVal createInstance(instanceConf_t **pinst) {
|
|
instanceConf_t *inst;
|
|
DEFiRet;
|
|
CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
|
|
inst->next = NULL;
|
|
|
|
inst->pszBindPort = NULL;
|
|
inst->pszBindAddr = NULL;
|
|
inst->pszBindRuleset = NULL;
|
|
inst->pszInputName = NULL;
|
|
inst->pBindRuleset = NULL;
|
|
inst->bKeepAlive = 0;
|
|
inst->iKeepAliveIntvl = 0;
|
|
inst->iKeepAliveProbes = 0;
|
|
inst->iKeepAliveTime = 0;
|
|
inst->ratelimitInterval = -1;
|
|
inst->ratelimitBurst = -1;
|
|
inst->pszRatelimitName = NULL;
|
|
inst->bEnableTLS = 0;
|
|
inst->bEnableTLSZip = 0;
|
|
inst->bEnableLstn = 0;
|
|
inst->dhBits = 0;
|
|
inst->pristring = NULL;
|
|
inst->authmode = NULL;
|
|
inst->permittedPeers.nmemb = 0;
|
|
inst->caCertFile = NULL;
|
|
inst->myCertFile = NULL;
|
|
inst->myPrivKeyFile = NULL;
|
|
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
|
|
inst->tlscfgcmd = NULL;
|
|
#endif
|
|
inst->maxDataSize = 0;
|
|
inst->flowCtlType = eFLOWCTL_LIGHT_DELAY;
|
|
#ifdef HAVE_RELPSRVSETOVERSIZEMODE
|
|
inst->oversizeMode = RELP_OVERSIZE_TRUNCATE;
|
|
#endif
|
|
|
|
/* node created, let's add to config */
|
|
if (loadModConf->tail == NULL) {
|
|
loadModConf->tail = loadModConf->root = inst;
|
|
} else {
|
|
loadModConf->tail->next = inst;
|
|
loadModConf->tail = inst;
|
|
}
|
|
|
|
*pinst = inst;
|
|
finalize_it:
|
|
RETiRet;
|
|
}
|
|
|
|
|
|
/* function to generate an error message if the ruleset cannot be found */
|
|
static inline void std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst) {
|
|
LogError(0, NO_ERRCODE,
|
|
"imrelp[%s]: ruleset '%s' not found - "
|
|
"using default ruleset instead",
|
|
inst->pszBindPort, inst->pszBindRuleset);
|
|
}
|
|
|
|
|
|
/* This function is called when a new listener instance shall be added to
|
|
* the current config object via the legacy config system. It just shuffles
|
|
* all parameters to the listener in-memory instance.
|
|
* rgerhards, 2011-05-04
|
|
*/
|
|
static rsRetVal addInstance(void __attribute__((unused)) * pVal, uchar *pNewVal) {
|
|
instanceConf_t *inst;
|
|
DEFiRet;
|
|
|
|
CHKiRet(createInstance(&inst));
|
|
|
|
if (pNewVal == NULL || *pNewVal == '\0') {
|
|
LogError(0, NO_ERRCODE, "imrelp: port number must be specified, listener ignored");
|
|
}
|
|
if ((pNewVal == NULL) || (*pNewVal == '\0')) {
|
|
inst->pszBindPort = NULL;
|
|
} else {
|
|
CHKmalloc(inst->pszBindPort = ustrdup(pNewVal));
|
|
}
|
|
if ((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
|
|
inst->pszBindRuleset = NULL;
|
|
} else {
|
|
CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset));
|
|
}
|
|
inst->pBindRuleset = NULL;
|
|
|
|
inst->bEnableLstn = -1; /* all ok, ready to start up */
|
|
finalize_it:
|
|
free(pNewVal);
|
|
RETiRet;
|
|
}
|
|
|
|
|
|
static rsRetVal addListner(modConfData_t __attribute__((unused)) * modConf, instanceConf_t *inst) {
|
|
relpSrv_t *pSrv;
|
|
int relpRet;
|
|
uchar statname[64];
|
|
int i;
|
|
DEFiRet;
|
|
|
|
if (!inst->bEnableLstn) {
|
|
DBGPRINTF("listener not started because it is disabled by config error\n");
|
|
FINALIZE;
|
|
}
|
|
|
|
if (pRelpEngine == NULL) {
|
|
CHKiRet(relpEngineConstruct(&pRelpEngine));
|
|
CHKiRet(relpEngineSetDbgprint(pRelpEngine, (void (*)(char *, ...))imrelp_dbgprintf));
|
|
CHKiRet(relpEngineSetFamily(pRelpEngine, glbl.GetDefPFFamily(runModConf->pConf)));
|
|
CHKiRet(relpEngineSetEnableCmd(pRelpEngine, (uchar *)"syslog", eRelpCmdState_Required));
|
|
CHKiRet(relpEngineSetSyslogRcv2(pRelpEngine, onSyslogRcv));
|
|
CHKiRet(relpEngineSetOnErr(pRelpEngine, onErr));
|
|
CHKiRet(relpEngineSetOnGenericErr(pRelpEngine, onGenericErr));
|
|
CHKiRet(relpEngineSetOnAuthErr(pRelpEngine, onAuthErr));
|
|
if (!glbl.GetDisableDNS(runModConf->pConf)) {
|
|
CHKiRet(relpEngineSetDnsLookupMode(pRelpEngine, 1));
|
|
}
|
|
#if defined(HAVE_RELPENGINESETTLSLIBBYNAME)
|
|
if (modConf->tlslib != NULL) {
|
|
if (relpEngineSetTLSLibByName(pRelpEngine, modConf->tlslib) != RELP_RET_OK) {
|
|
LogMsg(0, RS_RET_CONF_PARAM_INVLD, LOG_WARNING,
|
|
"imrelp: tlslib '%s' not accepted as valid by librelp - using default", modConf->tlslib);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
CHKiRet(relpEngineListnerConstruct(pRelpEngine, &pSrv));
|
|
CHKiRet(relpSrvSetMaxDataSize(pSrv, inst->maxDataSize));
|
|
CHKiRet(relpSrvSetLstnPort(pSrv, inst->pszBindPort));
|
|
#if defined(HAVE_RELPSRVSETLSTNADDR)
|
|
CHKiRet(relpSrvSetLstnAddr(pSrv, inst->pszBindAddr));
|
|
#endif
|
|
|
|
#ifdef HAVE_RELPSRVSETOVERSIZEMODE
|
|
CHKiRet(relpSrvSetOversizeMode(pSrv, inst->oversizeMode));
|
|
#endif
|
|
inst->pszInputName = ustrdup((inst->pszInputName == NULL) ? UCHAR_CONSTANT("imrelp") : inst->pszInputName);
|
|
CHKiRet(prop.Construct(&inst->pInputName));
|
|
CHKiRet(prop.SetString(inst->pInputName, inst->pszInputName, ustrlen(inst->pszInputName)));
|
|
CHKiRet(prop.ConstructFinalize(inst->pInputName));
|
|
/* support statistics gathering */
|
|
CHKiRet(statsobj.Construct(&(inst->data.stats)));
|
|
snprintf((char *)statname, sizeof(statname), "%s(%s)", inst->pszInputName, inst->pszBindPort);
|
|
statname[sizeof(statname) - 1] = '\0'; /* just to be on the save side... */
|
|
CHKiRet(statsobj.SetName(inst->data.stats, statname));
|
|
CHKiRet(statsobj.SetOrigin(inst->data.stats, (uchar *)"imrelp"));
|
|
STATSCOUNTER_INIT(inst->data.ctrSubmit, inst->data.mutCtrSubmit);
|
|
CHKiRet(statsobj.AddCounter(inst->data.stats, UCHAR_CONSTANT("submitted"), ctrType_IntCtr, CTR_FLAG_RESETTABLE,
|
|
&(inst->data.ctrSubmit)));
|
|
CHKiRet(statsobj.ConstructFinalize(inst->data.stats));
|
|
/* end stats counters */
|
|
/* set up ratelimiter */
|
|
inst->data.ratelimiter = NULL;
|
|
if (inst->pszRatelimitName != NULL) {
|
|
CHKiRet(ratelimitNewFromConfig(&inst->data.ratelimiter, runModConf->pConf, (char *)inst->pszRatelimitName,
|
|
"imrelp", (char *)inst->pszBindPort));
|
|
} else if (inst->ratelimitInterval > 0) {
|
|
CHKiRet(ratelimitNew(&inst->data.ratelimiter, "imrelp", (char *)inst->pszBindPort));
|
|
ratelimitSetLinuxLike(inst->data.ratelimiter, (unsigned)inst->ratelimitInterval,
|
|
(unsigned)inst->ratelimitBurst);
|
|
}
|
|
if (inst->data.ratelimiter != NULL) {
|
|
ratelimitSetThreadSafe(inst->data.ratelimiter);
|
|
}
|
|
relpSrvSetUsrPtr(pSrv, inst);
|
|
relpSrvSetKeepAlive(pSrv, inst->bKeepAlive, inst->iKeepAliveIntvl, inst->iKeepAliveProbes, inst->iKeepAliveTime);
|
|
if (inst->bEnableTLS) {
|
|
relpRet = relpSrvEnableTLS2(pSrv);
|
|
if (relpRet == RELP_RET_ERR_NO_TLS) {
|
|
LogError(0, RS_RET_RELP_NO_TLS,
|
|
"imrelp: could not activate relp TLS, librelp "
|
|
"does not support it (most probably GnuTLS lib "
|
|
"is too old)!");
|
|
ABORT_FINALIZE(RS_RET_RELP_NO_TLS);
|
|
} else if (relpRet == RELP_RET_ERR_NO_TLS_AUTH) {
|
|
LogError(0, RS_RET_RELP_NO_TLS_AUTH,
|
|
"imrelp: could not activate relp TLS with "
|
|
"authentication, librelp does not support it "
|
|
"(most probably GnuTLS lib is too old)! "
|
|
"Note: anonymous TLS is probably supported.");
|
|
ABORT_FINALIZE(RS_RET_RELP_NO_TLS_AUTH);
|
|
} else if (relpRet != RELP_RET_OK) {
|
|
LogError(0, RS_RET_RELP_ERR, "imrelp: could not activate relp TLS, code %d", relpRet);
|
|
ABORT_FINALIZE(RS_RET_RELP_ERR);
|
|
}
|
|
if (inst->bEnableTLSZip) {
|
|
relpSrvEnableTLSZip2(pSrv);
|
|
}
|
|
if (inst->dhBits) {
|
|
relpSrvSetDHBits(pSrv, inst->dhBits);
|
|
}
|
|
relpSrvSetGnuTLSPriString(pSrv, (char *)inst->pristring);
|
|
if (relpSrvSetAuthMode(pSrv, (char *)inst->authmode) != RELP_RET_OK) {
|
|
LogError(0, RS_RET_RELP_ERR, "imrelp: invalid auth mode '%s'", inst->authmode);
|
|
ABORT_FINALIZE(RS_RET_RELP_ERR);
|
|
}
|
|
if (relpSrvSetCACert(pSrv, (char *)inst->caCertFile) != RELP_RET_OK) ABORT_FINALIZE(RS_RET_RELP_ERR);
|
|
if (relpSrvSetOwnCert(pSrv, (char *)inst->myCertFile) != RELP_RET_OK) ABORT_FINALIZE(RS_RET_RELP_ERR);
|
|
if (relpSrvSetPrivKey(pSrv, (char *)inst->myPrivKeyFile) != RELP_RET_OK) ABORT_FINALIZE(RS_RET_RELP_ERR);
|
|
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
|
|
if (inst->tlscfgcmd != NULL) {
|
|
if (relpSrvSetTlsConfigCmd(pSrv, (char *)inst->tlscfgcmd) != RELP_RET_OK) ABORT_FINALIZE(RS_RET_RELP_ERR);
|
|
}
|
|
#endif
|
|
for (i = 0; i < inst->permittedPeers.nmemb; ++i) {
|
|
relpSrvAddPermittedPeer(pSrv, (char *)inst->permittedPeers.name[i]);
|
|
}
|
|
}
|
|
relpRet = relpEngineListnerConstructFinalize(pRelpEngine, pSrv);
|
|
/* re-check error TLS error codes. librelp seems to emit them only
|
|
* after finalize in some cases...
|
|
*/
|
|
if (relpRet == RELP_RET_ERR_NO_TLS) {
|
|
LogError(0, RS_RET_RELP_NO_TLS,
|
|
"imrelp: could not activate relp TLS listener, librelp "
|
|
"does not support it (most probably GnuTLS lib "
|
|
"is too old)!");
|
|
ABORT_FINALIZE(RS_RET_RELP_NO_TLS);
|
|
} else if (relpRet == RELP_RET_ERR_NO_TLS_AUTH) {
|
|
LogError(0, RS_RET_RELP_NO_TLS_AUTH,
|
|
"imrelp: could not activate relp TLS listener with "
|
|
"authentication, librelp does not support it "
|
|
"(most probably GnuTLS lib is too old)! "
|
|
"Note: anonymous TLS is probably supported.");
|
|
ABORT_FINALIZE(RS_RET_RELP_NO_TLS_AUTH);
|
|
} else if (relpRet != RELP_RET_OK) {
|
|
LogError(0, RS_RET_RELP_ERR, "imrelp: could not activate relp listener, code %d", relpRet);
|
|
ABORT_FINALIZE(RS_RET_RELP_ERR);
|
|
}
|
|
|
|
DBGPRINTF("imrelp: max data size %zd\n", inst->maxDataSize);
|
|
resetConfigVariables(NULL, NULL);
|
|
|
|
finalize_it:
|
|
RETiRet;
|
|
}
|
|
|
|
|
|
BEGINnewInpInst
|
|
struct cnfparamvals *pvals;
|
|
instanceConf_t *inst = NULL;
|
|
int i, j;
|
|
FILE *fp;
|
|
CODESTARTnewInpInst;
|
|
DBGPRINTF("newInpInst (imrelp)\n");
|
|
|
|
if ((pvals = nvlstGetParams(lst, &inppblk, NULL)) == NULL) {
|
|
ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
|
|
}
|
|
|
|
if (Debug) {
|
|
dbgprintf("input param blk in imrelp:\n");
|
|
cnfparamsPrint(&inppblk, pvals);
|
|
}
|
|
|
|
CHKiRet(createInstance(&inst));
|
|
|
|
for (i = 0; i < inppblk.nParams; ++i) {
|
|
if (!pvals[i].bUsed) continue;
|
|
if (!strcmp(inppblk.descr[i].name, "port")) {
|
|
CHKmalloc(inst->pszBindPort = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
} else if (!strcmp(inppblk.descr[i].name, "address")) {
|
|
#if defined(HAVE_RELPSRVSETLSTNADDR)
|
|
CHKmalloc(inst->pszBindAddr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
#else
|
|
parser_errmsg(
|
|
"imrelp: librelp does not support input parameter 'address'; "
|
|
"it probably is too old (1.2.16 should be fine); ignoring setting now, "
|
|
"listening on all interfaces");
|
|
#endif
|
|
} else if (!strcmp(inppblk.descr[i].name, "name")) {
|
|
CHKmalloc(inst->pszInputName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
} else if (!strcmp(inppblk.descr[i].name, "ruleset")) {
|
|
CHKmalloc(inst->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
} else if (!strcmp(inppblk.descr[i].name, "maxdatasize")) {
|
|
inst->maxDataSize = (size_t)pvals[i].val.d.n;
|
|
} else if (!strcmp(inppblk.descr[i].name, "flowcontrol")) {
|
|
if (!es_strconstcmp(pvals[i].val.d.estr, "none")) {
|
|
inst->flowCtlType = eFLOWCTL_NO_DELAY;
|
|
} else if (!es_strconstcmp(pvals[i].val.d.estr, "light")) {
|
|
inst->flowCtlType = eFLOWCTL_LIGHT_DELAY;
|
|
} else if (!es_strconstcmp(pvals[i].val.d.estr, "full")) {
|
|
inst->flowCtlType = eFLOWCTL_FULL_DELAY;
|
|
} else {
|
|
char *mode = NULL;
|
|
CHKmalloc(mode = es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
parser_errmsg(
|
|
"imrelp: wrong flowcontrol parameter "
|
|
"value '%s', using default: 'light'; possible "
|
|
"values: 'no', 'light', 'full'\n",
|
|
mode);
|
|
free((void *)mode);
|
|
}
|
|
} else if (!strcmp(inppblk.descr[i].name, "oversizemode")) {
|
|
#ifdef HAVE_RELPSRVSETOVERSIZEMODE
|
|
char *mode;
|
|
CHKmalloc(mode = es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
if (!strcmp(mode, "abort")) {
|
|
inst->oversizeMode = RELP_OVERSIZE_ABORT;
|
|
} else if (!strcmp(mode, "truncate")) {
|
|
inst->oversizeMode = RELP_OVERSIZE_TRUNCATE;
|
|
} else if (!strcmp(mode, "accept")) {
|
|
inst->oversizeMode = RELP_OVERSIZE_ACCEPT;
|
|
} else {
|
|
parser_errmsg(
|
|
"imrelp: wrong oversizeMode parameter "
|
|
"value %s, using default: truncate\n",
|
|
mode);
|
|
inst->oversizeMode = RELP_OVERSIZE_TRUNCATE;
|
|
}
|
|
#else
|
|
parser_errmsg(
|
|
"imrelp: parameter oversizeMode is not available in "
|
|
"this relp version and is therefore disabled.");
|
|
#endif
|
|
} else if (!strcmp(inppblk.descr[i].name, "keepalive")) {
|
|
inst->bKeepAlive = (sbool)pvals[i].val.d.n;
|
|
} else if (!strcmp(inppblk.descr[i].name, "keepalive.probes")) {
|
|
inst->iKeepAliveProbes = (int)pvals[i].val.d.n;
|
|
} else if (!strcmp(inppblk.descr[i].name, "keepalive.time")) {
|
|
inst->iKeepAliveTime = (int)pvals[i].val.d.n;
|
|
} else if (!strcmp(inppblk.descr[i].name, "keepalive.interval")) {
|
|
inst->iKeepAliveIntvl = (int)pvals[i].val.d.n;
|
|
} else if (!strcmp(inppblk.descr[i].name, "ratelimit.interval")) {
|
|
inst->ratelimitInterval = (int)pvals[i].val.d.n;
|
|
} else if (!strcmp(inppblk.descr[i].name, "ratelimit.burst")) {
|
|
inst->ratelimitBurst = (int)pvals[i].val.d.n;
|
|
} else if (!strcmp(inppblk.descr[i].name, "ratelimit.name")) {
|
|
CHKmalloc(inst->pszRatelimitName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
} else if (!strcmp(inppblk.descr[i].name, "tls")) {
|
|
inst->bEnableTLS = (unsigned)pvals[i].val.d.n;
|
|
} else if (!strcmp(inppblk.descr[i].name, "tls.dhbits")) {
|
|
inst->dhBits = (unsigned)pvals[i].val.d.n;
|
|
} else if (!strcmp(inppblk.descr[i].name, "tls.prioritystring")) {
|
|
CHKmalloc(inst->pristring = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
} else if (!strcmp(inppblk.descr[i].name, "tls.authmode")) {
|
|
CHKmalloc(inst->authmode = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
} else if (!strcmp(inppblk.descr[i].name, "tls.compression")) {
|
|
inst->bEnableTLSZip = (unsigned)pvals[i].val.d.n;
|
|
} else if (!strcmp(inppblk.descr[i].name, "tls.cacert")) {
|
|
CHKmalloc(inst->caCertFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
fp = fopen((const char *)inst->caCertFile, "r");
|
|
if (fp == NULL) {
|
|
LogError(errno, RS_RET_NO_FILE_ACCESS, "error: certificate file %s couldn't be accessed",
|
|
inst->caCertFile);
|
|
} else {
|
|
fclose(fp);
|
|
}
|
|
} else if (!strcmp(inppblk.descr[i].name, "tls.mycert")) {
|
|
CHKmalloc(inst->myCertFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
fp = fopen((const char *)inst->myCertFile, "r");
|
|
if (fp == NULL) {
|
|
LogError(errno, RS_RET_NO_FILE_ACCESS, "error: certificate file %s couldn't be accessed",
|
|
inst->myCertFile);
|
|
} else {
|
|
fclose(fp);
|
|
}
|
|
} else if (!strcmp(inppblk.descr[i].name, "tls.myprivkey")) {
|
|
CHKmalloc(inst->myPrivKeyFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
fp = fopen((const char *)inst->myPrivKeyFile, "r");
|
|
if (fp == NULL) {
|
|
LogError(errno, RS_RET_NO_FILE_ACCESS, "error: certificate file %s couldn't be accessed",
|
|
inst->myPrivKeyFile);
|
|
} else {
|
|
fclose(fp);
|
|
}
|
|
} else if (!strcmp(inppblk.descr[i].name, "tls.tlscfgcmd")) {
|
|
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
|
|
CHKmalloc(inst->tlscfgcmd = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
#else
|
|
parser_errmsg(
|
|
"imrelp: librelp does not support input parameter 'tls.tlscfgcmd'; "
|
|
"it probably is too old (1.5.0 or higher should be fine); ignoring setting now.");
|
|
#endif
|
|
} else if (!strcmp(inppblk.descr[i].name, "tls.permittedpeer")) {
|
|
inst->permittedPeers.nmemb = pvals[i].val.d.ar->nmemb;
|
|
CHKmalloc(inst->permittedPeers.name = malloc(sizeof(uchar *) * inst->permittedPeers.nmemb));
|
|
for (j = 0; j < pvals[i].val.d.ar->nmemb; ++j) {
|
|
inst->permittedPeers.name[j] = (uchar *)es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
|
|
}
|
|
} else {
|
|
dbgprintf(
|
|
"imrelp: program error, non-handled "
|
|
"param '%s'\n",
|
|
inppblk.descr[i].name);
|
|
}
|
|
}
|
|
|
|
if (inst->myCertFile != NULL && inst->myPrivKeyFile == NULL) {
|
|
LogError(0, RS_RET_ERR,
|
|
"imrelp: certificate file given but no corresponding "
|
|
"private key file - this is invalid, listener cannot be started");
|
|
ABORT_FINALIZE(RS_RET_ERR);
|
|
}
|
|
if (inst->myCertFile == NULL && inst->myPrivKeyFile != NULL) {
|
|
LogError(0, RS_RET_ERR,
|
|
"imrelp: private key file given but no corresponding "
|
|
"certificate file - this is invalid, listener cannot be started");
|
|
ABORT_FINALIZE(RS_RET_ERR);
|
|
}
|
|
|
|
if (inst->pszRatelimitName != NULL) {
|
|
if (inst->ratelimitInterval != -1 || inst->ratelimitBurst != -1) {
|
|
LogError(0, RS_RET_INVALID_PARAMS,
|
|
"imrelp: ratelimit.name is mutually exclusive with "
|
|
"ratelimit.interval and ratelimit.burst - using ratelimit.name");
|
|
}
|
|
inst->ratelimitInterval = 0;
|
|
inst->ratelimitBurst = 0;
|
|
} else {
|
|
if (inst->ratelimitInterval == -1) inst->ratelimitInterval = 0;
|
|
if (inst->ratelimitBurst == -1) inst->ratelimitBurst = 10000;
|
|
}
|
|
|
|
inst->bEnableLstn = -1; /* all ok, ready to start up */
|
|
|
|
finalize_it:
|
|
CODE_STD_FINALIZERnewInpInst cnfparamvalsDestruct(pvals, &inppblk);
|
|
if (iRet != RS_RET_OK) {
|
|
if (inst != NULL) {
|
|
free(inst->myCertFile);
|
|
inst->myCertFile = NULL;
|
|
free(inst->myPrivKeyFile);
|
|
inst->myPrivKeyFile = NULL;
|
|
}
|
|
}
|
|
ENDnewInpInst
|
|
|
|
|
|
BEGINbeginCnfLoad
|
|
CODESTARTbeginCnfLoad;
|
|
loadModConf = pModConf;
|
|
pModConf->pConf = pConf;
|
|
pModConf->pszBindRuleset = NULL;
|
|
pModConf->tlslib = NULL;
|
|
/* init legacy config variables */
|
|
cs.pszBindRuleset = NULL;
|
|
bLegacyCnfModGlobalsPermitted = 1;
|
|
ENDbeginCnfLoad
|
|
|
|
|
|
BEGINsetModCnf
|
|
struct cnfparamvals *pvals = NULL;
|
|
int i;
|
|
CODESTARTsetModCnf;
|
|
pvals = nvlstGetParams(lst, &modpblk, NULL);
|
|
if (pvals == NULL) {
|
|
LogError(0, RS_RET_MISSING_CNFPARAMS,
|
|
"error processing module "
|
|
"config parameters [module(...)]");
|
|
ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
|
|
}
|
|
|
|
if (Debug) {
|
|
dbgprintf("module (global) param blk for imrelp:\n");
|
|
cnfparamsPrint(&modpblk, pvals);
|
|
}
|
|
|
|
for (i = 0; i < modpblk.nParams; ++i) {
|
|
if (!pvals[i].bUsed) continue;
|
|
if (!strcmp(modpblk.descr[i].name, "ruleset")) {
|
|
CHKmalloc(loadModConf->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
} else if (!strcmp(modpblk.descr[i].name, "tls.tlslib")) {
|
|
#if defined(HAVE_RELPENGINESETTLSLIBBYNAME)
|
|
CHKmalloc(loadModConf->tlslib = es_str2cstr(pvals[i].val.d.estr, NULL));
|
|
#else
|
|
LogError(0, RS_RET_NOT_IMPLEMENTED,
|
|
"imrelp warning: parameter tls.tlslib ignored - librelp does not support "
|
|
"this API call. Using whatever librelp was compiled with.");
|
|
#endif
|
|
} else {
|
|
dbgprintf(
|
|
"imrelp: program error, non-handled "
|
|
"param '%s' in beginCnfLoad\n",
|
|
modpblk.descr[i].name);
|
|
}
|
|
}
|
|
/* remove all of our legacy module handlers, as they can not used in addition
|
|
* the the new-style config method.
|
|
*/
|
|
bLegacyCnfModGlobalsPermitted = 0;
|
|
finalize_it:
|
|
if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk);
|
|
ENDsetModCnf
|
|
|
|
BEGINendCnfLoad
|
|
CODESTARTendCnfLoad;
|
|
if (loadModConf->pszBindRuleset == NULL) {
|
|
if ((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
|
|
loadModConf->pszBindRuleset = NULL;
|
|
} else {
|
|
CHKmalloc(loadModConf->pszBindRuleset = ustrdup(cs.pszBindRuleset));
|
|
}
|
|
} else {
|
|
if ((cs.pszBindRuleset != NULL) && (cs.pszBindRuleset[0] != '\0')) {
|
|
LogError(0, RS_RET_DUP_PARAM,
|
|
"imrelp: ruleset "
|
|
"set via legacy directive ignored");
|
|
}
|
|
}
|
|
finalize_it:
|
|
free(cs.pszBindRuleset);
|
|
cs.pszBindRuleset = NULL;
|
|
loadModConf = NULL; /* done loading */
|
|
ENDendCnfLoad
|
|
|
|
BEGINcheckCnf
|
|
instanceConf_t *inst;
|
|
size_t maxMessageSize;
|
|
CODESTARTcheckCnf;
|
|
for (inst = pModConf->root; inst != NULL; inst = inst->next) {
|
|
if (inst->pszBindRuleset == NULL && pModConf->pszBindRuleset != NULL) {
|
|
CHKmalloc(inst->pszBindRuleset = ustrdup(pModConf->pszBindRuleset));
|
|
}
|
|
std_checkRuleset(pModConf, inst);
|
|
|
|
|
|
if (inst->maxDataSize == 0) {
|
|
/* We set default value for maxDataSize here because
|
|
* otherwise the maxMessageSize isn't set.
|
|
*/
|
|
inst->maxDataSize = glbl.GetMaxLine(loadConf);
|
|
}
|
|
maxMessageSize = (size_t)glbl.GetMaxLine(loadConf);
|
|
if (inst->maxDataSize < maxMessageSize) {
|
|
LogError(0, RS_RET_INVALID_PARAMS,
|
|
"error: "
|
|
"maxDataSize (%zu) is smaller than global parameter "
|
|
"maxMessageSize (%zu) - global parameter will be used.",
|
|
inst->maxDataSize, maxMessageSize);
|
|
inst->maxDataSize = maxMessageSize;
|
|
}
|
|
}
|
|
|
|
finalize_it:
|
|
ENDcheckCnf
|
|
|
|
|
|
BEGINactivateCnfPrePrivDrop
|
|
instanceConf_t *inst;
|
|
CODESTARTactivateCnfPrePrivDrop;
|
|
runModConf = pModConf;
|
|
for (inst = runModConf->root; inst != NULL; inst = inst->next) {
|
|
addListner(pModConf, inst);
|
|
}
|
|
if (pRelpEngine == NULL) {
|
|
LogError(0, RS_RET_NO_LSTN_DEFINED, "imrelp: no RELP listener defined, module can not run.");
|
|
ABORT_FINALIZE(RS_RET_NO_RUN);
|
|
}
|
|
finalize_it:
|
|
ENDactivateCnfPrePrivDrop
|
|
|
|
BEGINactivateCnf
|
|
CODESTARTactivateCnf;
|
|
ENDactivateCnf
|
|
|
|
|
|
BEGINfreeCnf
|
|
instanceConf_t *inst, *del;
|
|
int i;
|
|
CODESTARTfreeCnf;
|
|
if (pRelpEngine != NULL) iRet = relpEngineDestruct(&pRelpEngine);
|
|
|
|
for (inst = pModConf->root; inst != NULL;) {
|
|
free(inst->pszBindPort);
|
|
if (inst->pszBindAddr != NULL) {
|
|
free(inst->pszBindAddr);
|
|
}
|
|
free(inst->pszBindRuleset);
|
|
free(inst->pszInputName);
|
|
free(inst->pristring);
|
|
free(inst->authmode);
|
|
for (i = 0; i < inst->permittedPeers.nmemb; ++i) {
|
|
free(inst->permittedPeers.name[i]);
|
|
}
|
|
if (inst->bEnableLstn) {
|
|
prop.Destruct(&inst->pInputName);
|
|
statsobj.Destruct(&(inst->data.stats));
|
|
if (inst->data.ratelimiter != NULL) ratelimitDestruct(inst->data.ratelimiter);
|
|
}
|
|
free(inst->pszRatelimitName);
|
|
del = inst;
|
|
inst = inst->next;
|
|
free(del);
|
|
}
|
|
free(pModConf->pszBindRuleset);
|
|
ENDfreeCnf
|
|
|
|
/* This is used to terminate the plugin. Note that the signal handler blocks
|
|
* other activity on the thread. As such, it is safe to request the stop. When
|
|
* we terminate, relpEngine is called, and it's select() loop interrupted. But
|
|
* only *after this function is done*. So we do not have a race!
|
|
*/
|
|
static void doSIGTTIN(int __attribute__((unused)) sig) {
|
|
const int bTerminate = ATOMIC_FETCH_32BIT(&bTerminateInputs, &mutTerminateInputs);
|
|
if (bTerminate && (pRelpEngine != NULL)) {
|
|
relpEngineSetStop(pRelpEngine);
|
|
}
|
|
}
|
|
|
|
|
|
/* This function is called to gather input.
|
|
*/
|
|
BEGINrunInput
|
|
sigset_t sigSet;
|
|
struct sigaction sigAct;
|
|
CODESTARTrunInput;
|
|
/* we want to support non-cancel input termination. To do so, we must signal librelp
|
|
* when to stop. As we run on the same thread, we need to register as SIGTTIN handler,
|
|
* which will be used to put the terminating condition into librelp.
|
|
*/
|
|
sigfillset(&sigSet);
|
|
pthread_sigmask(SIG_BLOCK, &sigSet, NULL);
|
|
sigemptyset(&sigSet);
|
|
sigaddset(&sigSet, SIGTTIN);
|
|
pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL);
|
|
memset(&sigAct, 0, sizeof(sigAct));
|
|
sigemptyset(&sigAct.sa_mask);
|
|
sigAct.sa_handler = doSIGTTIN;
|
|
sigaction(SIGTTIN, &sigAct, NULL);
|
|
|
|
iRet = relpEngineRun(pRelpEngine);
|
|
ENDrunInput
|
|
|
|
|
|
BEGINwillRun
|
|
CODESTARTwillRun;
|
|
ENDwillRun
|
|
|
|
|
|
BEGINafterRun
|
|
CODESTARTafterRun;
|
|
/* do cleanup here */
|
|
ENDafterRun
|
|
|
|
|
|
BEGINmodExit
|
|
CODESTARTmodExit;
|
|
struct sigaction newAct;
|
|
memset(&newAct, 0, sizeof(newAct));
|
|
sigemptyset(&newAct.sa_mask);
|
|
newAct.sa_handler = SIG_IGN;
|
|
sigaction(SIGTTIN, &newAct, NULL);
|
|
|
|
/* release objects we used */
|
|
objRelease(statsobj, CORE_COMPONENT);
|
|
objRelease(ruleset, CORE_COMPONENT);
|
|
objRelease(glbl, CORE_COMPONENT);
|
|
objRelease(prop, CORE_COMPONENT);
|
|
objRelease(net, LM_NET_FILENAME);
|
|
ENDmodExit
|
|
|
|
|
|
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal) {
|
|
free(cs.pszBindRuleset);
|
|
cs.pszBindRuleset = NULL;
|
|
return RS_RET_OK;
|
|
}
|
|
|
|
|
|
BEGINisCompatibleWithFeature
|
|
CODESTARTisCompatibleWithFeature;
|
|
if (eFeat == sFEATURENonCancelInputTermination) iRet = RS_RET_OK;
|
|
ENDisCompatibleWithFeature
|
|
|
|
|
|
BEGINqueryEtryPt
|
|
CODESTARTqueryEtryPt;
|
|
CODEqueryEtryPt_STD_IMOD_QUERIES;
|
|
CODEqueryEtryPt_STD_CONF2_QUERIES;
|
|
CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES;
|
|
CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES;
|
|
CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES;
|
|
CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES;
|
|
ENDqueryEtryPt
|
|
|
|
|
|
BEGINmodInit()
|
|
CODESTARTmodInit;
|
|
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
|
|
CODEmodInit_QueryRegCFSLineHdlr pRelpEngine = NULL;
|
|
/* request objects we use */
|
|
CHKiRet(objUse(glbl, CORE_COMPONENT));
|
|
CHKiRet(objUse(prop, CORE_COMPONENT));
|
|
CHKiRet(objUse(net, LM_NET_FILENAME));
|
|
CHKiRet(objUse(ruleset, CORE_COMPONENT));
|
|
CHKiRet(objUse(statsobj, CORE_COMPONENT));
|
|
|
|
#ifndef HAVE_RELPSRVSETOVERSIZEMODE
|
|
LogMsg(0, RS_RET_OK_WARN, LOG_WARNING,
|
|
"imrelp: librelp too old, oversizemode "
|
|
"defaults to \"abort\"");
|
|
#endif
|
|
|
|
/* register config file handlers */
|
|
CHKiRet(regCfSysLineHdlr2((uchar *)"inputrelpserverbindruleset", 0, eCmdHdlrGetWord, NULL, &cs.pszBindRuleset,
|
|
STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
|
|
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrelpserverrun", 0, eCmdHdlrGetWord, addInstance, NULL,
|
|
STD_LOADABLE_MODULE_ID));
|
|
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL,
|
|
STD_LOADABLE_MODULE_ID));
|
|
ENDmodInit
|