Hello community,
here is the log from the commit of package librelp for openSUSE:Factory checked in at 2013-07-12 20:47:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/librelp (Old)
and /work/SRC/openSUSE:Factory/.librelp.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "librelp"
Changes:
--------
--- /work/SRC/openSUSE:Factory/librelp/librelp.changes 2013-07-02 07:38:23.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.librelp.new/librelp.changes 2013-07-12 20:47:58.000000000 +0200
@@ -1,0 +2,25 @@
+Thu Jul 11 21:41:09 UTC 2013 - andreas.stieger@gmx.de
+
+- update to 1.1.5:
+ This is a bug-fixing release that takes care of a memory leak on
+ connection close as well as potential misadressing on session
+ close.
+ - bugfix: memory leak on connection close
+ - bugfix: potential misadressing on session close
+
+-------------------------------------------------------------------
+Thu Jul 11 21:35:53 UTC 2013 - andreas.stieger@gmx.de
+
+- update to 1.1.4:
+ This version of the library provides certificate wildcard name
+ checks. It also supports enhanced performance options (burst
+ support, requires support from the caller). It also contains
+ some bug fixes, especially for BSD.
+ - fix build problems on BSD
+ - add ability to specify a non-standard RELP Window size
+ - add burst support to the client API
+ - wildcards are now supported in TLS name peer authentication
+ - new APIs: relpCltHintBurstBegin, relpCltHintBurstEnd,
+ relpCltSetWindowSize
+
+-------------------------------------------------------------------
Old:
----
librelp-1.1.3.tar.gz
New:
----
librelp-1.1.5.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ librelp.spec ++++++
--- /var/tmp/diff_new_pack.F8AMNh/_old 2013-07-12 20:47:59.000000000 +0200
+++ /var/tmp/diff_new_pack.F8AMNh/_new 2013-07-12 20:47:59.000000000 +0200
@@ -18,7 +18,7 @@
Name: librelp
%define library_name librelp0
-Version: 1.1.3
+Version: 1.1.5
Release: 0
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Url: http://www.librelp.com/
++++++ librelp-1.1.3.tar.gz -> librelp-1.1.5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/ChangeLog new/librelp-1.1.5/ChangeLog
--- old/librelp-1.1.3/ChangeLog 2013-06-26 15:24:33.000000000 +0200
+++ new/librelp-1.1.5/ChangeLog 2013-07-05 09:55:19.000000000 +0200
@@ -1,4 +1,25 @@
----------------------------------------------------------------------
+Version 1.1.5 - 2013-07-05
+- bugfix: memory leak on connection close
+ around 60 bytes of memory were lost on each connection close at the
+ server side (when the client initiated a close)
+- bugfix: potential misadressing on session close
+ This can happen if also a write was outstanding, a quite unusable
+ situation. In that case, already freed memory was being accessed.
+----------------------------------------------------------------------
+Version 1.1.4 - 2013-07-03
+- fix build problems on BSD
+ Thanks to Christiano for analysis and patch suggestion.
+- add ability to specify a non-standard RELP Window size
+- add burst support to the client API
+ With this, we remove the unconditional performance improvement
+ done in 1.1.3 - it is better to call the APIs explicitely.
+- wildcards are now supported in TLS name peer authentication
+ They follow RFC5425 recommandations, e.g.
+ *.example.com, client*.example.com, client01.*.com
+- new APIs: relpCltHintBurstBegin, relpCltHintBurstEnd,
+ relpCltSetWindowSize
+----------------------------------------------------------------------
Version 1.1.3 - 2013-06-26
- increased performance of RELP connection
- bugfix: potential segfault if no GnuTLS priority string was set
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/configure new/librelp-1.1.5/configure
--- old/librelp-1.1.3/configure 2013-06-26 15:24:57.000000000 +0200
+++ new/librelp-1.1.5/configure 2013-07-05 10:31:22.000000000 +0200
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for librelp 1.1.3.
+# Generated by GNU Autoconf 2.69 for librelp 1.1.5.
#
# Report bugs to .
#
@@ -590,8 +590,8 @@
# Identity of this package.
PACKAGE_NAME='librelp'
PACKAGE_TARNAME='librelp'
-PACKAGE_VERSION='1.1.3'
-PACKAGE_STRING='librelp 1.1.3'
+PACKAGE_VERSION='1.1.5'
+PACKAGE_STRING='librelp 1.1.5'
PACKAGE_BUGREPORT='rgerhards@adiscon.com'
PACKAGE_URL=''
@@ -1322,7 +1322,7 @@
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures librelp 1.1.3 to adapt to many kinds of systems.
+\`configure' configures librelp 1.1.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1392,7 +1392,7 @@
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of librelp 1.1.3:";;
+ short | recursive ) echo "Configuration of librelp 1.1.5:";;
esac
cat <<\_ACEOF
@@ -1506,7 +1506,7 @@
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-librelp configure 1.1.3
+librelp configure 1.1.5
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1986,7 +1986,7 @@
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by librelp $as_me 1.1.3, which was
+It was created by librelp $as_me 1.1.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2810,7 +2810,7 @@
# Define the identity of the package.
PACKAGE='librelp'
- VERSION='1.1.3'
+ VERSION='1.1.5'
cat >>confdefs.h <<_ACEOF
@@ -2878,7 +2878,7 @@
# Define the identity of the package.
PACKAGE='librelp'
- VERSION='1.1.3'
+ VERSION='1.1.5'
cat >>confdefs.h <<_ACEOF
@@ -13036,7 +13036,7 @@
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by librelp $as_me 1.1.3, which was
+This file was extended by librelp $as_me 1.1.5, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -13102,7 +13102,7 @@
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-librelp config.status 1.1.3
+librelp config.status 1.1.5
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/configure.ac new/librelp-1.1.5/configure.ac
--- old/librelp-1.1.3/configure.ac 2013-06-26 15:24:42.000000000 +0200
+++ new/librelp-1.1.5/configure.ac 2013-07-05 09:55:36.000000000 +0200
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([librelp], [1.1.3], [rgerhards@adiscon.com])
+AC_INIT([librelp], [1.1.5], [rgerhards@adiscon.com])
AM_INIT_AUTOMAKE
AM_INIT_AUTOMAKE
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/cmdif.h new/librelp-1.1.5/src/cmdif.h
--- old/librelp-1.1.3/src/cmdif.h 2013-02-05 16:09:25.000000000 +0100
+++ new/librelp-1.1.5/src/cmdif.h 2013-06-27 12:49:14.000000000 +0200
@@ -49,7 +49,7 @@
relpRetVal relp##type##C##cmd(relpFrame_t *pFrame, relpSess_t *pSess);
#define BEGINcommand(type, cmd) \
- relpRetVal relp##type##C##cmd(relpFrame_t *pFrame, relpSess_t *pSess) \
+ relpRetVal relp##type##C##cmd(relpFrame_t __attribute__((unused)) *pFrame, relpSess_t *pSess) \
{ \
RELPOBJ_assert(pFrame, Frame); \
RELPOBJ_assert(pSess, Sess);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/librelp.h new/librelp-1.1.5/src/librelp.h
--- old/librelp-1.1.3/src/librelp.h 2013-06-25 14:55:56.000000000 +0200
+++ new/librelp-1.1.5/src/librelp.h 2013-07-05 09:54:46.000000000 +0200
@@ -145,6 +145,10 @@
#define RELP_RET_AUTH_NO_CERT RELPERR_BASE + 35 /**< auth failed: peer did not present a certificate */
#define RELP_RET_AUTH_CERT_INVL RELPERR_BASE + 36 /**< auth failed: peer certificate invalid (did not pass validation) */
#define RELP_RET_INVLD_AUTH_MD RELPERR_BASE + 37 /**< lib user tried to set invalid auth mode */
+#define RELP_RET_INVLD_WILDCARD RELPERR_BASE + 38 /**< invalid wildcard given in permitted peer name */
+#define RELP_RET_ERR_TLS_HANDS RELPERR_BASE + 39 /**< TLS handshake failed */
+#define RELP_RET_ERR_TLS RELPERR_BASE + 40 /**< generic TLS error */
+#define RELP_RET_ERR_INVAL RELPERR_BASE + 41 /**< some parameter is invalid (like EINVAL) */
/* some macros to work with librelp error codes */
#define CHKRet(code) if((iRet = code) != RELP_RET_OK) goto finalize_it
@@ -174,6 +178,8 @@
relpRetVal relpEngineSetDnsLookupMode(relpEngine_t *pThis, int iMode);
relpRetVal relpEngineSetOnAuthErr(relpEngine_t *pThis,
void (*pCB)(void*pUsr, char *authinfo, char*errmsg, relpRetVal errcode) );
+relpRetVal relpEngineSetOnErr(relpEngine_t *pThis,
+ void (*pCB)(void*pUsr, char *objinfo, char*errmsg, relpRetVal errcode) );
/* exposed server property set functions */
relpRetVal relpSrvSetLstnPort(relpSrv_t *pThis, unsigned char *pLstnPort);
@@ -192,6 +198,7 @@
relpRetVal relpCltConnect(relpClt_t *pThis, int protFamily, unsigned char *port, unsigned char *host);
relpRetVal relpCltSendSyslog(relpClt_t *pThis, unsigned char *pMsg, size_t lenMsg);
relpRetVal relpCltSetTimeout(relpClt_t *pThis, unsigned timeout);
+relpRetVal relpCltSetWindowSize(relpClt_t *pThis, int sizeWindow);
relpRetVal relpCltSetClientIP(relpClt_t *pThis, unsigned char *ipAddr);
relpRetVal relpCltEnableTLS(relpClt_t *pThis);
relpRetVal relpCltEnableTLSZip(relpClt_t *pThis);
@@ -203,5 +210,7 @@
relpRetVal relpCltAddPermittedPeer(relpClt_t *pThis, char *peer);
relpRetVal relpCltSetUsrPtr(relpClt_t *pThis, void *pUsr);
relpRetVal relpCltReconnect(relpClt_t *pThis);
+void relpCltHintBurstBegin(relpClt_t *pThis);
+void relpCltHintBurstEnd(relpClt_t *pThis);
#endif /* #ifndef RELP_H_INCLUDED */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/relp.c new/librelp-1.1.5/src/relp.c
--- old/librelp-1.1.3/src/relp.c 2013-06-25 14:55:56.000000000 +0200
+++ new/librelp-1.1.5/src/relp.c 2013-07-05 09:54:46.000000000 +0200
@@ -304,6 +304,30 @@
LEAVE_RELPFUNC;
}
+/**
+ * Set an event handler that shall receive information when some error
+ * occured for which no special handler exists. Note that even if the
+ * special handler (e.g. AuthErr) is not set, this handler here will
+ * not be called. This permits the lib-user to set fine-grained control
+ * on which error messages it intends to handle.
+ *
+ * Callback parameters:
+ *
+ * pUsr - the user pointer set
+ * objinfo - some information identifying the object in error; depends
+ * on the actual error case.
+ * errmsg - error message as far as librelp is concerned
+ * errcode - contains librelp error status
+ */
+relpRetVal
+relpEngineSetOnErr(relpEngine_t *pThis, void (*pCB)(void*pUsr, char *objinfo, char*errmsg, relpRetVal errcode) )
+{
+ ENTER_RELPFUNC;
+ RELPOBJ_assert(pThis, Engine);
+ pThis->onErr = pCB;
+ LEAVE_RELPFUNC;
+}
+
/* Deprecated, use relpEngineListnerConstruct() family of functions.
* See there for further information.
*/
@@ -385,7 +409,7 @@
/* helper for relpEngineRun; receives data when it is time to
* do so. Includes all housekeeping, like closing the session.
*/
-static inline void
+static inline relpRetVal
doRecv(relpEngine_t *pThis, relpEngSessLst_t *pSessEtry, int sock)
{
relpRetVal localRet;
@@ -399,6 +423,7 @@
sock, localRet);
relpEngineDelSess(pThis, pSessEtry);
}
+ return localRet;
}
/* helper for relpEngineRun; sends session data when it is time
* to send. Includes all housekeeping, like closing the session.
@@ -471,7 +496,7 @@
for(pSessEtry = pThis->pSessLstRoot ; pSessEtry != NULL ; pSessEtry = pSessEtry->pNext) {
sock = relpSessGetSock(pSessEtry->pSess);
if(relpSessTcpRequiresRtry(pSessEtry->pSess)) {
- pThis->dbgprint("***<librelp> retry op requested for sock %d\n", sock);
+ pThis->dbgprint("librelp: retry op requested for sock %d\n", sock);
if(relpTcpGetRtryDirection(pSessEtry->pSess->pTcp) == 0) {
FD_SET(sock, &readfds);
} else {
@@ -489,7 +514,7 @@
/* done adding all sockets */
if(pThis->dbgprint != dbgprintDummy) {
- pThis->dbgprint("***<librelp> calling select, active file descriptors (max %d): ", maxfds);
+ pThis->dbgprint("librelp: calling select, active file descriptors (max %d): ", maxfds);
for(nfds = 0; nfds <= maxfds; ++nfds)
if(FD_ISSET(nfds, &readfds))
pThis->dbgprint("%d ", nfds);
@@ -529,7 +554,7 @@
}
/* now check if we have some action waiting for sessions */
- for(pSessEtry = pThis->pSessLstRoot ; nfds && pSessEtry != NULL ; ) {
+ for(pSessEtry = pThis->pSessLstRoot ; nfds && pSessEtry != NULL ; pSessEtry = pSessEtryNext) {
if(relpEngineShouldStop(pThis)) break;
pSessEtryNext = pSessEtry->pNext; /* we need to cache this as we may delete the entry! */
sock = relpSessGetSock(pSessEtry->pSess);
@@ -553,7 +578,8 @@
}
} else {
if(FD_ISSET(sock, &readfds)) {
- doRecv(pThis, pSessEtry, sock);
+ if(doRecv(pThis, pSessEtry, sock) != RELP_RET_OK)
+ continue; /* else write may cause invld mem access! */
--nfds; /* indicate we have processed one */
}
if(FD_ISSET(sock, &writefds)) {
@@ -561,8 +587,6 @@
--nfds; /* indicate we have processed one */
}
}
-
- pSessEtry = pSessEtryNext;
}
}
@@ -603,17 +627,19 @@
/* currently, we hardcode the commands. Over time, they may be dynamically
* loaded and, when so, should come from a linked list.
+ * NOTE: the command handler are sorted so that most frequently used are
+ * at the top of the list!
*/
- if(!strcmp((char*)pFrame->cmd, "open")) {
+ if(!strcmp((char*)pFrame->cmd, "syslog")) {
+ CHKRet(relpSCSyslog(pFrame, pSess));
+ } else if(!strcmp((char*)pFrame->cmd, "rsp")) {
+ CHKRet(relpSCRsp(pFrame, pSess));
+ } else if(!strcmp((char*)pFrame->cmd, "open")) {
CHKRet(relpSCInit(pFrame, pSess));
} else if(!strcmp((char*)pFrame->cmd, "close")) {
CHKRet(relpSCClose(pFrame, pSess));
} else if(!strcmp((char*)pFrame->cmd, "serverclose")) {
CHKRet(relpCCServerclose(pFrame, pSess));
- } else if(!strcmp((char*)pFrame->cmd, "syslog")) {
- CHKRet(relpSCSyslog(pFrame, pSess));
- } else if(!strcmp((char*)pFrame->cmd, "rsp")) {
- CHKRet(relpSCRsp(pFrame, pSess));
} else {
pThis->dbgprint("invalid or not supported relp command '%s'\n", pFrame->cmd);
ABORT_FINALIZE(RELP_RET_INVALID_CMD);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/relp.h new/librelp-1.1.5/src/relp.h
--- old/librelp-1.1.3/src/relp.h 2013-06-25 17:11:27.000000000 +0200
+++ new/librelp-1.1.5/src/relp.h 2013-07-05 09:54:46.000000000 +0200
@@ -92,6 +92,7 @@
relpRetVal (*onSyslogRcv2)(void*, unsigned char*pHostname, unsigned char *pIP,
unsigned char *pMsg, size_t lenMsg); /**< callback for "syslog" cmd */
void (*onAuthErr)(void*pUsr, char *authinfo, char*errmsg, relpRetVal errcode);
+ void (*onErr)(void*pUsr, char *objinfo, char*errmsg, relpRetVal errcode);
int protocolVersion; /**< version of the relp protocol supported by this engine */
/* Flags */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/relpclt.c new/librelp-1.1.5/src/relpclt.c
--- old/librelp-1.1.3/src/relpclt.c 2013-06-25 14:55:56.000000000 +0200
+++ new/librelp-1.1.5/src/relpclt.c 2013-07-02 12:21:29.000000000 +0200
@@ -115,8 +115,9 @@
ENTER_RELPFUNC;
RELPOBJ_assert(pThis, Clt);
- CHKRet(relpSessConstruct(&pThis->pSess, pThis->pEngine, NULL));
+ CHKRet(relpSessConstruct(&pThis->pSess, pThis->pEngine, RELP_CLT_CONN, pThis));
CHKRet(relpSessSetTimeout(pThis->pSess, pThis->timeout));
+ CHKRet(relpSessSetWindowSize(pThis->pSess, pThis->sizeWindow));
CHKRet(relpSessSetClientIP(pThis->pSess, pThis->clientIP));
CHKRet(relpSessSetUsrPtr(pThis->pSess, pThis->pUsr));
if(pThis->bEnableTLS) {
@@ -164,8 +165,23 @@
}
-/** Set the timeout value for this client.
+/** Set the relp window size for this client. Value 0 means
+ * that the default value is to be used.
*/
+relpRetVal
+relpCltSetWindowSize(relpClt_t *pThis, int sizeWindow)
+{
+ ENTER_RELPFUNC;
+ RELPOBJ_assert(pThis, Clt);
+ if(sizeWindow < 0)
+ ABORT_FINALIZE(RELP_RET_ERR_INVAL);
+ if(sizeWindow != 0)
+ pThis->sizeWindow = sizeWindow;
+finalize_it:
+ LEAVE_RELPFUNC;
+}
+
+/** Set the timeout value for this client. */
relpRetVal relpCltSetTimeout(relpClt_t *pThis, unsigned timeout)
{
ENTER_RELPFUNC;
@@ -322,6 +338,23 @@
LEAVE_RELPFUNC;
}
+/* this function is called to hint librelp that a "burst" of data is to be
+ * sent. librelp can than try to optimize it's handling.
+ * The function is intentionally void as it must operate in a way that
+ * does not interfere with normal operations.
+ */
+void
+relpCltHintBurstBegin(relpClt_t *pThis)
+{
+ relpTcpHintBurstBegin(pThis->pSess->pTcp);
+}
+/* this is the counterpart to relpCltHintBurstBegin -- see there for doc */
+void
+relpCltHintBurstEnd(relpClt_t *pThis)
+{
+ relpTcpHintBurstEnd(pThis->pSess->pTcp);
+}
+
/* Send a syslog message through RELP. The session must be established.
* The provided message buffer is not touched by this function. The caller
* must free it if it is no longer needed.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/relpclt.h new/librelp-1.1.5/src/relpclt.h
--- old/librelp-1.1.3/src/relpclt.h 2013-06-25 14:55:56.000000000 +0200
+++ new/librelp-1.1.5/src/relpclt.h 2013-07-02 12:04:20.000000000 +0200
@@ -43,6 +43,7 @@
void *pUsr; /**< user pointer (opaque data) */
int bEnableTLS; /**< is TLS to be used? */
int bEnableTLSZip; /**< is compression to be used together with TLS? */
+ int sizeWindow; /**< size of our app-level communications window */
char *pristring; /**< priority string for GnuTLS */
relpAuthMode_t authmode;
char *caCertFile;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/relpsess.c new/librelp-1.1.5/src/relpsess.c
--- old/librelp-1.1.3/src/relpsess.c 2013-06-25 14:55:56.000000000 +0200
+++ new/librelp-1.1.5/src/relpsess.c 2013-07-04 17:05:08.000000000 +0200
@@ -65,7 +65,7 @@
* the pSrv parameter may be set to NULL if the session object is for a client.
*/
relpRetVal
-relpSessConstruct(relpSess_t **ppThis, relpEngine_t *pEngine, relpSrv_t *pSrv)
+relpSessConstruct(relpSess_t **ppThis, relpEngine_t *pEngine, int connType, void *pParent)
{
relpSess_t *pThis;
@@ -81,11 +81,15 @@
pThis->pEngine = pEngine;
/* use Engine's command enablement states as default */
pThis->stateCmdSyslog = pEngine->stateCmdSyslog;
- pThis->pSrv = pSrv;
+ if(connType == RELP_SRV_CONN) {
+ pThis->pSrv = (relpSrv_t*) pParent;
+ } else {
+ pThis->pClt = (relpClt_t*) pParent;
+ }
pThis->txnr = 1; /* txnr start at 1 according to spec */
pThis->timeout = 90;
pThis->pUsr = NULL;
- pThis->sizeWindow = RELP_DFLT_WINDOW_SIZE; /* TODO: make configurable */
+ pThis->sizeWindow = RELP_DFLT_WINDOW_SIZE;
pThis->maxDataSize = RELP_DFLT_MAX_DATA_SIZE;
pThis->authmode = eRelpAuthMode_None;
pThis->pristring = NULL;
@@ -183,10 +187,9 @@
RELPOBJ_assert(pSrv, Srv);
assert(sock >= 0);
- CHKRet(relpSessConstruct(&pThis, pSrv->pEngine, pSrv));
+ CHKRet(relpSessConstruct(&pThis, pSrv->pEngine, RELP_SRV_CONN, pSrv));
CHKRet(relpTcpAcceptConnReq(&pThis->pTcp, sock, pSrv));
- /* TODO: check hostname against ACL (callback?) */
/* TODO: check against max# sessions */
*ppThis = pThis;
@@ -306,7 +309,7 @@
relpSessSrvSendHint(relpSess_t *pThis, unsigned char *pHint, size_t lenHint,
unsigned char *pData, size_t lenData)
{
- relpSendbuf_t *pSendbuf;
+ relpSendbuf_t *pSendbuf = NULL;
ENTER_RELPFUNC;
assert(pHint != NULL);
@@ -319,6 +322,8 @@
CHKRet(relpSendbufSend(pSendbuf, pThis->pTcp));
finalize_it:
+ if(pSendbuf != NULL)
+ relpSendbufDestruct(&pSendbuf);
LEAVE_RELPFUNC;
}
@@ -479,6 +484,11 @@
ENTER_RELPFUNC;
RELPOBJ_assert(pThis, Sess);
+ /* are we already ready? */
+ if(pThis->sessState == stateExpected || pThis->sessState == eRelpSessState_BROKEN) {
+ FINALIZE;
+ }
+
/* first read any outstanding data and process the packets. Note that this
* call DOES NOT block.
*/
@@ -486,7 +496,7 @@
if(localRet != RELP_RET_OK && localRet != RELP_RET_SESSION_BROKEN)
ABORT_FINALIZE(localRet);
- /* check if we are already in the desired state. If so, we can immediately
+ /* re-check if we are already in the desired state. If so, we can immediately
* return. That saves us doing a costly clock call to set the timeout. As a
* side-effect, the timeout is actually applied without the time needed for
* above reception. I think is is OK, even a bit logical ;)
@@ -732,7 +742,6 @@
if(pOffers != NULL)
relpOffersDestruct(&pOffers);
-pEngine->dbgprint("DDDD: end offer processing\n");
LEAVE_RELPFUNC;
}
@@ -785,7 +794,7 @@
pThis->txnr = 1;
pThis->sessType = eRelpSess_Client; /* indicate we have a client session */
- CHKRet(relpTcpConstruct(&pThis->pTcp, pThis->pEngine, RELP_CLT_CONN));
+ CHKRet(relpTcpConstruct(&pThis->pTcp, pThis->pEngine, RELP_CLT_CONN, pThis->pClt));
CHKRet(relpTcpSetUsrPtr(pThis->pTcp, pThis->pUsr));
if(pThis->bEnableTLS) {
CHKRet(relpTcpEnableTLS(pThis->pTcp));
@@ -877,6 +886,16 @@
relpRetVal
+relpSessSetWindowSize(relpSess_t *pThis, int sizeWindow)
+{
+ ENTER_RELPFUNC;
+ RELPOBJ_assert(pThis, Sess);
+ if(sizeWindow > 1)
+ pThis->sizeWindow = sizeWindow;
+ LEAVE_RELPFUNC;
+}
+
+relpRetVal
relpSessSetTimeout(relpSess_t *pThis, unsigned timeout)
{
ENTER_RELPFUNC;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/relpsess.h new/librelp-1.1.5/src/relpsess.h
--- old/librelp-1.1.3/src/relpsess.h 2013-06-25 14:55:56.000000000 +0200
+++ new/librelp-1.1.5/src/relpsess.h 2013-07-02 12:08:07.000000000 +0200
@@ -76,6 +76,8 @@
relpTxnr_t txnr; /**< next txnr expected when receiving or to be used when sending */
size_t maxDataSize; /**< maximum size of a DATA element (TODO: set after handshake on connect) */
pthread_mutex_t mutSend; /**< mutex for send operation (make sure txnr is correct) */
+ relpSrv_t *pSrv; /**< a pointer to our server object, if NULL, we belong to a client */
+ relpClt_t *pClt; /**< ptr to our client; only valid if pSrv == NULL */
/* connection parameters */
int protocolVersion; /* relp protocol version in use in this session */
@@ -97,7 +99,6 @@
unsigned char *clientIP; /* ar */
/* properties needed for server operation */
- relpSrv_t *pSrv; /**< the server we belong to */
struct relpSendq_s *pSendq; /**< our send queue */
/* properties needed for client operation */
@@ -128,7 +129,7 @@
}
/* prototypes */
-relpRetVal relpSessConstruct(relpSess_t **ppThis, relpEngine_t *pEngine, relpSrv_t *pSrv);
+relpRetVal relpSessConstruct(relpSess_t **ppThis, relpEngine_t *pEngine, int connType, void *pParent);
relpRetVal relpSessDestruct(relpSess_t **ppThis);
relpRetVal relpSessAcceptAndConstruct(relpSess_t **ppThis, relpSrv_t *pSrv, int sock);
relpRetVal relpSessRcvData(relpSess_t *pThis);
@@ -143,6 +144,7 @@
relpRetVal relpSessTryReestablish(relpSess_t *pThis);
relpRetVal relpSessSetProtocolVersion(relpSess_t *pThis, int protocolVersion);
relpRetVal relpSessSetTimeout(relpSess_t *pThis, unsigned timeout);
+relpRetVal relpSessSetWindowSize(relpSess_t *pThis, int sizeWindow);
relpRetVal relpSessSetClientIP(relpSess_t *pThis, unsigned char *ip);
relpRetVal relpSessEnableTLS(relpSess_t *pThis);
relpRetVal relpSessEnableTLSZip(relpSess_t *pThis);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/relpsrv.c new/librelp-1.1.5/src/relpsrv.c
--- old/librelp-1.1.3/src/relpsrv.c 2013-06-25 14:55:56.000000000 +0200
+++ new/librelp-1.1.5/src/relpsrv.c 2013-07-02 12:05:25.000000000 +0200
@@ -144,8 +144,7 @@
}
-/* set the user pointer inside the RELP server. Whatever value the user
- * provides is accepted.
+/* set the user pointer. Whatever value the user provides is accepted.
* rgerhards, 2008-07-08
*/
relpRetVal
@@ -308,7 +307,7 @@
ENTER_RELPFUNC;
RELPOBJ_assert(pThis, Srv);
- CHKRet(relpTcpConstruct(&pTcp, pThis->pEngine, RELP_SRV_CONN));
+ CHKRet(relpTcpConstruct(&pTcp, pThis->pEngine, RELP_SRV_CONN, pThis));
relpTcpSetUsrPtr(pTcp, pThis->pUsr);
if(pThis->bEnableTLS) {
relpTcpEnableTLS(pTcp);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/sendbuf.c new/librelp-1.1.5/src/sendbuf.c
--- old/librelp-1.1.3/src/sendbuf.c 2013-06-25 14:55:56.000000000 +0200
+++ new/librelp-1.1.5/src/sendbuf.c 2013-07-04 16:52:52.000000000 +0200
@@ -170,36 +170,42 @@
{
ssize_t lenToWrite;
ssize_t lenWritten;
- time_t timeout, currtime;
+ struct timespec tCurr; /* absolute timeout value */
+ struct timespec tTimeout; /* absolute timeout value */
ENTER_RELPFUNC;
RELPOBJ_assert(pThis, Sendbuf);
RELPOBJ_assert(pSess, Sess);
- time(&timeout);
- timeout += pSess->timeout;
+ clock_gettime(CLOCK_REALTIME, &tTimeout);
+ tTimeout.tv_sec += pSess->timeout;
lenToWrite = pThis->lenData - pThis->bufPtr;
+ /* we compute the absolute timeout, as we may need to use it multiple
+ * times in the loop below. Using the relative value would potentially
+ * prolong it for quite some time!
+ */
while(lenToWrite != 0) {
lenWritten = lenToWrite;
-//pSess->pEngine->dbgprint("sendbuf len %d, still to write %d\n", (int) pThis->lenData, (int) lenToWrite);
CHKRet(relpTcpSend(pSess->pTcp, pThis->pData + (9 - pThis->lenTxnr) + pThis->bufPtr, &lenWritten));
-
if(lenWritten == -1) {
ABORT_FINALIZE(RELP_RET_IO_ERR);
} else if(lenWritten == 0) {
- time(&currtime);
- pSess->pEngine->dbgprint("relpSendbufSendAll() wrote "
- "0 octets, timeout %lld, curr %lld\n",
- (long long) timeout, (long long) currtime);
- if(currtime >= timeout)
- ABORT_FINALIZE(RELP_RET_IO_ERR);
- /* we put ourselves to sleep to avoid busy waiting */
- doSleep(0, 100);
+ pSess->pEngine->dbgprint("relpSendbufSendAll() wrote 0 octets, waiting...\n");
+ if(relpTcpWaitWriteable(pSess->pTcp, &tTimeout) == 0) {
+ ABORT_FINALIZE(RELP_RET_IO_ERR); /* timed out! */
+ }
} else if(lenWritten == lenToWrite) {
lenToWrite = 0;
} else {
pThis->bufPtr += lenWritten;
lenToWrite = pThis->lenData - pThis->bufPtr;
}
+ if(lenToWrite != 0) {
+ clock_gettime(CLOCK_REALTIME, &tCurr);
+ if( (tCurr.tv_sec > tTimeout.tv_sec)
+ || (tCurr.tv_sec == tTimeout.tv_sec && tCurr.tv_nsec >= tTimeout.tv_nsec)) {
+ ABORT_FINALIZE(RELP_RET_IO_ERR);
+ }
+ }
}
/* ok, we now have sent the full buf. So we now need to add it to the unacked list, so that
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/sendq.c new/librelp-1.1.5/src/sendq.c
--- old/librelp-1.1.3/src/sendq.c 2013-06-25 14:55:56.000000000 +0200
+++ new/librelp-1.1.5/src/sendq.c 2013-06-29 11:38:43.000000000 +0200
@@ -243,6 +243,7 @@
pEntry = pThis->pRoot;
+ relpTcpHintBurstBegin(pTcp);
while(pEntry != NULL) {
RELPOBJ_assert(pEntry, Sendqe);
localRet = relpSendbufSend(pEntry->pBuf, pTcp);
@@ -258,5 +259,6 @@
}
finalize_it:
+ relpTcpHintBurstEnd(pTcp);
LEAVE_RELPFUNC;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/tcp.c new/librelp-1.1.5/src/tcp.c
--- old/librelp-1.1.3/src/tcp.c 2013-06-25 16:31:39.000000000 +0200
+++ new/librelp-1.1.5/src/tcp.c 2013-07-01 13:02:38.000000000 +0200
@@ -45,6 +45,8 @@
#include
#include "relp.h"
#include "relpsrv.h"
+#include "relpclt.h"
+#include "relpsess.h"
#include "tcp.h"
#include
#include
@@ -61,6 +63,7 @@
/* forward definitions */
static int relpTcpVerifyCertificateCallback(gnutls_session_t session);
+static relpRetVal relpTcpPermittedPeerWildcardCompile(tcpPermittedPeerEntry_t *pEtry);
/* helper to free permittedPeer structure */
static inline void
@@ -68,17 +71,18 @@
{
int i;
for(i = 0 ; i < pThis->permittedPeers.nmemb ; ++i)
- free(pThis->permittedPeers.name[i]);
+ free(pThis->permittedPeers.peer[i].name);
pThis->permittedPeers.nmemb = 0;
}
/** Construct a RELP tcp instance
* This is the first thing that a caller must do before calling any
* RELP function. The relp tcp must only destructed after all RELP
- * operations have been finished.
+ * operations have been finished. Parameter pParent contains a pointer
+ * to the "parent" client or server object, depending on connType.
*/
relpRetVal
-relpTcpConstruct(relpTcp_t **ppThis, relpEngine_t *pEngine, int connType)
+relpTcpConstruct(relpTcp_t **ppThis, relpEngine_t *pEngine, int connType, void *pParent)
{
relpTcp_t *pThis;
@@ -89,7 +93,11 @@
}
RELP_CORE_CONSTRUCTOR(pThis, Tcp);
- pThis->bIsClient = (connType == RELP_SRV_CONN) ? 0 : 1;
+ if(connType == RELP_SRV_CONN) {
+ pThis->pSrv = (relpSrv_t*) pParent;
+ } else {
+ pThis->pClt = (relpClt_t*) pParent;
+ }
pThis->sock = -1;
pThis->pEngine = pEngine;
pThis->iSessMax = 500; /* default max nbr of sessions - TODO: make configurable -- rgerhards, 2008-03-17*/
@@ -142,7 +150,6 @@
gnuRet = gnutls_bye(pThis->session, GNUTLS_SHUT_RDWR);
}
gnutls_deinit(pThis->session);
-pThis->pEngine->dbgprint("DDDD: gnutls_deinit done %p\n", pThis->session);
}
relpTcpFreePermittedPeers(pThis);
@@ -161,6 +168,56 @@
}
+/* helper to call onErr if set */
+static void
+callOnErr(relpTcp_t *pThis, char *emsg, relpRetVal ecode)
+{
+ char objinfo[1024];
+ pThis->pEngine->dbgprint("librelp: generic error: ecode %d, "
+ "emsg '%s'\n", ecode, emsg);
+ if(pThis->pEngine->onErr != NULL) {
+ if(pThis->pSrv == NULL) { /* client */
+ snprintf(objinfo, sizeof(objinfo), "conn to srvr %s:%s",
+ pThis->pClt->pSess->srvAddr,
+ pThis->pClt->pSess->srvPort);
+ } else if(pThis->pRemHostIP == NULL) { /* server listener */
+ snprintf(objinfo, sizeof(objinfo), "lstn %s",
+ pThis->pSrv->pLstnPort);
+ } else { /* server connection to client */
+ snprintf(objinfo, sizeof(objinfo), "lstn %s: conn to clt %s/%s",
+ pThis->pSrv->pLstnPort, pThis->pRemHostIP,
+ pThis->pRemHostName);
+ }
+ objinfo[sizeof(objinfo)-1] = '\0';
+ pThis->pEngine->onErr(pThis->pUsr, objinfo, emsg, ecode);
+ }
+}
+
+
+/* helper to call an error code handler if gnutls failed. If there is a failure,
+ * an error message is pulled form gnutls and the error message properly
+ * populated.
+ * Returns 1 if an error was detected, 0 otherwise. This can be used as a
+ * shortcut for error handling (safes doing it twice).
+ */
+static int
+chkGnutlsCode(relpTcp_t *pThis, char *emsg, relpRetVal ecode, int gnuRet)
+{
+ char msgbuf[4096];
+ int r;
+
+ if(gnuRet == GNUTLS_E_SUCCESS) {
+ r = 0;
+ } else {
+ r = 1;
+ snprintf(msgbuf, sizeof(msgbuf), "%s [gnutls error %d: %s]",
+ emsg, gnuRet, gnutls_strerror(gnuRet));
+ msgbuf[sizeof(msgbuf)-1] = '\0';
+ callOnErr(pThis, msgbuf, ecode);
+ }
+ return r;
+}
+
/* helper to call onAuthErr if set */
static inline void
callOnAuthErr(relpTcp_t *pThis, char *authdata, char *emsg, relpRetVal ecode)
@@ -310,14 +367,17 @@
relpTcpFreePermittedPeers(pThis);
if(pPeers->nmemb != 0) {
- if((pThis->permittedPeers.name =
- malloc(sizeof(char*) * pPeers->nmemb)) == NULL) {
+ if((pThis->permittedPeers.peer =
+ malloc(sizeof(tcpPermittedPeerEntry_t) * pPeers->nmemb)) == NULL) {
ABORT_FINALIZE(RELP_RET_OUT_OF_MEMORY);
}
for(i = 0 ; i < pPeers->nmemb ; ++i) {
- if((pThis->permittedPeers.name[i] = strdup(pPeers->name[i])) == NULL) {
+ if((pThis->permittedPeers.peer[i].name = strdup(pPeers->name[i])) == NULL) {
ABORT_FINALIZE(RELP_RET_OUT_OF_MEMORY);
}
+ pThis->permittedPeers.peer[i].wildcardRoot = NULL;
+ pThis->permittedPeers.peer[i].wildcardLast = NULL;
+ CHKRet(relpTcpPermittedPeerWildcardCompile(&(pThis->permittedPeers.peer[i])));
}
}
pThis->permittedPeers.nmemb = pPeers->nmemb;
@@ -462,13 +522,14 @@
}
r = gnutls_priority_set_direct(pThis->session, pristring, NULL);
- pThis->pEngine->dbgprint("DDDD: gnutls_priority_set_direct(\"%s\"): %d: %s\n", pristring, r, gnutls_strerror(r));
if(r == GNUTLS_E_INVALID_REQUEST) {
ABORT_FINALIZE(RELP_RET_INVLD_TLS_PRIO);
} else if(r != GNUTLS_E_SUCCESS) {
ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
}
finalize_it:
+ if(iRet != RELP_RET_OK)
+ chkGnutlsCode(pThis, "Failed to set GnuTLS priority", iRet, r);
LEAVE_RELPFUNC;
}
@@ -480,7 +541,10 @@
ENTER_RELPFUNC;
r = gnutls_init(&pThis->session, GNUTLS_SERVER);
-pThis->pEngine->dbgprint("DDDD: gnutls_init[%p] %d: %s\n", pThis->session, r, gnutls_strerror(r));
+ if(chkGnutlsCode(pThis, "Failed to initialize GnuTLS", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
+
gnutls_session_set_ptr(pThis->session, pThis);
if(pSrv->pTcp->pristring != NULL)
@@ -491,26 +555,31 @@
if(isAnonAuth(pSrv->pTcp)) {
r = gnutls_credentials_set(pThis->session, GNUTLS_CRD_ANON, pSrv->pTcp->anoncredSrv);
- pThis->pEngine->dbgprint("DDDD: gnutls_credentials_set (anon) %d: %s\n", r, gnutls_strerror(r));
+ if(chkGnutlsCode(pThis, "Failed setting anonymous credentials", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
} else { /* cert-based auth */
if(pSrv->pTcp->caCertFile == NULL) {
gnutls_certificate_send_x509_rdn_sequence(pThis->session, 0);
}
r = gnutls_credentials_set(pThis->session, GNUTLS_CRD_CERTIFICATE, pSrv->pTcp->xcred);
- pThis->pEngine->dbgprint("DDDD: gnutls_credentials_set(cert) %d: %s\n", r, gnutls_strerror(r));
+ if(chkGnutlsCode(pThis, "Failed setting certificate credentials", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
}
gnutls_dh_set_prime_bits(pThis->session, pThis->dhBits);
gnutls_certificate_server_set_request(pThis->session, GNUTLS_CERT_REQUEST);
gnutls_transport_set_ptr(pThis->session, (gnutls_transport_ptr_t) pThis->sock);
r = gnutls_handshake(pThis->session);
-pThis->pEngine->dbgprint("DDDD: gnutls_handshake: %d: %s\n", r, gnutls_strerror(r));
if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN) {
pThis->pEngine->dbgprint("librelp: gnutls_handshake retry necessary (this is OK and expected)\n");
pThis->rtryOp = relpTCP_RETRY_handshake;
} else if(r != GNUTLS_E_SUCCESS) {
- ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ chkGnutlsCode(pThis, "TLS handshake failed", RELP_RET_ERR_TLS_HANDS, r);
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_HANDS);
}
+
pThis->bTLSActive = 1;
finalize_it:
@@ -540,11 +609,11 @@
}
/* construct our object so that we can use it... */
- CHKRet(relpTcpConstruct(&pThis, pEngine, RELP_SRV_CONN));
+ CHKRet(relpTcpConstruct(&pThis, pEngine, RELP_SRV_CONN, pSrv));
/* TODO: obtain hostname, normalize (callback?), save it */
CHKRet(relpTcpSetRemHost(pThis, (struct sockaddr*) &addr));
-pThis->pEngine->dbgprint("remote host is '%s', ip '%s'\n", pThis->pRemHostName, pThis->pRemHostIP);
+ pThis->pEngine->dbgprint("remote host is '%s', ip '%s'\n", pThis->pRemHostName, pThis->pRemHostIP);
/* set the new socket to non-blocking IO */
if((sockflags = fcntl(iNewSock, F_GETFL)) != -1) {
@@ -562,6 +631,7 @@
pThis->sock = iNewSock;
if(pSrv->pTcp->bEnableTLS) {
pThis->bEnableTLS = 1;
+ pThis->pSrv = pSrv;
CHKRet(relpTcpSetPermittedPeers(pThis, &(pSrv->permittedPeers)));
CHKRet(relpTcpAcceptConnReqInitTLS(pThis, pSrv));
}
@@ -608,17 +678,19 @@
/* obtain the SHA1 fingerprint */
size = sizeof(fingerprint);
- gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, fingerprint, &size);
-pThis->pEngine->dbgprint("DDDD: crt_get_fingerprint returned %d: %s\n", r, gnutls_strerror(r));
+ r = gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, fingerprint, &size);
+ if(chkGnutlsCode(pThis, "Failed to obtain fingerprint from certificate", RELP_RET_ERR_TLS, r)) {
+ r = GNUTLS_E_CERTIFICATE_ERROR; goto done;
+ }
GenFingerprintStr(fingerprint, (int) size, fpPrintable);
pThis->pEngine->dbgprint("DDDD: peer's certificate SHA1 fingerprint: %s\n", fpPrintable);
/* now search through the permitted peers to see if we can find a permitted one */
found = 0;
-pThis->pEngine->dbgprint("DDDD: n peers %d\n", pThis->permittedPeers.nmemb);
+ pThis->pEngine->dbgprint("DDDD: n peers %d\n", pThis->permittedPeers.nmemb);
for(i = 0 ; i < pThis->permittedPeers.nmemb ; ++i) {
-pThis->pEngine->dbgprint("DDDD: checking peer '%s','%s'\n", fpPrintable, pThis->permittedPeers.name[i]);
- if(!strcmp(fpPrintable, pThis->permittedPeers.name[i])) {
+ pThis->pEngine->dbgprint("DDDD: checking peer '%s','%s'\n", fpPrintable, pThis->permittedPeers.peer[i].name);
+ if(!strcmp(fpPrintable, pThis->permittedPeers.peer[i].name)) {
found = 1;
break;
}
@@ -633,6 +705,219 @@
return r;
}
+/* add a wildcard entry to this permitted peer. Entries are always
+ * added at the tail of the list. pszStr and lenStr identify the wildcard
+ * entry to be added. Note that the string is NOT \0 terminated, so
+ * we must rely on lenStr for when it is finished.
+ * rgerhards, 2008-05-27
+ */
+static relpRetVal
+AddPermittedPeerWildcard(tcpPermittedPeerEntry_t *pEtry, char* pszStr, int lenStr)
+{
+ tcpPermittedPeerWildcardComp_t *pNew = NULL;
+ int iSrc;
+ int iDst;
+ ENTER_RELPFUNC;
+
+ if((pNew = calloc(1, sizeof(tcpPermittedPeerWildcardComp_t))) == NULL) {
+ ABORT_FINALIZE(RELP_RET_OUT_OF_MEMORY);
+ }
+
+ if(lenStr == 0) {
+ pNew->wildcardType = tcpPEER_WILDCARD_EMPTY_COMPONENT;
+ FINALIZE;
+ } else {
+ /* alloc memory for the domain component. We may waste a byte or
+ * two, but that's ok.
+ */
+ if((pNew->pszDomainPart = malloc(lenStr +1 )) == NULL) {
+ ABORT_FINALIZE(RELP_RET_OUT_OF_MEMORY);
+ }
+ }
+
+ if(pszStr[0] == '*') {
+ pNew->wildcardType = tcpPEER_WILDCARD_AT_START;
+ iSrc = 1; /* skip '*' */
+ } else {
+ iSrc = 0;
+ }
+
+ for(iDst = 0 ; iSrc < lenStr && pszStr[iSrc] != '*' ; ++iSrc, ++iDst) {
+ pNew->pszDomainPart[iDst] = pszStr[iSrc];
+ }
+
+ if(iSrc < lenStr) {
+ if(iSrc + 1 == lenStr && pszStr[iSrc] == '*') {
+ if(pNew->wildcardType == tcpPEER_WILDCARD_AT_START) {
+ ABORT_FINALIZE(RELP_RET_INVLD_WILDCARD);
+ } else {
+ pNew->wildcardType = tcpPEER_WILDCARD_AT_END;
+ }
+ } else {
+ /* we have an invalid wildcard, something follows the asterisk! */
+ ABORT_FINALIZE(RELP_RET_INVLD_WILDCARD);
+ }
+ }
+
+ if(lenStr == 1 && pNew->wildcardType == tcpPEER_WILDCARD_AT_START) {
+ pNew->wildcardType = tcpPEER_WILDCARD_MATCH_ALL;
+ }
+
+ /* if we reach this point, we had a valid wildcard. We now need to
+ * properly terminate the domain component string.
+ */
+ pNew->pszDomainPart[iDst] = '\0';
+ pNew->lenDomainPart = strlen((char*)pNew->pszDomainPart);
+
+finalize_it:
+ if(iRet != RELP_RET_OK) {
+ if(pNew != NULL) {
+ if(pNew->pszDomainPart != NULL)
+ free(pNew->pszDomainPart);
+ free(pNew);
+ }
+ } else {
+ /* add the element to linked list */
+ if(pEtry->wildcardRoot == NULL) {
+ pEtry->wildcardRoot = pNew;
+ pEtry->wildcardLast = pNew;
+ } else {
+ pEtry->wildcardLast->pNext = pNew;
+ }
+ pEtry->wildcardLast = pNew;
+ }
+ LEAVE_RELPFUNC;
+}
+
+/* Compile a wildcard - must not yet be comipled */
+static relpRetVal
+relpTcpPermittedPeerWildcardCompile(tcpPermittedPeerEntry_t *pEtry)
+{
+ char *pC;
+ char *pStart;
+ ENTER_RELPFUNC;
+
+ /* first check if we have a wildcard */
+ for(pC = pEtry->name ; *pC != '\0' && *pC != '*' ; ++pC)
+ /*EMPTY, just skip*/;
+
+ if(*pC == '\0') { /* no wildcard found, we are done */
+ FINALIZE;
+ }
+
+ /* if we reach this point, the string contains wildcards. So let's
+ * compile the structure. To do so, we must parse from dot to dot
+ * and create a wildcard entry for each domain component we find.
+ * We must also flag problems if we have an asterisk in the middle
+ * of the text (it is supported at the start or end only).
+ */
+ pC = pEtry->name;
+ while(*pC) {
+ pStart = pC;
+ /* find end of domain component */
+ for( ; *pC != '\0' && *pC != '.' ; ++pC)
+ /*EMPTY, just skip*/;
+ CHKRet(AddPermittedPeerWildcard(pEtry, pStart, pC - pStart));
+ /* now check if we have an empty component at end of string */
+ if(*pC == '.' && *(pC + 1) == '\0') {
+ /* pStart is a dummy, it is not used if length is 0 */
+ CHKRet(AddPermittedPeerWildcard(pEtry, pStart, 0));
+ }
+ if(*pC != '\0')
+ ++pC;
+ }
+
+finalize_it:
+ LEAVE_RELPFUNC;
+}
+
+/* check a peer against a wildcard entry. This is a more lengthy
+ * operation.
+ */
+static void
+relpTcpChkOnePeerWildcard(tcpPermittedPeerWildcardComp_t *pRoot, char *peername, int *pbFoundPositiveMatch)
+{
+ tcpPermittedPeerWildcardComp_t *pWildcard;
+ char *pC;
+ char *pStart; /* start of current domain component */
+ int iWildcard, iName; /* work indexes for backward comparisons */
+
+ *pbFoundPositiveMatch = 0;
+ pWildcard = pRoot;
+ pC = peername;
+ while(*pC != '\0') {
+ if(pWildcard == NULL) {
+ /* we have more domain components than we have wildcards --> no match */
+ goto done;
+ }
+ pStart = pC;
+ while(*pC != '\0' && *pC != '.') {
+ ++pC;
+ }
+
+ /* got the component, now do the match */
+ switch(pWildcard->wildcardType) {
+ case tcpPEER_WILDCARD_NONE:
+ if( pWildcard->lenDomainPart != pC - pStart
+ || strncmp((char*)pStart, (char*)pWildcard->pszDomainPart, pC - pStart)) {
+ goto done;
+ }
+ break;
+ case tcpPEER_WILDCARD_AT_START:
+ /* we need to do the backwards-matching manually */
+ if(pWildcard->lenDomainPart > pC - pStart) {
+ goto done;
+ }
+ iName = (size_t) (pC - pStart) - pWildcard->lenDomainPart;
+ iWildcard = 0;
+ while(iWildcard < pWildcard->lenDomainPart) {
+ if(pWildcard->pszDomainPart[iWildcard] != pStart[iName]) {
+ goto done;
+ }
+ ++iName;
+ ++iWildcard;
+ }
+ break;
+ case tcpPEER_WILDCARD_AT_END:
+ if( pWildcard->lenDomainPart > pC - pStart
+ || strncmp((char*)pStart, (char*)pWildcard->pszDomainPart, pWildcard->lenDomainPart)) {
+ goto done;
+ }
+ break;
+ case tcpPEER_WILDCARD_MATCH_ALL:
+ /* everything is OK, just continue */
+ break;
+ case tcpPEER_WILDCARD_EMPTY_COMPONENT:
+ if(pC - pStart > 0) {
+ /* if it is not empty, it is no match... */
+ goto done;
+ }
+ break;
+ }
+ pWildcard = pWildcard->pNext; /* we processed this entry */
+
+ /* skip '.' if we had it and so prepare for next iteration */
+ if(*pC == '.')
+ ++pC;
+ }
+
+ /* we need to adjust for a border case, that is if the last component is
+ * empty. That happens frequently if the domain root (e.g. "example.com.")
+ * is properly given.
+ */
+ if(pWildcard->wildcardType == tcpPEER_WILDCARD_EMPTY_COMPONENT)
+ pWildcard = pWildcard->pNext;
+
+ if(pWildcard != NULL) {
+ /* we have more domain components than in the name to be
+ * checked. So this is no match.
+ */
+ goto done;
+ }
+ *pbFoundPositiveMatch = 1;
+done: return;
+}
+
/* Perform a match on ONE peer name obtained from the certificate. This name
* is checked against the set of configured credentials. *pbFoundPositiveMatch is
* set to 1 if the ID matches. *pbFoundPositiveMatch must have been initialized
@@ -640,14 +925,20 @@
* called multiple times).
*/
static void
-gtlsChkOnePeerName(relpTcp_t *pThis, char *peername, int *pbFoundPositiveMatch)
+relpTcpChkOnePeerName(relpTcp_t *pThis, char *peername, int *pbFoundPositiveMatch)
{
int i;
for(i = 0 ; i < pThis->permittedPeers.nmemb ; ++i) {
- if(!strcmp(peername, pThis->permittedPeers.name[i])) {
- *pbFoundPositiveMatch = 1;
- break;
+ if(pThis->permittedPeers.peer[i].wildcardRoot == NULL) {
+ /* simple string, only, no wildcards */
+ if(!strcmp(peername, pThis->permittedPeers.peer[i].name)) {
+ *pbFoundPositiveMatch = 1;
+ break;
+ }
+ } else {
+ relpTcpChkOnePeerWildcard(pThis->permittedPeers.peer[i].wildcardRoot,
+ peername, pbFoundPositiveMatch);
}
}
}
@@ -664,7 +955,7 @@
* Note that non-0 is also returned if no CN is found.
*/
static int
-gtlsGetCN(gnutls_x509_crt cert, char *namebuf, int lenNamebuf)
+relpTcpGetCN(relpTcp_t *pThis, gnutls_x509_crt cert, char *namebuf, int lenNamebuf)
{
int r;
int gnuRet;
@@ -675,7 +966,7 @@
size = sizeof(szDN);
gnuRet = gnutls_x509_crt_get_dn(cert, (char*)szDN, &size);
- if(gnuRet != 0) {
+ if(chkGnutlsCode(pThis, "Failed to obtain DN from certificate", RELP_RET_ERR_TLS, gnuRet)) {
r = 1; goto done;
}
@@ -738,7 +1029,6 @@
int gnuRet;
ret = gnutls_certificate_verify_peers2(pThis->session, &status);
- pThis->pEngine->dbgprint("DDDD: gnutls_certificate_verify_peers2 returned %d: %s\n", ret, gnutls_strerror(ret));
if(ret < 0) {
callOnAuthErr(pThis, "", "certificate validation failed",
RELP_RET_AUTH_CERT_INVL);
@@ -765,7 +1055,7 @@
pThis->pEngine->dbgprint("librelp: subject alt dnsName: '%s'\n", szAltName);
iAllNames += snprintf(allNames+iAllNames, sizeof(allNames)-iAllNames,
"DNSname: %s; ", szAltName);
- gtlsChkOnePeerName(pThis, szAltName, &bFoundPositiveMatch);
+ relpTcpChkOnePeerName(pThis, szAltName, &bFoundPositiveMatch);
/* do NOT break, because there may be multiple dNSName's! */
}
++iAltName;
@@ -773,11 +1063,11 @@
if(!bFoundPositiveMatch) {
/* if we did not succeed so far, we try the CN part of the DN... */
- if(gtlsGetCN(cert, cnBuf, sizeof(cnBuf)) == 0) {
- pThis->pEngine->dbgprint("librelp: gtls now checking auth for CN '%s'\n", cnBuf);
+ if(relpTcpGetCN(pThis, cert, cnBuf, sizeof(cnBuf)) == 0) {
+ pThis->pEngine->dbgprint("librelp: relpTcp now checking auth for CN '%s'\n", cnBuf);
iAllNames += snprintf(allNames+iAllNames, sizeof(allNames)-iAllNames,
"CN: %s; ", cnBuf);
- gtlsChkOnePeerName(pThis, cnBuf, &bFoundPositiveMatch);
+ relpTcpChkOnePeerName(pThis, cnBuf, &bFoundPositiveMatch);
}
}
@@ -867,34 +1157,42 @@
if(isAnonAuth(pThis)) {
r = gnutls_dh_params_init(&pThis->dh_params);
- pThis->pEngine->dbgprint("DDDD: dh_param_init returns %d\n", r);
+ if(chkGnutlsCode(pThis, "Failed to initialize dh_params", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
r = gnutls_dh_params_generate2(pThis->dh_params, pThis->dhBits);
- pThis->pEngine->dbgprint("DDDD: paramgenerate returns %d\n", r);
+ if(chkGnutlsCode(pThis, "Failed to generate dh_params", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
r = gnutls_anon_allocate_server_credentials(&pThis->anoncredSrv);
- pThis->pEngine->dbgprint("DDDD: generating server DH params...\n");
+ if(chkGnutlsCode(pThis, "Failed to allocate server credentials", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
gnutls_anon_set_server_dh_params(pThis->anoncredSrv, pThis->dh_params);
} else {
- gnutls_certificate_allocate_credentials(&pThis->xcred);
+ r = gnutls_certificate_allocate_credentials(&pThis->xcred);
+ if(chkGnutlsCode(pThis, "Failed to allocate certificate credentials", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
if(pThis->caCertFile != NULL) {
r = gnutls_certificate_set_x509_trust_file(pThis->xcred,
pThis->caCertFile, GNUTLS_X509_FMT_PEM);
- pThis->pEngine->dbgprint("DDDD: certificate_set_x509_trust_file returns %d: %s\n", r, gnutls_strerror(r));
- if(r >= 0) {
- pThis->pEngine->dbgprint("librelp: obtained %d certificates from %s\n",
- r, pThis->caCertFile);
- } else {
- // TODO: save error message
+ if(r < 0) {
+ chkGnutlsCode(pThis, "Failed to set certificate trust files", RELP_RET_ERR_TLS_SETUP, r);
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
}
+ pThis->pEngine->dbgprint("librelp: obtained %d certificates from %s\n", r, pThis->caCertFile);
}
r = gnutls_certificate_set_x509_key_file (pThis->xcred,
pThis->ownCertFile, pThis->privKeyFile, GNUTLS_X509_FMT_PEM);
- pThis->pEngine->dbgprint("DDDD: certificate_set_x509_key_file returns %d\n", r);
- //gnutls_certificate_set_dh_params(pThis->xcred, pThis->dh_params);
+ if(chkGnutlsCode(pThis, "Failed to set certificate key files", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
if(pThis->authmode == eRelpAuthMode_None)
pThis->authmode = eRelpAuthMode_Fingerprint;
gnutls_certificate_set_verify_function(pThis->xcred, relpTcpVerifyCertificateCallback);
}
-
+finalize_it:
LEAVE_RELPFUNC;
}
@@ -915,7 +1213,9 @@
RELPOBJ_assert(pThis, Tcp);
pLstnPt = pLstnPort;
- assert(pLstnPt != NULL); pThis->pEngine->dbgprint("creating relp tcp listen socket on port %s\n", pLstnPt);
+ assert(pLstnPt != NULL);
+
+ pThis->pEngine->dbgprint("creating relp tcp listen socket on port %s\n", pLstnPt);
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
@@ -1059,6 +1359,8 @@
pThis->pEngine->dbgprint("librelp: gnutls_record_recv must be retried\n");
pThis->rtryOp = relpTCP_RETRY_recv;
} else {
+ if(r < 0)
+ chkGnutlsCode(pThis, "TLS record reception failed", RELP_RET_IO_ERR, r);
pThis->rtryOp = relpTCP_RETRY_none;
}
*pLenBuf = (r < 0) ? -1 : r;
@@ -1069,6 +1371,39 @@
LEAVE_RELPFUNC;
}
+
+/* helper for CORK option manipulation. As this is not portable, the
+ * helper abstracts it. Note that it is a null-operation if no
+ * such option is available on the platform in question.
+ */
+static inline void
+setCORKopt(int sock, int onOff)
+{
+#if defined(TCP_CORK)
+ setsockopt(sock, SOL_TCP, TCP_CORK, &onOff, sizeof (onOff));
+#elif defined(TCP_NOPUSH)
+ setsockopt(sock, IPPROTO_TCP, TCP_NOPUSH, &onOff, sizeof (onOff));
+#endif
+}
+/* this function is called to hint librelp that a "burst" of data is to be
+ * sent. librelp can than try to optimize it's handling. Right now, this
+ * means we turn on the CORK option and will turn it off when we are
+ * hinted that the burst is over.
+ * The function is intentionally void as it must operate in a way that
+ * does not interfere with normal operations.
+ */
+void
+relpTcpHintBurstBegin(relpTcp_t *pThis)
+{
+ setCORKopt(pThis->sock, 1);
+}
+/* this is the counterpart to relpTcpHintBurstBegin -- see there for doc */
+void
+relpTcpHintBurstEnd(relpTcp_t *pThis)
+{
+ setCORKopt(pThis->sock, 0);
+}
+
/* send a buffer via TCP.
* On entry, pLenBuf contains the number of octets to
* write. On exit, it contains the number of octets actually written.
@@ -1092,8 +1427,7 @@
} else {
pThis->rtryOp = relpTCP_RETRY_none;
if(written < 1) {
- pThis->pEngine->dbgprint("librelp: error in gnutls_record_send: %s\n",
- gnutls_strerror(written));
+ chkGnutlsCode(pThis, "TLS record write failed", RELP_RET_IO_ERR, written);
ABORT_FINALIZE(RELP_RET_IO_ERR);
}
}
@@ -1137,37 +1471,48 @@
called_gnutls_global_init = 1;
}
r = gnutls_init(&pThis->session, GNUTLS_CLIENT);
- pThis->pEngine->dbgprint("DDDD: gnutls_init[%p]: %d\n", pThis->session, r);
+ if(chkGnutlsCode(pThis, "Failed to initialize GnuTLS", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
gnutls_session_set_ptr(pThis->session, pThis);
CHKRet(relpTcpTLSSetPrio(pThis));
if(isAnonAuth(pThis)) {
r = gnutls_anon_allocate_client_credentials(&pThis->anoncred);
- pThis->pEngine->dbgprint("DDDD: gnutls_anon_allocat_client_credentials: %d\n", r);
+ if(chkGnutlsCode(pThis, "Failed to allocate client credentials", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
/* put the anonymous credentials to the current session */
r = gnutls_credentials_set(pThis->session, GNUTLS_CRD_ANON, pThis->anoncred);
- pThis->pEngine->dbgprint("DDDD: gnutls_credentials_set: %d\n", r);
+ if(chkGnutlsCode(pThis, "Failed to set credentials", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
} else {
- gnutls_certificate_allocate_credentials(&pThis->xcred);
+ r = gnutls_certificate_allocate_credentials(&pThis->xcred);
+ if(chkGnutlsCode(pThis, "Failed to allocate certificate credentials", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
if(pThis->caCertFile != NULL) {
r = gnutls_certificate_set_x509_trust_file(pThis->xcred,
pThis->caCertFile, GNUTLS_X509_FMT_PEM);
- pThis->pEngine->dbgprint("DDDD: certificate_set_x509_trust_file returns %d: %s\n", r, gnutls_strerror(r));
- if(r >= 0) {
- pThis->pEngine->dbgprint("librelp: obtained %d certificates from %s\n",
- r, pThis->caCertFile);
- } else {
- // TODO: save error message
+ if(r < 0) {
+ chkGnutlsCode(pThis, "Failed to set certificate trust file", RELP_RET_ERR_TLS_SETUP, r);
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
}
+ pThis->pEngine->dbgprint("librelp: obtained %d certificates from %s\n", r, pThis->caCertFile);
}
if(pThis->ownCertFile != NULL) {
r = gnutls_certificate_set_x509_key_file (pThis->xcred,
pThis->ownCertFile, pThis->privKeyFile, GNUTLS_X509_FMT_PEM);
- pThis->pEngine->dbgprint("DDDD: certificate_set_x509_key_file returns %d\n", r);
+ if(chkGnutlsCode(pThis, "Failed to set certificate key file", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
}
r = gnutls_credentials_set(pThis->session, GNUTLS_CRD_CERTIFICATE, pThis->xcred);
- pThis->pEngine->dbgprint("DDDD: gnutls_credentials_set(cert) %d: %s\n", r, gnutls_strerror(r));
+ if(chkGnutlsCode(pThis, "Failed to set credentials", RELP_RET_ERR_TLS_SETUP, r)) {
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
+ }
if(pThis->authmode == eRelpAuthMode_None)
pThis->authmode = eRelpAuthMode_Fingerprint;
gnutls_certificate_set_verify_function(pThis->xcred, relpTcpVerifyCertificateCallback);
@@ -1177,14 +1522,14 @@
//gnutls_handshake_set_timeout(pThis->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
/* Perform the TLS handshake */
- do
- {
+ do {
r = gnutls_handshake(pThis->session);
pThis->pEngine->dbgprint("DDDD: gnutls_handshake: %d: %s\n", r, gnutls_strerror(r));
if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN) {
pThis->pEngine->dbgprint("librelp: gnutls_handshake must be retried\n");
pThis->rtryOp = relpTCP_RETRY_handshake;
} else if(r != GNUTLS_E_SUCCESS) {
+ chkGnutlsCode(pThis, "TLS handshake failed", RELP_RET_ERR_TLS_SETUP, r);
ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
}
}
@@ -1212,7 +1557,6 @@
struct addrinfo *res = NULL;
struct addrinfo hints;
struct addrinfo *reslocal = NULL;
- int on = 1;
ENTER_RELPFUNC;
RELPOBJ_assert(pThis, Tcp);
@@ -1231,13 +1575,6 @@
if((pThis->sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
ABORT_FINALIZE(RELP_RET_IO_ERR);
}
- /* we set the cork option as performance testing has shown this results
- * in 50 to 100% more performance. In the longer term, we should consider
- * putting messages into a buffer, which then is sent as whole. Much like
- * CORK, but under better control (especially without 200ms timeout!).
- * rgerhards, 2013-06-25
- */
- setsockopt (pThis->sock, SOL_TCP, TCP_CORK, &on, sizeof (on));
if(clientIP != NULL) {
if(getaddrinfo((char*)clientIP, (char*)NULL, &hints, &reslocal) != 0) {
@@ -1298,9 +1635,44 @@
} else if(r == 0) {
pThis->rtryOp = relpTCP_RETRY_none;
} else {
- ABORT_FINALIZE(RELP_RET_IO_ERR);
+ chkGnutlsCode(pThis, "TLS handshake failed", RELP_RET_ERR_TLS_SETUP, r);
+ ABORT_FINALIZE(RELP_RET_ERR_TLS_SETUP);
}
finalize_it:
LEAVE_RELPFUNC;
}
+
+
+/* wait until a socket is writable again. This is primarily for use in client cases.
+ * It does NOT take care of our regular event loop, and must not be used by parts
+ * of the code that are driven by this loop. Returns 0 if a timeout occured and 1
+ * otherwise.
+ */
+int
+relpTcpWaitWriteable(relpTcp_t *pThis, struct timespec *tTimeout)
+{
+ int r;
+ fd_set writefds;
+ struct timespec tCurr; /* current time */
+ struct timeval tvSelect;
+
+ clock_gettime(CLOCK_REALTIME, &tCurr);
+ tvSelect.tv_sec = tTimeout->tv_sec - tCurr.tv_sec;
+ tvSelect.tv_usec = (tTimeout->tv_nsec - tCurr.tv_nsec) / 1000000;
+ if(tvSelect.tv_usec < 0) {
+ tvSelect.tv_usec += 1000000;
+ tvSelect.tv_sec--;
+ }
+ if(tvSelect.tv_sec < 0) {
+ r = 0; goto done;
+ }
+
+ FD_ZERO(&writefds);
+ FD_SET(pThis->sock, &writefds);
+ pThis->pEngine->dbgprint("librelp: telpTcpWaitWritable doing select() "
+ "on fd %d, timoeut %lld.%lld\n", pThis->sock,
+ (long long) tTimeout->tv_sec, (long long) tTimeout->tv_nsec);
+ r = select(pThis->sock+1, NULL, &writefds, NULL, &tvSelect);
+done: return r;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librelp-1.1.3/src/tcp.h new/librelp-1.1.5/src/tcp.h
--- old/librelp-1.1.3/src/tcp.h 2013-06-25 14:55:56.000000000 +0200
+++ new/librelp-1.1.5/src/tcp.h 2013-06-29 15:30:20.000000000 +0200
@@ -45,6 +45,42 @@
#define RELP_SRV_CONN 0 /**< this conection is a server connection */
#define RELP_CLT_CONN 1 /**< this conection is a client connection */
+
+/* The tcp module uses an extended version of the permittedPeers structure,
+ * as it finally needs to "compile" patters that contain wildcards. Doing
+ * that on the fly would not make sense from a performance PoV. Note that
+ * we do not use this exteded structure in highe layers, as it is not
+ * needed there and would at least make things lool much more complicated
+ * than they must be.
+ */
+
+/* if we have wildcards inside permitted peers, we need to maintain
+ * a separate linked list for the wildcard components.
+ */
+typedef struct tcpPermittedPeerWildcardComp_s {
+ char *pszDomainPart;
+ int16_t lenDomainPart;
+ enum {
+ tcpPEER_WILDCARD_NONE = 0, /**< no wildcard in this entry */
+ tcpPEER_WILDCARD_AT_START = 1, /**< wildcard at start of entry (*name) */
+ tcpPEER_WILDCARD_AT_END = 2, /**< wildcard at end of entry (name*) */
+ tcpPEER_WILDCARD_MATCH_ALL = 3, /**< only * wildcard, matches all values */
+ tcpPEER_WILDCARD_EMPTY_COMPONENT = 4/**< special case: domain component empty (e.g. "..") */
+ } wildcardType;
+ struct tcpPermittedPeerWildcardComp_s *pNext;
+} tcpPermittedPeerWildcardComp_t;
+
+typedef struct {
+ char *name;
+ tcpPermittedPeerWildcardComp_t *wildcardRoot;
+ tcpPermittedPeerWildcardComp_t *wildcardLast;
+} tcpPermittedPeerEntry_t;
+/* a structure to store permitted peer information (a type of ACL) */
+typedef struct tcpPermittedPeers_s {
+ int nmemb;
+ tcpPermittedPeerEntry_t *peer;
+} tcpPermittedPeers_t;
+
/* the RELPTCP object
* rgerhards, 2008-03-16
*/
@@ -52,6 +88,8 @@
BEGIN_RELP_OBJ;
relpEngine_t *pEngine;
void *pUsr; /**< user pointer for callbacks */
+ relpSrv_t *pSrv; /**< a pointer to our server object, if NULL, we belong to a client */
+ relpClt_t *pClt; /**< ptr to our client; only valid if pSrv == NULL */
unsigned char *pRemHostIP; /**< IP address of remote peer (currently used in server mode, only) */
unsigned char *pRemHostName; /**< host name of remote peer (currently used in server mode, only) */
int sock; /**< the socket we use for regular, single-socket, operations */
@@ -61,13 +99,12 @@
uint8_t bEnableTLS;
uint8_t bTLSActive; /**< is TLS actually active (properly activated) on this session? */
uint8_t bEnableTLSZip;
- uint8_t bIsClient; /**< set if this belongs to a client, if unset --> server */
int dhBits; /**< number of bits for Diffie-Hellman key */
char *pristring; /**< priority string for GnuTLS */
relpAuthMode_t authmode;
gnutls_anon_client_credentials_t anoncred; /**< client anon credentials */
gnutls_anon_server_credentials_t anoncredSrv; /**< server anon credentials */
- relpPermittedPeers_t permittedPeers;
+ tcpPermittedPeers_t permittedPeers;
/* GnuTLS certificat support */
gnutls_certificate_credentials_t xcred; /**< certificate credentials */
char *caCertFile;
@@ -78,7 +115,6 @@
relpTcpRtryState_t rtryOp;
} relpTcp_t;
-
/* macros for quick member access */
#define relpTcpGetNumSocks(pThis) ((pThis)->socks[0])
#define relpTcpGetLstnSock(pThis, i) ((pThis)->socks[i])
@@ -92,7 +128,7 @@
}
/* prototypes */
-relpRetVal relpTcpConstruct(relpTcp_t **ppThis, relpEngine_t *pEngine, int connType);
+relpRetVal relpTcpConstruct(relpTcp_t **ppThis, relpEngine_t *pEngine, int connType, void *pParent);
relpRetVal relpTcpDestruct(relpTcp_t **ppThis);
relpRetVal relpTcpAbortDestruct(relpTcp_t **ppThis);
relpRetVal relpTcpLstnInit(relpTcp_t *pThis, unsigned char *pLstnPort, int ai_family);
@@ -111,6 +147,9 @@
relpRetVal relpTcpRtryHandshake(relpTcp_t *pThis);
relpRetVal relpTcpSetUsrPtr(relpTcp_t *pThis, void *pUsr);
relpRetVal relpTcpSetAuthMode(relpTcp_t *pThis, relpAuthMode_t authmode);
+void relpTcpHintBurstBegin(relpTcp_t *pThis);
+void relpTcpHintBurstEnd(relpTcp_t *pThis);
int relpTcpGetRtryDirection(relpTcp_t *pThis);
+int relpTcpWaitWriteable(relpTcp_t *pThis, struct timespec *timeout);
#endif /* #ifndef RELPTCP_H_INCLUDED */
--
To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org
For additional commands, e-mail: opensuse-commit+help@opensuse.org