summaryrefslogtreecommitdiffstats
path: root/plugins/imtcp/imtcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/imtcp/imtcp.c')
-rw-r--r--plugins/imtcp/imtcp.c1192
1 files changed, 1192 insertions, 0 deletions
diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c
new file mode 100644
index 0000000..0c31c93
--- /dev/null
+++ b/plugins/imtcp/imtcp.c
@@ -0,0 +1,1192 @@
+/* imtcp.c
+ * This is the implementation of the TCP input module.
+ *
+ * File begun on 2007-12-21 by RGerhards (extracted from syslogd.c,
+ * which at the time of the rsyslog fork was BSD-licensed)
+ *
+ * Copyright 2007-2022 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.
+ */
+
+/* This note shall explain the calling sequence while we do not have
+ * have full RainerScript support for (TLS) sender authentication:
+ *
+ * imtcp --> tcpsrv --> netstrms (this sequence stored pPermPeers in netstrms class)
+ * then a callback (doOpenLstnSocks) into imtcp happens, which in turn calls
+ * into tcpsrv.create_tcp_socket(),
+ * which calls into netstrm.LstnInit(), which receives a pointer to netstrms obj
+ * which calls into the driver function LstnInit (again, netstrms obj passed)
+ * which finally calls back into netstrms obj's get functions to obtain the auth
+ * parameters and then applies them to the driver object instance
+ *
+ * rgerhards, 2008-05-19
+ */
+#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 <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include "rsyslog.h"
+#include "dirty.h"
+#include "cfsysline.h"
+#include "module-template.h"
+#include "unicode-helper.h"
+#include "net.h"
+#include "netstrm.h"
+#include "errmsg.h"
+#include "tcpsrv.h"
+#include "ruleset.h"
+#include "rainerscript.h"
+#include "net.h"
+#include "parserif.h"
+
+MODULE_TYPE_INPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("imtcp")
+
+/* static data */
+DEF_IMOD_STATIC_DATA
+DEFobjCurrIf(tcpsrv)
+DEFobjCurrIf(tcps_sess)
+DEFobjCurrIf(net)
+DEFobjCurrIf(netstrm)
+DEFobjCurrIf(ruleset)
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+/* Module static data */
+typedef struct tcpsrv_etry_s {
+ tcpsrv_t *tcpsrv;
+ pthread_t tid; /* the worker's thread ID */
+ struct tcpsrv_etry_s *next;
+} tcpsrv_etry_t;
+static tcpsrv_etry_t *tcpsrv_root = NULL;
+static int n_tcpsrv = 0;
+
+static permittedPeers_t *pPermPeersRoot = NULL;
+
+#define FRAMING_UNSET -1
+
+/* config settings */
+static struct configSettings_s {
+ int iTCPSessMax;
+ int iTCPLstnMax;
+ int bSuppOctetFram;
+ int iStrmDrvrMode;
+ int bKeepAlive;
+ int iKeepAliveIntvl;
+ int iKeepAliveProbes;
+ int iKeepAliveTime;
+ int bEmitMsgOnClose;
+ int bEmitMsgOnOpen;
+ int iAddtlFrameDelim;
+ int maxFrameSize;
+ int bDisableLFDelim;
+ int discardTruncatedMsg;
+ int bUseFlowControl;
+ int bPreserveCase;
+ uchar *gnutlsPriorityString;
+ uchar *pszStrmDrvrAuthMode;
+ uchar *pszStrmDrvrPermitExpiredCerts;
+ uchar *pszInputName;
+ uchar *pszBindRuleset;
+ uchar *lstnIP; /* which IP we should listen on? */
+ uchar *lstnPortFile;
+} cs;
+
+struct instanceConf_s {
+ int iTCPSessMax;
+ int iTCPLstnMax;
+ tcpLstnParams_t *cnf_params; /**< listener config parameters */
+ uchar *pszBindRuleset; /* name of ruleset to bind to */
+ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */
+ uchar *pszInputName; /* value for inputname property, NULL is OK and handled by core engine */
+ uchar *dfltTZ;
+ sbool bSPFramingFix;
+ unsigned int ratelimitInterval;
+ unsigned int ratelimitBurst;
+ int iAddtlFrameDelim; /* addtl frame delimiter, e.g. for netscreen, default none */
+ int maxFrameSize;
+ int bUseFlowControl;
+ int bDisableLFDelim;
+ int discardTruncatedMsg;
+ int bEmitMsgOnClose;
+ int bEmitMsgOnOpen;
+ int bPreserveCase;
+ uchar *pszStrmDrvrName; /* stream driver to use */
+ int iStrmDrvrMode;
+ uchar *pszStrmDrvrAuthMode;
+ uchar *pszStrmDrvrPermitExpiredCerts;
+ uchar *pszStrmDrvrCAFile;
+ uchar *pszStrmDrvrCRLFile;
+ uchar *pszStrmDrvrKeyFile;
+ uchar *pszStrmDrvrCertFile;
+ permittedPeers_t *pPermPeersRoot;
+ uchar *gnutlsPriorityString;
+ int iStrmDrvrExtendedCertCheck;
+ int iStrmDrvrSANPreference;
+ int iStrmTlsVerifyDepth;
+ int bKeepAlive;
+ int iKeepAliveIntvl;
+ int iKeepAliveProbes;
+ int iKeepAliveTime;
+ struct instanceConf_s *next;
+};
+
+
+struct modConfData_s {
+ rsconf_t *pConf; /* our overall config object */
+ instanceConf_t *root, *tail;
+ int iTCPSessMax; /* max number of sessions */
+ int iTCPLstnMax; /* max number of sessions */
+ int iStrmDrvrMode; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */
+ int iStrmDrvrExtendedCertCheck; /* verify also purpose OID in certificate extended field */
+ int iStrmDrvrSANPreference; /* ignore CN when any SAN set */
+ int iStrmTlsVerifyDepth; /**< Verify Depth for certificate chains */
+ int iAddtlFrameDelim; /* addtl frame delimiter, e.g. for netscreen, default none */
+ int maxFrameSize;
+ int bSuppOctetFram;
+ sbool bDisableLFDelim; /* disable standard LF delimiter */
+ sbool discardTruncatedMsg;
+ sbool bUseFlowControl; /* use flow control, what means indicate ourselfs a "light delayable" */
+ sbool bKeepAlive;
+ int iKeepAliveIntvl;
+ int iKeepAliveProbes;
+ int iKeepAliveTime;
+ sbool bEmitMsgOnClose; /* emit an informational message on close by remote peer */
+ sbool bEmitMsgOnOpen; /* emit an informational message on close by remote peer */
+ uchar *gnutlsPriorityString;
+ uchar *pszStrmDrvrName; /* stream driver to use */
+ uchar *pszStrmDrvrAuthMode; /* authentication mode to use */
+ uchar *pszStrmDrvrPermitExpiredCerts; /* control how to handly expired certificates */
+ uchar *pszStrmDrvrCAFile;
+ uchar *pszStrmDrvrCRLFile;
+ uchar *pszStrmDrvrKeyFile;
+ uchar *pszStrmDrvrCertFile;
+ permittedPeers_t *pPermPeersRoot;
+ sbool configSetViaV2Method;
+ sbool bPreserveCase; /* preserve case of fromhost; true by default */
+};
+
+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[] = {
+ { "flowcontrol", eCmdHdlrBinary, 0 },
+ { "disablelfdelimiter", eCmdHdlrBinary, 0 },
+ { "discardtruncatedmsg", eCmdHdlrBinary, 0 },
+ { "octetcountedframing", eCmdHdlrBinary, 0 },
+ { "notifyonconnectionclose", eCmdHdlrBinary, 0 },
+ { "notifyonconnectionopen", eCmdHdlrBinary, 0 },
+ { "addtlframedelimiter", eCmdHdlrNonNegInt, 0 },
+ { "maxframesize", eCmdHdlrInt, 0 },
+ { "maxsessions", eCmdHdlrPositiveInt, 0 },
+ { "maxlistners", eCmdHdlrPositiveInt, 0 },
+ { "maxlisteners", eCmdHdlrPositiveInt, 0 },
+ { "streamdriver.mode", eCmdHdlrNonNegInt, 0 },
+ { "streamdriver.authmode", eCmdHdlrString, 0 },
+ { "streamdriver.permitexpiredcerts", eCmdHdlrString, 0 },
+ { "streamdriver.name", eCmdHdlrString, 0 },
+ { "streamdriver.CheckExtendedKeyPurpose", eCmdHdlrBinary, 0 },
+ { "streamdriver.PrioritizeSAN", eCmdHdlrBinary, 0 },
+ { "streamdriver.TlsVerifyDepth", eCmdHdlrPositiveInt, 0 },
+ { "permittedpeer", eCmdHdlrArray, 0 },
+ { "keepalive", eCmdHdlrBinary, 0 },
+ { "keepalive.probes", eCmdHdlrNonNegInt, 0 },
+ { "keepalive.time", eCmdHdlrNonNegInt, 0 },
+ { "keepalive.interval", eCmdHdlrNonNegInt, 0 },
+ { "gnutlsprioritystring", eCmdHdlrString, 0 },
+ { "preservecase", eCmdHdlrBinary, 0 }
+};
+static struct cnfparamblk modpblk =
+ { CNFPARAMBLK_VERSION,
+ sizeof(modpdescr)/sizeof(struct cnfparamdescr),
+ modpdescr
+ };
+
+/* input instance parameters */
+static struct cnfparamdescr inppdescr[] = {
+ { "port", eCmdHdlrString, CNFPARAM_REQUIRED }, /* legacy: InputTCPServerRun */
+ { "maxsessions", eCmdHdlrPositiveInt, 0 },
+ { "maxlisteners", eCmdHdlrPositiveInt, 0 },
+ { "flowcontrol", eCmdHdlrBinary, 0 },
+ { "disablelfdelimiter", eCmdHdlrBinary, 0 },
+ { "discardtruncatedmsg", eCmdHdlrBinary, 0 },
+ { "notifyonconnectionclose", eCmdHdlrBinary, 0 },
+ { "notifyonconnectionopen", eCmdHdlrBinary, 0 },
+ { "addtlframedelimiter", eCmdHdlrNonNegInt, 0 },
+ { "maxframesize", eCmdHdlrInt, 0 },
+ { "preservecase", eCmdHdlrBinary, 0 },
+ { "listenportfilename", eCmdHdlrString, 0 },
+ { "address", eCmdHdlrString, 0 },
+ { "name", eCmdHdlrString, 0 },
+ { "defaulttz", eCmdHdlrString, 0 },
+ { "ruleset", eCmdHdlrString, 0 },
+ { "streamdriver.mode", eCmdHdlrNonNegInt, 0 },
+ { "streamdriver.authmode", eCmdHdlrString, 0 },
+ { "streamdriver.permitexpiredcerts", eCmdHdlrString, 0 },
+ { "streamdriver.name", eCmdHdlrString, 0 },
+ { "streamdriver.CheckExtendedKeyPurpose", eCmdHdlrBinary, 0 },
+ { "streamdriver.PrioritizeSAN", eCmdHdlrBinary, 0 },
+ { "streamdriver.TlsVerifyDepth", eCmdHdlrPositiveInt, 0 },
+ { "streamdriver.cafile", eCmdHdlrString, 0 },
+ { "streamdriver.keyfile", eCmdHdlrString, 0 },
+ { "streamdriver.certfile", eCmdHdlrString, 0 },
+ { "permittedpeer", eCmdHdlrArray, 0 },
+ { "gnutlsprioritystring", eCmdHdlrString, 0 },
+ { "keepalive", eCmdHdlrBinary, 0 },
+ { "keepalive.probes", eCmdHdlrNonNegInt, 0 },
+ { "keepalive.time", eCmdHdlrNonNegInt, 0 },
+ { "keepalive.interval", eCmdHdlrNonNegInt, 0 },
+ { "supportoctetcountedframing", eCmdHdlrBinary, 0 },
+ { "ratelimit.interval", eCmdHdlrInt, 0 },
+ { "framingfix.cisco.asa", eCmdHdlrBinary, 0 },
+ { "ratelimit.burst", eCmdHdlrInt, 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 */
+/* this shall go into a specific ACL module! */
+static int
+isPermittedHost(struct sockaddr *addr, char *fromHostFQDN, void __attribute__((unused)) *pUsrSrv,
+ void __attribute__((unused)) *pUsrSess)
+{
+ return net.isAllowedSender2(UCHAR_CONSTANT("TCP"), addr, fromHostFQDN, 1);
+}
+
+
+static rsRetVal
+doOpenLstnSocks(tcpsrv_t *pSrv)
+{
+ ISOBJ_TYPE_assert(pSrv, tcpsrv);
+ dbgprintf("in imtcp doOpenLstnSocks\n");
+ return tcpsrv.create_tcp_socket(pSrv);
+}
+
+
+static rsRetVal
+doRcvData(tcps_sess_t *pSess, char *buf, size_t lenBuf, ssize_t *piLenRcvd, int *const oserr)
+{
+ assert(pSess != NULL);
+ assert(piLenRcvd != NULL);
+ *piLenRcvd = lenBuf;
+ return netstrm.Rcv(pSess->pStrm, (uchar*) buf, piLenRcvd, oserr);
+}
+
+static rsRetVal
+onRegularClose(tcps_sess_t *pSess)
+{
+ DEFiRet;
+ assert(pSess != NULL);
+
+ /* process any incomplete frames left over */
+ tcps_sess.PrepareClose(pSess);
+ /* Session closed */
+ tcps_sess.Close(pSess);
+ RETiRet;
+}
+
+
+static rsRetVal
+onErrClose(tcps_sess_t *pSess)
+{
+ DEFiRet;
+ assert(pSess != NULL);
+
+ tcps_sess.Close(pSess);
+ RETiRet;
+}
+
+/* ------------------------------ end callbacks ------------------------------ */
+
+
+/* set permitted peer -- rgerhards, 2008-05-19
+ */
+static rsRetVal
+setPermittedPeer(void __attribute__((unused)) *pVal, uchar *pszID)
+{
+ DEFiRet;
+ CHKiRet(net.AddPermittedPeer(&pPermPeersRoot, pszID));
+ free(pszID); /* no longer needed, but we need to free as of interface def */
+finalize_it:
+ RETiRet;
+}
+
+
+/* create input instance, set default parameters, and
+ * add it to the list of instances.
+ */
+static rsRetVal
+createInstance(instanceConf_t **pinst)
+{
+ instanceConf_t *inst = NULL;
+
+ DEFiRet;
+ CHKmalloc(inst = (instanceConf_t*) calloc(1, sizeof(instanceConf_t)));
+ CHKmalloc(inst->cnf_params = (tcpLstnParams_t*) calloc(1, sizeof(tcpLstnParams_t)));
+ inst->next = NULL;
+ inst->pszBindRuleset = NULL;
+ inst->pszInputName = NULL;
+ inst->dfltTZ = NULL;
+ inst->cnf_params->bSuppOctetFram = -1; /* unset */
+ inst->bSPFramingFix = 0;
+ inst->ratelimitInterval = 0;
+ inst->ratelimitBurst = 10000;
+
+ inst->pszStrmDrvrName = NULL;
+ inst->pszStrmDrvrAuthMode = NULL;
+ inst->pszStrmDrvrPermitExpiredCerts = NULL;
+ inst->pszStrmDrvrCAFile = NULL;
+ inst->pszStrmDrvrCRLFile = NULL;
+ inst->pszStrmDrvrKeyFile = NULL;
+ inst->pszStrmDrvrCertFile = NULL;
+ inst->pPermPeersRoot = NULL;
+ inst->gnutlsPriorityString = NULL;
+ inst->iStrmDrvrMode = loadModConf->iStrmDrvrMode;
+ inst->iStrmDrvrExtendedCertCheck = loadModConf->iStrmDrvrExtendedCertCheck;
+ inst->iStrmDrvrSANPreference = loadModConf->iStrmDrvrSANPreference;
+ inst->iStrmTlsVerifyDepth = loadModConf->iStrmTlsVerifyDepth;
+ inst->bKeepAlive = loadModConf->bKeepAlive;
+ inst->iKeepAliveIntvl = loadModConf->iKeepAliveIntvl;
+ inst->iKeepAliveProbes = loadModConf->iKeepAliveProbes;
+ inst->iKeepAliveTime = loadModConf->iKeepAliveTime;
+ inst->iAddtlFrameDelim = loadModConf->iAddtlFrameDelim;
+ inst->maxFrameSize = loadModConf->maxFrameSize;
+ inst->bUseFlowControl = loadModConf->bUseFlowControl;
+ inst->bDisableLFDelim = loadModConf->bDisableLFDelim;
+ inst->discardTruncatedMsg = loadModConf->discardTruncatedMsg;
+ inst->bEmitMsgOnClose = loadModConf->bEmitMsgOnClose;
+ inst->bEmitMsgOnOpen = loadModConf->bEmitMsgOnOpen;
+ inst->bPreserveCase = loadModConf->bPreserveCase;
+ inst->iTCPLstnMax = loadModConf->iTCPLstnMax;
+ inst->iTCPSessMax = loadModConf->iTCPSessMax;
+
+ inst->cnf_params->pszLstnPortFileName = 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:
+ if(iRet != RS_RET_OK) {
+ free(inst->cnf_params);
+ free(inst);
+ }
+ RETiRet;
+}
+
+
+/* This function is called when a new listener instace 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));
+
+ CHKmalloc(inst->cnf_params->pszPort = ustrdup((pNewVal == NULL || *pNewVal == '\0')
+ ? (uchar*) "10514" : pNewVal));
+ if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
+ inst->pszBindRuleset = NULL;
+ } else {
+ CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset));
+ }
+ if((cs.lstnIP == NULL) || (cs.lstnIP[0] == '\0')) {
+ inst->cnf_params->pszAddr = NULL;
+ } else {
+ CHKmalloc(inst->cnf_params->pszAddr = ustrdup(cs.lstnIP));
+ }
+ if((cs.lstnPortFile == NULL) || (cs.lstnPortFile[0] == '\0')) {
+ inst->cnf_params->pszLstnPortFileName = NULL;
+ } else {
+ CHKmalloc(inst->cnf_params->pszLstnPortFileName = ustrdup(cs.lstnPortFile));
+ }
+
+ if((cs.pszInputName == NULL) || (cs.pszInputName[0] == '\0')) {
+ inst->pszInputName = NULL;
+ } else {
+ CHKmalloc(inst->pszInputName = ustrdup(cs.pszInputName));
+ }
+ inst->cnf_params->bSuppOctetFram = cs.bSuppOctetFram;
+ inst->iStrmDrvrMode = cs.iStrmDrvrMode;
+ inst->bKeepAlive = cs.bKeepAlive ;
+ inst->bUseFlowControl = cs.bUseFlowControl;
+ inst->bDisableLFDelim = cs.bDisableLFDelim;
+ inst->bEmitMsgOnClose = cs.bEmitMsgOnClose;
+ inst->bPreserveCase = cs.bPreserveCase;
+ inst->iKeepAliveProbes = cs.iKeepAliveProbes;
+ inst->iKeepAliveIntvl = cs.iKeepAliveIntvl;
+ inst->iKeepAliveTime = cs.iKeepAliveTime;
+ inst->iKeepAliveTime = cs.iKeepAliveTime;
+ inst->iAddtlFrameDelim = cs.iAddtlFrameDelim;
+ inst->iTCPLstnMax = cs.iTCPLstnMax;
+ inst->iTCPSessMax = cs.iTCPSessMax;
+ inst->iStrmDrvrMode = cs.iStrmDrvrMode;
+
+finalize_it:
+ free(pNewVal);
+ RETiRet;
+}
+
+
+static rsRetVal
+addListner(modConfData_t *modConf, instanceConf_t *inst)
+{
+ DEFiRet;
+ uchar *psz; /* work variable */
+ permittedPeers_t *peers;
+
+ tcpsrv_t *pOurTcpsrv;
+ CHKiRet(tcpsrv.Construct(&pOurTcpsrv));
+ /* callbacks */
+ CHKiRet(tcpsrv.SetCBIsPermittedHost(pOurTcpsrv, isPermittedHost));
+ CHKiRet(tcpsrv.SetCBRcvData(pOurTcpsrv, doRcvData));
+ CHKiRet(tcpsrv.SetCBOpenLstnSocks(pOurTcpsrv, doOpenLstnSocks));
+ CHKiRet(tcpsrv.SetCBOnRegularClose(pOurTcpsrv, onRegularClose));
+ CHKiRet(tcpsrv.SetCBOnErrClose(pOurTcpsrv, onErrClose));
+ /* params */
+ CHKiRet(tcpsrv.SetKeepAlive(pOurTcpsrv, inst->bKeepAlive));
+ CHKiRet(tcpsrv.SetKeepAliveIntvl(pOurTcpsrv, inst->iKeepAliveIntvl));
+ CHKiRet(tcpsrv.SetKeepAliveProbes(pOurTcpsrv, inst->iKeepAliveProbes));
+ CHKiRet(tcpsrv.SetKeepAliveTime(pOurTcpsrv, inst->iKeepAliveTime));
+ CHKiRet(tcpsrv.SetSessMax(pOurTcpsrv, inst->iTCPSessMax));
+ CHKiRet(tcpsrv.SetLstnMax(pOurTcpsrv, inst->iTCPLstnMax));
+ CHKiRet(tcpsrv.SetDrvrMode(pOurTcpsrv, inst->iStrmDrvrMode));
+ CHKiRet(tcpsrv.SetDrvrCheckExtendedKeyUsage(pOurTcpsrv, inst->iStrmDrvrExtendedCertCheck));
+ CHKiRet(tcpsrv.SetDrvrPrioritizeSAN(pOurTcpsrv, inst->iStrmDrvrSANPreference));
+ CHKiRet(tcpsrv.SetDrvrTlsVerifyDepth(pOurTcpsrv, inst->iStrmTlsVerifyDepth));
+ CHKiRet(tcpsrv.SetUseFlowControl(pOurTcpsrv, inst->bUseFlowControl));
+ CHKiRet(tcpsrv.SetAddtlFrameDelim(pOurTcpsrv, inst->iAddtlFrameDelim));
+ CHKiRet(tcpsrv.SetMaxFrameSize(pOurTcpsrv, inst->maxFrameSize));
+ CHKiRet(tcpsrv.SetbDisableLFDelim(pOurTcpsrv, inst->bDisableLFDelim));
+ CHKiRet(tcpsrv.SetDiscardTruncatedMsg(pOurTcpsrv, inst->discardTruncatedMsg));
+ CHKiRet(tcpsrv.SetNotificationOnRemoteClose(pOurTcpsrv, inst->bEmitMsgOnClose));
+ CHKiRet(tcpsrv.SetNotificationOnRemoteOpen(pOurTcpsrv, inst->bEmitMsgOnOpen));
+ CHKiRet(tcpsrv.SetPreserveCase(pOurTcpsrv, inst->bPreserveCase));
+ /* now set optional params, but only if they were actually configured */
+ psz = (inst->pszStrmDrvrName == NULL) ? modConf->pszStrmDrvrName : inst->pszStrmDrvrName;
+ if(psz != NULL) {
+ CHKiRet(tcpsrv.SetDrvrName(pOurTcpsrv, psz));
+ }
+ psz = (inst->pszStrmDrvrAuthMode == NULL) ? modConf->pszStrmDrvrAuthMode : inst->pszStrmDrvrAuthMode;
+ if(psz != NULL) {
+ CHKiRet(tcpsrv.SetDrvrAuthMode(pOurTcpsrv, psz));
+ }
+ psz = (inst->gnutlsPriorityString == NULL)
+ ? modConf->gnutlsPriorityString : inst->gnutlsPriorityString;
+ CHKiRet(tcpsrv.SetGnutlsPriorityString(pOurTcpsrv, psz));
+ /* Call SetDrvrPermitExpiredCerts required
+ * when param is NULL default handling for ExpiredCerts is set! */
+ psz = (inst->pszStrmDrvrPermitExpiredCerts == NULL)
+ ? modConf->pszStrmDrvrPermitExpiredCerts : inst->pszStrmDrvrPermitExpiredCerts;
+ CHKiRet(tcpsrv.SetDrvrPermitExpiredCerts(pOurTcpsrv, psz));
+
+ psz = (inst->pszStrmDrvrCAFile == NULL)
+ ? modConf->pszStrmDrvrCAFile : inst->pszStrmDrvrCAFile;
+ CHKiRet(tcpsrv.SetDrvrCAFile(pOurTcpsrv, psz));
+
+ psz = (inst->pszStrmDrvrCRLFile == NULL)
+ ? modConf->pszStrmDrvrCRLFile : inst->pszStrmDrvrCRLFile;
+ CHKiRet(tcpsrv.SetDrvrCRLFile(pOurTcpsrv, psz));
+
+ psz = (inst->pszStrmDrvrKeyFile == NULL)
+ ? modConf->pszStrmDrvrKeyFile : inst->pszStrmDrvrKeyFile;
+ CHKiRet(tcpsrv.SetDrvrKeyFile(pOurTcpsrv, psz));
+
+ psz = (inst->pszStrmDrvrCertFile == NULL)
+ ? modConf->pszStrmDrvrCertFile : inst->pszStrmDrvrCertFile;
+ CHKiRet(tcpsrv.SetDrvrCertFile(pOurTcpsrv, psz));
+
+ peers = (inst->pPermPeersRoot == NULL)
+ ? modConf->pPermPeersRoot : inst->pPermPeersRoot;
+ if(peers != NULL) {
+ CHKiRet(tcpsrv.SetDrvrPermPeers(pOurTcpsrv, peers));
+ }
+
+ /* initialized, now add socket and listener params */
+ DBGPRINTF("imtcp: trying to add port *:%s\n", inst->cnf_params->pszPort);
+ inst->cnf_params->pRuleset = inst->pBindRuleset;
+ CHKiRet(tcpsrv.SetInputName(pOurTcpsrv, inst->cnf_params, inst->pszInputName == NULL ?
+ UCHAR_CONSTANT("imtcp") : inst->pszInputName));
+ CHKiRet(tcpsrv.SetOrigin(pOurTcpsrv, (uchar*)"imtcp"));
+ CHKiRet(tcpsrv.SetDfltTZ(pOurTcpsrv, (inst->dfltTZ == NULL) ? (uchar*)"" : inst->dfltTZ));
+ CHKiRet(tcpsrv.SetbSPFramingFix(pOurTcpsrv, inst->bSPFramingFix));
+ CHKiRet(tcpsrv.SetLinuxLikeRatelimiters(pOurTcpsrv, inst->ratelimitInterval, inst->ratelimitBurst));
+
+ if((ustrcmp(inst->cnf_params->pszPort, UCHAR_CONSTANT("0")) == 0
+ && inst->cnf_params->pszLstnPortFileName == NULL)
+ || ustrcmp(inst->cnf_params->pszPort, UCHAR_CONSTANT("0")) < 0) {
+ LogMsg(0, RS_RET_OK, LOG_WARNING, "imtcp: port 0 and no port file set -> using port 514 instead");
+ CHKmalloc(inst->cnf_params->pszPort = (uchar*)strdup("514"));
+ }
+ tcpsrv.configureTCPListen(pOurTcpsrv, inst->cnf_params);
+
+ tcpsrv_etry_t *etry;
+ CHKmalloc(etry = (tcpsrv_etry_t*) calloc(1, sizeof(tcpsrv_etry_t)));
+ etry->tcpsrv = pOurTcpsrv;
+ etry->next = tcpsrv_root;
+ tcpsrv_root = etry;
+ ++n_tcpsrv;
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ LogError(0, NO_ERRCODE, "imtcp: error %d trying to add listener", iRet);
+ }
+ RETiRet;
+}
+
+
+BEGINnewInpInst
+ struct cnfparamvals *pvals;
+ instanceConf_t *inst;
+ int i;
+CODESTARTnewInpInst
+ DBGPRINTF("newInpInst (imtcp)\n");
+
+ pvals = nvlstGetParams(lst, &inppblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS,
+ "imtcp: required parameter are missing\n");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("input param blk in imtcp:\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->cnf_params->pszPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "address")) {
+ inst->cnf_params->pszAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "name")) {
+ inst->pszInputName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "defaulttz")) {
+ inst->dfltTZ = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "framingfix.cisco.asa")) {
+ inst->bSPFramingFix = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+ inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.mode")) {
+ inst->iStrmDrvrMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.CheckExtendedKeyPurpose")) {
+ inst->iStrmDrvrExtendedCertCheck = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.PrioritizeSAN")) {
+ inst->iStrmDrvrSANPreference = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.TlsVerifyDepth")) {
+ if (pvals[i].val.d.n >= 2) {
+ inst->iStrmTlsVerifyDepth = (int) pvals[i].val.d.n;
+ } else {
+ parser_errmsg("streamdriver.TlsVerifyDepth must be 2 or higher but is %d",
+ (int) pvals[i].val.d.n);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.authmode")) {
+ inst->pszStrmDrvrAuthMode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.permitexpiredcerts")) {
+ inst->pszStrmDrvrPermitExpiredCerts = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.cafile")) {
+ inst->pszStrmDrvrCAFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.crlfile")) {
+ inst->pszStrmDrvrCRLFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.keyfile")) {
+ inst->pszStrmDrvrKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.certfile")) {
+ inst->pszStrmDrvrCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "streamdriver.name")) {
+ inst->pszStrmDrvrName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "gnutlsprioritystring")) {
+ inst->gnutlsPriorityString = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(inppblk.descr[i].name, "permittedpeer")) {
+ for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ uchar *const peer = (uchar*) es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ CHKiRet(net.AddPermittedPeer(&inst->pPermPeersRoot, peer));
+ free(peer);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "flowcontrol")) {
+ inst->bUseFlowControl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "disablelfdelimiter")) {
+ inst->bDisableLFDelim = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "discardtruncatedmsg")) {
+ inst->discardTruncatedMsg = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "notifyonconnectionclose")) {
+ inst->bEmitMsgOnClose = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "notifyonconnectionopen")) {
+ inst->bEmitMsgOnOpen = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "addtlframedelimiter")) {
+ inst->iAddtlFrameDelim = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "maxframesize")) {
+ const int max = (int) pvals[i].val.d.n;
+ if(max <= 200000000) {
+ inst->maxFrameSize = max;
+ } else {
+ LogError(0, RS_RET_PARAM_ERROR, "imtcp: invalid value for 'maxFrameSize' "
+ "parameter given is %d, max is 200000000", max);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ } else if(!strcmp(inppblk.descr[i].name, "maxsessions")) {
+ inst->iTCPSessMax = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "maxlisteners")) {
+ inst->iTCPLstnMax = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "supportoctetcountedframing")) {
+ inst->cnf_params->bSuppOctetFram = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "keepalive")) {
+ inst->bKeepAlive = (int) 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.burst")) {
+ inst->ratelimitBurst = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "ratelimit.interval")) {
+ inst->ratelimitInterval = (unsigned int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "preservecase")) {
+ inst->bPreserveCase = (int) pvals[i].val.d.n;
+ } else if(!strcmp(inppblk.descr[i].name, "listenportfilename")) {
+ inst->cnf_params->pszLstnPortFileName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else {
+ dbgprintf("imtcp: 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;
+ /* init our settings */
+ loadModConf->iTCPSessMax = 200;
+ loadModConf->iTCPLstnMax = 20;
+ loadModConf->bSuppOctetFram = 1;
+ loadModConf->iStrmDrvrMode = 0;
+ loadModConf->iStrmDrvrExtendedCertCheck = 0;
+ loadModConf->iStrmDrvrSANPreference = 0;
+ loadModConf->iStrmTlsVerifyDepth = 0;
+ loadModConf->bUseFlowControl = 1;
+ loadModConf->bKeepAlive = 0;
+ loadModConf->iKeepAliveIntvl = 0;
+ loadModConf->iKeepAliveProbes = 0;
+ loadModConf->iKeepAliveTime = 0;
+ loadModConf->bEmitMsgOnClose = 0;
+ loadModConf->bEmitMsgOnOpen = 0;
+ loadModConf->iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
+ loadModConf->maxFrameSize = 200000;
+ loadModConf->bDisableLFDelim = 0;
+ loadModConf->discardTruncatedMsg = 0;
+ loadModConf->gnutlsPriorityString = NULL;
+ loadModConf->pszStrmDrvrName = NULL;
+ loadModConf->pszStrmDrvrAuthMode = NULL;
+ loadModConf->pszStrmDrvrPermitExpiredCerts = NULL;
+ loadModConf->pszStrmDrvrCAFile = NULL;
+ loadModConf->pszStrmDrvrCRLFile = NULL;
+ loadModConf->pszStrmDrvrKeyFile = NULL;
+ loadModConf->pszStrmDrvrCertFile = NULL;
+ loadModConf->pPermPeersRoot = NULL;
+ loadModConf->configSetViaV2Method = 0;
+ loadModConf->bPreserveCase = 1; /* default to true */
+ bLegacyCnfModGlobalsPermitted = 1;
+ /* init legacy config variables */
+ resetConfigVariables(NULL, NULL); /* dummy parameters just to fulfill interface def */
+ENDbeginCnfLoad
+
+
+BEGINsetModCnf
+ struct cnfparamvals *pvals = NULL;
+ int i;
+CODESTARTsetModCnf
+ pvals = nvlstGetParams(lst, &modpblk, NULL);
+ if(pvals == NULL) {
+ LogError(0, RS_RET_MISSING_CNFPARAMS, "imtcp: error processing module "
+ "config parameters [module(...)]");
+ ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS);
+ }
+
+ if(Debug) {
+ dbgprintf("module (global) param blk for imtcp:\n");
+ cnfparamsPrint(&modpblk, pvals);
+ }
+
+ for(i = 0 ; i < modpblk.nParams ; ++i) {
+ if(!pvals[i].bUsed)
+ continue;
+ if(!strcmp(modpblk.descr[i].name, "flowcontrol")) {
+ loadModConf->bUseFlowControl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "disablelfdelimiter")) {
+ loadModConf->bDisableLFDelim = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "discardtruncatedmsg")) {
+ loadModConf->discardTruncatedMsg = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "octetcountedframing")) {
+ loadModConf->bSuppOctetFram = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "notifyonconnectionclose")) {
+ loadModConf->bEmitMsgOnClose = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "notifyonconnectionopen")) {
+ loadModConf->bEmitMsgOnOpen = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "addtlframedelimiter")) {
+ loadModConf->iAddtlFrameDelim = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "maxframesize")) {
+ const int max = (int) pvals[i].val.d.n;
+ if(max <= 200000000) {
+ loadModConf->maxFrameSize = max;
+ } else {
+ LogError(0, RS_RET_PARAM_ERROR, "imtcp: invalid value for 'maxFrameSize' "
+ "parameter given is %d, max is 200000000", max);
+ ABORT_FINALIZE(RS_RET_PARAM_ERROR);
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "maxsessions")) {
+ loadModConf->iTCPSessMax = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "maxlisteners") ||
+ !strcmp(modpblk.descr[i].name, "maxlistners")) { /* keep old name for a while */
+ loadModConf->iTCPLstnMax = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "keepalive")) {
+ loadModConf->bKeepAlive = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "keepalive.probes")) {
+ loadModConf->iKeepAliveProbes = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "keepalive.time")) {
+ loadModConf->iKeepAliveTime = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "keepalive.interval")) {
+ loadModConf->iKeepAliveIntvl = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "gnutlsprioritystring")) {
+ loadModConf->gnutlsPriorityString = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.mode")) {
+ loadModConf->iStrmDrvrMode = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.CheckExtendedKeyPurpose")) {
+ loadModConf->iStrmDrvrExtendedCertCheck = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.PrioritizeSAN")) {
+ loadModConf->iStrmDrvrSANPreference = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.TlsVerifyDepth")) {
+ if (pvals[i].val.d.n >= 2) {
+ loadModConf->iStrmTlsVerifyDepth = (int) pvals[i].val.d.n;
+ } else {
+ parser_errmsg("streamdriver.TlsVerifyDepth must be 2 or higher but is %d",
+ (int) pvals[i].val.d.n);
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.authmode")) {
+ loadModConf->pszStrmDrvrAuthMode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.permitexpiredcerts")) {
+ loadModConf->pszStrmDrvrPermitExpiredCerts = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.cafile")) {
+ loadModConf->pszStrmDrvrCAFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.crlfile")) {
+ loadModConf->pszStrmDrvrCRLFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.keyfile")) {
+ loadModConf->pszStrmDrvrKeyFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.certfile")) {
+ loadModConf->pszStrmDrvrCertFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "streamdriver.name")) {
+ loadModConf->pszStrmDrvrName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "permittedpeer")) {
+ for(int j = 0 ; j < pvals[i].val.d.ar->nmemb ; ++j) {
+ uchar *const peer = (uchar*) es_str2cstr(pvals[i].val.d.ar->arr[j], NULL);
+ CHKiRet(net.AddPermittedPeer(&loadModConf->pPermPeersRoot, peer));
+ free(peer);
+ }
+ } else if(!strcmp(modpblk.descr[i].name, "preservecase")) {
+ loadModConf->bPreserveCase = (int) pvals[i].val.d.n;
+ } else {
+ dbgprintf("imtcp: program error, non-handled "
+ "param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
+ }
+ }
+
+ /* remove all of our legacy handlers, as they can not used in addition
+ * the the new-style config method.
+ */
+ bLegacyCnfModGlobalsPermitted = 0;
+ loadModConf->configSetViaV2Method = 1;
+
+finalize_it:
+ if(pvals != NULL)
+ cnfparamvalsDestruct(pvals, &modpblk);
+ENDsetModCnf
+
+
+BEGINendCnfLoad
+CODESTARTendCnfLoad
+ if(!loadModConf->configSetViaV2Method) {
+ /* persist module-specific settings from legacy config system */
+ pModConf->iTCPSessMax = cs.iTCPSessMax;
+ pModConf->iTCPLstnMax = cs.iTCPLstnMax;
+ pModConf->iStrmDrvrMode = cs.iStrmDrvrMode;
+ pModConf->bEmitMsgOnClose = cs.bEmitMsgOnClose;
+ pModConf->bSuppOctetFram = cs.bSuppOctetFram;
+ pModConf->iAddtlFrameDelim = cs.iAddtlFrameDelim;
+ pModConf->maxFrameSize = cs.maxFrameSize;
+ pModConf->bDisableLFDelim = cs.bDisableLFDelim;
+ pModConf->bUseFlowControl = cs.bUseFlowControl;
+ pModConf->bKeepAlive = cs.bKeepAlive;
+ pModConf->iKeepAliveProbes = cs.iKeepAliveProbes;
+ pModConf->iKeepAliveIntvl = cs.iKeepAliveIntvl;
+ pModConf->iKeepAliveTime = cs.iKeepAliveTime;
+ if(pPermPeersRoot != NULL) {
+ assert(pModConf->pPermPeersRoot == NULL);
+ pModConf->pPermPeersRoot = pPermPeersRoot;
+ pPermPeersRoot = NULL; /* memory handed over! */
+ }
+ if((cs.pszStrmDrvrAuthMode == NULL) || (cs.pszStrmDrvrAuthMode[0] == '\0')) {
+ loadModConf->pszStrmDrvrAuthMode = NULL;
+ } else {
+ loadModConf->pszStrmDrvrAuthMode = cs.pszStrmDrvrAuthMode;
+ cs.pszStrmDrvrAuthMode = NULL;
+ }
+ pModConf->bPreserveCase = cs.bPreserveCase;
+ }
+ free(cs.pszStrmDrvrAuthMode);
+ cs.pszStrmDrvrAuthMode = NULL;
+
+ loadModConf = NULL; /* done loading */
+ENDendCnfLoad
+
+
+/* function to generate error message if framework does not find requested ruleset */
+static inline void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+ LogError(0, NO_ERRCODE, "imtcp: ruleset '%s' for port %s not found - "
+ "using default ruleset instead", inst->pszBindRuleset,
+ inst->cnf_params->pszPort);
+}
+
+BEGINcheckCnf
+ instanceConf_t *inst;
+CODESTARTcheckCnf
+ for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ std_checkRuleset(pModConf, inst);
+ if(inst->cnf_params->bSuppOctetFram == FRAMING_UNSET)
+ inst->cnf_params->bSuppOctetFram = pModConf->bSuppOctetFram;
+ }
+ if(pModConf->root == NULL) {
+ LogError(0, RS_RET_NO_LISTNERS , "imtcp: module loaded, but "
+ "no listeners defined - no input will be gathered");
+ iRet = RS_RET_NO_LISTNERS;
+ }
+ENDcheckCnf
+
+
+BEGINactivateCnfPrePrivDrop
+ instanceConf_t *inst;
+CODESTARTactivateCnfPrePrivDrop
+ runModConf = pModConf;
+ for(inst = runModConf->root ; inst != NULL ; inst = inst->next) {
+ addListner(runModConf, inst);
+ }
+ if(tcpsrv_root == NULL)
+ ABORT_FINALIZE(RS_RET_NO_RUN);
+ tcpsrv_etry_t *etry = tcpsrv_root;
+ while(etry != NULL) {
+ CHKiRet(tcpsrv.ConstructFinalize(etry->tcpsrv));
+ etry = etry->next;
+ }
+finalize_it:
+ENDactivateCnfPrePrivDrop
+
+
+BEGINactivateCnf
+CODESTARTactivateCnf
+ /* sorry, nothing to do here... */
+ENDactivateCnf
+
+
+BEGINfreeCnf
+ instanceConf_t *inst, *del;
+CODESTARTfreeCnf
+ free(pModConf->gnutlsPriorityString);
+ free(pModConf->pszStrmDrvrName);
+ free(pModConf->pszStrmDrvrAuthMode);
+ free(pModConf->pszStrmDrvrPermitExpiredCerts);
+ free(pModConf->pszStrmDrvrCAFile);
+ free(pModConf->pszStrmDrvrCRLFile);
+ free(pModConf->pszStrmDrvrKeyFile);
+ free(pModConf->pszStrmDrvrCertFile);
+ if(pModConf->pPermPeersRoot != NULL) {
+ net.DestructPermittedPeers(&pModConf->pPermPeersRoot);
+ }
+
+ for(inst = pModConf->root ; inst != NULL ; ) {
+ free((void*)inst->pszBindRuleset);
+ free((void*)inst->pszStrmDrvrAuthMode);
+ free((void*)inst->pszStrmDrvrName);
+ free((void*)inst->pszStrmDrvrPermitExpiredCerts);
+ free((void*)inst->pszStrmDrvrCAFile);
+ free((void*)inst->pszStrmDrvrCRLFile);
+ free((void*)inst->pszStrmDrvrKeyFile);
+ free((void*)inst->pszStrmDrvrCertFile);
+ free((void*)inst->gnutlsPriorityString);
+ free((void*)inst->pszInputName);
+ free((void*)inst->dfltTZ);
+ if(inst->pPermPeersRoot != NULL) {
+ net.DestructPermittedPeers(&inst->pPermPeersRoot);
+ }
+ del = inst;
+ inst = inst->next;
+ free(del);
+ }
+ENDfreeCnf
+
+static void *
+RunServerThread(void *myself)
+{
+ tcpsrv_etry_t *const etry = (tcpsrv_etry_t*) myself;
+ rsRetVal iRet;
+ iRet = tcpsrv.Run(etry->tcpsrv);
+ if(iRet != RS_RET_OK) {
+ LogError(0, iRet, "imtcp: error while terminating server; rsyslog may hang on shutdown");
+ }
+ return NULL;
+}
+
+
+/* support for running multiple servers on multiple threads (one server per thread) */
+static void
+startSrvWrkr(tcpsrv_etry_t *const etry)
+{
+ int r;
+ pthread_attr_t sessThrdAttr;
+
+ /* We need to temporarily block all signals because the new thread
+ * inherits our signal mask. There is a race if we do not block them
+ * now, and we have seen in practice that this race causes grief.
+ * So we 1. save the current set, 2. block evertyhing, 3. start
+ * threads, and 4 reset the current set to saved state.
+ * rgerhards, 2019-08-16
+ */
+ sigset_t sigSet, sigSetSave;
+ sigfillset(&sigSet);
+ /* enable signals we still need */
+ sigdelset(&sigSet, SIGTTIN);
+ sigdelset(&sigSet, SIGSEGV);
+ pthread_sigmask(SIG_SETMASK, &sigSet, &sigSetSave);
+
+ pthread_attr_init(&sessThrdAttr);
+ pthread_attr_setstacksize(&sessThrdAttr, 4096*1024);
+ r = pthread_create(&etry->tid, &sessThrdAttr, RunServerThread, etry);
+ if(r != 0) {
+ LogError(r, NO_ERRCODE, "imtcp error creating server thread");
+ /* we do NOT abort, as other servers may run - after all, we logged an error */
+ }
+ pthread_attr_destroy(&sessThrdAttr);
+ pthread_sigmask(SIG_SETMASK, &sigSetSave, NULL);
+}
+
+/* stop server worker thread
+ */
+static void
+stopSrvWrkr(tcpsrv_etry_t *const etry)
+{
+ DBGPRINTF("Wait for thread shutdown etry %p\n", etry);
+ pthread_kill(etry->tid, SIGTTIN);
+ pthread_join(etry->tid, NULL);
+ DBGPRINTF("input %p terminated\n", etry);
+}
+
+/* This function is called to gather input.
+ */
+BEGINrunInput
+CODESTARTrunInput
+ tcpsrv_etry_t *etry = tcpsrv_root->next;
+ while(etry != NULL) {
+ startSrvWrkr(etry);
+ etry = etry->next;
+ }
+
+ iRet = tcpsrv.Run(tcpsrv_root->tcpsrv);
+
+ /* de-init remaining servers */
+ etry = tcpsrv_root->next;
+ while(etry != NULL) {
+ stopSrvWrkr(etry);
+ etry = etry->next;
+ }
+ENDrunInput
+
+
+/* initialize and return if will run or not */
+BEGINwillRun
+CODESTARTwillRun
+ net.PrintAllowedSenders(2); /* TCP */
+ENDwillRun
+
+
+BEGINafterRun
+CODESTARTafterRun
+ tcpsrv_etry_t *etry = tcpsrv_root;
+ tcpsrv_etry_t *del;
+ while(etry != NULL) {
+ iRet = tcpsrv.Destruct(&etry->tcpsrv);
+ // TODO: check iRet, reprot error
+ del = etry;
+ etry = etry->next;
+ free(del);
+ }
+ net.clearAllowedSenders(UCHAR_CONSTANT("TCP"));
+ENDafterRun
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURENonCancelInputTermination)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINmodExit
+CODESTARTmodExit
+ /* release objects we used */
+ objRelease(net, LM_NET_FILENAME);
+ objRelease(netstrm, LM_NETSTRMS_FILENAME);
+ objRelease(tcps_sess, LM_TCPSRV_FILENAME);
+ objRelease(tcpsrv, LM_TCPSRV_FILENAME);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+
+static rsRetVal
+resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ cs.iTCPSessMax = 200;
+ cs.iTCPLstnMax = 20;
+ cs.bSuppOctetFram = 1;
+ cs.iStrmDrvrMode = 0;
+ cs.bUseFlowControl = 1;
+ cs.bKeepAlive = 0;
+ cs.iKeepAliveProbes = 0;
+ cs.iKeepAliveTime = 0;
+ cs.iKeepAliveIntvl = 0;
+ cs.bEmitMsgOnClose = 0;
+ cs.iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER;
+ cs.maxFrameSize = 200000;
+ cs.bDisableLFDelim = 0;
+ cs.bPreserveCase = 1;
+ free(cs.pszStrmDrvrAuthMode);
+ cs.pszStrmDrvrAuthMode = NULL;
+ free(cs.pszInputName);
+ cs.pszInputName = NULL;
+ free(cs.lstnPortFile);
+ cs.lstnPortFile = NULL;
+ return RS_RET_OK;
+}
+
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_IMOD_QUERIES
+CODEqueryEtryPt_STD_CONF2_QUERIES
+CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES
+CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES
+CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES
+CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit()
+CODESTARTmodInit
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ tcpsrv_root = NULL;
+ /* request objects we use */
+ CHKiRet(objUse(net, LM_NET_FILENAME));
+ CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(tcps_sess, LM_TCPSRV_FILENAME));
+ CHKiRet(objUse(tcpsrv, LM_TCPSRV_FILENAME));
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ /* register config file handlers */
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpserverrun"), 0, eCmdHdlrGetWord,
+ addInstance, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpserverinputname"), 0, eCmdHdlrGetWord,
+ NULL, &cs.pszInputName, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("inputtcpserverbindruleset"), 0, eCmdHdlrGetWord,
+ NULL, &cs.pszBindRuleset, STD_LOADABLE_MODULE_ID));
+ /* module-global config params - will be disabled in configs that are loaded
+ * via module(...).
+ */
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverstreamdriverpermittedpeer"), 0, eCmdHdlrGetWord,
+ setPermittedPeer, NULL, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverstreamdriverauthmode"), 0, eCmdHdlrGetWord,
+ NULL, &cs.pszStrmDrvrAuthMode, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverkeepalive"), 0, eCmdHdlrBinary,
+ NULL, &cs.bKeepAlive, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverkeepalive_probes"), 0, eCmdHdlrInt,
+ NULL, &cs.iKeepAliveProbes, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverkeepalive_intvl"), 0, eCmdHdlrInt,
+ NULL, &cs.iKeepAliveIntvl, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverkeepalive_time"), 0, eCmdHdlrInt,
+ NULL, &cs.iKeepAliveTime, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpflowcontrol"), 0, eCmdHdlrBinary,
+ NULL, &cs.bUseFlowControl, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverdisablelfdelimiter"), 0, eCmdHdlrBinary,
+ NULL, &cs.bDisableLFDelim, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserveraddtlframedelimiter"), 0, eCmdHdlrInt,
+ NULL, &cs.iAddtlFrameDelim, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserversupportoctetcountedframing"), 0, eCmdHdlrBinary,
+ NULL, &cs.bSuppOctetFram, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpmaxsessions"), 0, eCmdHdlrInt,
+ NULL, &cs.iTCPSessMax, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpmaxlisteners"), 0, eCmdHdlrInt,
+ NULL, &cs.iTCPLstnMax, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpservernotifyonconnectionclose"), 0, eCmdHdlrBinary,
+ NULL, &cs.bEmitMsgOnClose, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverstreamdrivermode"), 0, eCmdHdlrInt,
+ NULL, &cs.iStrmDrvrMode, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverpreservecase"), 1, eCmdHdlrBinary,
+ NULL, &cs.bPreserveCase, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(regCfSysLineHdlr2(UCHAR_CONSTANT("inputtcpserverlistenportfile"), 1, eCmdHdlrGetWord,
+ NULL, &cs.lstnPortFile, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted));
+ CHKiRet(omsdRegCFSLineHdlr(UCHAR_CONSTANT("resetconfigvariables"), 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit