2013-12-10 17:01:43 +01:00

673 lines
20 KiB
C

/* imrelp.c
*
* This is the implementation of the RELP input module.
*
* File begun on 2008-03-13 by RGerhards
*
* Copyright 2008-2013 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"
MODULE_TYPE_INPUT
MODULE_TYPE_NOKEEP
MODULE_CNFNAME("imrelp")
/* static data */
DEF_IMOD_STATIC_DATA
DEFobjCurrIf(net)
DEFobjCurrIf(prop)
DEFobjCurrIf(errmsg)
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 */
static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this module */
static struct configSettings_s {
uchar *pszBindRuleset; /* name of Ruleset to bind to */
} cs;
struct instanceConf_s {
uchar *pszBindPort; /* port to bind to */
sbool bKeepAlive; /* support keep-alive packets */
sbool bEnableTLS;
sbool bEnableTLSZip;
int dhBits;
uchar *pristring; /* GnuTLS priority string (NULL if not to be provided) */
uchar *authmode; /* TLS auth mode */
uchar *caCertFile;
uchar *myCertFile;
uchar *myPrivKeyFile;
int iKeepAliveIntvl;
int iKeepAliveProbes;
int iKeepAliveTime;
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)
} data;
};
struct modConfData_s {
rsconf_t *pConf; /* our overall config object */
instanceConf_t *root, *tail;
uchar *pszBindRuleset; /* name of Ruleset to bind to */
ruleset_t *pBindRuleset; /* due to librelp limitation, we need to bind all listerns to the same set */
};
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 },
};
static struct cnfparamblk modpblk =
{ CNFPARAMBLK_VERSION,
sizeof(modpdescr)/sizeof(struct cnfparamdescr),
modpdescr
};
/* input instance parameters */
static struct cnfparamdescr inppdescr[] = {
{ "port", eCmdHdlrString, CNFPARAM_REQUIRED },
{ "keepalive", eCmdHdlrBinary, 0 },
{ "keepalive.probes", eCmdHdlrInt, 0 },
{ "keepalive.time", eCmdHdlrInt, 0 },
{ "keepalive.interval", eCmdHdlrInt, 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.compression", eCmdHdlrBinary, 0 }
};
static struct cnfparamblk inppblk =
{ CNFPARAMBLK_VERSION,
sizeof(inppdescr)/sizeof(struct cnfparamdescr),
inppdescr
};
/* ------------------------------ callbacks ------------------------------ */
static void
onErr(void *pUsr, char *objinfo, char* errmesg, __attribute__((unused)) relpRetVal errcode)
{
instanceConf_t *inst = (instanceConf_t*) pUsr;
errmsg.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)
{
errmsg.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;
errmsg.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;
msg_t *pMsg;
instanceConf_t *inst = (instanceConf_t*) pUsr;
DEFiRet;
CHKiRet(msgConstruct(&pMsg));
MsgSetInputName(pMsg, pInputName);
MsgSetRawMsg(pMsg, (char*)msg, lenMsg);
MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY);
MsgSetRuleset(pMsg, runModConf->pBindRuleset);
pMsg->msgFlags = PARSE_HOSTNAME | NEEDS_PARSING;
/* TODO: optimize this, we can store it inside the session, requires
* changes to librelp --> next librelp iteration?. rgerhards, 2012-10-29
*/
MsgSetRcvFromStr(pMsg, pHostname, ustrlen(pHostname), &pProp);
CHKiRet(prop.Destruct(&pProp));
CHKiRet(MsgSetRcvFromIPStr(pMsg, pIP, ustrlen(pIP), &pProp));
CHKiRet(prop.Destruct(&pProp));
CHKiRet(submitMsg2(pMsg));
STATSCOUNTER_INC(inst->data.ctrSubmit, inst->data.mutCtrSubmit);
finalize_it:
RETiRet;
}
/* ------------------------------ end callbacks ------------------------------ */
/* create input instance, set default paramters, 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->bKeepAlive = 0;
inst->bEnableTLS = 0;
inst->bEnableTLSZip = 0;
inst->dhBits = 0;
inst->pristring = NULL;
inst->authmode = NULL;
inst->permittedPeers.nmemb = 0;
inst->caCertFile = NULL;
inst->myCertFile = NULL;
inst->myPrivKeyFile = NULL;
/* 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;
}
/* modified to work for module, not instance (as usual) */
static inline void
std_checkRuleset_genErrMsg(modConfData_t *modConf, __attribute__((unused)) instanceConf_t *inst)
{
errmsg.LogError(0, NO_ERRCODE, "imrelp: ruleset '%s' not found - "
"using default ruleset instead", modConf->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') {
errmsg.LogError(0, NO_ERRCODE, "imrelp: port number must be specified, listener ignored");
}
inst->pszBindPort = pNewVal;
finalize_it:
RETiRet;
}
static rsRetVal
addListner(modConfData_t __attribute__((unused)) *modConf, instanceConf_t *inst)
{
relpSrv_t *pSrv;
uchar statname[64];
int i;
DEFiRet;
if(pRelpEngine == NULL) {
CHKiRet(relpEngineConstruct(&pRelpEngine));
CHKiRet(relpEngineSetDbgprint(pRelpEngine, dbgprintf));
CHKiRet(relpEngineSetFamily(pRelpEngine, glbl.GetDefPFFamily()));
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()) {
CHKiRet(relpEngineSetDnsLookupMode(pRelpEngine, 1));
}
}
CHKiRet(relpEngineListnerConstruct(pRelpEngine, &pSrv));
CHKiRet(relpSrvSetLstnPort(pSrv, inst->pszBindPort));
/* support statistics gathering */
CHKiRet(statsobj.Construct(&(inst->data.stats)));
snprintf((char*)statname, sizeof(statname), "imrelp(%s)",
inst->pszBindPort);
statname[sizeof(statname)-1] = '\0'; /* just to be on the save side... */
CHKiRet(statsobj.SetName(inst->data.stats, statname));
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 */
relpSrvSetUsrPtr(pSrv, inst);
relpSrvSetKeepAlive(pSrv, inst->bKeepAlive, inst->iKeepAliveIntvl,
inst->iKeepAliveProbes, inst->iKeepAliveTime);
if(inst->bEnableTLS) {
relpSrvEnableTLS(pSrv);
if(inst->bEnableTLSZip) {
relpSrvEnableTLSZip(pSrv);
}
if(inst->dhBits) {
relpSrvSetDHBits(pSrv, inst->dhBits);
}
relpSrvSetGnuTLSPriString(pSrv, (char*)inst->pristring);
if(relpSrvSetAuthMode(pSrv, (char*)inst->authmode) != RELP_RET_OK) {
errmsg.LogError(0, RS_RET_RELP_ERR,
"imrelp: invalid auth mode '%s'\n", 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);
for(i = 0 ; i < inst->permittedPeers.nmemb ; ++i) {
relpSrvAddPermittedPeer(pSrv, (char*)inst->permittedPeers.name[i]);
}
}
CHKiRet(relpEngineListnerConstructFinalize(pRelpEngine, pSrv));
finalize_it:
RETiRet;
}
BEGINnewInpInst
struct cnfparamvals *pvals;
instanceConf_t *inst;
int i,j;
CODESTARTnewInpInst
DBGPRINTF("newInpInst (imrelp)\n");
pvals = nvlstGetParams(lst, &inppblk, NULL);
if(pvals == NULL) {
errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS,
"imrelp: required parameter are missing\n");
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")) {
inst->pszBindPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} 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, "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")) {
inst->pristring = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if(!strcmp(inppblk.descr[i].name, "tls.authmode")) {
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")) {
inst->caCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if(!strcmp(inppblk.descr[i].name, "tls.mycert")) {
inst->myCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if(!strcmp(inppblk.descr[i].name, "tls.myprivkey")) {
inst->myPrivKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} 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);
}
}
finalize_it:
CODE_STD_FINALIZERnewInpInst
cnfparamvalsDestruct(pvals, &inppblk);
ENDnewInpInst
BEGINbeginCnfLoad
CODESTARTbeginCnfLoad
loadModConf = pModConf;
pModConf->pConf = pConf;
pModConf->pszBindRuleset = NULL;
pModConf->pBindRuleset = NULL;
/* init legacy config variables */
cs.pszBindRuleset = NULL;
ENDbeginCnfLoad
BEGINsetModCnf
struct cnfparamvals *pvals = NULL;
int i;
CODESTARTsetModCnf
pvals = nvlstGetParams(lst, &modpblk, NULL);
if(pvals == NULL) {
errmsg.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")) {
loadModConf->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else {
dbgprintf("imrelp: program error, non-handled "
"param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
}
}
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')) {
errmsg.LogError(0, RS_RET_DUP_PARAM, "imrelp: warning: ruleset "
"set via legacy directive ignored");
}
}
finalize_it:
free(cs.pszBindRuleset);
loadModConf = NULL; /* done loading */
ENDendCnfLoad
BEGINcheckCnf
rsRetVal localRet;
ruleset_t *pRuleset;
CODESTARTcheckCnf
/* we emulate the standard "ruleset query" code provided by the framework
* for *instances* (which we can currently not support due to librelp).
*/
if(pModConf->pszBindRuleset == NULL) {
pModConf->pBindRuleset = NULL;
} else {
DBGPRINTF("imrelp: using ruleset '%s'\n", pModConf->pszBindRuleset);
localRet = ruleset.GetRuleset(pModConf->pConf, &pRuleset, pModConf->pszBindRuleset);
if(localRet == RS_RET_NOT_FOUND) {
std_checkRuleset_genErrMsg(pModConf, NULL);
}
CHKiRet(localRet);
pModConf->pBindRuleset = pRuleset;
}
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)
ABORT_FINALIZE(RS_RET_NO_RUN);
finalize_it:
ENDactivateCnfPrePrivDrop
BEGINactivateCnf
CODESTARTactivateCnf
ENDactivateCnf
BEGINfreeCnf
instanceConf_t *inst, *del;
int i;
CODESTARTfreeCnf
for(inst = pModConf->root ; inst != NULL ; ) {
free(inst->pszBindPort);
free(inst->pristring);
free(inst->authmode);
statsobj.Destruct(&(inst->data.stats));
for(i = 0 ; i < inst->permittedPeers.nmemb ; ++i) {
free(inst->permittedPeers.name[i]);
}
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)
{
DBGPRINTF("imrelp: termination requested via SIGTTIN - telling RELP engine\n");
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
if(pRelpEngine != NULL)
iRet = relpEngineDestruct(&pRelpEngine);
/* global variable cleanup */
if(pInputName != NULL)
prop.Destruct(&pInputName);
/* 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);
objRelease(errmsg, CORE_COMPONENT);
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(errmsg, CORE_COMPONENT));
CHKiRet(objUse(net, LM_NET_FILENAME));
CHKiRet(objUse(ruleset, CORE_COMPONENT));
CHKiRet(objUse(statsobj, CORE_COMPONENT));
/* register config file handlers */
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrelpserverbindruleset", 0, eCmdHdlrGetWord,
NULL, &cs.pszBindRuleset, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrelpserverrun", 0, eCmdHdlrGetWord,
addInstance, NULL, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
/* we need to create the inputName property (only once during our lifetime) */
CHKiRet(prop.Construct(&pInputName));
CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imrelp"), sizeof("imrelp") - 1));
CHKiRet(prop.ConstructFinalize(pInputName));
ENDmodInit
/* vim:set ai:
*/