diff --git a/SOURCES/rsyslog-8.2102.0-imtcp-param-refactor.patch b/SOURCES/rsyslog-8.2102.0-imtcp-param-refactor.patch
new file mode 100644
index 0000000..224533e
--- /dev/null
+++ b/SOURCES/rsyslog-8.2102.0-imtcp-param-refactor.patch
@@ -0,0 +1,908 @@
+diff --git a/plugins/imdiag/imdiag.c b/plugins/imdiag/imdiag.c
+index 3e27ee4d36..d57dd5661c 100644
+--- a/plugins/imdiag/imdiag.c
++++ b/plugins/imdiag/imdiag.c
+@@ -566,28 +566,33 @@ setInjectDelayMode(void __attribute__((unused)) *pVal, uchar *const pszMode)
+ }
+ 
+ 
+-static rsRetVal addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVal)
++static rsRetVal
++addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVal)
+ {
++	tcpLstnParams_t *cnf_params = NULL;
+ 	DEFiRet;
+ 
+-	if(pOurTcpsrv == NULL) {
+-		CHKiRet(tcpsrv.Construct(&pOurTcpsrv));
+-		CHKiRet(tcpsrv.SetSessMax(pOurTcpsrv, iTCPSessMax));
+-		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));
+-		CHKiRet(tcpsrv.SetDrvrMode(pOurTcpsrv, iStrmDrvrMode));
+-		CHKiRet(tcpsrv.SetOnMsgReceive(pOurTcpsrv, OnMsgReceived));
+-		CHKiRet(tcpsrv.SetLstnPortFileName(pOurTcpsrv, pszLstnPortFileName));
+-		/* now set optional params, but only if they were actually configured */
+-		if(pszStrmDrvrAuthMode != NULL) {
+-			CHKiRet(tcpsrv.SetDrvrAuthMode(pOurTcpsrv, pszStrmDrvrAuthMode));
+-		}
+-		if(pPermPeersRoot != NULL) {
+-			CHKiRet(tcpsrv.SetDrvrPermPeers(pOurTcpsrv, pPermPeersRoot));
+-		}
++	if(pOurTcpsrv != NULL) {
++		LogError(0, NO_ERRCODE, "imdiag: only a single listener is supported, "
++			"trying to add a second");
++		ABORT_FINALIZE(RS_RET_ERR);
++	}
++	CHKmalloc(cnf_params = (tcpLstnParams_t*) calloc(1, sizeof(tcpLstnParams_t)));
++	CHKiRet(tcpsrv.Construct(&pOurTcpsrv));
++	CHKiRet(tcpsrv.SetSessMax(pOurTcpsrv, iTCPSessMax));
++	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));
++	CHKiRet(tcpsrv.SetDrvrMode(pOurTcpsrv, iStrmDrvrMode));
++	CHKiRet(tcpsrv.SetOnMsgReceive(pOurTcpsrv, OnMsgReceived));
++	/* now set optional params, but only if they were actually configured */
++	if(pszStrmDrvrAuthMode != NULL) {
++		CHKiRet(tcpsrv.SetDrvrAuthMode(pOurTcpsrv, pszStrmDrvrAuthMode));
++	}
++	if(pPermPeersRoot != NULL) {
++		CHKiRet(tcpsrv.SetDrvrPermPeers(pOurTcpsrv, pPermPeersRoot));
+ 	}
+ 
+ 	/* initialized, now add socket */
+@@ -595,7 +600,11 @@ static rsRetVal addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVa
+ 						UCHAR_CONSTANT("imdiag") : pszInputName));
+ 	CHKiRet(tcpsrv.SetOrigin(pOurTcpsrv, (uchar*)"imdiag"));
+ 	/* we support octect-counted frame (constant 1 below) */
+-	tcpsrv.configureTCPListen(pOurTcpsrv, pNewVal, 1, NULL, pszLstnPortFileName);
++	cnf_params->pszPort = pNewVal;
++	cnf_params->bSuppOctetFram = 1;
++	CHKmalloc(cnf_params->pszLstnPortFileName = (const uchar*) strdup((const char*)pszLstnPortFileName));
++	tcpsrv.configureTCPListen(pOurTcpsrv, cnf_params);
++	cnf_params = NULL;
+ 
+ finalize_it:
+ 	if(iRet != RS_RET_OK) {
+@@ -603,7 +612,7 @@ static rsRetVal addTCPListener(void __attribute__((unused)) *pVal, uchar *pNewVa
+ 		if(pOurTcpsrv != NULL)
+ 			tcpsrv.Destruct(&pOurTcpsrv);
+ 	}
+-	free(pNewVal);
++	free(cnf_params);
+ 	RETiRet;
+ }
+ 
+@@ -760,6 +769,7 @@ CODESTARTmodExit
+ 
+ 	/* free some globals to keep valgrind happy */
+ 	free(pszInputName);
++fprintf(stderr, "FINAL FREE %p\n", pszLstnPortFileName);
+ 	free(pszLstnPortFileName);
+ 	free(pszStrmDrvrAuthMode);
+ 
+diff --git a/plugins/imgssapi/imgssapi.c b/plugins/imgssapi/imgssapi.c
+index e0cab01664..4041e88b14 100644
+--- a/plugins/imgssapi/imgssapi.c
++++ b/plugins/imgssapi/imgssapi.c
+@@ -334,34 +334,38 @@ static rsRetVal
+ actGSSListener(uchar *port)
+ {
+ 	DEFiRet;
++	tcpLstnParams_t *cnf_params = NULL;
+ 	gsssrv_t *pGSrv = NULL;
+ 
+-	if(pOurTcpsrv == NULL) {
+-		/* first create/init the gsssrv "object" */
+-		if((pGSrv = calloc(1, sizeof(gsssrv_t))) == NULL)
+-			ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+-
+-		pGSrv->allowedMethods = ALLOWEDMETHOD_GSS;
+-		if(bPermitPlainTcp)
+-			pGSrv->allowedMethods |= ALLOWEDMETHOD_TCP;
+-		/* gsssrv initialized */
+-
+-		CHKiRet(tcpsrv.Construct(&pOurTcpsrv));
+-		CHKiRet(tcpsrv.SetUsrP(pOurTcpsrv, pGSrv));
+-		CHKiRet(tcpsrv.SetCBOnSessConstructFinalize(pOurTcpsrv, OnSessConstructFinalize));
+-		CHKiRet(tcpsrv.SetCBOnSessDestruct(pOurTcpsrv, OnSessDestruct));
+-		CHKiRet(tcpsrv.SetCBIsPermittedHost(pOurTcpsrv, isPermittedHost));
+-		CHKiRet(tcpsrv.SetCBRcvData(pOurTcpsrv, doRcvData));
+-		CHKiRet(tcpsrv.SetCBOpenLstnSocks(pOurTcpsrv, doOpenLstnSocks));
+-		CHKiRet(tcpsrv.SetCBOnSessAccept(pOurTcpsrv, onSessAccept));
+-		CHKiRet(tcpsrv.SetCBOnRegularClose(pOurTcpsrv, onRegularClose));
+-		CHKiRet(tcpsrv.SetCBOnErrClose(pOurTcpsrv, onErrClose));
+-		CHKiRet(tcpsrv.SetInputName(pOurTcpsrv, UCHAR_CONSTANT("imgssapi")));
+-		CHKiRet(tcpsrv.SetKeepAlive(pOurTcpsrv, bKeepAlive));
+-		CHKiRet(tcpsrv.SetOrigin(pOurTcpsrv, UCHAR_CONSTANT("imgssapi")));
+-		tcpsrv.configureTCPListen(pOurTcpsrv, port, 1, NULL, NULL);
+-		CHKiRet(tcpsrv.ConstructFinalize(pOurTcpsrv));
+-	}
++	assert(pOurTcpsrv == NULL);
++	CHKmalloc(cnf_params = (tcpLstnParams_t*) calloc(1, sizeof(tcpLstnParams_t)));
++	/* first create/init the gsssrv "object" */
++	if((pGSrv = calloc(1, sizeof(gsssrv_t))) == NULL)
++		ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
++
++	pGSrv->allowedMethods = ALLOWEDMETHOD_GSS;
++	if(bPermitPlainTcp)
++		pGSrv->allowedMethods |= ALLOWEDMETHOD_TCP;
++	/* gsssrv initialized */
++
++	CHKiRet(tcpsrv.Construct(&pOurTcpsrv));
++	CHKiRet(tcpsrv.SetUsrP(pOurTcpsrv, pGSrv));
++	CHKiRet(tcpsrv.SetCBOnSessConstructFinalize(pOurTcpsrv, OnSessConstructFinalize));
++	CHKiRet(tcpsrv.SetCBOnSessDestruct(pOurTcpsrv, OnSessDestruct));
++	CHKiRet(tcpsrv.SetCBIsPermittedHost(pOurTcpsrv, isPermittedHost));
++	CHKiRet(tcpsrv.SetCBRcvData(pOurTcpsrv, doRcvData));
++	CHKiRet(tcpsrv.SetCBOpenLstnSocks(pOurTcpsrv, doOpenLstnSocks));
++	CHKiRet(tcpsrv.SetCBOnSessAccept(pOurTcpsrv, onSessAccept));
++	CHKiRet(tcpsrv.SetCBOnRegularClose(pOurTcpsrv, onRegularClose));
++	CHKiRet(tcpsrv.SetCBOnErrClose(pOurTcpsrv, onErrClose));
++	CHKiRet(tcpsrv.SetInputName(pOurTcpsrv, UCHAR_CONSTANT("imgssapi")));
++	CHKiRet(tcpsrv.SetKeepAlive(pOurTcpsrv, bKeepAlive));
++	CHKiRet(tcpsrv.SetOrigin(pOurTcpsrv, UCHAR_CONSTANT("imgssapi")));
++	cnf_params->pszPort = port;
++	cnf_params->bSuppOctetFram = 1;
++	tcpsrv.configureTCPListen(pOurTcpsrv, cnf_params);
++	CHKiRet(tcpsrv.ConstructFinalize(pOurTcpsrv));
++	cnf_params = NULL;
+ 
+ finalize_it:
+ 	if(iRet != RS_RET_OK) {
+@@ -370,6 +374,7 @@ actGSSListener(uchar *port)
+ 			tcpsrv.Destruct(&pOurTcpsrv);
+ 		free(pGSrv);
+ 	}
++	free(cnf_params);
+ 	RETiRet;
+ }
+ 
+diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c
+index cf74d4c616..c336e6c24d 100644
+--- a/plugins/imtcp/imtcp.c
++++ b/plugins/imtcp/imtcp.c
+@@ -4,7 +4,7 @@
+  * 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-2017 Adiscon GmbH.
++ * Copyright 2007-2020 Adiscon GmbH.
+  *
+  * This file is part of rsyslog.
+  *
+@@ -112,9 +112,7 @@ static struct configSettings_s {
+ } cs;
+ 
+ struct instanceConf_s {
+-	uchar *pszBindPort;		/* port to bind to */
+-	uchar *pszLstnPortFileName;	/* file dynamic port is written to */
+-	uchar *pszBindAddr;             /* IP to bind socket to */
++	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 */
+@@ -122,7 +120,6 @@ struct instanceConf_s {
+ 	sbool bSPFramingFix;
+ 	unsigned int ratelimitInterval;
+ 	unsigned int ratelimitBurst;
+-	int bSuppOctetFram;
+ 	struct instanceConf_s *next;
+ };
+ 
+@@ -288,19 +285,20 @@ setPermittedPeer(void __attribute__((unused)) *pVal, uchar *pszID)
+ static rsRetVal
+ createInstance(instanceConf_t **pinst)
+ {
+-	instanceConf_t *inst;
++	instanceConf_t *inst = NULL;
++
+ 	DEFiRet;
+ 	CHKmalloc(inst = malloc(sizeof(instanceConf_t)));
++	CHKmalloc(inst->cnf_params = (tcpLstnParams_t*) calloc(1, sizeof(tcpLstnParams_t)));
+ 	inst->next = NULL;
+ 	inst->pszBindRuleset = NULL;
+ 	inst->pszInputName = NULL;
+-	inst->pszBindAddr = NULL;
+ 	inst->dfltTZ = NULL;
+-	inst->bSuppOctetFram = -1; /* unset */
++	inst->cnf_params->bSuppOctetFram = -1; /* unset */
+ 	inst->bSPFramingFix = 0;
+ 	inst->ratelimitInterval = 0;
+ 	inst->ratelimitBurst = 10000;
+-	inst->pszLstnPortFileName = NULL;
++	inst->cnf_params->pszLstnPortFileName = NULL;
+ 
+ 	/* node created, let's add to config */
+ 	if(loadModConf->tail == NULL) {
+@@ -312,6 +310,9 @@ createInstance(instanceConf_t **pinst)
+ 
+ 	*pinst = inst;
+ finalize_it:
++	if(iRet != RS_RET_OK) {
++		free(inst);
++	}
+ 	RETiRet;
+ }
+ 
+@@ -328,7 +329,7 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal)
+ 
+ 	CHKiRet(createInstance(&inst));
+ 
+-	CHKmalloc(inst->pszBindPort = ustrdup((pNewVal == NULL || *pNewVal == '\0')
++	CHKmalloc(inst->cnf_params->pszPort = ustrdup((pNewVal == NULL || *pNewVal == '\0')
+ 				 	       ? (uchar*) "10514" : pNewVal));
+ 	if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) {
+ 		inst->pszBindRuleset = NULL;
+@@ -336,14 +337,14 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal)
+ 		CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset));
+ 	}
+ 	if((cs.lstnIP == NULL) || (cs.lstnIP[0] == '\0')) {
+-		inst->pszBindAddr = NULL;
++		inst->cnf_params->pszAddr = NULL;
+ 	} else {
+-		CHKmalloc(inst->pszBindAddr = ustrdup(cs.lstnIP));
++		CHKmalloc(inst->cnf_params->pszAddr = ustrdup(cs.lstnIP));
+ 	}
+ 	if((cs.lstnPortFile == NULL) || (cs.lstnPortFile[0] == '\0')) {
+-		inst->pszBindAddr = NULL;
++		inst->cnf_params->pszAddr = NULL;
+ 	} else {
+-		CHKmalloc(inst->pszLstnPortFileName = ustrdup(cs.lstnPortFile));
++		CHKmalloc(inst->cnf_params->pszLstnPortFileName = ustrdup(cs.lstnPortFile));
+ 	}
+ 
+ 	if((cs.pszInputName == NULL) || (cs.pszInputName[0] == '\0')) {
+@@ -351,7 +352,7 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal)
+ 	} else {
+ 		CHKmalloc(inst->pszInputName = ustrdup(cs.pszInputName));
+ 	}
+-	inst->bSuppOctetFram = cs.bSuppOctetFram;
++	inst->cnf_params->bSuppOctetFram = cs.bSuppOctetFram;
+ 
+ finalize_it:
+ 	free(pNewVal);
+@@ -407,7 +408,7 @@ addListner(modConfData_t *modConf, instanceConf_t *inst)
+ 	}
+ 
+ 	/* initialized, now add socket and listener params */
+-	DBGPRINTF("imtcp: trying to add port *:%s\n", inst->pszBindPort);
++	DBGPRINTF("imtcp: trying to add port *:%s\n", inst->cnf_params->pszPort);
+ 	CHKiRet(tcpsrv.SetRuleset(pOurTcpsrv, inst->pBindRuleset));
+ 	CHKiRet(tcpsrv.SetInputName(pOurTcpsrv, inst->pszInputName == NULL ?
+ 						UCHAR_CONSTANT("imtcp") : inst->pszInputName));
+@@ -416,12 +417,12 @@ addListner(modConfData_t *modConf, instanceConf_t *inst)
+ 	CHKiRet(tcpsrv.SetbSPFramingFix(pOurTcpsrv, inst->bSPFramingFix));
+ 	CHKiRet(tcpsrv.SetLinuxLikeRatelimiters(pOurTcpsrv, inst->ratelimitInterval, inst->ratelimitBurst));
+ 
+-	if((ustrcmp(inst->pszBindPort, UCHAR_CONSTANT("0")) == 0 && inst->pszLstnPortFileName == NULL)
+-			|| ustrcmp(inst->pszBindPort, UCHAR_CONSTANT("0")) < 0) {
+-		CHKmalloc(inst->pszBindPort = (uchar*)strdup("514"));
++	if((ustrcmp(inst->cnf_params->pszPort, UCHAR_CONSTANT("0")) == 0
++		&& inst->cnf_params->pszLstnPortFileName == NULL)
++			|| ustrcmp(inst->cnf_params->pszPort, UCHAR_CONSTANT("0")) < 0) {
++		CHKmalloc(inst->cnf_params->pszPort = (uchar*)strdup("514"));
+ 	}
+-	tcpsrv.configureTCPListen(pOurTcpsrv, inst->pszBindPort, inst->bSuppOctetFram,
+-		inst->pszBindAddr, inst->pszLstnPortFileName);
++	tcpsrv.configureTCPListen(pOurTcpsrv, inst->cnf_params);
+ 
+ finalize_it:
+ 	if(iRet != RS_RET_OK) {
+@@ -456,9 +457,9 @@ CODESTARTnewInpInst
+ 		if(!pvals[i].bUsed)
+ 			continue;
+ 		if(!strcmp(inppblk.descr[i].name, "port")) {
+-			inst->pszBindPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
++			inst->cnf_params->pszPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ 		} else if(!strcmp(inppblk.descr[i].name, "address")) {
+-			inst->pszBindAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
++			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")) {
+@@ -468,13 +469,13 @@ CODESTARTnewInpInst
+ 		} 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, "supportoctetcountedframing")) {
+-			inst->bSuppOctetFram = (int) pvals[i].val.d.n;
++			inst->cnf_params->bSuppOctetFram = (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, "listenportfilename")) {
+-			inst->pszLstnPortFileName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
++			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);
+@@ -656,7 +657,7 @@ std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, insta
+ {
+ 	LogError(0, NO_ERRCODE, "imtcp: ruleset '%s' for port %s not found - "
+ 			"using default ruleset instead", inst->pszBindRuleset,
+-			inst->pszBindPort);
++			inst->cnf_params->pszPort);
+ }
+ 
+ BEGINcheckCnf
+@@ -664,8 +665,8 @@ BEGINcheckCnf
+ CODESTARTcheckCnf
+ 	for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+ 		std_checkRuleset(pModConf, inst);
+-		if(inst->bSuppOctetFram == FRAMING_UNSET)
+-			inst->bSuppOctetFram = pModConf->bSuppOctetFram;
++		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 "
+@@ -713,12 +714,9 @@ CODESTARTfreeCnf
+ 		free(pModConf->permittedPeers);
+ 	}
+ 	for(inst = pModConf->root ; inst != NULL ; ) {
+-		free(inst->pszBindPort);
+-		free(inst->pszLstnPortFileName);
+-		free(inst->pszBindAddr);
+-		free(inst->pszBindRuleset);
+-		free(inst->pszInputName);
+-		free(inst->dfltTZ);
++		free((void*)inst->pszBindRuleset);
++		free((void*)inst->pszInputName);
++		free((void*)inst->dfltTZ);
+ 		del = inst;
+ 		inst = inst->next;
+ 		free(del);
+diff --git a/runtime/netstrm.c b/runtime/netstrm.c
+index 8a394a02eb..2c1db46378 100644
+--- a/runtime/netstrm.c
++++ b/runtime/netstrm.c
+@@ -12,12 +12,18 @@
+  * to carry out its work (including, and most importantly, transport
+  * drivers).
+  *
++ * Note on processing:
++ * - Initiating a listener may be driver-specific, but in regard to TLS/non-TLS
++ *   it actually is not. This is because TLS is negotiated after a connection
++ *   has been established. So it is the "acceptConnReq" driver entry where TLS
++ *   params need to be applied.
++ *
+  * Work on this module begun 2008-04-17 by Rainer Gerhards. This code
+  * borrows from librelp's tcp.c/.h code. librelp is dual licensed and
+  * Rainer Gerhards and Adiscon GmbH have agreed to permit using the code
+  * under the terms of the GNU Lesser General Public License.
+  *
+- * Copyright 2007-2009 Rainer Gerhards and Adiscon GmbH.
++ * Copyright 2007-2020 Rainer Gerhards and Adiscon GmbH.
+  *
+  * This file is part of the rsyslog runtime library.
+  *
+@@ -134,18 +140,17 @@ AcceptConnReq(netstrm_t *pThis, netstrm_t **ppNew)
+  * pLstnPort must point to a port name or number. NULL is NOT permitted.
+  * rgerhards, 2008-04-22
+  */
+-static rsRetVal
++static rsRetVal ATTR_NONNULL(1,3,5)
+ LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+-	 uchar *pLstnPort, uchar *pLstnIP, int iSessMax,
+-	 uchar *pszLstnPortFileName)
++	 const int iSessMax, const tcpLstnParams_t *const cnf_params)
+ {
+ 	DEFiRet;
+ 
+ 	ISOBJ_TYPE_assert(pNS, netstrms);
+ 	assert(fAddLstn != NULL);
+-	assert(pLstnPort != NULL);
++	assert(cnf_params->pszPort != NULL);
+ 
+-	CHKiRet(pNS->Drvr.LstnInit(pNS, pUsr, fAddLstn, pLstnPort, pLstnIP, iSessMax, pszLstnPortFileName));
++	CHKiRet(pNS->Drvr.LstnInit(pNS, pUsr, fAddLstn, iSessMax, cnf_params));
+ 
+ finalize_it:
+ 	RETiRet;
+diff --git a/runtime/netstrm.h b/runtime/netstrm.h
+index 2e28d7e2e6..4ca35805e7 100644
+--- a/runtime/netstrm.h
++++ b/runtime/netstrm.h
+@@ -1,6 +1,6 @@
+ /* Definitions for the stream-based netstrmworking class.
+  *
+- * Copyright 2007, 2008 Rainer Gerhards and Adiscon GmbH.
++ * Copyright 2007-2020 Rainer Gerhards and Adiscon GmbH.
+  *
+  * This file is part of the rsyslog runtime library.
+  *
+@@ -24,6 +24,7 @@
+ #ifndef INCLUDED_NETSTRM_H
+ #define INCLUDED_NETSTRM_H
+ 
++#include "tcpsrv.h"
+ #include "netstrms.h"
+ 
+ /* the netstrm object */
+@@ -31,6 +32,7 @@ struct netstrm_s {
+ 	BEGINobjInstance;	/* Data to implement generic object - MUST be the first data element! */
+ 	nsd_t *pDrvrData;	/**< the driver's data elements (at most other places, this is called pNsd) */
+ 	nsd_if_t Drvr;		/**< our stream driver */
++	uchar *pszDrvrAuthMode;	/**< auth mode of the stream driver to use */
+ 	void *pUsr;		/**< pointer to user-provided data structure */
+ 	netstrms_t *pNS;	/**< pointer to our netstream subsystem object */
+ };
+@@ -76,8 +78,8 @@ BEGINinterface(netstrm) /* name must also be changed in ENDinterface macro! */
+ 	rsRetVal (*SetKeepAliveIntvl)(netstrm_t *pThis, int keepAliveIntvl);
+ 	rsRetVal (*SetGnutlsPriorityString)(netstrm_t *pThis, uchar *priorityString);
+ 	/* v11 -- Parameter pszLstnFileName added to LstnInit*/
+-	rsRetVal (*LstnInit)(netstrms_t *pNS, void *pUsr, rsRetVal(*)(void*,netstrm_t*),
+-		             uchar *pLstnPort, uchar *pLstnIP, int iSessMax, uchar *pszLstnPortFileName);
++	rsRetVal (ATTR_NONNULL(1,3,5) *LstnInit)(netstrms_t *pNS, void *pUsr, rsRetVal(*)(void*,netstrm_t*),
++			 const int iSessMax, const tcpLstnParams_t *const cnf_params);
+ 	/* v12 -- two new binary flags added to gtls driver enabling stricter operation */
+ 	rsRetVal (*SetDrvrCheckExtendedKeyUsage)(netstrm_t *pThis, int ChkExtendedKeyUsage);
+ 	rsRetVal (*SetDrvrPrioritizeSAN)(netstrm_t *pThis, int prioritizeSan);
+diff --git a/runtime/nsd.h b/runtime/nsd.h
+index e862348fd6..eecffed05e 100644
+--- a/runtime/nsd.h
++++ b/runtime/nsd.h
+@@ -84,8 +84,8 @@ BEGINinterface(nsd) /* name must also be changed in ENDinterface macro! */
+ 	rsRetVal (*SetKeepAliveTime)(nsd_t *pThis, int keepAliveTime);
+ 	rsRetVal (*SetGnutlsPriorityString)(nsd_t *pThis, uchar *gnutlsPriorityString);
+ 	/* v12 -- parameter pszLstnPortFileName added to LstnInit()*/
+-	rsRetVal (*LstnInit)(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+-				 uchar *pLstnPort, uchar *pLstnIP, int iSessMax, uchar *pszLstnPortFileName);
++	rsRetVal (ATTR_NONNULL(1,3,5) *LstnInit)(netstrms_t *pNS, void *pUsr, rsRetVal(*)(void*,netstrm_t*),
++			 const int iSessMax, const tcpLstnParams_t *const cnf_params);
+ 	/* v13 -- two new binary flags added to gtls driver enabling stricter operation */
+ 	rsRetVal (*SetCheckExtendedKeyUsage)(nsd_t *pThis, int ChkExtendedKeyUsage);
+ 	rsRetVal (*SetPrioritizeSAN)(nsd_t *pThis, int prioritizeSan);
+diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c
+index da90c2e096..55f6713d62 100644
+--- a/runtime/nsd_gtls.c
++++ b/runtime/nsd_gtls.c
+@@ -1692,14 +1692,13 @@ Abort(nsd_t *pNsd)
+  * a session, but not during listener setup.
+  * gerhards, 2008-04-25
+  */
+-static rsRetVal
++static rsRetVal ATTR_NONNULL(1,3,5)
+ LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+-	 uchar *pLstnPort, uchar *pLstnIP, int iSessMax,
+-	 uchar *pszLstnPortFileName)
++	 const int iSessMax, const tcpLstnParams_t *const cnf_params)
+ {
+ 	DEFiRet;
+ 	CHKiRet(gtlsGlblInitLstn());
+-	iRet = nsd_ptcp.LstnInit(pNS, pUsr, fAddLstn, pLstnPort, pLstnIP, iSessMax, pszLstnPortFileName);
++	iRet = nsd_ptcp.LstnInit(pNS, pUsr, fAddLstn, iSessMax, cnf_params);
+ finalize_it:
+ 	RETiRet;
+ }
+@@ -1785,6 +1784,7 @@ AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
+ 		FINALIZE;
+ 	}
+ 	/* copy Properties to pnew first */
++dbgprintf("RGER: pThis %p pNew %p, authMode %d\n", pThis, pNew, pThis->authMode);
+ 	pNew->authMode = pThis->authMode;
+ 	pNew->permitExpiredCerts = pThis->permitExpiredCerts;
+ 	pNew->pPermPeers = pThis->pPermPeers;
+diff --git a/runtime/nsd_ossl.c b/runtime/nsd_ossl.c
+index 431ea738b8..79347916e4 100644
+--- a/runtime/nsd_ossl.c
++++ b/runtime/nsd_ossl.c
+@@ -1308,16 +1308,15 @@ Abort(nsd_t *pNsd)
+  */
+ static rsRetVal
+ LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+-	 uchar *pLstnPort, uchar *pLstnIP, int iSessMax, uchar *pszLstnPortFileName)
++	 const int iSessMax, const tcpLstnParams_t *const cnf_params)
+ {
+ 	DEFiRet;
+ 
+ 	dbgprintf("LstnInit for openssl: entering LstnInit (%p) for %s:%s SessMax=%d\n",
+-		fAddLstn, pLstnIP, pLstnPort, iSessMax);
++		fAddLstn, cnf_params->pszAddr, cnf_params->pszPort, iSessMax);
+ 
+ 	/* Init TCP Listener using base ptcp class */
+-	iRet = nsd_ptcp.LstnInit(pNS, pUsr, fAddLstn, pLstnPort, pLstnIP,
+-			iSessMax, pszLstnPortFileName);
++	iRet = nsd_ptcp.LstnInit(pNS, pUsr, fAddLstn, iSessMax, cnf_params);
+ 	RETiRet;
+ }
+ 
+diff --git a/runtime/nsd_ptcp.c b/runtime/nsd_ptcp.c
+index c35138fb7a..2f9e77ba03 100644
+--- a/runtime/nsd_ptcp.c
++++ b/runtime/nsd_ptcp.c
+@@ -474,10 +474,9 @@ AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
+  * number of sessions permitted.
+  * rgerhards, 2008-04-22
+  */
+-static rsRetVal
++static rsRetVal ATTR_NONNULL(1,3,5)
+ LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+-	 uchar *pLstnPort, uchar *pLstnIP, int iSessMax,
+-	 uchar *pszLstnPortFileName)
++	 const int iSessMax, const tcpLstnParams_t *const cnf_params)
+ {
+ 	DEFiRet;
+ 	netstrm_t *pNewStrm = NULL;
+@@ -497,20 +496,20 @@ LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+ 
+ 	ISOBJ_TYPE_assert(pNS, netstrms);
+ 	assert(fAddLstn != NULL);
+-	assert(pLstnPort != NULL);
++	assert(cnf_params->pszPort != NULL);
+ 	assert(iSessMax >= 0);
+ 
+-	dbgprintf("creating tcp listen socket on port %s\n", pLstnPort);
++	dbgprintf("creating tcp listen socket on port %s\n", cnf_params->pszPort);
+ 
+ 	memset(&hints, 0, sizeof(hints));
+ 	hints.ai_flags = AI_PASSIVE;
+ 	hints.ai_family = glbl.GetDefPFFamily();
+ 	hints.ai_socktype = SOCK_STREAM;
+ 
+-	error = getaddrinfo((char*)pLstnIP, (char*) pLstnPort, &hints, &res);
++	error = getaddrinfo((const char*)cnf_params->pszAddr, (const char*) cnf_params->pszPort, &hints, &res);
+ 	if(error) {
+ 		LogError(0, RS_RET_INVALID_PORT, "error querying port '%s': %s",
+-			pLstnPort, gai_strerror(error));
++			cnf_params->pszAddr, gai_strerror(error));
+ 		ABORT_FINALIZE(RS_RET_INVALID_PORT);
+ 	}
+ 
+@@ -622,9 +621,9 @@ LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
+ 			r->ai_addrlen = socklen_r;
+ 			savecast.sa = (struct sockaddr*)r->ai_addr;
+ 			port_override = (isIPv6) ?  savecast.ipv6->sin6_port : savecast.ipv4->sin_port;
+-			if(pszLstnPortFileName != NULL) {
++			if(cnf_params->pszLstnPortFileName != NULL) {
+ 				FILE *fp;
+-				if((fp = fopen((const char*)pszLstnPortFileName, "w+")) == NULL) {
++				if((fp = fopen((const char*)cnf_params->pszLstnPortFileName, "w+")) == NULL) {
+ 					LogError(errno, RS_RET_IO_ERROR, "nsd_ptcp: ListenPortFileName: "
+ 							"error while trying to open file");
+ 					ABORT_FINALIZE(RS_RET_IO_ERROR);
+diff --git a/runtime/nsd_ptcp.h b/runtime/nsd_ptcp.h
+index 137b7c3ce7..1c91718c19 100644
+--- a/runtime/nsd_ptcp.h
++++ b/runtime/nsd_ptcp.h
+@@ -1,6 +1,6 @@
+ /* An implementation of the nsd interface for plain tcp sockets.
+  *
+- * Copyright 2007-2012 Adiscon GmbH.
++ * Copyright 2007-2020 Adiscon GmbH.
+  *
+  * This file is part of the rsyslog runtime library.
+  *
+@@ -23,6 +23,7 @@
+ #define INCLUDED_NSD_PTCP_H
+ 
+ #include <sys/socket.h>
++#include "tcpsrv.h"
+ 
+ #include "nsd.h"
+ typedef nsd_if_t nsd_ptcp_if_t; /* we just *implement* this interface */
+diff --git a/runtime/tcps_sess.c b/runtime/tcps_sess.c
+index 58528c81ec..845e944582 100644
+--- a/runtime/tcps_sess.c
++++ b/runtime/tcps_sess.c
+@@ -194,8 +194,8 @@ SetLstnInfo(tcps_sess_t *pThis, tcpLstnPortList_t *pLstnInfo)
+ 	assert(pLstnInfo != NULL);
+ 	pThis->pLstnInfo = pLstnInfo;
+ 	/* set cached elements */
+-	pThis->bSuppOctetFram = pLstnInfo->bSuppOctetFram;
+-	pThis->bSPFramingFix = pLstnInfo->bSPFramingFix;
++	pThis->bSuppOctetFram = pLstnInfo->cnf_params->bSuppOctetFram;
++	pThis->bSPFramingFix = pLstnInfo->cnf_params->bSPFramingFix;
+ 	RETiRet;
+ }
+ 
+@@ -235,6 +235,7 @@ defaultDoSubmitMessage(tcps_sess_t *pThis, struct syslogTime *stTime, time_t ttG
+ 	DEFiRet;
+ 
+ 	ISOBJ_TYPE_assert(pThis, tcps_sess);
++	const tcpLstnParams_t *const cnf_params = pThis->pLstnInfo->cnf_params;
+ 	
+ 	if(pThis->iMsg == 0) {
+ 		DBGPRINTF("discarding zero-sized message\n");
+@@ -249,15 +250,15 @@ defaultDoSubmitMessage(tcps_sess_t *pThis, struct syslogTime *stTime, time_t ttG
+ 	/* we now create our own message object and submit it to the queue */
+ 	CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime));
+ 	MsgSetRawMsg(pMsg, (char*)pThis->pMsg, pThis->iMsg);
+-	MsgSetInputName(pMsg, pThis->pLstnInfo->pInputName);
+-	if(pThis->pLstnInfo->dfltTZ[0] != '\0')
+-		MsgSetDfltTZ(pMsg, (char*) pThis->pLstnInfo->dfltTZ);
++	MsgSetInputName(pMsg, cnf_params->pInputName);
++	if(cnf_params->dfltTZ[0] != '\0')
++		MsgSetDfltTZ(pMsg, (char*) cnf_params->dfltTZ);
+ 	MsgSetFlowControlType(pMsg, pThis->pSrv->bUseFlowControl
+ 			            ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY);
+ 	pMsg->msgFlags  = NEEDS_PARSING | PARSE_HOSTNAME;
+ 	MsgSetRcvFrom(pMsg, pThis->fromHost);
+ 	CHKiRet(MsgSetRcvFromIP(pMsg, pThis->fromHostIP));
+-	MsgSetRuleset(pMsg, pThis->pLstnInfo->pRuleset);
++	MsgSetRuleset(pMsg, cnf_params->pRuleset);
+ 
+ 	STATSCOUNTER_INC(pThis->pLstnInfo->ctrSubmit, pThis->pLstnInfo->mutCtrSubmit);
+ 	ratelimitAddMsg(pThis->pLstnInfo->ratelimiter, pMultiSub, pMsg);
+diff --git a/runtime/tcpsrv.c b/runtime/tcpsrv.c
+index 76a50357c3..ab9573e5b8 100644
+--- a/runtime/tcpsrv.c
++++ b/runtime/tcpsrv.c
+@@ -123,9 +123,7 @@ static int wrkrRunning;
+  * rgerhards, 2009-05-21
+  */
+ static rsRetVal ATTR_NONNULL(1, 2)
+-addNewLstnPort(tcpsrv_t *const pThis, const uchar *const pszPort,
+-	const int bSuppOctetFram, const uchar *const pszAddr,
+-	const uchar *const pszLstnPortFileName)
++addNewLstnPort(tcpsrv_t *const pThis, tcpLstnParams_t *const cnf_params)
+ {
+ 	tcpLstnPortList_t *pEntry;
+ 	uchar statname[64];
+@@ -135,25 +133,17 @@ addNewLstnPort(tcpsrv_t *const pThis, const uchar *const pszPort,
+ 
+ 	/* create entry */
+ 	CHKmalloc(pEntry = (tcpLstnPortList_t*)calloc(1, sizeof(tcpLstnPortList_t)));
+-	CHKmalloc(pEntry->pszPort = ustrdup(pszPort));
++	pEntry->cnf_params = cnf_params;
+ 
+-	pEntry->pszAddr = NULL;
+-	/* only if a bind adress is defined copy it in struct */
+-	if (pszAddr != NULL) {
+-		CHKmalloc(pEntry->pszAddr = ustrdup(pszAddr));
+-	}
+-
+-	strcpy((char*)pEntry->dfltTZ, (char*)pThis->dfltTZ);
+-	pEntry->bSPFramingFix = pThis->bSPFramingFix;
++	strcpy((char*)pEntry->cnf_params->dfltTZ, (char*)pThis->dfltTZ);
++	pEntry->cnf_params->bSPFramingFix = pThis->bSPFramingFix;
++	pEntry->cnf_params->pRuleset = pThis->pRuleset;
+ 	pEntry->pSrv = pThis;
+-	pEntry->pRuleset = pThis->pRuleset;
+-	pEntry->bSuppOctetFram = bSuppOctetFram;
+-	pEntry->pszLstnPortFileName = pszLstnPortFileName;
+ 
+ 	/* we need to create a property */
+-	CHKiRet(prop.Construct(&pEntry->pInputName));
+-	CHKiRet(prop.SetString(pEntry->pInputName, pThis->pszInputName, ustrlen(pThis->pszInputName)));
+-	CHKiRet(prop.ConstructFinalize(pEntry->pInputName));
++	CHKiRet(prop.Construct(&pEntry->cnf_params->pInputName));
++	CHKiRet(prop.SetString(pEntry->cnf_params->pInputName, pThis->pszInputName, ustrlen(pThis->pszInputName)));
++	CHKiRet(prop.ConstructFinalize(pEntry->cnf_params->pInputName));
+ 
+ 	/* support statistics gathering */
+ 	CHKiRet(ratelimitNew(&pEntry->ratelimiter, "tcperver", NULL));
+@@ -161,7 +151,7 @@ addNewLstnPort(tcpsrv_t *const pThis, const uchar *const pszPort,
+ 	ratelimitSetThreadSafe(pEntry->ratelimiter);
+ 
+ 	CHKiRet(statsobj.Construct(&(pEntry->stats)));
+-	snprintf((char*)statname, sizeof(statname), "%s(%s)", pThis->pszInputName, pszPort);
++	snprintf((char*)statname, sizeof(statname), "%s(%s)", pThis->pszInputName, cnf_params->pszPort);
+ 	statname[sizeof(statname)-1] = '\0'; /* just to be on the save side... */
+ 	CHKiRet(statsobj.SetName(pEntry->stats, statname));
+ 	CHKiRet(statsobj.SetOrigin(pEntry->stats, pThis->pszOrigin));
+@@ -177,10 +167,8 @@ addNewLstnPort(tcpsrv_t *const pThis, const uchar *const pszPort,
+ finalize_it:
+ 	if(iRet != RS_RET_OK) {
+ 		if(pEntry != NULL) {
+-			free(pEntry->pszAddr);
+-			free(pEntry->pszPort);
+-			if(pEntry->pInputName != NULL) {
+-				prop.Destruct(&pEntry->pInputName);
++			if(pEntry->cnf_params->pInputName != NULL) {
++				prop.Destruct(&pEntry->cnf_params->pInputName);
+ 			}
+ 			if(pEntry->ratelimiter != NULL) {
+ 				ratelimitDestruct(pEntry->ratelimiter);
+@@ -201,29 +189,25 @@ addNewLstnPort(tcpsrv_t *const pThis, const uchar *const pszPort,
+  * rgerhards, 2008-03-20
+  */
+ static rsRetVal ATTR_NONNULL(1,2)
+-configureTCPListen(tcpsrv_t *const pThis,
+-	const uchar *const pszPort,
+-	const int bSuppOctetFram,
+-	const uchar *const pszAddr,
+-	const uchar *const pszLstnPortFileName)
++configureTCPListen(tcpsrv_t *const pThis, tcpLstnParams_t *const cnf_params)
+ {
++	assert(cnf_params->pszPort != NULL);
+ 	int i;
+-	const uchar *pPort = pszPort;
+ 	DEFiRet;
+ 
+-	assert(pszPort != NULL);
+ 	ISOBJ_TYPE_assert(pThis, tcpsrv);
+ 
+ 	/* extract port */
++	const uchar *pPort = cnf_params->pszPort;
+ 	i = 0;
+ 	while(isdigit((int) *pPort)) {
+ 		i = i * 10 + *pPort++ - '0';
+ 	}
+ 
+ 	if(i >= 0 && i <= 65535) {
+-		CHKiRet(addNewLstnPort(pThis, pszPort, bSuppOctetFram, pszAddr, pszLstnPortFileName));
++		CHKiRet(addNewLstnPort(pThis, cnf_params));
+ 	} else {
+-		LogError(0, NO_ERRCODE, "Invalid TCP listen port %s - ignored.\n", pszPort);
++		LogError(0, NO_ERRCODE, "Invalid TCP listen port %s - ignored.\n", cnf_params->pszPort);
+ 	}
+ 
+ finalize_it:
+@@ -331,8 +315,11 @@ deinit_tcp_listener(tcpsrv_t *const pThis)
+ 	/* free list of tcp listen ports */
+ 	pEntry = pThis->pLstnPorts;
+ 	while(pEntry != NULL) {
+-		free(pEntry->pszPort);
+-		prop.Destruct(&pEntry->pInputName);
++		prop.Destruct(&pEntry->cnf_params->pInputName);
++		free((void*)pEntry->cnf_params->pszPort);
++		free((void*)pEntry->cnf_params->pszAddr);
++		free((void*)pEntry->cnf_params->pszLstnPortFileName);
++		free((void*)pEntry->cnf_params);
+ 		ratelimitDestruct(pEntry->ratelimiter);
+ 		statsobj.Destruct(&(pEntry->stats));
+ 		pDel = pEntry;
+@@ -373,22 +360,21 @@ addTcpLstn(void *pUsr, netstrm_t *pLstn)
+ 
+ 
+ /* Initialize TCP listener socket for a single port
++ * Note: at this point, TLS vs. non-TLS does not matter; TLS params are
++ * set on connect!
+  * rgerhards, 2009-05-21
+  */
+ static rsRetVal
+ initTCPListener(tcpsrv_t *pThis, tcpLstnPortList_t *pPortEntry)
+ {
+ 	DEFiRet;
+-	uchar *TCPLstnPort;
+ 
+ 	ISOBJ_TYPE_assert(pThis, tcpsrv);
+ 	assert(pPortEntry != NULL);
+ 
+-	TCPLstnPort = pPortEntry->pszPort;
+-
+ 	// pPortEntry->pszAddr = NULL ==> bind to all interfaces
+-	CHKiRet(netstrm.LstnInit(pThis->pNS, (void*)pPortEntry, addTcpLstn, TCPLstnPort,
+-		pPortEntry->pszAddr, pThis->iSessMax, (uchar*)pPortEntry->pszLstnPortFileName));
++	CHKiRet(netstrm.LstnInit(pThis->pNS, (void*)pPortEntry, addTcpLstn,
++		pThis->iSessMax, pPortEntry->cnf_params));
+ 
+ finalize_it:
+ 	RETiRet;
+@@ -408,11 +394,12 @@ create_tcp_socket(tcpsrv_t *pThis)
+ 	/* init all configured ports */
+ 	pEntry = pThis->pLstnPorts;
+ 	while(pEntry != NULL) {
++dbgprintf("RGER: configuring listener %p\n", pEntry);
+ 		localRet = initTCPListener(pThis, pEntry);
+ 		if(localRet != RS_RET_OK) {
+ 			LogError(0, localRet, "Could not create tcp listener, ignoring port "
+-			"%s bind-address %s.", pEntry->pszPort,
+-			(pEntry->pszAddr == NULL) ? "(null)" : (const char*)pEntry->pszAddr);
++			"%s bind-address %s.", pEntry->cnf_params->pszPort,
++			(pEntry->cnf_params->pszAddr == NULL) ? "(null)" : (const char*)pEntry->cnf_params->pszAddr);
+ 		}
+ 		pEntry = pEntry->pNext;
+ 	}
+@@ -1236,15 +1223,6 @@ SetGnutlsPriorityString(tcpsrv_t *pThis, uchar *iVal)
+ 	RETiRet;
+ }
+ 
+-static rsRetVal
+-SetLstnPortFileName(tcpsrv_t *pThis, uchar *iVal)
+-{
+-	DEFiRet;
+-	DBGPRINTF("tcpsrv: LstnPortFileName set to %s\n",
+-		(iVal == NULL) ? "(null)" : (const char*) iVal);
+-	pThis->pszLstnPortFileName = iVal;
+-	RETiRet;
+-}
+ 
+ static rsRetVal
+ SetOnMsgReceive(tcpsrv_t *pThis, rsRetVal (*OnMsgReceive)(tcps_sess_t*, uchar*, int))
+@@ -1309,6 +1287,7 @@ SetDfltTZ(tcpsrv_t *const pThis, uchar *const tz)
+ {
+ 	DEFiRet;
+ 	ISOBJ_TYPE_assert(pThis, tcpsrv);
++dbgprintf("dfltTZ prev: %s\n", pThis->dfltTZ);
+ 	strncpy((char*)pThis->dfltTZ, (char*)tz, sizeof(pThis->dfltTZ));
+ 	pThis->dfltTZ[sizeof(pThis->dfltTZ)-1] = '\0';
+ 	RETiRet;
+@@ -1557,7 +1536,6 @@ CODESTARTobjQueryInterface(tcpsrv)
+ 	pIf->SetKeepAliveProbes = SetKeepAliveProbes;
+ 	pIf->SetKeepAliveTime = SetKeepAliveTime;
+ 	pIf->SetGnutlsPriorityString = SetGnutlsPriorityString;
+-	pIf->SetLstnPortFileName = SetLstnPortFileName;
+ 	pIf->SetUsrP = SetUsrP;
+ 	pIf->SetInputName = SetInputName;
+ 	pIf->SetOrigin = SetOrigin;
+diff --git a/runtime/tcpsrv.h b/runtime/tcpsrv.h
+index db5a1d110a..bae7e3b8b9 100644
+--- a/runtime/tcpsrv.h
++++ b/runtime/tcpsrv.h
+@@ -1,6 +1,6 @@
+ /* Definitions for tcpsrv class.
+  *
+- * Copyright 2008-2015 Adiscon GmbH.
++ * Copyright 2008-2020 Adiscon GmbH.
+  *
+  * This file is part of rsyslog.
+  *
+@@ -23,6 +23,7 @@
+ 
+ #include "obj.h"
+ #include "prop.h"
++#include "net.h"
+ #include "tcps_sess.h"
+ #include "statsobj.h"
+ 
+@@ -34,19 +35,24 @@ typedef enum ETCPsyslogFramingAnomaly {
+ } eTCPsyslogFramingAnomaly;
+ 
+ 
++/* config parameters for TCP listeners */
++struct tcpLstnParams_s {
++	const uchar *pszPort;			/**< the ports the listener shall listen on */
++	const uchar *pszAddr;                 /**< the addrs the listener shall listen on */
++	sbool bSuppOctetFram;	/**< do we support octect-counted framing? (if no->legay only!)*/
++	sbool bSPFramingFix;	/**< support work-around for broken Cisco ASA framing? */
++	const uchar *pszLstnPortFileName;	/**< File in which the dynamic port is written */
++	prop_t *pInputName;
++	ruleset_t *pRuleset;		/**< associated ruleset */
++	uchar dfltTZ[8];		/**< default TZ if none in timestamp; '\0' =No Default */
++};
++
+ /* list of tcp listen ports */
+ struct tcpLstnPortList_s {
+-	uchar *pszPort;			/**< the ports the listener shall listen on */
+-	uchar *pszAddr;                 /**< the addrs the listener shall listen on */
+-	prop_t *pInputName;
++	tcpLstnParams_t *cnf_params;	/**< listener config parameters */
+ 	tcpsrv_t *pSrv;			/**< pointer to higher-level server instance */
+-	ruleset_t *pRuleset;		/**< associated ruleset */
+ 	statsobj_t *stats;		/**< associated stats object */
+-	sbool bSuppOctetFram;	/**< do we support octect-counted framing? (if no->legay only!)*/
+ 	ratelimit_t *ratelimiter;
+-	uchar dfltTZ[8];		/**< default TZ if none in timestamp; '\0' =No Default */
+-	sbool bSPFramingFix;	/**< support work-around for broken Cisco ASA framing? */
+-	const uchar *pszLstnPortFileName;	/**< File in which the dynamic port is written */
+ 	STATSCOUNTER_DEF(ctrSubmit, mutCtrSubmit)
+ 	tcpLstnPortList_t *pNext;	/**< next port or NULL */
+ };
+@@ -130,8 +136,7 @@ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */
+ 	rsRetVal (*Construct)(tcpsrv_t **ppThis);
+ 	rsRetVal (*ConstructFinalize)(tcpsrv_t __attribute__((unused)) *pThis);
+ 	rsRetVal (*Destruct)(tcpsrv_t **ppThis);
+-	rsRetVal (*ATTR_NONNULL(1,2) configureTCPListen)(tcpsrv_t*,
+-		const uchar *pszPort, int bSuppOctetFram, const uchar *pszAddr, const uchar *);
++	rsRetVal (*ATTR_NONNULL(1,2) configureTCPListen)(tcpsrv_t*, tcpLstnParams_t *const cnf_params);
+ 	rsRetVal (*create_tcp_socket)(tcpsrv_t *pThis);
+ 	rsRetVal (*Run)(tcpsrv_t *pThis);
+ 	/* set methods */
+@@ -188,8 +193,6 @@ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */
+ 	rsRetVal (*SetGnutlsPriorityString)(tcpsrv_t*, uchar*);
+ 	/* added v21 -- Preserve case in fromhost, 2018-08-16 */
+ 	rsRetVal (*SetPreserveCase)(tcpsrv_t *pThis, int bPreserveCase);
+-	/* added v22 -- File for dynamic Port, 2018-08-29 */
+-	rsRetVal (*SetLstnPortFileName)(tcpsrv_t*, uchar*);
+ 	/* added v23 -- Options for stricter driver behavior, 2019-08-16 */
+ 	rsRetVal (*SetDrvrCheckExtendedKeyUsage)(tcpsrv_t *pThis, int ChkExtendedKeyUsage);
+ 	rsRetVal (*SetDrvrPrioritizeSAN)(tcpsrv_t *pThis, int prioritizeSan);
+diff --git a/runtime/typedefs.h b/runtime/typedefs.h
+index 06f5c25a8c..000b4da4fe 100644
+--- a/runtime/typedefs.h
++++ b/runtime/typedefs.h
+@@ -123,6 +123,7 @@ typedef int rs_size_t; /* we do never need more than 2Gig strings, signed permit
+ typedef rsRetVal (*prsf_t)(struct vmstk_s*, int);	/* pointer to a RainerScript function */
+ typedef uint64 qDeqID;	/* queue Dequeue order ID. 32 bits is considered dangerously few */
+ 
++typedef struct tcpLstnParams_s tcpLstnParams_t;
+ typedef struct tcpLstnPortList_s tcpLstnPortList_t; // TODO: rename?
+ typedef struct strmLstnPortList_s strmLstnPortList_t; // TODO: rename?
+ typedef struct actWrkrIParams actWrkrIParams_t;
diff --git a/SOURCES/rsyslog-8.2102.0-nsd_ossl-better-logs.patch b/SOURCES/rsyslog-8.2102.0-nsd_ossl-better-logs.patch
new file mode 100644
index 0000000..b45f19a
--- /dev/null
+++ b/SOURCES/rsyslog-8.2102.0-nsd_ossl-better-logs.patch
@@ -0,0 +1,124 @@
+diff --git a/runtime/nsd_ossl.c b/runtime/nsd_ossl.c
+index e55b014b2c..431ea738b8 100644
+--- a/runtime/nsd_ossl.c
++++ b/runtime/nsd_ossl.c
+@@ -210,7 +210,8 @@ void osslLastSSLErrorMsg(int ret, SSL *ssl, int severity, const char* pszCallSou
+ 
+ 	/* Loop through ERR_get_error */
+ 	while ((un_error = ERR_get_error()) > 0){
+-		LogMsg(0, RS_RET_NO_ERRCODE, severity, "OpenSSL Error Stack: %s", ERR_error_string(un_error, NULL) );
++		LogMsg(0, RS_RET_NO_ERRCODE, severity,
++			"nsd_ossl:OpenSSL Error Stack: %s", ERR_error_string(un_error, NULL) );
+ 	}
+ }
+ 
+@@ -721,9 +722,10 @@ osslChkPeerFingerprint(nsd_ossl_t *pThis, X509 *pCert)
+ 		if(pThis->bReportAuthErr == 1) {
+ 			errno = 0;
+ 			LogError(0, RS_RET_INVALID_FINGERPRINT,
+-			"nsd_ossl:error:"
+-			" peer fingerprint '%s' unknown - we are "
+-			"not permitted to talk to it", cstrGetSzStrNoNULL(pstrFingerprint));
++				"nsd_ossl:error: peer fingerprint '%s' unknown - we are "
++				"not permitted to talk to it", cstrGetSzStrNoNULL(pstrFingerprint));
++			LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO,
++				"nsd_ossl:TLS session terminated with remote syslog server.");
+ 			pThis->bReportAuthErr = 0;
+ 		}
+ 		ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT);
+@@ -834,8 +836,10 @@ osslChkPeerName(nsd_ossl_t *pThis, X509 *pCert)
+ 			cstrFinalize(pStr);
+ 			errno = 0;
+ 			LogError(0, RS_RET_INVALID_FINGERPRINT, "nsd_ossl:error: peer name not authorized -  "
+-					"not permitted to talk to it. Names: %s",
+-					cstrGetSzStrNoNULL(pStr));
++				"not permitted to talk to it. Names: %s",
++				cstrGetSzStrNoNULL(pStr));
++			LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO,
++				"nsd_ossl:TLS session terminated with remote syslog server.");
+ 			pThis->bReportAuthErr = 0;
+ 		}
+ 		ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT);
+@@ -871,8 +875,10 @@ osslChkPeerID(nsd_ossl_t *pThis)
+ 		if(pThis->bReportAuthErr == 1) {
+ 			errno = 0;
+ 			LogError(0, RS_RET_TLS_NO_CERT, "nsd_ossl:error: peer did not provide a certificate, "
+-					"not permitted to talk to it");
++				"not permitted to talk to it");
+ 			pThis->bReportAuthErr = 0;
++			LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO,
++				"nsd_ossl:TLS session terminated with remote syslog server.");
+ 		}
+ 		ABORT_FINALIZE(RS_RET_TLS_NO_CERT);
+ 	}
+@@ -905,15 +911,19 @@ osslChkPeerCertValidity(nsd_ossl_t *pThis)
+ 		if (iVerErr == X509_V_ERR_CERT_HAS_EXPIRED) {
+ 			if (pThis->permitExpiredCerts == OSSL_EXPIRED_DENY) {
+ 				LogError(0, RS_RET_CERT_EXPIRED,
+-					"nsd_ossl:CertValidity check"
+-"- not permitted to talk to peer: certificate expired: %s",
++					"nsd_ossl:CertValidity check - not permitted to talk to peer: "
++					"certificate expired: %s",
+ 					X509_verify_cert_error_string(iVerErr));
++				LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO,
++					"nsd_ossl:TLS session terminated with remote syslog server.");
+ 				ABORT_FINALIZE(RS_RET_CERT_EXPIRED);
+ 			} else if (pThis->permitExpiredCerts == OSSL_EXPIRED_WARN) {
+ 				LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING,
+-					"nsd_ossl:CertValidity check"
+-"- warning talking to peer: certificate expired: %s",
++					"nsd_ossl:CertValidity check - warning talking to peer: "
++					"certificate expired: %s",
+ 					X509_verify_cert_error_string(iVerErr));
++				LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO,
++					"nsd_ossl:TLS session terminated with remote syslog server.");
+ 			} else {
+ 				dbgprintf("osslChkPeerCertValidity: talking to peer: certificate expired: %s\n",
+ 					X509_verify_cert_error_string(iVerErr));
+@@ -921,6 +931,8 @@ osslChkPeerCertValidity(nsd_ossl_t *pThis)
+ 		} else {
+ 			LogError(0, RS_RET_CERT_INVALID, "nsd_ossl:not permitted to talk to peer: "
+ 				"certificate validation failed: %s", X509_verify_cert_error_string(iVerErr));
++			LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO,
++				"nsd_ossl:TLS session terminated with remote syslog server.");
+ 			ABORT_FINALIZE(RS_RET_CERT_INVALID);
+ 		}
+ 	} else {
+@@ -1384,7 +1396,7 @@ osslPostHandshakeCheck(nsd_ossl_t *pNsd)
+ 	#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ 	if(SSL_get_shared_curve(pNsd->ssl, -1) == 0) {
+ 		LogError(0, RS_RET_NO_ERRCODE, "nsd_ossl:"
+-"No shared curve between syslog client and server.");
++		"No shared curve between syslog client and server.");
+ 	}
+ 	#endif
+ 	sslCipher = (const SSL_CIPHER*) SSL_get_current_cipher(pNsd->ssl);
+@@ -1446,8 +1458,6 @@ osslHandshakeCheck(nsd_ossl_t *pNsd)
+ 				resErr == SSL_ERROR_WANT_WRITE) {
+ 				pNsd->rtryCall = osslRtry_handshake;
+ 				pNsd->rtryOsslErr = resErr; /* Store SSL ErrorCode into*/
+-				LogError(0, RS_RET_NO_ERRCODE, "nsd_ossl:"
+-"TLS handshake failed between syslog client and server.");
+ 				dbgprintf("osslHandshakeCheck: OpenSSL Client handshake does not complete "
+ 					"immediately - setting to retry (this is OK and normal)\n");
+ 				FINALIZE;
+@@ -1458,6 +1468,8 @@ osslHandshakeCheck(nsd_ossl_t *pNsd)
+ 				ABORT_FINALIZE(RS_RET_NO_ERRCODE /*RS_RET_RETRY*/);
+ 			} else {
+ 				osslLastSSLErrorMsg(res, pNsd->ssl, LOG_ERR, "osslHandshakeCheck Client");
++				LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO,
++					"nsd_ossl:TLS session terminated with remote syslog server.");
+ 				ABORT_FINALIZE(RS_RET_NO_ERRCODE);
+ 			}
+ 		}
+@@ -1738,8 +1750,8 @@ Connect(nsd_t *pNsd, int family, uchar *port, uchar *host, char *device)
+ 	conn = BIO_new_socket(pPtcp->sock, BIO_CLOSE /*BIO_NOCLOSE*/);
+ 	dbgprintf("Connect: Init conn BIO[%p] done\n", (void *)conn);
+ 
+-	LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "nsd_ossl:"
+-"TLS Connection initiated with remote syslog server.");
++	LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "nsd_ossl: "
++		"TLS Connection initiated with remote syslog server.");
+ 	/*if we reach this point we are in tls mode */
+ 	DBGPRINTF("Connect: TLS Mode\n");
+ 	if(!(pThis->ssl = SSL_new(ctx))) {
diff --git a/SOURCES/rsyslog-8.2102.0-nsd_ossl-memory-leak.patch b/SOURCES/rsyslog-8.2102.0-nsd_ossl-memory-leak.patch
new file mode 100644
index 0000000..7b75773
--- /dev/null
+++ b/SOURCES/rsyslog-8.2102.0-nsd_ossl-memory-leak.patch
@@ -0,0 +1,25 @@
+diff --git a/runtime/nsd_ossl.c b/runtime/nsd_ossl.c
+index 79347916e4..69ec57af09 100644
+--- a/runtime/nsd_ossl.c
++++ b/runtime/nsd_ossl.c
+@@ -1821,11 +1821,8 @@ BIO_set_nbio( conn, 1 );
+ }
+ 
+ 
+-/* Empty wrapper for GNUTLS helper function
+- * TODO: implement a similar capability
+- */
+ static rsRetVal
+-SetGnutlsPriorityString(__attribute__((unused)) nsd_t *pNsd, __attribute__((unused)) uchar *gnutlsPriorityString)
++SetGnutlsPriorityString(nsd_t *const pNsd, uchar *const gnutlsPriorityString)
+ {
+ 	DEFiRet;
+ 	nsd_ossl_t* pThis = (nsd_ossl_t*) pNsd;
+@@ -1905,6 +1902,7 @@ SetGnutlsPriorityString(__attribute__((unused)) nsd_t *pNsd, __attribute__((unus
+ 						pThis->gnutlsPriorityString);
+ 				osslLastSSLErrorMsg(0, NULL, LOG_ERR, "SetGnutlsPriorityString");
+ 			}
++			SSL_CONF_CTX_free(cctx);
+ 		}
+ #else
+ 		dbgprintf("gnutlsPriorityString: set to '%s'\n", gnutlsPriorityString);
diff --git a/SOURCES/rsyslog-8.2102.0-rhbz1909639-statefiles-doc.patch b/SOURCES/rsyslog-8.2102.0-rhbz1909639-statefiles-doc.patch
new file mode 100644
index 0000000..b717972
--- /dev/null
+++ b/SOURCES/rsyslog-8.2102.0-rhbz1909639-statefiles-doc.patch
@@ -0,0 +1,47 @@
+diff -up rsyslog-8.2102.0/doc/configuration/modules/imfile.html.state-file-leaking-doc rsyslog-8.2102.0/doc/configuration/modules/imfile.html
+--- rsyslog-8.2102.0/doc/configuration/modules/imfile.html.state-file-leaking-doc	2021-02-15 12:53:31.000000000 +0100
++++ rsyslog-8.2102.0/doc/configuration/modules/imfile.html	2022-03-29 10:35:07.187827004 +0200
+@@ -294,6 +294,28 @@ rsyslog needs write permissions to work
+ also might require SELinux definitions (or similar for other enhanced security
+ systems).</p>
+ </div>
++<div class="section" id="deletestateonfilemove">
++<h4>deleteStateOnFileMove<a class="headerlink" href="#deletestateonfilemove" title="Permalink to this headline">¶</a></h4>
++<table border="1" class="colwidths-auto parameter-table docutils">
++<thead valign="bottom">
++<tr class="row-odd"><th class="head">type</th>
++<th class="head">default</th>
++<th class="head">mandatory</th>
++<th class="head"><code class="docutils literal notranslate"><span class="pre">obsolete</span> <span class="pre">legacy</span></code> directive</th>
++</tr>
++</thead>
++<tbody valign="top">
++<tr class="row-even"><td>binary</td>
++<td>off</td>
++<td>no</td>
++<td>none</td>
++</tr>
++</tbody>
++</table>
++<p>This parameter controls if state files are deleted if their associated main file is rotated via move. Usually, this is a good idea, because otherwise state files are not deleted when log rotation occurs.</p>
++
++<p>However, there is one situation where not deleting associated state file after log rotation makes sense: this is the case if a monitored file is later moved back to the same location as it was before.</p>
++</div>
+ </div>
+ <div class="section" id="input-parameters">
+ <h3>Input Parameters<a class="headerlink" href="#input-parameters" title="Permalink to this headline">¶</a></h3>
+@@ -1214,6 +1236,7 @@ and Others.</p>
+ <li><a class="reference internal" href="#sortfiles">sortFiles</a></li>
+ <li><a class="reference internal" href="#pollinginterval">PollingInterval</a></li>
+ <li><a class="reference internal" href="#statefile-directory">statefile.directory</a></li>
++<li><a class="reference internal" href="#deletestateonfilemove">deleteStateOnFileMove</a></li>
+ </ul>
+ </li>
+ <li><a class="reference internal" href="#input-parameters">Input Parameters</a><ul>
+@@ -1311,4 +1334,4 @@ and Others.</p>
+     <div class="footer" role="contentinfo">
+     </div>
+   </body>
+-</html>
+\ No newline at end of file
++</html>
diff --git a/SOURCES/rsyslog-8.2102.0-rhbz1909639-statefiles-fix.patch b/SOURCES/rsyslog-8.2102.0-rhbz1909639-statefiles-fix.patch
new file mode 100644
index 0000000..161f90c
--- /dev/null
+++ b/SOURCES/rsyslog-8.2102.0-rhbz1909639-statefiles-fix.patch
@@ -0,0 +1,162 @@
+diff -up rsyslog-8.2102.0/plugins/imfile/imfile.c.state-file-leaking rsyslog-8.2102.0/plugins/imfile/imfile.c
+--- rsyslog-8.2102.0/plugins/imfile/imfile.c.state-file-leaking	2021-01-18 11:21:14.000000000 +0100
++++ rsyslog-8.2102.0/plugins/imfile/imfile.c	2022-03-28 12:51:03.572554843 +0200
+@@ -259,6 +259,7 @@ struct modConfData_s {
+ 				   Must be manually reset to 0 if desired. Helper for
+ 				   polling mode.
+ 				 */
++	sbool deleteStateOnFileMove;
+ };
+ static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */
+ static modConfData_t *runModConf = NULL;/* modConf ptr to use for run process */
+@@ -305,7 +306,8 @@ static struct cnfparamdescr modpdescr[]
+ 	{ "sortfiles", eCmdHdlrBinary, 0 },
+ 	{ "statefile.directory", eCmdHdlrString, 0 },
+ 	{ "normalizepath", eCmdHdlrBinary, 0 },
+-	{ "mode", eCmdHdlrGetWord, 0 }
++	{ "mode", eCmdHdlrGetWord, 0 },
++	{ "deletestateonfilemove", eCmdHdlrBinary, 0 }
+ };
+ static struct cnfparamblk modpblk =
+ 	{ CNFPARAMBLK_VERSION,
+@@ -545,11 +547,20 @@ static int
+ in_setupWatch(act_obj_t *const act, const int is_file)
+ {
+ 	int wd = -1;
++	int flags;
+ 	if(runModConf->opMode != OPMODE_INOTIFY)
+ 		goto done;
+ 
+-	wd = inotify_add_watch(ino_fd, act->name,
+-		(is_file) ? IN_MODIFY|IN_DONT_FOLLOW : IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO);
++	// wd = inotify_add_watch(ino_fd, act->name,
++	// 	(is_file) ? IN_MODIFY|IN_DONT_FOLLOW : IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO);
++	if(is_file)
++		flags = IN_MODIFY|IN_DONT_FOLLOW;
++	else if(runModConf->deleteStateOnFileMove)
++		flags = IN_CREATE|IN_DELETE|IN_MOVED_TO;
++	else
++		flags = IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO;
++	wd = inotify_add_watch(ino_fd, act->name, flags);
++
+ 	if(wd < 0) {
+ 		if (errno == EACCES) { /* There is high probability of selinux denial on top-level paths */
+ 			DBGPRINTF("imfile: permission denied when adding watch for '%s'\n", act->name);
+@@ -713,7 +724,7 @@ act_obj_add(fs_edge_t *const edge, const
+ 	char basename[MAXFNAME];
+ 	DEFiRet;
+ 	int fd = -1;
+-	
++
+ 	DBGPRINTF("act_obj_add: edge %p, name '%s' (source '%s')\n", edge, name, source? source : "---");
+ 	for(act = edge->active ; act != NULL ; act = act->next) {
+ 		if(!strcmp(act->name, name)) {
+@@ -977,9 +988,18 @@ act_obj_destroy(act_obj_t *const act, co
+ 	if(act == NULL)
+ 		return;
+ 
+-	DBGPRINTF("act_obj_destroy: act %p '%s' (source '%s'), wd %d, pStrm %p, is_deleted %d, in_move %d\n",
+-		act, act->name, act->source_name? act->source_name : "---", act->wd, act->pStrm, is_deleted,
+-		act->in_move);
++	// DBGPRINTF("act_obj_destroy: act %p '%s' (source '%s'), wd %d, pStrm %p, is_deleted %d, in_move %d\n",
++	// 	act, act->name, act->source_name? act->source_name : "---", act->wd, act->pStrm, is_deleted,
++	// 	act->in_move);
++	if (runModConf->deleteStateOnFileMove) {
++		DBGPRINTF("act_obj_destroy: act %p '%s' (source '%s'), wd %d, pStrm %p, is_deleted %d\n",
++			act, act->name, act->source_name? act->source_name : "---", act->wd, act->pStrm, is_deleted);
++	} else {
++		DBGPRINTF("act_obj_destroy: act %p '%s' (source '%s'), wd %d, pStrm %p, is_deleted %d, in_move %d\n",
++			act, act->name, act->source_name? act->source_name : "---", act->wd, act->pStrm,
++			is_deleted, act->in_move);
++	}
++
+ 	if(act->is_symlink && is_deleted) {
+ 		act_obj_t *target_act;
+ 		for(target_act = act->edge->active ; target_act != NULL ; target_act = target_act->next) {
+@@ -996,13 +1016,15 @@ act_obj_destroy(act_obj_t *const act, co
+ 		pollFile(act); /* get any left-over data */
+ 		if(inst->bRMStateOnDel) {
+ 			statefn = getStateFileName(act, statefile, sizeof(statefile));
+-			getFullStateFileName(statefn, "", toDel, sizeof(toDel)); // TODO: check!
++			// getFullStateFileName(statefn, "", toDel, sizeof(toDel)); // TODO: check!
++			getFullStateFileName(statefn, act->file_id, toDel, sizeof(toDel)); // TODO: check!
+ 			statefn = toDel;
+ 		}
+ 		persistStrmState(act);
+ 		strm.Destruct(&act->pStrm);
+ 		/* we delete state file after destruct in case strm obj initiated a write */
+-		if(is_deleted && !act->in_move && inst->bRMStateOnDel) {
++		// if(is_deleted && !act->in_move && inst->bRMStateOnDel) {
++		if(is_deleted && inst->bRMStateOnDel && (runModConf->deleteStateOnFileMove || !act->in_move)) {
+ 			DBGPRINTF("act_obj_destroy: deleting state file %s\n", statefn);
+ 			unlink((char*)statefn);
+ 		}
+@@ -1012,6 +1034,7 @@ act_obj_destroy(act_obj_t *const act, co
+ 	}
+ 	#ifdef HAVE_INOTIFY_INIT
+ 	if(act->wd != -1) {
++		inotify_rm_watch(ino_fd, act->wd);
+ 		wdmapDel(act->wd);
+ 	}
+ 	#endif
+@@ -2026,6 +2049,7 @@ CODESTARTbeginCnfLoad
+ 	loadModConf->timeoutGranularity = 1000; /* default: 1 second */
+ 	loadModConf->haveReadTimeouts = 0; /* default: no timeout */
+ 	loadModConf->normalizePath = 1;
++	loadModConf->deleteStateOnFileMove = 0;
+ 	loadModConf->sortFiles = GLOB_NOSORT;
+ 	loadModConf->stateFileDirectory = NULL;
+ 	loadModConf->conf_tree = calloc(sizeof(fs_node_t), 1);
+@@ -2085,6 +2109,8 @@ CODESTARTsetModCnf
+ 			loadModConf->stateFileDirectory = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ 		} else if(!strcmp(modpblk.descr[i].name, "normalizepath")) {
+ 			loadModConf->normalizePath = (sbool) pvals[i].val.d.n;
++		} else if(!strcmp(modpblk.descr[i].name, "deletestateonfilemove")) {
++			loadModConf->deleteStateOnFileMove = (sbool) pvals[i].val.d.n;
+ 		} else if(!strcmp(modpblk.descr[i].name, "mode")) {
+ 			if(!es_strconstcmp(pvals[i].val.d.estr, "polling"))
+ 				loadModConf->opMode = OPMODE_POLLING;
+@@ -2388,16 +2414,35 @@ in_processEvent(struct inotify_event *ev
+ 	DBGPRINTF("in_processEvent process Event %x is_file %d, act->name '%s'\n",
+ 		ev->mask, etry->act->edge->is_file, etry->act->name);
+ 
+-	if((ev->mask & IN_MOVED_FROM)) {
+-		flag_in_move(etry->act->edge->node->edges, ev->name);
+-	}
+-	if(ev->mask & (IN_MOVED_FROM | IN_MOVED_TO))  {
+-		fs_node_walk(etry->act->edge->node, poll_tree);
+-	} else if(etry->act->edge->is_file && !(etry->act->is_symlink)) {
+-		in_handleFileEvent(ev, etry); // esentially poll_file()!
++	// if((ev->mask & IN_MOVED_FROM)) {
++	// 	flag_in_move(etry->act->edge->node->edges, ev->name);
++	// }
++	// if(ev->mask & (IN_MOVED_FROM | IN_MOVED_TO))  {
++	// 	fs_node_walk(etry->act->edge->node, poll_tree);
++	// } else if(etry->act->edge->is_file && !(etry->act->is_symlink)) {
++	// 	in_handleFileEvent(ev, etry); // esentially poll_file()!
++	// } else {
++	// 	fs_node_walk(etry->act->edge->node, poll_tree);
++	// }
++	if(!runModConf->deleteStateOnFileMove) {
++		if((ev->mask & IN_MOVED_FROM)) {
++			flag_in_move(etry->act->edge->node->edges, ev->name);
++		}
++		if(ev->mask & (IN_MOVED_FROM | IN_MOVED_TO))  {
++			fs_node_walk(etry->act->edge->node, poll_tree);
++		} else if(etry->act->edge->is_file && !(etry->act->is_symlink)) {
++			in_handleFileEvent(ev, etry); // esentially poll_file()!
++		} else {
++			fs_node_walk(etry->act->edge->node, poll_tree);
++		}
+ 	} else {
+-		fs_node_walk(etry->act->edge->node, poll_tree);
++		if((ev->mask & IN_MODIFY) && etry->act->edge->is_file && !(etry->act->is_symlink)) {
++			in_handleFileEvent(ev, etry); // esentially poll_file()!
++		} else {
++			fs_node_walk(etry->act->edge->node, poll_tree);
++		}
+ 	}
++
+ done:	return;
+ }
+ 
diff --git a/SOURCES/rsyslog-8.2102.0-rhbz1962318-errfile-maxsize.patch b/SOURCES/rsyslog-8.2102.0-rhbz1962318-errfile-maxsize.patch
new file mode 100644
index 0000000..912a8b1
--- /dev/null
+++ b/SOURCES/rsyslog-8.2102.0-rhbz1962318-errfile-maxsize.patch
@@ -0,0 +1,190 @@
+--- rsyslog-8.2102.0/action.c	2021-02-15 12:06:16.000000000 +0100
++++ rsyslog-8.2102.0-changes/action.c	2022-03-08 15:55:33.989525382 +0100
+@@ -198,6 +198,7 @@
+ 	{ "name", eCmdHdlrGetWord, 0 }, /* legacy: actionname */
+ 	{ "type", eCmdHdlrString, CNFPARAM_REQUIRED }, /* legacy: actionname */
+ 	{ "action.errorfile", eCmdHdlrString, 0 },
++	{ "action.errorfile.maxsize", eCmdHdlrInt, 0 },
+ 	{ "action.writeallmarkmessages", eCmdHdlrBinary, 0 }, /* legacy: actionwriteallmarkmessages */
+ 	{ "action.execonlyeverynthtime", eCmdHdlrInt, 0 }, /* legacy: actionexeconlyeverynthtime */
+ 	{ "action.execonlyeverynthtimetimeout", eCmdHdlrInt, 0 }, /* legacy: actionexeconlyeverynthtimetimeout */
+@@ -400,6 +401,8 @@
+ 	pThis->iResumeRetryCount = 0;
+ 	pThis->pszName = NULL;
+ 	pThis->pszErrFile = NULL;
++	pThis->maxErrFileSize = 0;
++	pThis->errFileWritten = 0;	
+ 	pThis->pszExternalStateFile = NULL;
+ 	pThis->fdErrFile = -1;
+ 	pThis->bWriteAllMarkMsgs = 1;
+@@ -1436,6 +1439,12 @@
+ 				pThis->pszName, pThis->pszErrFile);
+ 			goto done;
+ 		}
++		struct stat statbuf;
++		if (fstat(pThis->fdErrFile, &statbuf) == -1) {
++			LogError(errno, RS_RET_ERR, "failed to fstat %s", pThis->pszErrFile);
++			goto done;
++		}
++		pThis->errFileWritten += statbuf.st_size;
+ 	}
+ 
+ 	for(int i = 0 ; i < nparams ; ++i) {
+@@ -1454,16 +1463,26 @@
+ 		char *const rendered = strdup((char*)fjson_object_to_json_string(etry));
+ 		if(rendered == NULL)
+ 			goto done;
+-		const size_t toWrite = strlen(rendered) + 1;
+-		/* note: we use the '\0' inside the string to store a LF - we do not
+-		 * otherwise need it and it safes us a copy/realloc.
+-		 */
+-		rendered[toWrite-1] = '\n'; /* NO LONGER A STRING! */
+-		const ssize_t wrRet = write(pThis->fdErrFile, rendered, toWrite);
+-		if(wrRet != (ssize_t) toWrite) {
+-			LogError(errno, RS_RET_IO_ERROR,
+-				"action %s: error writing errorFile %s, write returned %lld",
+-				pThis->pszName, pThis->pszErrFile, (long long) wrRet);
++		size_t toWrite = strlen(rendered) + 1;
++		// Check if need to truncate the amount of bytes to write
++		if (pThis->maxErrFileSize > 0) {
++			if (pThis->errFileWritten + toWrite > pThis->maxErrFileSize) {
++				// Truncate to the pending available
++				toWrite = pThis->maxErrFileSize - pThis->errFileWritten;
++			}
++			pThis->errFileWritten += toWrite;
++		}
++		if(toWrite > 0) {
++			/* note: we use the '\0' inside the string to store a LF - we do not
++			 * otherwise need it and it safes us a copy/realloc.
++			 */
++			rendered[toWrite-1] = '\n'; /* NO LONGER A STRING! */
++			const ssize_t wrRet = write(pThis->fdErrFile, rendered, toWrite);
++			if(wrRet != (ssize_t) toWrite) {
++				LogError(errno, RS_RET_IO_ERROR,
++					"action %s: error writing errorFile %s, write returned %lld",
++					pThis->pszName, pThis->pszErrFile, (long long) wrRet);
++			}
+ 		}
+ 		free(rendered);
+ 
+@@ -2048,6 +2067,8 @@
+ 			continue; /* this is handled seperately during module select! */
+ 		} else if(!strcmp(pblk.descr[i].name, "action.errorfile")) {
+ 			pAction->pszErrFile = es_str2cstr(pvals[i].val.d.estr, NULL);
++		} else if(!strcmp(pblk.descr[i].name, "action.errorfile.maxsize")) {
++			pAction->maxErrFileSize = pvals[i].val.d.n;
+ 		} else if(!strcmp(pblk.descr[i].name, "action.externalstate.file")) {
+ 			pAction->pszExternalStateFile = es_str2cstr(pvals[i].val.d.estr, NULL);
+ 		} else if(!strcmp(pblk.descr[i].name, "action.writeallmarkmessages")) {
+--- rsyslog-8.2102.0-ori/action.h	2020-10-03 19:06:47.000000000 +0200
++++ rsyslog-8.2102.0-changes/action.h	2022-03-04 11:36:47.024588972 +0100
+@@ -77,6 +77,8 @@
+ 	/* error file */
+ 	const char *pszErrFile;
+ 	int fdErrFile;
++	size_t maxErrFileSize;
++	size_t errFileWritten;
+ 	pthread_mutex_t mutErrFile;
+ 	/* external stat file system */
+ 	const char *pszExternalStateFile;
+--- rsyslog-8.2102.0-ori/tests/Makefile.am	2021-02-15 12:06:16.000000000 +0100
++++ rsyslog-8.2102.0-changes/tests/Makefile.am	2022-03-04 11:38:01.625095709 +0100
+@@ -695,7 +695,8 @@
+ 	mysql-actq-mt.sh \
+ 	mysql-actq-mt-withpause.sh \
+ 	action-tx-single-processing.sh \
+-	action-tx-errfile.sh
++	action-tx-errfile.sh \
++	action-tx-errfile-maxsize.sh
+ 
+ mysql-basic.log: mysqld-start.log
+ mysql-basic-cnf6.log: mysqld-start.log
+@@ -2156,6 +2157,8 @@
+ 	sndrcv_omudpspoof_nonstdpt.sh \
+ 	sndrcv_gzip.sh \
+ 	action-tx-single-processing.sh \
++	omfwd-errfile-maxsize.sh \
++	action-tx-errfile-maxsize.sh \
+ 	action-tx-errfile.sh \
+ 	testsuites/action-tx-errfile.result \
+ 	pipeaction.sh \
+--- rsyslog-8.2102.0-ori/tests/omfwd-errfile-maxsize.sh	1970-01-01 01:00:00.000000000 +0100
++++ rsyslog-8.2102.0-changes/tests/omfwd-errfile-maxsize.sh	2022-03-04 11:39:02.060506234 +0100
+@@ -0,0 +1,17 @@
++#!/bin/bash
++# part of the rsyslog project, released under ASL 2.0
++. ${srcdir:=.}/diag.sh init
++
++export MAX_ERROR_SIZE=1999
++
++generate_conf
++add_conf '
++action(type="omfwd" target="1.2.3.4" port="1234" Protocol="tcp" NetworkNamespace="doesNotExist"
++       action.errorfile="'$RSYSLOG2_OUT_LOG'" action.errorfile.maxsize="'$MAX_ERROR_SIZE'")
++'
++startup
++shutdown_when_empty
++wait_shutdown
++check_file_exists ${RSYSLOG2_OUT_LOG}
++file_size_check ${RSYSLOG2_OUT_LOG} ${MAX_ERROR_SIZE}
++exit_test
+--- rsyslog-8.2102.0-ori/tests/action-tx-errfile-maxsize.sh	1970-01-01 01:00:00.000000000 +0100
++++ rsyslog-8.2102.0-changes/tests/action-tx-errfile-maxsize.sh	2022-03-04 11:59:22.592796989 +0100
+@@ -0,0 +1,35 @@
++#!/bin/bash
++# part of the rsyslog project, released under ASL 2.0
++
++. ${srcdir:=.}/diag.sh init
++
++export NUMMESSAGES=50 # enough to generate big file
++export MAX_ERROR_SIZE=100
++
++generate_conf
++add_conf '
++$ModLoad ../plugins/ommysql/.libs/ommysql
++global(errormessagestostderr.maxnumber="5")
++
++template(type="string" name="tpl" string="insert into SystemEvents (Message, Facility) values (\"%msg%\", %$!facility%)" option.sql="on")
++
++if((not($msg contains "error")) and ($msg contains "msgnum:")) then {
++	set $.num = field($msg, 58, 2);
++	if $.num % 2 == 0 then {
++		set $!facility = $syslogfacility;
++	} else {
++		set $/cntr = 0;
++	}
++	action(type="ommysql" name="mysql_action_errfile_maxsize" server="127.0.0.1" template="tpl"
++	       db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench" action.errorfile="'$RSYSLOG2_OUT_LOG'" action.errorfile.maxsize="'$MAX_ERROR_SIZE'")
++}
++'
++mysql_prep_for_test
++startup
++injectmsg
++shutdown_when_empty
++wait_shutdown
++mysql_get_data
++check_file_exists ${RSYSLOG2_OUT_LOG}
++file_size_check ${RSYSLOG2_OUT_LOG} ${MAX_ERROR_SIZE}
++exit_test
+--- rsyslog-8.2102.0/tests/omfwd-errfile-maxsize-filled.sh	1970-01-01 01:00:00.000000000 +0100
++++ rsyslog-8.2102.0-changes/tests/omfwd-errfile-maxsize-filled.sh	2022-03-08 16:24:01.174365289 +0100
+@@ -0,0 +1,19 @@
++#!/bin/bash
++# part of the rsyslog project, released under ASL 2.0
++. ${srcdir:=.}/diag.sh init
++ERRFILE=$(mktemp)
++export MAX_ERROR_SIZE=1999
++export INITIAL_FILE_SIZE=$((MAX_ERROR_SIZE - 100))
++dd if=/dev/urandom of=${ERRFILE}  bs=1 count=${INITIAL_FILE_SIZE}
++generate_conf
++add_conf '
++action(type="omfwd" target="1.2.3.4" port="1234" Protocol="tcp" NetworkNamespace="doesNotExist"
++       action.errorfile="'$ERRFILE'" action.errorfile.maxsize="'$MAX_ERROR_SIZE'")
++'
++startup
++shutdown_when_empty
++wait_shutdown
++check_file_exists ${ERRFILE}
++file_size_check ${ERRFILE} ${MAX_ERROR_SIZE}
++exit_test
++rm ${ERRFILE}
diff --git a/SOURCES/rsyslog-8.2102.0-rhbz2046158-correct-custom-ciphers-behaviour.patch b/SOURCES/rsyslog-8.2102.0-rhbz2046158-correct-custom-ciphers-behaviour.patch
new file mode 100644
index 0000000..e98ead2
--- /dev/null
+++ b/SOURCES/rsyslog-8.2102.0-rhbz2046158-correct-custom-ciphers-behaviour.patch
@@ -0,0 +1,354 @@
+diff -up rsyslog-8.2102.0/runtime/nsd_ossl.c.orig rsyslog-8.2102.0/runtime/nsd_ossl.c
+--- rsyslog-8.2102.0/runtime/nsd_ossl.c.orig	2022-04-15 13:42:05.320615894 +0200
++++ rsyslog-8.2102.0/runtime/nsd_ossl.c	2022-04-15 14:33:43.472482696 +0200
+@@ -609,10 +609,10 @@ finalize_it:
+ }
+ 
+ static rsRetVal
+-osslInitSession(nsd_ossl_t *pThis) /* , nsd_ossl_t *pServer) */
++osslInitSession(nsd_ossl_t *pThis, osslSslState_t osslType) /* , nsd_ossl_t *pServer) */
+ {
+ 	DEFiRet;
+-	BIO *client;
++	BIO *conn;
+ 	char pristringBuf[4096];
+ 	nsd_ptcp_t *pPtcp = (nsd_ptcp_t*) pThis->pTcp;
+ 
+@@ -633,10 +633,8 @@ osslInitSession(nsd_ossl_t *pThis) /* ,
+ 		if (pThis->DrvrVerifyDepth != 0) {
+ 			SSL_set_verify_depth(pThis->ssl, pThis->DrvrVerifyDepth);
+ 		}
+-	}
+-
+-	if (bAnonInit == 1) { /* no mutex needed, read-only after init */
+-		/* Allow ANON Ciphers */
++	} else 	if (bAnonInit == 1 && pThis->gnutlsPriorityString == NULL) {
++		/* Allow ANON Ciphers only in ANON Mode and if no custom priority string is defined */
+ 		#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ 		 /* NOTE: do never use: +eNULL, it DISABLES encryption! */
+ 		strncpy(pristringBuf, "ALL:+COMPLEMENTOFDEFAULT:+ADH:+ECDH:+aNULL@SECLEVEL=0",
+@@ -653,21 +651,28 @@ osslInitSession(nsd_ossl_t *pThis) /* ,
+ 		}
+ 	}
+ 
+-	/* Create BIO from ptcp socket! */
+-	client = BIO_new_socket(pPtcp->sock, BIO_CLOSE /*BIO_NOCLOSE*/);
+-	dbgprintf("osslInitSession: Init client BIO[%p] done\n", (void *)client);
+ 
+-	/* Set debug Callback for client BIO as well! */
+-	BIO_set_callback(client, BIO_debug_callback);
++	/* Create BIO from ptcp socket! */
++	conn = BIO_new_socket(pPtcp->sock, BIO_CLOSE /*BIO_NOCLOSE*/);
++	dbgprintf("osslInitSession: Init conn BIO[%p] done\n", (void *)conn);
+ 
+-/* TODO: still needed? Set to NON blocking ! */
+-BIO_set_nbio( client, 1 );
++	/* Set debug Callback for conn BIO as well! */
++	BIO_set_callback(conn, BIO_debug_callback);
+ 
+-	SSL_set_bio(pThis->ssl, client, client);
+-	SSL_set_accept_state(pThis->ssl); /* sets ssl to work in server mode. */
++	/* TODO: still needed? Set to NON blocking ! */
++	BIO_set_nbio( conn, 1 );
++	SSL_set_bio(pThis->ssl, conn, conn);
+ 
++	if (osslType == osslServer) {
++		/* Server Socket */
++		SSL_set_accept_state(pThis->ssl); /* sets ssl to work in server mode. */
++		pThis->sslState = osslServer; /*set Server state */
++	} else {
++		/* Client Socket */
++		SSL_set_connect_state(pThis->ssl); /*sets ssl to work in client mode.*/
++		pThis->sslState = osslClient; /*set Client state */
++	}
+ 	pThis->bHaveSess = 1;
+-	pThis->sslState = osslServer; /*set Server state */
+ 
+ 	/* we are done */
+ 	FINALIZE;
+@@ -1136,8 +1141,8 @@ SetAuthMode(nsd_t *const pNsd, uchar *co
+ 		ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED);
+ 	}
+ 
+-		/* Init Anon OpenSSL stuff */
+-		CHKiRet(osslAnonInit());
++	/* Init Anon OpenSSL stuff */
++	CHKiRet(osslAnonInit());
+ 
+ 	dbgprintf("SetAuthMode: Set Mode %s/%d\n", mode, pThis->authMode);
+ 
+@@ -1394,8 +1399,9 @@ osslPostHandshakeCheck(nsd_ossl_t *pNsd)
+ 
+ 	#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ 	if(SSL_get_shared_curve(pNsd->ssl, -1) == 0) {
+-		LogError(0, RS_RET_NO_ERRCODE, "nsd_ossl:"
+-		"No shared curve between syslog client and server.");
++		// This is not a failure
++		LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "nsd_ossl: "
++		"Information, no shared curve between syslog client and server");
+ 	}
+ 	#endif
+ 	sslCipher = (const SSL_CIPHER*) SSL_get_current_cipher(pNsd->ssl);
+@@ -1518,7 +1524,7 @@ AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew
+ 	pNew->permitExpiredCerts = pThis->permitExpiredCerts;
+ 	pNew->pPermPeers = pThis->pPermPeers;
+ 	pNew->DrvrVerifyDepth = pThis->DrvrVerifyDepth;
+-	CHKiRet(osslInitSession(pNew));
++	CHKiRet(osslInitSession(pNew, osslServer));
+ 
+ 	/* Store nsd_ossl_t* reference in SSL obj */
+ 	SSL_set_ex_data(pNew->ssl, 0, pThis);
+@@ -1729,9 +1735,6 @@ Connect(nsd_t *pNsd, int family, uchar *
+ 	DEFiRet;
+ 	DBGPRINTF("openssl: entering Connect family=%d, device=%s\n", family, device);
+ 	nsd_ossl_t* pThis = (nsd_ossl_t*) pNsd;
+-	nsd_ptcp_t* pPtcp = (nsd_ptcp_t*) pThis->pTcp;
+-	BIO *conn;
+-	char pristringBuf[4096];
+ 
+ 	ISOBJ_TYPE_assert(pThis, nsd_ossl);
+ 	assert(port != NULL);
+@@ -1745,61 +1748,13 @@ Connect(nsd_t *pNsd, int family, uchar *
+ 		FINALIZE;
+ 	}
+ 
+-	/* Create BIO from ptcp socket! */
+-	conn = BIO_new_socket(pPtcp->sock, BIO_CLOSE /*BIO_NOCLOSE*/);
+-	dbgprintf("Connect: Init conn BIO[%p] done\n", (void *)conn);
+-
+ 	LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "nsd_ossl: "
+ 		"TLS Connection initiated with remote syslog server.");
+ 	/*if we reach this point we are in tls mode */
+ 	DBGPRINTF("Connect: TLS Mode\n");
+-	if(!(pThis->ssl = SSL_new(ctx))) {
+-		pThis->ssl = NULL;
+-		osslLastSSLErrorMsg(0, pThis->ssl, LOG_ERR, "Connect");
+-		ABORT_FINALIZE(RS_RET_NO_ERRCODE);
+-	}
+ 
+-	// Set SSL_MODE_AUTO_RETRY to SSL obj
+-	SSL_set_mode(pThis->ssl, SSL_MODE_AUTO_RETRY);
+-
+-	if (pThis->authMode != OSSL_AUTH_CERTANON) {
+-		dbgprintf("Connect: enable certificate checking (Mode=%d, VerifyDepth=%d)\n",
+-			pThis->authMode, pThis->DrvrVerifyDepth);
+-		/* Enable certificate valid checking */
+-		SSL_set_verify(pThis->ssl, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback);
+-		if (pThis->DrvrVerifyDepth != 0) {
+-			SSL_set_verify_depth(pThis->ssl, pThis->DrvrVerifyDepth);
+-		}
+-	}
+-
+-	if (bAnonInit == 1) { /* no mutex needed, read-only after init */
+-		/* Allow ANON Ciphers */
+-		#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+-		 /* NOTE: do never use: +eNULL, it DISABLES encryption! */
+-		strncpy(pristringBuf, "ALL:+COMPLEMENTOFDEFAULT:+ADH:+ECDH:+aNULL@SECLEVEL=0",
+-			sizeof(pristringBuf));
+-		#else
+-		strncpy(pristringBuf, "ALL:+COMPLEMENTOFDEFAULT:+ADH:+ECDH:+aNULL",
+-			sizeof(pristringBuf));
+-		#endif
+-
+-		dbgprintf("Connect: setting anon ciphers: %s\n", pristringBuf);
+-		if ( SSL_set_cipher_list(pThis->ssl, pristringBuf) == 0 ){
+-			dbgprintf("Connect: Error setting ciphers '%s'\n", pristringBuf);
+-			ABORT_FINALIZE(RS_RET_SYS_ERR);
+-		}
+-	}
+-
+-	/* Set debug Callback for client BIO as well! */
+-	BIO_set_callback(conn, BIO_debug_callback);
+-
+-/* TODO: still needed? Set to NON blocking ! */
+-BIO_set_nbio( conn, 1 );
+-
+-	SSL_set_bio(pThis->ssl, conn, conn);
+-	SSL_set_connect_state(pThis->ssl); /*sets ssl to work in client mode.*/
+-	pThis->sslState = osslClient; /*set Client state */
+-	pThis->bHaveSess = 1;
++	/* Do SSL Session init */
++	CHKiRet(osslInitSession(pThis, osslClient));
+ 
+ 	/* Store nsd_ossl_t* reference in SSL obj */
+ 	SSL_set_ex_data(pThis->ssl, 0, pThis);
+@@ -1828,90 +1783,106 @@ SetGnutlsPriorityString(nsd_t *const pNs
+ 	nsd_ossl_t* pThis = (nsd_ossl_t*) pNsd;
+ 	ISOBJ_TYPE_assert(pThis, nsd_ossl);
+ 
+-	pThis->gnutlsPriorityString = gnutlsPriorityString;
++	dbgprintf("gnutlsPriorityString: set to '%s'\n",
++		(gnutlsPriorityString != NULL ? (char*)gnutlsPriorityString : "NULL"));
+ 
+ 	/* Skip function if function is NULL gnutlsPriorityString */
+-	if (gnutlsPriorityString == NULL) {
+-		RETiRet;
+-	} else {
+-		dbgprintf("gnutlsPriorityString: set to '%s'\n", gnutlsPriorityString);
+ #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
+-		char *pCurrentPos;
+-		char *pNextPos;
+-		char *pszCmd;
+-		char *pszValue;
+-		int iConfErr;
+-
+-		/* Set working pointer */
+-		pCurrentPos = (char*) pThis->gnutlsPriorityString;
+-		if (pCurrentPos != NULL && strlen(pCurrentPos) > 0) {
+-			// Create CTX Config Helper
+-			SSL_CONF_CTX *cctx;
+-			cctx = SSL_CONF_CTX_new();
+-			if (pThis->sslState == osslServer) {
+-				SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
+-			} else {
+-				SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
+-			}
+-			SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
+-			SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS);
+-			SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
+-
+-			do
+-			{
+-				pNextPos = index(pCurrentPos, '=');
+-				if (pNextPos != NULL) {
+-					while (	*pCurrentPos != '\0' &&
+-						(*pCurrentPos == ' ' || *pCurrentPos == '\t') )
+-						pCurrentPos++;
+-					pszCmd = strndup(pCurrentPos, pNextPos-pCurrentPos);
+-					pCurrentPos = pNextPos+1;
+-					pNextPos = index(pCurrentPos, '\n');
+-					pszValue = (pNextPos == NULL ?
+-							strdup(pCurrentPos) :
+-							strndup(pCurrentPos, pNextPos - pCurrentPos));
+-					pCurrentPos = (pNextPos == NULL ? NULL : pNextPos+1);
+-
+-					/* Add SSL Conf Command */
+-					iConfErr = SSL_CONF_cmd(cctx, pszCmd, pszValue);
+-					if (iConfErr > 0) {
+-						dbgprintf("gnutlsPriorityString: Successfully added Command "
+-							"'%s':'%s'\n",
+-							pszCmd, pszValue);
+-					}
+-					else {
+-						LogError(0, RS_RET_SYS_ERR, "Failed to added Command: %s:'%s' "
+-							"in gnutlsPriorityString with error '%d'",
+-							pszCmd, pszValue, iConfErr);
+-					}
++	sbool ApplySettings = 0;
++	if ((gnutlsPriorityString != NULL && pThis->gnutlsPriorityString == NULL) ||
++		(gnutlsPriorityString != NULL &&
++		strcmp( (const char*)pThis->gnutlsPriorityString, (const char*)gnutlsPriorityString) != 0)
++		) {
++		ApplySettings = 1;
++	}
++
++	pThis->gnutlsPriorityString = gnutlsPriorityString;
++	dbgprintf("gnutlsPriorityString: set to '%s' Apply %s\n",
++		(gnutlsPriorityString != NULL ? (char*)gnutlsPriorityString : "NULL"),
++		(ApplySettings == 1? "TRUE" : "FALSE"));
+ 
+-					free(pszCmd);
+-					free(pszValue);
++	if (ApplySettings) {
++
++		if (gnutlsPriorityString == NULL || ctx == NULL) {
++			RETiRet;
++		} else {
++			dbgprintf("gnutlsPriorityString: set to '%s'\n", gnutlsPriorityString);
++			char *pCurrentPos;
++			char *pNextPos;
++			char *pszCmd;
++			char *pszValue;
++			int iConfErr;
++
++			/* Set working pointer */
++			pCurrentPos = (char*) pThis->gnutlsPriorityString;
++			if (pCurrentPos != NULL && strlen(pCurrentPos) > 0) {
++				// Create CTX Config Helper
++				SSL_CONF_CTX *cctx;
++				cctx = SSL_CONF_CTX_new();
++				if (pThis->sslState == osslServer) {
++					SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
+ 				} else {
+-					/* Abort further parsing */
+-					pCurrentPos = NULL;
++					SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
+ 				}
+-			}
+-			while (pCurrentPos != NULL);
++				SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
++				SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS);
++				SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
++
++				do
++				{
++					pNextPos = index(pCurrentPos, '=');
++					if (pNextPos != NULL) {
++						while (	*pCurrentPos != '\0' &&
++							(*pCurrentPos == ' ' || *pCurrentPos == '\t') )
++							pCurrentPos++;
++						pszCmd = strndup(pCurrentPos, pNextPos-pCurrentPos);
++						pCurrentPos = pNextPos+1;
++						pNextPos = index(pCurrentPos, '\n');
++						pszValue = (pNextPos == NULL ?
++								strdup(pCurrentPos) :
++								strndup(pCurrentPos, pNextPos - pCurrentPos));
++						pCurrentPos = (pNextPos == NULL ? NULL : pNextPos+1);
++
++						/* Add SSL Conf Command */
++						iConfErr = SSL_CONF_cmd(cctx, pszCmd, pszValue);
++						if (iConfErr > 0) {
++							dbgprintf("gnutlsPriorityString: Successfully added Command "
++								"'%s':'%s'\n",
++								pszCmd, pszValue);
++						}
++						else {
++							LogError(0, RS_RET_SYS_ERR, "Failed to added Command: %s:'%s' "
++								"in gnutlsPriorityString with error '%d'",
++								pszCmd, pszValue, iConfErr);
++						}
++
++						free(pszCmd);
++						free(pszValue);
++					} else {
++						/* Abort further parsing */
++						pCurrentPos = NULL;
++					}
++				}
++				while (pCurrentPos != NULL);
+ 
+-			/* Finalize SSL Conf */
+-			iConfErr = SSL_CONF_CTX_finish(cctx);
+-			if (!iConfErr) {
+-				LogError(0, RS_RET_SYS_ERR, "Error: setting openssl command parameters: %s"
+-						"Open ssl error info may follow in next messages",
+-						pThis->gnutlsPriorityString);
+-				osslLastSSLErrorMsg(0, NULL, LOG_ERR, "SetGnutlsPriorityString");
++				/* Finalize SSL Conf */
++				iConfErr = SSL_CONF_CTX_finish(cctx);
++				if (!iConfErr) {
++					LogError(0, RS_RET_SYS_ERR, "Error: setting openssl command parameters: %s"
++							"Open ssl error info may follow in next messages",
++							pThis->gnutlsPriorityString);
++					osslLastSSLErrorMsg(0, NULL, LOG_ERR, "SetGnutlsPriorityString");
++				}
++				SSL_CONF_CTX_free(cctx);
+ 			}
+-			SSL_CONF_CTX_free(cctx);
+ 		}
++	}
+ #else
+-		dbgprintf("gnutlsPriorityString: set to '%s'\n", gnutlsPriorityString);
+-		LogError(0, RS_RET_SYS_ERR, "Warning: TLS library does not support SSL_CONF_cmd API"
+-			"(maybe it is too old?). Cannot use gnutlsPriorityString ('%s'). For more see: "
+-			"https://www.rsyslog.com/doc/master/configuration/modules/imtcp.html#gnutlsprioritystring",
+-			gnutlsPriorityString);
++	LogError(0, RS_RET_SYS_ERR, "Warning: TLS library does not support SSL_CONF_cmd API"
++		"(maybe it is too old?). Cannot use gnutlsPriorityString ('%s'). For more see: "
++		"https://www.rsyslog.com/doc/master/configuration/modules/imtcp.html#gnutlsprioritystring",
++		gnutlsPriorityString);
+ #endif
+-	}
+ 
+ 	RETiRet;
+ }
diff --git a/SOURCES/rsyslog-8.2102.0-rhbz2046158-gnutls-broken-connection.patch b/SOURCES/rsyslog-8.2102.0-rhbz2046158-gnutls-broken-connection.patch
new file mode 100644
index 0000000..0c3a3a7
--- /dev/null
+++ b/SOURCES/rsyslog-8.2102.0-rhbz2046158-gnutls-broken-connection.patch
@@ -0,0 +1,215 @@
+diff -up rsyslog-8.2102.0/runtime/nsd_gtls.c.orig rsyslog-8.2102.0/runtime/nsd_gtls.c
+--- rsyslog-8.2102.0/runtime/nsd_gtls.c.orig	2022-04-11 09:26:17.826271989 +0200
++++ rsyslog-8.2102.0/runtime/nsd_gtls.c	2022-04-11 09:33:28.702012052 +0200
+@@ -556,7 +556,9 @@ gtlsRecordRecv(nsd_gtls_t *pThis)
+ 	DEFiRet;
+ 
+ 	ISOBJ_TYPE_assert(pThis, nsd_gtls);
+-	DBGPRINTF("gtlsRecordRecv: start\n");
++	DBGPRINTF("gtlsRecordRecv: start (Pending Data: %zd | Wanted Direction: %s)\n",
++		gnutls_record_check_pending(pThis->sess),
++		(gnutls_record_get_direction(pThis->sess) == gtlsDir_READ ? "READ" : "WRITE") );
+ 
+ 	lenRcvd = gnutls_record_recv(pThis->sess, pThis->pszRcvBuf, NSD_GTLS_MAX_RCVBUF);
+ 	if(lenRcvd >= 0) {
+@@ -581,14 +583,30 @@ gtlsRecordRecv(nsd_gtls_t *pThis)
+ 					(NSD_GTLS_MAX_RCVBUF+lenRcvd));
+ 				pThis->lenRcvBuf = NSD_GTLS_MAX_RCVBUF+lenRcvd;
+ 			} else {
+-				goto sslerr;
++				if (lenRcvd == GNUTLS_E_AGAIN || lenRcvd == GNUTLS_E_INTERRUPTED) {
++					goto sslerragain;	/* Go to ERR AGAIN handling */
++				} else {
++					/* Do all other error handling */
++					int gnuRet = lenRcvd;
++					ABORTgnutls;
++				}
+ 			}
+ 		}
+ 	} else if(lenRcvd == GNUTLS_E_AGAIN || lenRcvd == GNUTLS_E_INTERRUPTED) {
+-sslerr:
+-		pThis->rtryCall = gtlsRtry_recv;
+-		dbgprintf("GnuTLS receive requires a retry (this most probably is OK and no error condition)\n");
+-		ABORT_FINALIZE(RS_RET_RETRY);
++sslerragain:
++		/* Check if the underlaying file descriptor needs to read or write data!*/
++		if (gnutls_record_get_direction(pThis->sess) == gtlsDir_READ) {
++			pThis->rtryCall = gtlsRtry_recv;
++			dbgprintf("GnuTLS receive requires a retry, this most probably is OK and no error condition\n");
++			ABORT_FINALIZE(RS_RET_RETRY);
++		} else {
++			uchar *pErr = gtlsStrerror(lenRcvd);
++			LogError(0, RS_RET_GNUTLS_ERR, "GnuTLS receive error %zd has wrong read direction(wants write) "
++				"- this could be caused by a broken connection. GnuTLS reports: %s\n",
++				lenRcvd, pErr);
++			free(pErr);
++			ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
++		}
+ 	} else {
+ 		int gnuRet = lenRcvd;
+ 		ABORTgnutls;
+@@ -1978,6 +1996,7 @@ static rsRetVal
+ Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
+ {
+ 	int iSent;
++	int wantsWriteData = 0;
+ 	nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+ 	DEFiRet;
+ 	ISOBJ_TYPE_assert(pThis, nsd_gtls);
+@@ -1998,10 +2017,12 @@ Send(nsd_t *pNsd, uchar *pBuf, ssize_t *
+ 			break;
+ 		}
+ 		if(iSent != GNUTLS_E_INTERRUPTED && iSent != GNUTLS_E_AGAIN) {
++			/* Check if the underlaying file descriptor needs to read or write data!*/
++			wantsWriteData = gnutls_record_get_direction(pThis->sess);
+ 			uchar *pErr = gtlsStrerror(iSent);
+-			LogError(0, RS_RET_GNUTLS_ERR, "unexpected GnuTLS error %d - this "
+-				"could be caused by a broken connection. GnuTLS reports: %s \n",
+-				iSent, pErr);
++			LogError(0, RS_RET_GNUTLS_ERR, "unexpected GnuTLS error %d, wantsWriteData=%d - this "
++				"could be caused by a broken connection. GnuTLS reports: %s\n",
++				iSent, wantsWriteData, pErr);
+ 			free(pErr);
+ 			gnutls_perror(iSent);
+ 			ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+diff -up rsyslog-8.2102.0/runtime/nsd_gtls.h.orig rsyslog-8.2102.0/runtime/nsd_gtls.h
+--- rsyslog-8.2102.0/runtime/nsd_gtls.h.orig	2022-04-11 09:26:32.744262781 +0200
++++ rsyslog-8.2102.0/runtime/nsd_gtls.h	2022-04-11 09:34:29.909982895 +0200
+@@ -33,6 +33,11 @@ typedef enum {
+ 	gtlsRtry_recv = 2
+ } gtlsRtryCall_t;		/**< IDs of calls that needs to be retried */
+ 
++typedef enum {
++	gtlsDir_READ = 0,	/**< GNUTLS wants READ */
++	gtlsDir_WRITE = 1	/**< GNUTLS wants WRITE */
++} gtlsDirection_t;
++
+ typedef nsd_if_t nsd_gtls_if_t; /* we just *implement* this interface */
+ 
+ /* the nsd_gtls object */
+diff -up rsyslog-8.2102.0/runtime/nsdsel_gtls.c.orig rsyslog-8.2102.0/runtime/nsdsel_gtls.c
+--- rsyslog-8.2102.0/runtime/nsdsel_gtls.c.orig	2022-04-11 09:26:42.529256742 +0200
++++ rsyslog-8.2102.0/runtime/nsdsel_gtls.c	2022-04-11 09:38:27.425869737 +0200
+@@ -81,6 +81,7 @@ Add(nsdsel_t *pNsdsel, nsd_t *pNsd, nsds
+ 
+ 	ISOBJ_TYPE_assert(pThis, nsdsel_gtls);
+ 	ISOBJ_TYPE_assert(pNsdGTLS, nsd_gtls);
++	DBGPRINTF("Add on nsd %p:\n", pNsdGTLS);
+ 	if(pNsdGTLS->iMode == 1) {
+ 		if(waitOp == NSDSEL_RD && gtlsHasRcvInBuffer(pNsdGTLS)) {
+ 			++pThis->iBufferRcvReady;
+@@ -99,6 +100,8 @@ Add(nsdsel_t *pNsdsel, nsd_t *pNsd, nsds
+ 		}
+ 	}
+ 
++	dbgprintf("nsdsel_gtls: reached end on nsd %p, calling nsdsel_ptcp.Add with waitOp %d... \n", pNsdGTLS, waitOp);
++
+ 	/* if we reach this point, we need no special handling */
+ 	CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, waitOp));
+ 
+@@ -120,7 +123,8 @@ Select(nsdsel_t *pNsdsel, int *piNumRead
+ 	if(pThis->iBufferRcvReady > 0) {
+ 		/* we still have data ready! */
+ 		*piNumReady = pThis->iBufferRcvReady;
+-		dbgprintf("nsdsel_gtls: doing dummy select, data present\n");
++		dbgprintf("nsdsel_gtls: doing dummy select for %p->iBufferRcvReady=%d, data present\n",
++			pThis, pThis->iBufferRcvReady);
+ 	} else {
+ 		iRet = nsdsel_ptcp.Select(pThis->pTcp, piNumReady);
+ 	}
+@@ -138,7 +142,7 @@ doRetry(nsd_gtls_t *pNsd)
+ 	DEFiRet;
+ 	int gnuRet;
+ 
+-	dbgprintf("GnuTLS requested retry of %d operation - executing\n", pNsd->rtryCall);
++	dbgprintf("doRetry: GnuTLS requested retry of %d operation - executing\n", pNsd->rtryCall);
+ 
+ 	/* We follow a common scheme here: first, we do the systen call and
+ 	 * then we check the result. So far, the result is checked after the
+@@ -151,7 +155,7 @@ doRetry(nsd_gtls_t *pNsd)
+ 		case gtlsRtry_handshake:
+ 			gnuRet = gnutls_handshake(pNsd->sess);
+ 			if(gnuRet == GNUTLS_E_AGAIN || gnuRet == GNUTLS_E_INTERRUPTED) {
+-				dbgprintf("GnuTLS handshake retry did not finish - "
++				dbgprintf("doRetry: GnuTLS handshake retry did not finish - "
+ 					"setting to retry (this is OK and can happen)\n");
+ 				FINALIZE;
+ 			} else if(gnuRet == 0) {
+@@ -167,9 +171,20 @@ doRetry(nsd_gtls_t *pNsd)
+ 			}
+ 			break;
+ 		case gtlsRtry_recv:
+-			dbgprintf("retrying gtls recv, nsd: %p\n", pNsd);
+-			CHKiRet(gtlsRecordRecv(pNsd));
+-			pNsd->rtryCall = gtlsRtry_None; /* we are done */
++			dbgprintf("doRetry: retrying gtls recv, nsd: %p\n", pNsd);
++			iRet = gtlsRecordRecv(pNsd);
++			if (iRet == RS_RET_RETRY) {
++				// Check if there is pending data
++				size_t stBytesLeft = gnutls_record_check_pending(pNsd->sess);
++				if (stBytesLeft > 0) {
++					// We are in retry and more data waiting, finalize it
++					goto finalize_it;
++				} else {
++					dbgprintf("doRetry: gtlsRecordRecv returned RETRY, but there is no pending"
++						"data on nsd: %p\n", pNsd);
++				}
++			}
++			pNsd->rtryCall = gtlsRtry_None; /* no more data, we are done */
+ 			gnuRet = 0;
+ 			break;
+ 		case gtlsRtry_None:
+@@ -241,7 +256,7 @@ IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd,
+ 		 * socket. -- rgerhards, 2010-11-20
+ 		 */
+ 		if(pThis->iBufferRcvReady) {
+-			dbgprintf("nsd_gtls: dummy read, buffer not available for this FD\n");
++			dbgprintf("nsd_gtls: dummy read, %p->buffer not available for this FD\n", pThis);
+ 			*pbIsReady = 0;
+ 			FINALIZE;
+ 		}
+diff -up rsyslog-8.2102.0/runtime/tcpsrv.c.orig rsyslog-8.2102.0/runtime/tcpsrv.c
+--- rsyslog-8.2102.0/runtime/tcpsrv.c.orig	2022-04-11 09:27:00.376245726 +0200
++++ rsyslog-8.2102.0/runtime/tcpsrv.c	2022-04-11 09:41:57.885777708 +0200
+@@ -609,14 +609,15 @@ doReceive(tcpsrv_t *pThis, tcps_sess_t *
+ 	int oserr = 0;
+ 
+ 	ISOBJ_TYPE_assert(pThis, tcpsrv);
+-	DBGPRINTF("netstream %p with new data\n", (*ppSess)->pStrm);
++	prop.GetString((*ppSess)->fromHostIP, &pszPeer, &lenPeer);
++	DBGPRINTF("netstream %p with new data from remote peer %s\n", (*ppSess)->pStrm, pszPeer);
+ 	/* Receive message */
+ 	iRet = pThis->pRcvData(*ppSess, buf, sizeof(buf), &iRcvd, &oserr);
+ 	switch(iRet) {
+ 	case RS_RET_CLOSED:
+ 		if(pThis->bEmitMsgOnClose) {
+ 			errno = 0;
+-			prop.GetString((*ppSess)->fromHostIP, &pszPeer, &lenPeer);
++			// prop.GetString((*ppSess)->fromHostIP, &pszPeer, &lenPeer);
+ 			LogError(0, RS_RET_PEER_CLOSED_CONN, "Netstream session %p closed by remote "
+ 				"peer %s.\n", (*ppSess)->pStrm, pszPeer);
+ 		}
+@@ -632,13 +633,13 @@ doReceive(tcpsrv_t *pThis, tcps_sess_t *
+ 			/* in this case, something went awfully wrong.
+ 			 * We are instructed to terminate the session.
+ 			 */
+-			prop.GetString((*ppSess)->fromHostIP, &pszPeer, &lenPeer);
++			// prop.GetString((*ppSess)->fromHostIP, &pszPeer, &lenPeer);
+ 			LogError(oserr, localRet, "Tearing down TCP Session from %s", pszPeer);
+ 			CHKiRet(closeSess(pThis, ppSess, pPoll));
+ 		}
+ 		break;
+ 	default:
+-		prop.GetString((*ppSess)->fromHostIP, &pszPeer, &lenPeer);
++		// prop.GetString((*ppSess)->fromHostIP, &pszPeer, &lenPeer);
+ 		LogError(oserr, iRet, "netstream session %p from %s will be closed due to error",
+ 				(*ppSess)->pStrm, pszPeer);
+ 		CHKiRet(closeSess(pThis, ppSess, pPoll));
+@@ -838,6 +839,7 @@ RunSelect(tcpsrv_t *pThis, nsd_epworkset
+ 		while(iTCPSess != -1) {
+ 			/* TODO: access to pNsd is NOT really CLEAN, use method... */
+ 			CHKiRet(nssel.Add(pSel, pThis->pSessions[iTCPSess]->pStrm, NSDSEL_RD));
++			DBGPRINTF("tcpsrv process session %d:\n", iTCPSess);
+ 			/* now get next... */
+ 			iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess);
+ 		}
diff --git a/SOURCES/rsyslog-8.37.0-rhbz2081396-CVE-2022-24903.patch b/SOURCES/rsyslog-8.37.0-rhbz2081396-CVE-2022-24903.patch
new file mode 100644
index 0000000..e3b1453
--- /dev/null
+++ b/SOURCES/rsyslog-8.37.0-rhbz2081396-CVE-2022-24903.patch
@@ -0,0 +1,30 @@
+diff -up rsyslog-8.37.0/plugins/imptcp/imptcp.c.orig rsyslog-8.37.0/plugins/imptcp/imptcp.c
+--- rsyslog-8.37.0/plugins/imptcp/imptcp.c.orig	2022-05-09 12:22:59.050623119 +0200
++++ rsyslog-8.37.0/plugins/imptcp/imptcp.c	2022-05-09 12:34:39.979854853 +0200
+@@ -1032,7 +1032,10 @@ processDataRcvd(ptcpsess_t *const __rest
+ 			if(pThis->iOctetsRemain <= 200000000) {
+ 				pThis->iOctetsRemain = pThis->iOctetsRemain * 10 + c - '0';
+ 			}
+-			*(pThis->pMsg + pThis->iMsg++) = c;
++			// *(pThis->pMsg + pThis->iMsg++) = c;
++			if(pThis->iMsg < iMaxLine) {
++				*(pThis->pMsg + pThis->iMsg++) = c;
++			}
+ 		} else { /* done with the octet count, so this must be the SP terminator */
+ 			DBGPRINTF("TCP Message with octet-counter, size %d.\n", pThis->iOctetsRemain);
+ 			prop.GetString(pThis->peerName, &propPeerName, &lenPeerName);
+diff -up rsyslog-8.37.0/runtime/tcps_sess.c.orig rsyslog-8.37.0/runtime/tcps_sess.c
+--- rsyslog-8.37.0/runtime/tcps_sess.c.orig	2022-05-09 12:23:12.789627661 +0200
++++ rsyslog-8.37.0/runtime/tcps_sess.c	2022-05-09 12:36:51.426898549 +0200
+@@ -389,7 +389,10 @@ processDataRcvd(tcps_sess_t *pThis,
+ 			if(pThis->iOctetsRemain <= 200000000) {
+ 				pThis->iOctetsRemain = pThis->iOctetsRemain * 10 + c - '0';
+ 			}
+-			*(pThis->pMsg + pThis->iMsg++) = c;
++			// *(pThis->pMsg + pThis->iMsg++) = c;
++			if(pThis->iMsg < iMaxLine) {
++				*(pThis->pMsg + pThis->iMsg++) = c;
++			}
+ 		} else { /* done with the octet count, so this must be the SP terminator */
+ 			DBGPRINTF("TCP Message with octet-counter, size %d.\n", pThis->iOctetsRemain);
+ 			prop.GetString(pThis->fromHost, &propPeerName, &lenPeerName);
diff --git a/SPECS/rsyslog.spec b/SPECS/rsyslog.spec
index 0fed65c..7a10898 100644
--- a/SPECS/rsyslog.spec
+++ b/SPECS/rsyslog.spec
@@ -6,7 +6,7 @@
 Summary: Enhanced system logging and kernel message trapping daemon
 Name: rsyslog
 Version: 8.2102.0
-Release: 7%{?dist}
+Release: 10%{?dist}
 License: (GPLv3+ and ASL 2.0)
 Group: System Environment/Daemons
 ExcludeArch: i686
@@ -48,13 +48,22 @@ Provides: syslog
 Obsoletes: sysklogd < 1.5-11
 
 # imjournal: adds "journal" when tag/process name is missing
-Patch0: rsyslog-8.1911.0-rhbz1659898-imjournal-default-tag.patch
-Patch1: rsyslog-8.2102.0-rhbz1960536-fdleak-on-fsync.patch
-Patch2: rsyslog-8.2102.0-rhbz1886400-reduce-default-timeout.patch
-Patch3: rsyslog-8.2102.0-rhbz1866877-unexpected-length.patch
-Patch4: rsyslog-8.2102.0-rhbz1984616-imuxsock-ratelimit.patch
-Patch5: rsyslog-8.2102.0-rhbz1984489-remove-abort-on-id-resolution-fail.patch
-Patch6: rsyslog-8.2102.0-rhbz1832368-prioritize-SAN.patch
+Patch0:  rsyslog-8.1911.0-rhbz1659898-imjournal-default-tag.patch
+Patch1:  rsyslog-8.2102.0-rhbz1960536-fdleak-on-fsync.patch
+Patch2:  rsyslog-8.2102.0-rhbz1886400-reduce-default-timeout.patch
+Patch3:  rsyslog-8.2102.0-rhbz1866877-unexpected-length.patch
+Patch4:  rsyslog-8.2102.0-rhbz1984616-imuxsock-ratelimit.patch
+Patch5:  rsyslog-8.2102.0-rhbz1984489-remove-abort-on-id-resolution-fail.patch
+Patch6:  rsyslog-8.2102.0-rhbz1832368-prioritize-SAN.patch
+Patch7:  rsyslog-8.2102.0-rhbz1962318-errfile-maxsize.patch
+Patch8:  rsyslog-8.2102.0-rhbz1909639-statefiles-fix.patch
+Patch9:  rsyslog-8.2102.0-rhbz1909639-statefiles-doc.patch
+Patch10: rsyslog-8.2102.0-nsd_ossl-better-logs.patch
+Patch11: rsyslog-8.2102.0-imtcp-param-refactor.patch
+Patch12: rsyslog-8.2102.0-nsd_ossl-memory-leak.patch
+Patch13: rsyslog-8.2102.0-rhbz2046158-correct-custom-ciphers-behaviour.patch
+Patch14: rsyslog-8.37.0-rhbz2081396-CVE-2022-24903.patch
+Patch15: rsyslog-8.2102.0-rhbz2046158-gnutls-broken-connection.patch
 
 %package crypto
 Summary: Encryption support
@@ -279,13 +288,22 @@ mv build doc
 %setup -q -D
 %setup -q -D -T -b 5
 
-%patch0 -p1 -b .default-tag
-%patch1 -p1 -b .fd-leak-on-fsync
-%patch2 -p1 -b .timeout
-%patch3 -p1 -b .unexpected-priority-length
-%patch4 -p1 -b .imuxsock-rate-limit
-%patch5 -p1 -b .abort-on-id-resolution-fail
-%patch6 -p1 -b .prioritizeSAN
+%patch0  -p1 -b .default-tag
+%patch1  -p1 -b .fd-leak-on-fsync
+%patch2  -p1 -b .timeout
+%patch3  -p1 -b .unexpected-priority-length
+%patch4  -p1 -b .imuxsock-rate-limit
+%patch5  -p1 -b .abort-on-id-resolution-fail
+%patch6  -p1 -b .prioritizeSAN
+%patch7  -p1 -b .errfile-maxsize
+%patch8  -p1 -b .state-file-leaking
+%patch9  -p1 -b .state-file-leaking-doc
+%patch10 -p1 -b .ossl-better-logs
+%patch11 -p1 -b .imtcp-refactor-params
+%patch12 -p1 -b .ossl-memory-leak
+%patch13 -p1 -b .ossl-ciphers-behaviour
+%patch14 -p1 -b .CVE-24903
+%patch15 -p1 -b .gnutls-error-handling
 
 %build
 %ifarch sparc64
@@ -530,6 +548,23 @@ done
 %{_libdir}/rsyslog/omudpspoof.so
 
 %changelog
+* Wed Apr 13 2022 Attila Lakatos <alakatos@redhat.com> - 8.2102.0-10
+- openssl: Correct gnutlsPriorityString (custom ciphers) behaviour
+- Fix error handling in gtlsRecordRecv that can cause 100 percent CPU usage
+  resolves: rhbz#2046158
+- Address CVE-2022-24903, Heap-based overflow in TCP syslog server
+  resolves: rhbz#2081401
+
+* Mon Mar 28 2022 Attila Lakatos <alakatos@redhat.com> - 8.2102.0-9
+- Add deleteStateOnFileMove imfile module option
+  resolves: rhbz#1909639
+- Add inotify_rm_watch() inotify API call when object needs to be destroyed
+  resolves: rhbz#2052403
+
+* Fri Mar 04 2022 Sergio Arroutbi <sarroutb@redhat.com> - 8.2102.0-8
+- Include maxsize for error files
+  resolves: rhbz#1962318
+
 * Mon Nov 22 2021 Attila Lakatos <alakatos@redhat.com> - 8.2102.0-7
 - Propagate prioritizeSAN when accepting new connection
   resolves: rhbz#1832368