summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-05-06 10:25:42 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2008-05-06 10:25:42 +0200
commit9e0af15a324cca5bd50ec3226c64ca9ddb2e8d40 (patch)
treed6db3c3908fcada54d916fd680c669ff0e4f36c0 /runtime
parent4ec4f4ddae4285adf0a40618360ec5cea02d85c3 (diff)
parentfcbead3d4cbda4c79bb7110e65c85afad4131cb8 (diff)
downloadrsyslog-9e0af15a324cca5bd50ec3226c64ca9ddb2e8d40.tar.gz
rsyslog-9e0af15a324cca5bd50ec3226c64ca9ddb2e8d40.tar.xz
rsyslog-9e0af15a324cca5bd50ec3226c64ca9ddb2e8d40.zip
Merge branch 'tls'
Diffstat (limited to 'runtime')
-rw-r--r--runtime/Makefile.am34
-rw-r--r--runtime/debug.c2
-rw-r--r--runtime/glbl.c70
-rw-r--r--runtime/glbl.h3
-rw-r--r--runtime/modules.c13
-rw-r--r--runtime/netstrm.c62
-rw-r--r--runtime/netstrm.h13
-rw-r--r--runtime/netstrms.c101
-rw-r--r--runtime/netstrms.h7
-rw-r--r--runtime/nsd.h1
-rw-r--r--runtime/nsd_gtls.c190
-rw-r--r--runtime/nsd_gtls.h10
-rw-r--r--runtime/nsd_ptcp.c28
-rw-r--r--runtime/nsdsel_gtls.c107
-rw-r--r--runtime/nsdsel_gtls.h3
-rw-r--r--runtime/nsdsel_ptcp.c30
-rw-r--r--runtime/nsdsel_ptcp.h3
-rw-r--r--runtime/nssel.c66
-rw-r--r--runtime/nssel.h7
-rw-r--r--runtime/obj.c6
-rw-r--r--runtime/rsyslog.h3
21 files changed, 550 insertions, 209 deletions
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index dcb475d8..a7a2b91e 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -81,7 +81,7 @@ lmregexp_la_LIBADD =
endif
if ENABLE_INET
-pkglib_LTLIBRARIES += lmnet.la lmnetstrms.la lmnetstrm.la lmnssel.la
+pkglib_LTLIBRARIES += lmnet.la lmnetstrms.la
#
# network support
#
@@ -91,38 +91,19 @@ lmnet_la_LDFLAGS = -module -avoid-version
lmnet_la_LIBADD =
# network stream master class and stream factory
-lmnetstrms_la_SOURCES = netstrms.c netstrms.h
+lmnetstrms_la_SOURCES = netstrms.c netstrms.h netstrm.c netstrm.h nssel.c nssel.h
lmnetstrms_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
lmnetstrms_la_LDFLAGS = -module -avoid-version
lmnetstrms_la_LIBADD =
-# individual network streams
-lmnetstrm_la_SOURCES = netstrm.c netstrm.h
-lmnetstrm_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
-lmnetstrm_la_LDFLAGS = -module -avoid-version
-lmnetstrm_la_LIBADD =
-
-# network stream select support (a helper class)
-lmnssel_la_SOURCES = nssel.c nssel.h
-lmnssel_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
-lmnssel_la_LDFLAGS = -module -avoid-version
-lmnssel_la_LIBADD =
-
# netstream drivers
# plain tcp driver - main driver
pkglib_LTLIBRARIES += lmnsd_ptcp.la
-lmnsd_ptcp_la_SOURCES = nsd_ptcp.c nsd_ptcp.h
+lmnsd_ptcp_la_SOURCES = nsd_ptcp.c nsd_ptcp.h nsdsel_ptcp.c nsdsel_ptcp.h
lmnsd_ptcp_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
lmnsd_ptcp_la_LDFLAGS = -module -avoid-version
lmnsd_ptcp_la_LIBADD =
-
-# select interface for ptcp driver
-pkglib_LTLIBRARIES += lmnsdsel_ptcp.la
-lmnsdsel_ptcp_la_SOURCES = nsdsel_ptcp.c nsdsel_ptcp.h
-lmnsdsel_ptcp_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
-lmnsdsel_ptcp_la_LDFLAGS = -module -avoid-version
-lmnsdsel_ptcp_la_LIBADD =
endif # if ENABLE_INET
#
@@ -130,16 +111,9 @@ endif # if ENABLE_INET
#
if ENABLE_GNUTLS
pkglib_LTLIBRARIES += lmnsd_gtls.la
-lmnsd_gtls_la_SOURCES = nsd_gtls.c nsd_gtls.h
+lmnsd_gtls_la_SOURCES = nsd_gtls.c nsd_gtls.h nsdsel_gtls.c nsdsel_gtls.h
lmnsd_gtls_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags) $(gnutls_cflags)
lmnsd_gtls_la_LDFLAGS = -module -avoid-version
lmnsd_gtls_la_LIBADD = $(gnutls_libs)
-#
-# select interface for gtls driver
-pkglib_LTLIBRARIES += lmnsdsel_gtls.la
-lmnsdsel_gtls_la_SOURCES = nsdsel_gtls.c nsdsel_gtls.h
-lmnsdsel_gtls_la_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
-lmnsdsel_gtls_la_LDFLAGS = -module -avoid-version
-lmnsdsel_gtls_la_LIBADD =
endif
diff --git a/runtime/debug.c b/runtime/debug.c
index 53624e38..f543efd8 100644
--- a/runtime/debug.c
+++ b/runtime/debug.c
@@ -1145,8 +1145,6 @@ dbgPrintNameAdd(uchar *pName, dbgPrintName_t **ppRoot)
pEntry->pNext = *ppRoot; /* we enqueue at the front */
}
*ppRoot = pEntry;
-
-printf("Name %s added to %p\n", pName, *ppRoot);
}
diff --git a/runtime/glbl.c b/runtime/glbl.c
index 787b6ab7..20840318 100644
--- a/runtime/glbl.c
+++ b/runtime/glbl.c
@@ -40,9 +40,16 @@
/* some defaults */
#ifndef DFLT_NETSTRM_DRVR
-// TESTING ONLY# define DFLT_NETSTRM_DRVR ((uchar*)"lmnsd_ptcp")
-#warning "define must be restored for non-testing!"
-# define DFLT_NETSTRM_DRVR ((uchar*)"lmnsd_gtls")
+# define DFLT_NETSTRM_DRVR ((uchar*)"ptcp")
+#endif
+#ifndef DFLT_NETSTRM_DRVR_CAF
+# define DFLT_NETSTRM_DRVR_CAF ((uchar*)"ca.pem")
+#endif
+#ifndef DFLT_NETSTRM_DRVR_KEYFILE
+# define DFLT_NETSTRM_DRVR_KEYFILE ((uchar*)"key.pem")
+#endif
+#ifndef DFLT_NETSTRM_DRVR_CERTFILE
+# define DFLT_NETSTRM_DRVR_CERTFILE ((uchar*)"cert.pem")
#endif
/* static data */
@@ -62,6 +69,9 @@ static uchar *LocalDomain; /* our local domain name - read-only after startup *
static char **StripDomains = NULL;/* these domains may be stripped before writing logs - r/o after s.u., never touched by init */
static char **LocalHosts = NULL;/* these hosts are logged with their hostname - read-only after startup, never touched by init */
static uchar *pszDfltNetstrmDrvr = NULL; /* module name of default netstream driver */
+static uchar *pszDfltNetstrmDrvrCAF = NULL; /* default CA file for the netstrm driver */
+static uchar *pszDfltNetstrmDrvrKeyFile = NULL; /* default key file for the netstrm driver (server) */
+static uchar *pszDfltNetstrmDrvrCertFile = NULL; /* default cert file for the netstrm driver (server) */
/* define a macro for the simple properties' set and get functions
@@ -93,6 +103,9 @@ SIMP_PROP(LocalHosts, LocalHosts, char**)
SIMP_PROP_SET(LocalHostName, LocalHostName, uchar*)
SIMP_PROP_SET(DfltNetstrmDrvr, pszDfltNetstrmDrvr, uchar*) // TODO: use custom function which frees existing value
+SIMP_PROP_SET(DfltNetstrmDrvrCAF, pszDfltNetstrmDrvrCAF, uchar*) // TODO: use custom function which frees existing value
+SIMP_PROP_SET(DfltNetstrmDrvrKeyFile, pszDfltNetstrmDrvrKeyFile, uchar*) // TODO: use custom function which frees existing value
+SIMP_PROP_SET(DfltNetstrmDrvrCertFile, pszDfltNetstrmDrvrCertFile, uchar*) // TODO: use custom function which frees existing value
#undef SIMP_PROP
#undef SIMP_PROP_SET
@@ -120,7 +133,31 @@ GetWorkDir(void)
static uchar*
GetDfltNetstrmDrvr(void)
{
- return(pszDfltNetstrmDrvr == NULL ? DFLT_NETSTRM_DRVR : pszWorkDir);
+ return(pszDfltNetstrmDrvr == NULL ? DFLT_NETSTRM_DRVR : pszDfltNetstrmDrvr);
+}
+
+
+/* return the current default netstream driver CA File */
+static uchar*
+GetDfltNetstrmDrvrCAF(void)
+{
+ return(pszDfltNetstrmDrvrCAF == NULL ? DFLT_NETSTRM_DRVR_CAF : pszDfltNetstrmDrvrCAF);
+}
+
+
+/* return the current default netstream driver key File */
+static uchar*
+GetDfltNetstrmDrvrKeyFile(void)
+{
+ return(pszDfltNetstrmDrvrKeyFile == NULL ? DFLT_NETSTRM_DRVR_KEYFILE : pszDfltNetstrmDrvrKeyFile);
+}
+
+
+/* return the current default netstream driver certificate File */
+static uchar*
+GetDfltNetstrmDrvrCertFile(void)
+{
+ return(pszDfltNetstrmDrvrCertFile == NULL ? DFLT_NETSTRM_DRVR_CERTFILE : pszDfltNetstrmDrvrCertFile);
}
@@ -151,6 +188,9 @@ CODESTARTobjQueryInterface(glbl)
SIMP_PROP(StripDomains)
SIMP_PROP(LocalHosts)
SIMP_PROP(DfltNetstrmDrvr)
+ SIMP_PROP(DfltNetstrmDrvrCAF)
+ SIMP_PROP(DfltNetstrmDrvrKeyFile)
+ SIMP_PROP(DfltNetstrmDrvrCertFile)
#undef SIMP_PROP
finalize_it:
ENDobjQueryInterface(glbl)
@@ -165,6 +205,18 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a
free(pszDfltNetstrmDrvr);
pszDfltNetstrmDrvr = NULL;
}
+ if(pszDfltNetstrmDrvrCAF != NULL) {
+ free(pszDfltNetstrmDrvrCAF);
+ pszDfltNetstrmDrvrCAF = NULL;
+ }
+ if(pszDfltNetstrmDrvrKeyFile != NULL) {
+ free(pszDfltNetstrmDrvrKeyFile);
+ pszDfltNetstrmDrvrKeyFile = NULL;
+ }
+ if(pszDfltNetstrmDrvrCertFile != NULL) {
+ free(pszDfltNetstrmDrvrCertFile);
+ pszDfltNetstrmDrvrCertFile = NULL;
+ }
if(pszWorkDir != NULL) {
free(pszWorkDir);
pszWorkDir = NULL;
@@ -185,6 +237,10 @@ BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* register config handlers (TODO: we need to implement a way to unregister them) */
CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, NULL, &pszWorkDir, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, NULL, &bDropMalPTRMsgs, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriver", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvr, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercafile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrCAF, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriverkeyfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrKeyFile, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercertfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrCertFile, NULL));
CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL));
ENDObjClassInit(glbl)
@@ -195,6 +251,12 @@ ENDObjClassInit(glbl)
BEGINObjClassExit(glbl, OBJ_IS_CORE_MODULE) /* class, version */
if(pszDfltNetstrmDrvr != NULL)
free(pszDfltNetstrmDrvr);
+ if(pszDfltNetstrmDrvrCAF != NULL)
+ free(pszDfltNetstrmDrvrCAF);
+ if(pszDfltNetstrmDrvrKeyFile != NULL)
+ free(pszDfltNetstrmDrvrKeyFile);
+ if(pszDfltNetstrmDrvrCertFile != NULL)
+ free(pszDfltNetstrmDrvrCertFile);
if(pszWorkDir != NULL)
free(pszWorkDir);
if(LocalHostName != NULL)
diff --git a/runtime/glbl.h b/runtime/glbl.h
index b6864f3d..adfae27e 100644
--- a/runtime/glbl.h
+++ b/runtime/glbl.h
@@ -49,6 +49,9 @@ BEGINinterface(glbl) /* name must also be changed in ENDinterface macro! */
SIMP_PROP(StripDomains, char**)
SIMP_PROP(LocalHosts, char**)
SIMP_PROP(DfltNetstrmDrvr, uchar*)
+ SIMP_PROP(DfltNetstrmDrvrCAF, uchar*)
+ SIMP_PROP(DfltNetstrmDrvrKeyFile, uchar*)
+ SIMP_PROP(DfltNetstrmDrvrCertFile, uchar*)
#undef SIMP_PROP
ENDinterface(glbl)
#define glblCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
diff --git a/runtime/modules.c b/runtime/modules.c
index c156fef2..1e59a5fc 100644
--- a/runtime/modules.c
+++ b/runtime/modules.c
@@ -522,11 +522,16 @@ modUnloadAndDestructAll(eModLinkType_t modLinkTypesToUnload)
if(modLinkTypesToUnload == eMOD_LINK_ALL || pModCurr->eLinkType == modLinkTypesToUnload) {
if(modUnlinkAndDestroy(&pModCurr) == RS_RET_MODULE_STILL_REFERENCED) {
pModCurr = GetNxt(pModCurr);
+ } else {
+ /* Note: if the module was successfully unloaded, it has updated the
+ * pModCurr pointer to the next module. However, the unload process may
+ * still have indirectly referenced the pointer list in a way that the
+ * unloaded module is not aware of. So we restart the unload process
+ * to make sure we do not fall into a trap (what we did ;)). The
+ * performance toll is minimal. -- rgerhards, 2008-04-28
+ */
+ pModCurr = GetNxt(NULL);
}
- /* Note: if the module was successfully unloaded, it has updated the
- * pModCurr pointer to the next module. So we do NOT need to advance
- * to the next module on successful unload.
- */
} else {
pModCurr = GetNxt(pModCurr);
}
diff --git a/runtime/netstrm.c b/runtime/netstrm.c
index be754aae..a1384a28 100644
--- a/runtime/netstrm.c
+++ b/runtime/netstrm.c
@@ -46,12 +46,9 @@
#include "module-template.h"
#include "obj.h"
#include "errmsg.h"
-//#include "nsd.h"
#include "netstrms.h"
#include "netstrm.h"
-MODULE_TYPE_LIB
-
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
@@ -119,6 +116,7 @@ AcceptConnReq(netstrm_t *pThis, netstrm_t **ppNew)
/* accept the new connection */
CHKiRet(pThis->Drvr.AcceptConnReq(pThis->pDrvrData, &pNewNsd));
/* construct our object so that we can use it... */
+ CHKiRet(objUse(netstrms, DONT_LOAD_LIB)); /* use netstrms obj if not already done so */
CHKiRet(netstrms.CreateStrm(pThis->pNS, ppNew));
(*ppNew)->pDrvrData = pNewNsd;
@@ -175,6 +173,19 @@ Rcv(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf)
}
+/* set the driver mode
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+SetDrvrMode(netstrm_t *pThis, int iMode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ iRet = pThis->Drvr.SetMode(pThis->pDrvrData, iMode);
+ RETiRet;
+}
+
+
/* send a buffer. On entry, pLenBuf contains the number of octets to
* write. On exit, it contains the number of octets actually written.
* If this number is lower than on entry, only a partial buffer has
@@ -228,6 +239,22 @@ Connect(netstrm_t *pThis, int family, uchar *port, uchar *host)
}
+/* Provide access to the underlying OS socket. This is dirty
+ * and scheduled to be removed. Does not work with all nsd drivers.
+ * See comment in netstrm interface for details.
+ * rgerhards, 2008-05-05
+ */
+static rsRetVal
+GetSock(netstrm_t *pThis, int *pSock)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrm);
+ assert(pSock != NULL);
+ iRet = pThis->Drvr.GetSock(pThis->pDrvrData, pSock);
+ RETiRet;
+}
+
+
/* queryInterface function
*/
BEGINobjQueryInterface(netstrm)
@@ -252,6 +279,8 @@ CODESTARTobjQueryInterface(netstrm)
pIf->AcceptConnReq = AcceptConnReq;
pIf->GetRemoteHName = GetRemoteHName;
pIf->GetRemoteIP = GetRemoteIP;
+ pIf->SetDrvrMode = SetDrvrMode;
+ pIf->GetSock = GetSock;
finalize_it:
ENDobjQueryInterface(netstrm)
@@ -262,7 +291,7 @@ BEGINObjClassExit(netstrm, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END M
CODESTARTObjClassExit(netstrm)
/* release objects we no longer need */
objRelease(errmsg, CORE_COMPONENT);
- objRelease(netstrms, LM_NETSTRMS_FILENAME);
+ objRelease(netstrms, DONT_LOAD_LIB);
ENDObjClassExit(netstrm)
@@ -273,33 +302,8 @@ ENDObjClassExit(netstrm)
BEGINAbstractObjClassInit(netstrm, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
- CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME));
/* set our own handlers */
ENDObjClassInit(netstrm)
-
-
-/* --------------- here now comes the plumbing that makes as a library module --------------- */
-
-
-BEGINmodExit
-CODESTARTmodExit
- netstrmClassExit();
-ENDmodExit
-
-
-BEGINqueryEtryPt
-CODESTARTqueryEtryPt
-CODEqueryEtryPt_STD_LIB_QUERIES
-ENDqueryEtryPt
-
-
-BEGINmodInit()
-CODESTARTmodInit
- *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
-
- /* Initialize all classes that are in our module - this includes ourselfs */
- CHKiRet(netstrmClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
-ENDmodInit
/* vi:set ai:
*/
diff --git a/runtime/netstrm.h b/runtime/netstrm.h
index 160bbb0b..a15c1d9b 100644
--- a/runtime/netstrm.h
+++ b/runtime/netstrm.h
@@ -24,7 +24,7 @@
#ifndef INCLUDED_NETSTRM_H
#define INCLUDED_NETSTRM_H
-#include "nsd.h" /* we need our driver interface to be defined */
+#include "netstrms.h"
/* the netstrm object */
struct netstrm_s {
@@ -49,6 +49,15 @@ BEGINinterface(netstrm) /* name must also be changed in ENDinterface macro! */
rsRetVal (*Connect)(netstrm_t *pThis, int family, unsigned char *port, unsigned char *host);
rsRetVal (*GetRemoteHName)(netstrm_t *pThis, uchar **pszName);
rsRetVal (*GetRemoteIP)(netstrm_t *pThis, uchar **pszIP);
+ rsRetVal (*SetDrvrMode)(netstrm_t *pThis, int iMode);
+ /* the GetSock() below is a hack to make imgssapi work. In the long term,
+ * we should migrate imgssapi to a stream driver, which will relieve us of
+ * this problem. Please note that nobody else should use GetSock(). Using it
+ * will also tie the caller to nsd_ptcp, because other drivers may not support
+ * it at all. Once the imgssapi problem is solved, GetSock should be removed from
+ * this interface. -- rgerhards, 2008-05-05
+ */
+ rsRetVal (*GetSock)(netstrm_t *pThis, int *pSock);
ENDinterface(netstrm)
#define netstrmCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
@@ -56,6 +65,6 @@ ENDinterface(netstrm)
PROTOTYPEObj(netstrm);
/* the name of our library binary */
-#define LM_NETSTRM_FILENAME "lmnetstrm"
+#define LM_NETSTRM_FILENAME LM_NETSTRMS_FILENAME
#endif /* #ifndef INCLUDED_NETSTRM_H */
diff --git a/runtime/netstrms.c b/runtime/netstrms.c
index 661234e4..fde0788d 100644
--- a/runtime/netstrms.c
+++ b/runtime/netstrms.c
@@ -23,6 +23,7 @@
* A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
*/
#include "config.h"
+#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
@@ -31,9 +32,9 @@
#include "module-template.h"
#include "obj.h"
//#include "errmsg.h"
-//#include "net.h"
#include "nsd.h"
#include "netstrm.h"
+#include "nssel.h"
#include "netstrms.h"
MODULE_TYPE_LIB
@@ -43,24 +44,29 @@ DEFobjStaticHelpers
//DEFobjCurrIf(errmsg)
DEFobjCurrIf(glbl)
DEFobjCurrIf(netstrm)
-//DEFobjCurrIf(net)
/* load our low-level driver. This must be done before any
* driver-specific functions (allmost all...) can be carried
* out. Note that the driver's .ifIsLoaded is correctly
* initialized by calloc() and we depend on that.
+ * WARNING: this code is mostly identical to similar code in
+ * nssel.c - TODO: abstract it and move it to some common place.
* rgerhards, 2008-04-18
*/
static rsRetVal
loadDrvr(netstrms_t *pThis)
{
- uchar *pDrvrName;
DEFiRet;
+ uchar *pBaseDrvrName;
+ uchar szDrvrName[48]; /* 48 shall be large enough */
- pDrvrName = pThis->pDrvrName;
- if(pDrvrName == NULL) /* if no drvr name is set, use system default */
- pDrvrName = glbl.GetDfltNetstrmDrvr();
+ pBaseDrvrName = pThis->pBaseDrvrName;
+ if(pBaseDrvrName == NULL) /* if no drvr name is set, use system default */
+ pBaseDrvrName = glbl.GetDfltNetstrmDrvr();
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmnsd_%s", pBaseDrvrName) == sizeof(szDrvrName))
+ ABORT_FINALIZE(RS_RET_DRVRNAME_TOO_LONG);
+ CHKmalloc(pThis->pDrvrName = (uchar*) strdup((char*)szDrvrName));
pThis->Drvr.ifVersion = nsdCURR_IF_VERSION;
/* The pDrvrName+2 below is a hack to obtain the object name. It
@@ -69,8 +75,14 @@ loadDrvr(netstrms_t *pThis)
* about this hack, but for the time being it is efficient and clean
* enough. -- rgerhards, 2008-04-18
*/
- CHKiRet(obj.UseObj(__FILE__, pDrvrName+2, pDrvrName, (void*) &pThis->Drvr));
+ CHKiRet(obj.UseObj(__FILE__, szDrvrName+2, szDrvrName, (void*) &pThis->Drvr));
+
finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->pDrvrName != NULL)
+ free(pThis->pDrvrName);
+ pThis->pDrvrName = NULL;
+ }
RETiRet;
}
@@ -83,8 +95,18 @@ ENDobjConstruct(netstrms)
/* destructor for the netstrms object */
BEGINobjDestruct(netstrms) /* be sure to specify the object type also in END and CODESTART macros! */
CODESTARTobjDestruct(netstrms)
- if(pThis->pDrvrName != NULL)
+ /* and now we must release our driver, if we got one. We use the presence of
+ * a driver name string as load indicator (because we also need that string
+ * to release the driver
+ */
+ if(pThis->pDrvrName != NULL) {
+ obj.ReleaseObj(__FILE__, pThis->pDrvrName+2, pThis->pDrvrName, (void*) &pThis->Drvr);
free(pThis->pDrvrName);
+ }
+ if(pThis->pBaseDrvrName != NULL) {
+ free(pThis->pBaseDrvrName);
+ pThis->pBaseDrvrName = NULL;
+ }
ENDobjDestruct(netstrms)
@@ -100,6 +122,54 @@ finalize_it:
}
+/* set the base driver name. If the driver name
+ * is set to NULL, the previously set name is deleted but
+ * no name set again (which results in the system default being
+ * used)-- rgerhards, 2008-05-05
+ */
+static rsRetVal
+SetDrvrName(netstrms_t *pThis, uchar *pszName)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ if(pThis->pBaseDrvrName != NULL) {
+ free(pThis->pBaseDrvrName);
+ pThis->pBaseDrvrName = NULL;
+ }
+
+ if(pszName != NULL) {
+ CHKmalloc(pThis->pBaseDrvrName = (uchar*) strdup((char*) pszName));
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* set the driver mode -- rgerhards, 2008-04-30
+ */
+static rsRetVal
+SetDrvrMode(netstrms_t *pThis, int iMode)
+{
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ pThis->iDrvrMode = iMode;
+ RETiRet;
+}
+
+
+/* return the driver mode
+ * We use non-standard calling conventions because it makes an awful lot
+ * of sense here.
+ * rgerhards, 2008-04-30
+ */
+static int
+GetDrvrMode(netstrms_t *pThis)
+{
+ ISOBJ_TYPE_assert(pThis, netstrms);
+ return pThis->iDrvrMode;
+}
+
+
/* create an instance of a netstrm object. It is initialized with default
* values. The current driver is used. The caller may set netstrm properties
* and must call ConstructFinalize().
@@ -110,7 +180,7 @@ CreateStrm(netstrms_t *pThis, netstrm_t **ppStrm)
netstrm_t *pStrm = NULL;
DEFiRet;
- CHKiRet(objUse(netstrm, LM_NETSTRM_FILENAME));
+ CHKiRet(objUse(netstrm, DONT_LOAD_LIB));
CHKiRet(netstrm.Construct(&pStrm));
/* we copy over our driver structure. We could provide a pointer to
* ourselves, but that costs some performance on each driver invocation.
@@ -147,6 +217,9 @@ CODESTARTobjQueryInterface(netstrms)
pIf->ConstructFinalize = netstrmsConstructFinalize;
pIf->Destruct = netstrmsDestruct;
pIf->CreateStrm = CreateStrm;
+ pIf->SetDrvrName = SetDrvrName;
+ pIf->SetDrvrMode = SetDrvrMode;
+ pIf->GetDrvrMode = GetDrvrMode;
finalize_it:
ENDobjQueryInterface(netstrms)
@@ -155,9 +228,8 @@ ENDobjQueryInterface(netstrms)
BEGINObjClassExit(netstrms, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
CODESTARTObjClassExit(netstrms)
/* release objects we no longer need */
- //objRelease(net, CORE_COMPONENT);
objRelease(glbl, CORE_COMPONENT);
- objRelease(netstrm, LM_NETSTRM_FILENAME);
+ objRelease(netstrm, DONT_LOAD_LIB);
ENDObjClassExit(netstrms)
@@ -168,7 +240,6 @@ ENDObjClassExit(netstrms)
BEGINAbstractObjClassInit(netstrms, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
CHKiRet(objUse(glbl, CORE_COMPONENT));
- //CHKiRet(objUse(net, CORE_COMPONENT));
/* set our own handlers */
ENDObjClassInit(netstrms)
@@ -179,7 +250,9 @@ ENDObjClassInit(netstrms)
BEGINmodExit
CODESTARTmodExit
+ nsselClassExit();
netstrmsClassExit();
+ netstrmClassExit(); /* we use this object, so we must exit it after we are finished */
ENDmodExit
@@ -194,7 +267,9 @@ CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
/* Initialize all classes that are in our module - this includes ourselfs */
- CHKiRet(netstrmsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ CHKiRet(netstrmClassInit(pModInfo));
+ CHKiRet(nsselClassInit(pModInfo));
+ CHKiRet(netstrmsClassInit(pModInfo));
ENDmodInit
/* vi:set ai:
*/
diff --git a/runtime/netstrms.h b/runtime/netstrms.h
index 1e920304..1d1cc892 100644
--- a/runtime/netstrms.h
+++ b/runtime/netstrms.h
@@ -29,7 +29,9 @@
/* the netstrms object */
struct netstrms_s {
BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
- uchar *pDrvrName; /**< nsd driver name to use, or NULL if system default */
+ uchar *pBaseDrvrName; /**< nsd base driver name to use, or NULL if system default */
+ uchar *pDrvrName; /**< full base driver name (set when driver is loaded) */
+ int iDrvrMode; /**< current default driver mode */
nsd_if_t Drvr; /**< our stream driver */
};
@@ -40,6 +42,9 @@ BEGINinterface(netstrms) /* name must also be changed in ENDinterface macro! */
rsRetVal (*ConstructFinalize)(netstrms_t *pThis);
rsRetVal (*Destruct)(netstrms_t **ppThis);
rsRetVal (*CreateStrm)(netstrms_t *pThis, netstrm_t **ppStrm);
+ rsRetVal (*SetDrvrName)(netstrms_t *pThis, uchar *pszName);
+ rsRetVal (*SetDrvrMode)(netstrms_t *pThis, int iMode);
+ int (*GetDrvrMode)(netstrms_t *pThis);
ENDinterface(netstrms)
#define netstrmsCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
diff --git a/runtime/nsd.h b/runtime/nsd.h
index 1b3702a0..cc06c877 100644
--- a/runtime/nsd.h
+++ b/runtime/nsd.h
@@ -50,6 +50,7 @@ BEGINinterface(nsd) /* name must also be changed in ENDinterface macro! */
rsRetVal (*AcceptConnReq)(nsd_t *pThis, nsd_t **ppThis);
rsRetVal (*GetRemoteHName)(nsd_t *pThis, uchar **pszName);
rsRetVal (*GetRemoteIP)(nsd_t *pThis, uchar **pszIP);
+ rsRetVal (*SetMode)(nsd_t *pThis, int mode); /* sets a driver specific mode - see driver doc for details */
rsRetVal (*GetSock)(nsd_t *pThis, int *pSock);
rsRetVal (*SetSock)(nsd_t *pThis, int sock);
/* GetSock() and SetSock() return an error if the driver does not use plain
diff --git a/runtime/nsd_gtls.c b/runtime/nsd_gtls.c
index d59043f2..20de772a 100644
--- a/runtime/nsd_gtls.c
+++ b/runtime/nsd_gtls.c
@@ -30,11 +30,18 @@
#include "rsyslog.h"
#include "syslogd-types.h"
#include "module-template.h"
+#include "cfsysline.h"
#include "obj.h"
#include "errmsg.h"
#include "nsd_ptcp.h"
+#include "nsdsel_gtls.h"
#include "nsd_gtls.h"
+/* things to move to some better place/functionality - TODO */
+#define DH_BITS 1024
+#define CRLFILE "crl.pem"
+
+
MODULE_TYPE_LIB
/* static data */
@@ -43,25 +50,43 @@ DEFobjCurrIf(errmsg)
DEFobjCurrIf(glbl)
DEFobjCurrIf(nsd_ptcp)
+static int bGlblSrvrInitDone = 0; /**< 0 - server global init not yet done, 1 - already done */
/* a macro to check GnuTLS calls against unexpected errors */
#define CHKgnutls(x) \
if((gnuRet = (x)) != 0) { \
- dbgprintf("unexpected GnuTLS error %d in %s:%d\n", gnuRet, __FILE__, __LINE__); \
- gnutls_perror(gnuRet); /* TODO: can we do better? */ \
+ uchar *pErr = gtlsStrerror(gnuRet); \
+ dbgprintf("unexpected GnuTLS error %d in %s:%d: %s\n", gnuRet, __FILE__, __LINE__, pErr); \
+ free(pErr); \
ABORT_FINALIZE(RS_RET_GNUTLS_ERR); \
}
-#define CAFILE "ca.pem" // TODO: allow to specify
/* ------------------------------ GnuTLS specifics ------------------------------ */
static gnutls_certificate_credentials xcred;
+static gnutls_dh_params dh_params;
+
+/* a thread-safe variant of gnutls_strerror - TODO: implement it!
+ * The caller must free the returned string.
+ * rgerhards, 2008-04-30
+ */
+uchar *gtlsStrerror(int error)
+{
+ uchar *pErr;
+
+ // TODO: guard by mutex!
+ pErr = (uchar*) strdup(gnutls_strerror(error));
+
+ return pErr;
+}
+
/* globally initialize GnuTLS */
static rsRetVal
gtlsGlblInit(void)
{
int gnuRet;
+ uchar *cafile;
DEFiRet;
CHKgnutls(gnutls_global_init());
@@ -70,7 +95,90 @@ gtlsGlblInit(void)
CHKgnutls(gnutls_certificate_allocate_credentials(&xcred));
/* sets the trusted cas file */
- gnutls_certificate_set_x509_trust_file(xcred, CAFILE, GNUTLS_X509_FMT_PEM);
+ cafile = glbl.GetDfltNetstrmDrvrCAF();
+ dbgprintf("GTLS CA file: '%s'\n", cafile);
+ gnuRet = gnutls_certificate_set_x509_trust_file(xcred, (char*)cafile, GNUTLS_X509_FMT_PEM);
+ if(gnuRet < 0) {
+ /* TODO; a more generic error-tracking function (this one based on CHKgnutls()) */
+ uchar *pErr = gtlsStrerror(gnuRet);
+ dbgprintf("unexpected GnuTLS error %d in %s:%d: %s\n", gnuRet, __FILE__, __LINE__, pErr);
+ free(pErr);
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+static rsRetVal
+gtlsInitSession(nsd_gtls_t *pThis)
+{
+ DEFiRet;
+ int gnuRet;
+ gnutls_session session;
+
+ gnutls_init(&session, GNUTLS_SERVER);
+ pThis->bHaveSess = 1;
+ pThis->bIsInitiator = 0;
+
+ /* avoid calling all the priority functions, since the defaults are adequate. */
+ CHKgnutls(gnutls_set_default_priority(session));
+ CHKgnutls(gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred));
+
+ /* request client certificate if any. */
+ gnutls_certificate_server_set_request( session, GNUTLS_CERT_REQUEST);
+ gnutls_dh_set_prime_bits(session, DH_BITS);
+
+ pThis->sess = session;
+
+finalize_it:
+ RETiRet;
+}
+
+
+
+static rsRetVal
+generate_dh_params(void)
+{
+ int gnuRet;
+ DEFiRet;
+ /* Generate Diffie Hellman parameters - for use with DHE
+ * kx algorithms. These should be discarded and regenerated
+ * once a day, once a week or once a month. Depending on the
+ * security requirements.
+ */
+ CHKgnutls(gnutls_dh_params_init( &dh_params));
+ CHKgnutls(gnutls_dh_params_generate2( dh_params, DH_BITS));
+finalize_it:
+ RETiRet;
+}
+
+
+/* set up all global things that are needed for server operations
+ * rgerhards, 2008-04-30
+ */
+static rsRetVal
+gtlsGlblInitLstn(void)
+{
+ int gnuRet;
+ uchar *keyFile;
+ uchar *certFile;
+ DEFiRet;
+
+ if(bGlblSrvrInitDone == 0) {
+ /* we do not use CRLs right now, and I doubt we'll ever do. This functionality is
+ * considered legacy. -- rgerhards, 2008-05-05
+ */
+ /*CHKgnutls(gnutls_certificate_set_x509_crl_file(xcred, CRLFILE, GNUTLS_X509_FMT_PEM));*/
+ certFile = glbl.GetDfltNetstrmDrvrCertFile();
+ keyFile = glbl.GetDfltNetstrmDrvrKeyFile();
+ dbgprintf("GTLS certificate file: '%s'\n", certFile);
+ dbgprintf("GTLS key file: '%s'\n", keyFile);
+ CHKgnutls(gnutls_certificate_set_x509_key_file(xcred, (char*)certFile, (char*)keyFile, GNUTLS_X509_FMT_PEM));
+ CHKiRet(generate_dh_params());
+ gnutls_certificate_set_dh_params(xcred, dh_params); /* this is void */
+ bGlblSrvrInitDone = 1; /* we are all set now */
+ }
finalize_it:
RETiRet;
@@ -100,9 +208,11 @@ gtlsEndSess(nsd_gtls_t *pThis)
DEFiRet;
if(pThis->bHaveSess) {
- gnuRet = gnutls_bye(pThis->sess, GNUTLS_SHUT_RDWR);
- while(gnuRet == GNUTLS_E_INTERRUPTED || gnuRet == GNUTLS_E_AGAIN) {
+ if(pThis->bIsInitiator) {
gnuRet = gnutls_bye(pThis->sess, GNUTLS_SHUT_RDWR);
+ while(gnuRet == GNUTLS_E_INTERRUPTED || gnuRet == GNUTLS_E_AGAIN) {
+ gnuRet = gnutls_bye(pThis->sess, GNUTLS_SHUT_RDWR);
+ }
}
gnutls_deinit(pThis->sess);
}
@@ -116,8 +226,6 @@ gtlsEndSess(nsd_gtls_t *pThis)
/* Standard-Constructor */
BEGINobjConstruct(nsd_gtls) /* be sure to specify the object type also in END macro! */
iRet = nsd_ptcp.Construct(&pThis->pTcp);
- pThis->iMode = 1; /* TODO: must be made configurable */
- pThis->iMode = 0; /* TODO: must be made configurable */
ENDobjConstruct(nsd_gtls)
@@ -134,6 +242,29 @@ CODESTARTobjDestruct(nsd_gtls)
ENDobjDestruct(nsd_gtls)
+/* Set the driver mode. For us, this has the following meaning:
+ * 0 - work in plain tcp mode, without tls (e.g. before a STARTTLS)
+ * 1 - work in TLS mode
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+SetMode(nsd_t *pNsd, int mode)
+{
+ DEFiRet;
+ nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
+
+dbgprintf("SetMOde tries to set mode %d\n", mode);
+ ISOBJ_TYPE_assert((pThis), nsd_gtls);
+ if(mode != 0 && mode != 1)
+ ABORT_FINALIZE(RS_RET_INVAID_DRVR_MODE);
+
+ pThis->iMode = mode;
+
+finalize_it:
+ RETiRet;
+}
+
+
/* Provide access to the underlying OS socket. This is primarily
* useful for other drivers (like nsd_gtls) who utilize ourselfs
* for some of their functionality. -- rgerhards, 2008-04-18
@@ -184,7 +315,9 @@ LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
uchar *pLstnPort, uchar *pLstnIP, int iSessMax)
{
DEFiRet;
+ CHKiRet(gtlsGlblInitLstn());
iRet = nsd_ptcp.LstnInit(pNS, pUsr, fAddLstn, pLstnPort, pLstnIP, iSessMax);
+finalize_it:
RETiRet;
}
@@ -227,15 +360,38 @@ static rsRetVal
AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
{
DEFiRet;
+ int gnuRet;
nsd_gtls_t *pNew = NULL;
nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
ISOBJ_TYPE_assert((pThis), nsd_gtls);
- // TODO: method to construct without pTcp
CHKiRet(nsd_gtlsConstruct(&pNew));
CHKiRet(nsd_ptcp.Destruct(&pNew->pTcp));
CHKiRet(nsd_ptcp.AcceptConnReq(pThis->pTcp, &pNew->pTcp));
+ if(pThis->iMode == 0) {
+ /* we are in non-TLS mode, so we are done */
+ *ppNew = (nsd_t*) pNew;
+ FINALIZE;
+ }
+
+ /* if we reach this point, we are in TLS mode */
+ CHKiRet(gtlsInitSession(pNew));
+ gnutls_transport_set_ptr(pNew->sess, (gnutls_transport_ptr_t)((nsd_ptcp_t*) (pNew->pTcp))->sock);
+
+ /* we now do the handshake. This is a bit complicated, because we are
+ * on non-blocking sockets. Usually, the handshake will not complete
+ * immediately, so that we need to retry it some time later.
+ */
+ gnuRet = gnutls_handshake(pNew->sess);
+ if(gnuRet == GNUTLS_E_AGAIN || gnuRet == GNUTLS_E_INTERRUPTED) {
+ pNew->rtryCall = gtlsRtry_handshake;
+ dbgprintf("GnuTLS handshake does not complete immediately - setting to retry (this is OK and normal)\n");
+ } else if(gnuRet != 0) {
+ ABORT_FINALIZE(RS_RET_TLS_HANDSHAKE_ERR);
+ }
+ pNew->iMode = 1; /* this session is now in TLS mode! */
+
*ppNew = (nsd_t*) pNew;
finalize_it:
@@ -260,6 +416,8 @@ static rsRetVal
Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
{
DEFiRet;
+ int gnuRet;
+ ssize_t lenRcvd;
nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
ISOBJ_TYPE_assert(pThis, nsd_gtls);
@@ -269,6 +427,8 @@ Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
}
/* in TLS mode now */
+ lenRcvd = gnutls_record_recv(pThis->sess, pBuf, *pLenBuf);
+ *pLenBuf = lenRcvd;
finalize_it:
RETiRet;
@@ -301,8 +461,11 @@ Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
*pLenBuf = iSent;
break;
}
- if(iSent != GNUTLS_E_INTERRUPTED && iSent != GNUTLS_E_AGAIN)
+ if(iSent != GNUTLS_E_INTERRUPTED && iSent != GNUTLS_E_AGAIN) {
+ dbgprintf("unexpected GnuTLS error %d in %s:%d\n", iSent, __FILE__, __LINE__);
+ gnutls_perror(iSent); /* TODO: can we do better? */
ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ }
}
finalize_it:
@@ -335,6 +498,7 @@ Connect(nsd_t *pNsd, int family, uchar *port, uchar *host)
/* we reach this point if in TLS mode */
CHKgnutls(gnutls_init(&pThis->sess, GNUTLS_CLIENT));
pThis->bHaveSess = 1;
+ pThis->bIsInitiator = 1;
/* Use default priorities */
CHKgnutls(gnutls_set_default_priority(pThis->sess));
@@ -345,7 +509,7 @@ Connect(nsd_t *pNsd, int family, uchar *port, uchar *host)
/* assign the socket to GnuTls */
CHKiRet(nsd_ptcp.GetSock(pThis->pTcp, &sock));
- gnutls_transport_set_ptr(pThis->sess, (gnutls_transport_ptr)sock);
+ gnutls_transport_set_ptr(pThis->sess, (gnutls_transport_ptr_t)sock);
/* and perform the handshake */
CHKgnutls(gnutls_handshake(pThis->sess));
@@ -384,6 +548,7 @@ CODESTARTobjQueryInterface(nsd_gtls)
pIf->Send = Send;
pIf->Connect = Connect;
pIf->SetSock = SetSock;
+ pIf->SetMode = SetMode;
pIf->GetRemoteHName = GetRemoteHName;
pIf->GetRemoteIP = GetRemoteIP;
finalize_it:
@@ -423,6 +588,7 @@ ENDObjClassInit(nsd_gtls)
BEGINmodExit
CODESTARTmodExit
+ nsdsel_gtlsClassExit();
nsd_gtlsClassExit();
ENDmodExit
@@ -439,6 +605,8 @@ CODESTARTmodInit
/* Initialize all classes that are in our module - this includes ourselfs */
CHKiRet(nsd_gtlsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ CHKiRet(nsdsel_gtlsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+
ENDmodInit
/* vi:set ai:
*/
diff --git a/runtime/nsd_gtls.h b/runtime/nsd_gtls.h
index c193f57c..83e15f29 100644
--- a/runtime/nsd_gtls.h
+++ b/runtime/nsd_gtls.h
@@ -26,6 +26,11 @@
#include "nsd.h"
+typedef enum {
+ gtlsRtry_None = 0, /**< no call needs to be retried */
+ gtlsRtry_handshake = 1
+} gtlsRtryCall_t; /**< IDs of calls that needs to be retried */
+
typedef nsd_if_t nsd_gtls_if_t; /* we just *implement* this interface */
/* the nsd_gtls object */
@@ -33,8 +38,11 @@ struct nsd_gtls_s {
BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
nsd_t *pTcp; /**< our aggregated nsd_ptcp data */
int iMode; /* 0 - plain tcp, 1 - TLS */
+ gtlsRtryCall_t rtryCall;/**< what must we retry? */
+ int bIsInitiator; /**< 0 if socket is the server end (listener), 1 if it is the initiator */
gnutls_session sess;
- int bHaveSess;
+ int bHaveSess; /* as we don't know exactly which gnutls_session values are invalid, we use this one
+ to flag whether or not we are in a session (same as -1 for a socket meaning no sess) */
};
/* interface is defined in nsd.h, we just implement it! */
diff --git a/runtime/nsd_ptcp.c b/runtime/nsd_ptcp.c
index 2a74e061..c5480a05 100644
--- a/runtime/nsd_ptcp.c
+++ b/runtime/nsd_ptcp.c
@@ -47,6 +47,7 @@
#include "net.h"
#include "netstrms.h"
#include "netstrm.h"
+#include "nsdsel_ptcp.h"
#include "nsd_ptcp.h"
MODULE_TYPE_LIB
@@ -109,6 +110,22 @@ GetSock(nsd_t *pNsd, int *pSock)
}
+/* Set the driver mode. We support no different modes, but allow mode
+ * 0 to be set to be compatible with config file defaults and the other
+ * drivers.
+ * rgerhards, 2008-04-28
+ */
+static rsRetVal
+SetMode(nsd_t __attribute__((unused)) *pNsd, int mode)
+{
+ DEFiRet;
+ if(mode != 0)
+ ABORT_FINALIZE(RS_RET_INVAID_DRVR_MODE);
+finalize_it:
+ RETiRet;
+}
+
+
/* Provide access to the underlying OS socket. This is primarily
* useful for other drivers (like nsd_gtls) who utilize ourselfs
* for some of their functionality.
@@ -415,13 +432,11 @@ LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal(*fAddLstn)(void*,netstrm_t*),
* construct a new netstrm obj and hand it over to the upper layers for inclusion
* into their socket array. -- rgerhards, 2008-04-23
*/
-RUNLOG_VAR("%d", sock);
CHKiRet(pNS->Drvr.Construct(&pNewNsd));
CHKiRet(pNS->Drvr.SetSock(pNewNsd, sock));
-RUNLOG;
+ CHKiRet(pNS->Drvr.SetMode(pNewNsd, netstrms.GetDrvrMode(pNS)));
CHKiRet(netstrms.CreateStrm(pNS, &pNewStrm));
pNewStrm->pDrvrData = (nsd_t*) pNewNsd;
-RUNLOG;
CHKiRet(fAddLstn(pUsr, pNewStrm));
pNewNsd = NULL;
pNewStrm = NULL;
@@ -609,6 +624,7 @@ CODESTARTobjQueryInterface(nsd_ptcp)
pIf->Abort = Abort;
pIf->GetSock = GetSock;
pIf->SetSock = SetSock;
+ pIf->SetMode = SetMode;
pIf->Rcv = Rcv;
pIf->Send = Send;
pIf->LstnInit = LstnInit;
@@ -628,7 +644,7 @@ CODESTARTObjClassExit(nsd_ptcp)
objRelease(net, CORE_COMPONENT);
objRelease(glbl, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
- objRelease(netstrm, LM_NETSTRM_FILENAME);
+ objRelease(netstrm, DONT_LOAD_LIB);
objRelease(netstrms, LM_NETSTRMS_FILENAME);
ENDObjClassExit(nsd_ptcp)
@@ -642,8 +658,8 @@ BEGINObjClassInit(nsd_ptcp, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
CHKiRet(objUse(net, CORE_COMPONENT));
- CHKiRet(objUse(netstrm, LM_NETSTRM_FILENAME));
CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME));
+ CHKiRet(objUse(netstrm, DONT_LOAD_LIB));
/* set our own handlers */
ENDObjClassInit(nsd_ptcp)
@@ -654,6 +670,7 @@ ENDObjClassInit(nsd_ptcp)
BEGINmodExit
CODESTARTmodExit
+ nsdsel_ptcpClassExit();
nsd_ptcpClassExit();
ENDmodExit
@@ -670,6 +687,7 @@ CODESTARTmodInit
/* Initialize all classes that are in our module - this includes ourselfs */
CHKiRet(nsd_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ CHKiRet(nsdsel_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
ENDmodInit
/* vi:set ai:
*/
diff --git a/runtime/nsdsel_gtls.c b/runtime/nsdsel_gtls.c
index 7cafec49..8c1e705b 100644
--- a/runtime/nsdsel_gtls.c
+++ b/runtime/nsdsel_gtls.c
@@ -37,11 +37,10 @@
#include "errmsg.h"
#include "nsd.h"
#include "nsd_gtls.h"
+#include "nsd_ptcp.h"
#include "nsdsel_ptcp.h"
#include "nsdsel_gtls.h"
-MODULE_TYPE_LIB
-
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
@@ -74,7 +73,21 @@ Add(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp)
ISOBJ_TYPE_assert(pThis, nsdsel_gtls);
ISOBJ_TYPE_assert(pNsdGTLS, nsd_gtls);
- iRet = nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, waitOp);
+ if(pNsdGTLS->iMode == 1) {
+ if(pNsdGTLS->rtryCall != gtlsRtry_None) {
+ if(gnutls_record_get_direction(pNsdGTLS->sess) == 0) {
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, NSDSEL_RD));
+ } else {
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, NSDSEL_WR));
+ }
+ FINALIZE;
+ }
+ }
+
+ /* if we reach this point, we need no special handling */
+ CHKiRet(nsdsel_ptcp.Add(pThis->pTcp, pNsdGTLS->pTcp, waitOp));
+
+finalize_it:
RETiRet;
}
@@ -94,6 +107,47 @@ Select(nsdsel_t *pNsdsel, int *piNumReady)
}
+/* retry an interrupted GTLS operation
+ * rgerhards, 2008-04-30
+ */
+static rsRetVal
+doRetry(nsd_gtls_t *pNsd)
+{
+ DEFiRet;
+ int gnuRet;
+
+ dbgprintf("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
+ * switch, because the result check is the same for all calls. Note that
+ * this may change once we deal with the read and write calls (but
+ * probably this becomes an issue only when we begin to work on TLS
+ * for relp). -- rgerhards, 2008-04-30
+ */
+ switch(pNsd->rtryCall) {
+ case gtlsRtry_handshake:
+ gnuRet = gnutls_handshake(pNsd->sess);
+ break;
+ default:
+ assert(0); /* this shall not happen! */
+ break;
+ }
+
+ if(gnuRet == 0) {
+ pNsd->rtryCall = gtlsRtry_None; /* we are done */
+ } else if(gnuRet != GNUTLS_E_AGAIN && gnuRet != GNUTLS_E_INTERRUPTED) {
+ ABORT_FINALIZE(RS_RET_GNUTLS_ERR);
+ }
+ /* if we are interrupted once again (else case), we do not need to
+ * change our status because we are already setup for retries.
+ */
+
+finalize_it:
+ RETiRet;
+}
+
+
/* check if a socket is ready for IO */
static rsRetVal
IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady)
@@ -104,7 +158,20 @@ IsReady(nsdsel_t *pNsdsel, nsd_t *pNsd, nsdsel_waitOp_t waitOp, int *pbIsReady)
ISOBJ_TYPE_assert(pThis, nsdsel_gtls);
ISOBJ_TYPE_assert(pNsdGTLS, nsd_gtls);
- iRet = nsdsel_ptcp.IsReady(pThis->pTcp, pNsdGTLS->pTcp, waitOp, pbIsReady);
+ if(pNsdGTLS->iMode == 1) {
+ if(pNsdGTLS->rtryCall != gtlsRtry_None) {
+ CHKiRet(doRetry(pNsdGTLS));
+ /* we used this up for our own internal processing, so the socket
+ * is not ready from the upper layer point of view.
+ */
+ *pbIsReady = 0;
+ FINALIZE;
+ }
+ }
+
+ CHKiRet(nsdsel_ptcp.IsReady(pThis->pTcp, pNsdGTLS->pTcp, waitOp, pbIsReady));
+
+finalize_it:
RETiRet;
}
@@ -135,12 +202,12 @@ ENDobjQueryInterface(nsdsel_gtls)
/* exit our class
*/
-BEGINObjClassExit(nsdsel_gtls, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+BEGINObjClassExit(nsdsel_gtls, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */
CODESTARTObjClassExit(nsdsel_gtls)
/* release objects we no longer need */
objRelease(glbl, CORE_COMPONENT);
objRelease(errmsg, CORE_COMPONENT);
- objRelease(nsdsel_ptcp, LM_NSDSEL_PTCP_FILENAME);
+ objRelease(nsdsel_ptcp, LM_NSD_PTCP_FILENAME);
ENDObjClassExit(nsdsel_gtls)
@@ -148,37 +215,13 @@ ENDObjClassExit(nsdsel_gtls)
* before anything else is called inside this class.
* rgerhards, 2008-02-19
*/
-BEGINObjClassInit(nsdsel_gtls, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+BEGINObjClassInit(nsdsel_gtls, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
- CHKiRet(objUse(nsdsel_ptcp, LM_NSDSEL_PTCP_FILENAME));
+ CHKiRet(objUse(nsdsel_ptcp, LM_NSD_PTCP_FILENAME));
/* set our own handlers */
ENDObjClassInit(nsdsel_gtls)
-
-
-/* --------------- here now comes the plumbing that makes as a library module --------------- */
-
-
-BEGINmodExit
-CODESTARTmodExit
- nsdsel_gtlsClassExit();
-ENDmodExit
-
-
-BEGINqueryEtryPt
-CODESTARTqueryEtryPt
-CODEqueryEtryPt_STD_LIB_QUERIES
-ENDqueryEtryPt
-
-
-BEGINmodInit()
-CODESTARTmodInit
- *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
-
- /* Initialize all classes that are in our module - this includes ourselfs */
- CHKiRet(nsdsel_gtlsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
-ENDmodInit
/* vi:set ai:
*/
diff --git a/runtime/nsdsel_gtls.h b/runtime/nsdsel_gtls.h
index a309d302..7c2df684 100644
--- a/runtime/nsdsel_gtls.h
+++ b/runtime/nsdsel_gtls.h
@@ -39,7 +39,4 @@ struct nsdsel_gtls_s {
/* prototypes */
PROTOTYPEObj(nsdsel_gtls);
-/* the name of our library binary */
-#define LM_NSDSEL_GTLS_FILENAME "lmnsdsel_gtls"
-
#endif /* #ifndef INCLUDED_NSDSEL_GTLS_H */
diff --git a/runtime/nsdsel_ptcp.c b/runtime/nsdsel_ptcp.c
index b439063a..41b85e0c 100644
--- a/runtime/nsdsel_ptcp.c
+++ b/runtime/nsdsel_ptcp.c
@@ -37,8 +37,6 @@
#include "nsd_ptcp.h"
#include "nsdsel_ptcp.h"
-MODULE_TYPE_LIB
-
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(errmsg)
@@ -175,7 +173,7 @@ ENDobjQueryInterface(nsdsel_ptcp)
/* exit our class
*/
-BEGINObjClassExit(nsdsel_ptcp, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
+BEGINObjClassExit(nsdsel_ptcp, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */
CODESTARTObjClassExit(nsdsel_ptcp)
/* release objects we no longer need */
objRelease(glbl, CORE_COMPONENT);
@@ -187,36 +185,12 @@ ENDObjClassExit(nsdsel_ptcp)
* before anything else is called inside this class.
* rgerhards, 2008-02-19
*/
-BEGINObjClassInit(nsdsel_ptcp, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */
+BEGINObjClassInit(nsdsel_ptcp, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(glbl, CORE_COMPONENT));
/* set our own handlers */
ENDObjClassInit(nsdsel_ptcp)
-
-
-/* --------------- here now comes the plumbing that makes as a library module --------------- */
-
-
-BEGINmodExit
-CODESTARTmodExit
- nsdsel_ptcpClassExit();
-ENDmodExit
-
-
-BEGINqueryEtryPt
-CODESTARTqueryEtryPt
-CODEqueryEtryPt_STD_LIB_QUERIES
-ENDqueryEtryPt
-
-
-BEGINmodInit()
-CODESTARTmodInit
- *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
-
- /* Initialize all classes that are in our module - this includes ourselfs */
- CHKiRet(nsdsel_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
-ENDmodInit
/* vi:set ai:
*/
diff --git a/runtime/nsdsel_ptcp.h b/runtime/nsdsel_ptcp.h
index 93874e55..6c0c7fa7 100644
--- a/runtime/nsdsel_ptcp.h
+++ b/runtime/nsdsel_ptcp.h
@@ -41,7 +41,4 @@ struct nsdsel_ptcp_s {
/* prototypes */
PROTOTYPEObj(nsdsel_ptcp);
-/* the name of our library binary */
-#define LM_NSDSEL_PTCP_FILENAME "lmnsdsel_ptcp"
-
#endif /* #ifndef INCLUDED_NSDSEL_PTCP_H */
diff --git a/runtime/nssel.c b/runtime/nssel.c
index 5333fc75..d11d5fe1 100644
--- a/runtime/nssel.c
+++ b/runtime/nssel.c
@@ -44,8 +44,6 @@
#include "netstrm.h"
#include "nssel.h"
-MODULE_TYPE_LIB
-
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(glbl)
@@ -54,18 +52,28 @@ DEFobjCurrIf(glbl)
/* load our low-level driver. This must be done before any
* driver-specific functions (allmost all...) can be carried
* out. Note that the driver's .ifIsLoaded is correctly
- * initialized by calloc() and we depend on that.
- * rgerhards, 2008-04-18
+ * initialized by calloc() and we depend on that. Please note that
+ * we do some name-mangeling. We know that each nsd driver also needs
+ * a nssel driver. So we simply append "sel" to the nsd driver name: This,
+ * of course, means that the driver name must match these rules, but that
+ * shouldn't be a real problem.
+ * WARNING: this code is mostly identical to similar code in
+ * netstrms.c - TODO: abstract it and move it to some common place.
+ * rgerhards, 2008-04-28
*/
static rsRetVal
loadDrvr(nssel_t *pThis)
{
- uchar *pDrvrName;
DEFiRet;
+ uchar *pBaseDrvrName;
+ uchar szDrvrName[48]; /* 48 shall be large enough */
- pDrvrName = pThis->pDrvrName;
- if(pDrvrName == NULL) /* if no drvr name is set, use system default */
- pDrvrName = glbl.GetDfltNetstrmDrvr();
+ pBaseDrvrName = pThis->pBaseDrvrName;
+ if(pBaseDrvrName == NULL) /* if no drvr name is set, use system default */
+ pBaseDrvrName = glbl.GetDfltNetstrmDrvr();
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmnsdsel_%s", pBaseDrvrName) == sizeof(szDrvrName))
+ ABORT_FINALIZE(RS_RET_DRVRNAME_TOO_LONG);
+ CHKmalloc(pThis->pDrvrName = (uchar*) strdup((char*)szDrvrName));
pThis->Drvr.ifVersion = nsdCURR_IF_VERSION;
/* The pDrvrName+2 below is a hack to obtain the object name. It
@@ -74,9 +82,14 @@ loadDrvr(nssel_t *pThis)
* about this hack, but for the time being it is efficient and clean
* enough. -- rgerhards, 2008-04-18
*/
- //CHKiRet(obj.UseObj(__FILE__, pDrvrName+2, pDrvrName, (void*) &pThis->Drvr));
- CHKiRet(obj.UseObj(__FILE__, "nsdsel_gtls", "lmnsdsel_gtls", (void*) &pThis->Drvr));
+ CHKiRet(obj.UseObj(__FILE__, szDrvrName+2, DONT_LOAD_LIB, (void*) &pThis->Drvr));
+
finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis->pDrvrName != NULL)
+ free(pThis->pDrvrName);
+ pThis->pDrvrName = NULL;
+ }
RETiRet;
}
@@ -91,6 +104,15 @@ BEGINobjDestruct(nssel) /* be sure to specify the object type also in END and CO
CODESTARTobjDestruct(nssel)
if(pThis->pDrvrData != NULL)
pThis->Drvr.Destruct(&pThis->pDrvrData);
+
+ /* and now we must release our driver, if we got one. We use the presence of
+ * a driver name string as load indicator (because we also need that string
+ * to release the driver
+ */
+ if(pThis->pDrvrName != NULL) {
+ obj.ReleaseObj(__FILE__, pThis->pDrvrName+2, DONT_LOAD_LIB, (void*) &pThis->Drvr);
+ free(pThis->pDrvrName);
+ }
ENDobjDestruct(nssel)
@@ -201,29 +223,5 @@ BEGINObjClassInit(nssel, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* set our own handlers */
ENDObjClassInit(nssel)
-
-
-/* --------------- here now comes the plumbing that makes us a library module --------------- */
-
-
-BEGINmodExit
-CODESTARTmodExit
- nsselClassExit();
-ENDmodExit
-
-
-BEGINqueryEtryPt
-CODESTARTqueryEtryPt
-CODEqueryEtryPt_STD_LIB_QUERIES
-ENDqueryEtryPt
-
-
-BEGINmodInit()
-CODESTARTmodInit
- *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
-
- /* Initialize all classes that are in our module - this includes ourselfs */
- CHKiRet(nsselClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
-ENDmodInit
/* vi:set ai:
*/
diff --git a/runtime/nssel.h b/runtime/nssel.h
index 2f907caa..8cb34f5a 100644
--- a/runtime/nssel.h
+++ b/runtime/nssel.h
@@ -24,13 +24,14 @@
#ifndef INCLUDED_NSSEL_H
#define INCLUDED_NSSEL_H
-#include "nsd.h"
+#include "netstrms.h"
/* the nssel object */
struct nssel_s {
BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
nsd_t *pDrvrData; /**< the driver's data elements */
- uchar *pDrvrName; /**< nsd driver name to use, or NULL if system default */
+ uchar *pBaseDrvrName; /**< nsd base driver name to use, or NULL if system default */
+ uchar *pDrvrName; /**< full base driver name (set when driver is loaded) */
nsdsel_if_t Drvr; /**< our stream driver */
};
@@ -50,6 +51,6 @@ ENDinterface(nssel)
PROTOTYPEObj(nssel);
/* the name of our library binary */
-#define LM_NSSEL_FILENAME "lmnssel"
+#define LM_NSSEL_FILENAME LM_NETSTRMS_FILENAME
#endif /* #ifndef INCLUDED_NSSEL_H */
diff --git a/runtime/obj.c b/runtime/obj.c
index 18a4a726..312ed223 100644
--- a/runtime/obj.c
+++ b/runtime/obj.c
@@ -1192,15 +1192,14 @@ ReleaseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf)
objInfo_t *pObjInfo;
- dbgprintf("source file %s requests object '%s', ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded);
+ dbgprintf("source file %s releasing object '%s', ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded);
if(pObjFile == NULL)
FINALIZE; /* if it is not a lodable module, we do not need to do anything... */
if(pIf->ifIsLoaded == 0) {
ABORT_FINALIZE(RS_RET_OK); /* we are not loaded - this is perfectly OK... */
- }
- if(pIf->ifIsLoaded == 2) {
+ } else if(pIf->ifIsLoaded == 2) {
pIf->ifIsLoaded = 0; /* clean up */
ABORT_FINALIZE(RS_RET_OK); /* we had a load error and can not continue */
}
@@ -1209,7 +1208,6 @@ ReleaseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf)
CHKiRet(FindObjInfo(pStr, &pObjInfo));
/* if we reach this point, we have a valid pObjInfo */
- //if(pObjInfo->pModInfo != NULL) { /* NULL means core module */
module.Release(srcFile, &pObjInfo->pModInfo); /* decrease refcount */
pIf->ifIsLoaded = 0; /* indicated "no longer valid" */
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index 19fda468..c32e190c 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -219,6 +219,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_GNUTLS_ERR = -2078, /**< (unexpected) error in GnuTLS call */
RS_RET_MAX_SESS_REACHED = -2079, /**< max nbr of sessions reached, can not create more */
RS_RET_MAX_LSTN_REACHED = -2080, /**< max nbr of listeners reached, can not create more */
+ RS_RET_INVAID_DRVR_MODE = -2081, /**< tried to set mode not supported by driver */
+ RS_RET_DRVRNAME_TOO_LONG = -2082, /**< driver name too long - should never happen */
+ RS_RET_TLS_HANDSHAKE_ERR = -2083, /**< TLS handshake failed */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */