From 34a71d3cbb6cc9198936f4db2fe8039205b495ab Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 2 Jan 2019 00:12:35 -0800 Subject: [PATCH 1/6] Switch to OpenSSL's THREADID API The old callback was deprecated in version 1.0.0 of OpenSSL Fixes compilation without deprecated APIs enabled on 1.0.2. --- tlscommon.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tlscommon.c b/tlscommon.c index e429d12..623b007 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -44,8 +44,8 @@ static uint8_t cookie_secret_initialized = 0; #if OPENSSL_VERSION_NUMBER < 0x10100000 static pthread_mutex_t *ssl_locks = NULL; -unsigned long ssl_thread_id() { - return (unsigned long)pthread_self(); +void ssl_thread_id(CRYPTO_THREADID *id) { + CRYPTO_THREADID_set_numeric(id, (unsigned long)pthread_self()); } void ssl_locking_callback(int mode, int type, const char *file, int line) { @@ -69,7 +69,7 @@ void sslinit() { for (i = 0; i < CRYPTO_num_locks(); i++) { pthread_mutex_init(&ssl_locks[i], NULL); } - CRYPTO_set_id_callback(ssl_thread_id); + CRYPTO_THREADID_set_callback(ssl_thread_id); CRYPTO_set_locking_callback(ssl_locking_callback); SSL_load_error_strings(); #else From fe35459bad751de8dea9ade405ce588bd235d0a6 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Tue, 8 Jan 2019 20:44:55 +0200 Subject: [PATCH 2/6] Another spelling fix conneciton -> connection --- tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tls.c b/tls.c index 10622ac..158ca43 100644 --- a/tls.c +++ b/tls.c @@ -276,7 +276,7 @@ unsigned char *radtlsget(SSL *ssl, int timeout, pthread_mutex_t *lock) { len = RADLEN(buf); if (len < 20) { - debug(DBG_ERR, "radtlsget: length too small, malformed packet! closing conneciton!"); + debug(DBG_ERR, "radtlsget: length too small, malformed packet! closing connection!"); pthread_mutex_lock(lock); SSL_shutdown(ssl); pthread_mutex_unlock(lock); From 64524860919679365ced1d0d06dc9d149df20a45 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Tue, 8 Jan 2019 20:29:24 +0200 Subject: [PATCH 3/6] Replace SOL_TCP with IPPROTO_TCP SOL_TCP is deprecated and doesn't exist on all platforms (e.g. FreeBSD). IPPROTO_TCP is equivalent and portable. --- util.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util.c b/util.c index df6f821..fd9f59c 100644 --- a/util.c +++ b/util.c @@ -129,15 +129,15 @@ void enable_keepalive(int socket) { debug(DBG_NOTICE, "TCP Keepalive feature might be limited on this platform"); #else optval = 3; - if(setsockopt(socket, SOL_TCP, TCP_KEEPCNT, &optval, optlen) < 0) { + if(setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen) < 0) { debug(DBG_ERR, "enable_keepalive: setsockopt TCP_KEEPCNT failed"); } optval = 10; - if(setsockopt(socket, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) { + if(setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) { debug(DBG_ERR, "enable_keepalive: setsockopt TCP_KEEPIDLE %d failed", optval); } optval = 10; - if(setsockopt(socket, SOL_TCP, TCP_KEEPINTVL, &optval, optlen) < 0) { + if(setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen) < 0) { debug(DBG_ERR, "enable_keepalive: setsockopt TCP_KEEPINTVL failed"); } #endif From b5439433b75733292baf4cbb3162b00a45449711 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Tue, 8 Jan 2019 18:51:48 +0200 Subject: [PATCH 4/6] Use IP_RECVDSTADDR where applicable IP_PKTINFO is provided by many platforms (Linux among them), but not all. Most notably, FreeBSD does not provide this functionality, but provides a similar one with IP_RECVDSTADDR instead. Make the use of IP_PKTINFO conditional on the constant being defined, and add support for IP_RECVDSTADDR as well, restoring support for FreeBSD. Fixes: #25 --- dtls.c | 18 +++++++++++++++--- radsecproxy.c | 5 +++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/dtls.c b/dtls.c index 7c2c315..6ac1e16 100644 --- a/dtls.c +++ b/dtls.c @@ -400,12 +400,24 @@ int getConnectionInfo(int socket, struct sockaddr *from, socklen_t fromlen, stru if (getsockname(socket, to, &tolen)) return -1; for (ctrlhdr = CMSG_FIRSTHDR(&msghdr); ctrlhdr; ctrlhdr = CMSG_NXTHDR(&msghdr, ctrlhdr)) { +#if defined(IP_PKTINFO) if(ctrlhdr->cmsg_level == IPPROTO_IP && ctrlhdr->cmsg_type == IP_PKTINFO) { - debug(DBG_DBG, "udp packet to: %s", inet_ntop(AF_INET, &((struct in_pktinfo *)CMSG_DATA(ctrlhdr))->ipi_addr, tmp, sizeof(tmp))); + struct in_pktinfo *pktinfo = (struct in_pktinfo *)CMSG_DATA(ctrlhdr); + debug(DBG_DBG, "udp packet to: %s", inet_ntop(AF_INET, &(pktinfo->ipi_addr), tmp, sizeof(tmp))); - ((struct sockaddr_in *)to)->sin_addr = ((struct in_pktinfo *)CMSG_DATA(ctrlhdr))->ipi_addr; + ((struct sockaddr_in *)to)->sin_addr = pktinfo->ipi_addr; toaddrfound = 1; - } else if(ctrlhdr->cmsg_level == IPPROTO_IPV6 && ctrlhdr->cmsg_type == IPV6_RECVPKTINFO) { + } +#elif defined(IP_RECVDSTADDR) + if(ctrlhdr->cmsg_level == IPPROTO_IP && ctrlhdr->cmsg_type == IP_RECVDSTADDR) { + struct in_addr *addr = (struct in_addr *)CMSG_DATA(ctrlhdr); + debug(DBG_DBG, "udp packet to: %s", inet_ntop(AF_INET, addr, tmp, sizeof(tmp))); + + ((struct sockaddr_in *)to)->sin_addr = *addr; + toaddrfound = 1; + } +#endif + if(ctrlhdr->cmsg_level == IPPROTO_IPV6 && ctrlhdr->cmsg_type == IPV6_RECVPKTINFO) { info6 = (struct in6_pktinfo *)CMSG_DATA(ctrlhdr); debug(DBG_DBG, "udp packet to: %x", inet_ntop(AF_INET6, &info6->ipi6_addr, tmp, sizeof(tmp))); diff --git a/radsecproxy.c b/radsecproxy.c index e8d7527..70a7d6a 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -1997,8 +1997,13 @@ void createlistener(uint8_t type, char *arg) { if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) == -1) debugerrno(errno, DBG_WARN, "craetelistener: IPV6_RECVPKTINFO"); } else if (res->ai_family == AF_INET) { +#if defined(IP_PKTINFO) if (setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)) == -1) debugerrno(errno, DBG_WARN, "createlistener: IP_PKTINFO"); +#elif defined(IP_RECVDSTADDR) + if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on)) == -1) + debugerrno(errno, DBG_WARN, "createlistener: IP_RECVDSTADDR"); +#endif } } if (bind(s, res->ai_addr, res->ai_addrlen)) { From b72b59945a11a2d640fc47a054398f65b87430a1 Mon Sep 17 00:00:00 2001 From: Jonathan Tooker Date: Mon, 28 Jan 2019 12:29:37 -0600 Subject: [PATCH 5/6] Spelling fixes --- ChangeLog | 2 +- radsecproxy.conf.5 | 8 ++++---- tools/radsec-dynsrv.sh | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 228a532..236af7f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -271,7 +271,7 @@ changes since 1.7.2 2008-10-07 1.2 listenTCP and sourceTCP options renamed to listenTLS and sourceTLS - Old options deprecated but available for backwards compatiblity + Old options deprecated but available for backwards compatibility Logging reply-message attribute from Reject messages Contribution from Arne Schwabe Rewrite blocks have new options addAttribute and modifyAttribute diff --git a/radsecproxy.conf.5 b/radsecproxy.conf.5 index 1916f1e..149c8b6 100644 --- a/radsecproxy.conf.5 +++ b/radsecproxy.conf.5 @@ -189,7 +189,7 @@ See \fIradsecproxy.conf\-example\fR for details. The FTicksMAC option has the same function as LogMAC for FTicks. The default for FTicksMAC is \fBVendorKeyHashed\fR which needs \fBFTicksKey\fR to be set. -Before chosing any of +Before choosing any of .BR Original , .BR FullyHashed or @@ -466,7 +466,7 @@ Apply the operations in the specified \fIrewrite\fR block on incoming (request) or outgoing (response) messages from this client. Rewriting incoming messages is done before, outgoing after other processing. If the \fBRewriteIn\fR is not configured, the rewrite blocks \fBdefaultClient\fR or \fBdefault\fR will be -applied if defined. No default blocks are appied for \fBRewriteOut\fR. +applied if defined. No default blocks are applied for \fBRewriteOut\fR. .RE .BI "RewriteAttribute User-Name:/" regex / replace / @@ -576,7 +576,7 @@ Apply the operations in the specified \fIrewrite\fR block on outgoing (request) or incoming (response) messages to/from this server. Rewriting outgoing messages is done after, incoming before other processing. If the \fBRewriteIn\fR is not configured, the rewrite blocks \fBdefaultServer\fR or \fBdefault\fR will be -applied if defined. No default blocks are appied for \fBRewriteOut\fR. +applied if defined. No default blocks are applied for \fBRewriteOut\fR. .RE .BR "LoopPrevention (" on | off) @@ -806,7 +806,7 @@ block are: .BI "AddAttribute " attribute \fR: value .RS -Add an \fIattribute\fR to the radius mesage and set it to \fIvalue\fR. The +Add an \fIattribute\fR to the radius message and set it to \fIvalue\fR. The \fIattribute\fR must be specified using the numerical attribute id. The \fIvalue\fR can either be numerical, a string, or a hex value. See the \fBCONFIGURATION SYNTAX\fR section for details. diff --git a/tools/radsec-dynsrv.sh b/tools/radsec-dynsrv.sh index 2c87a33..2eff080 100755 --- a/tools/radsec-dynsrv.sh +++ b/tools/radsec-dynsrv.sh @@ -5,7 +5,7 @@ # realm given as argument, and creates a server template based # on that. It currently ignores weight markers, but does sort # servers on priority marker, lowest number first. -# For host command this is coloumn 5, for dig it is coloumn 1. +# For host command this is column 5, for dig it is column 1. usage() { echo "Usage: ${0} " From 524a096116fe828ce3cd9cd2133a17069b2e2e74 Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Wed, 1 May 2019 14:45:37 +0200 Subject: [PATCH 6/6] refactor reconnect timer to avoid platform issues with time_t. Fix #28 --- dtls.c | 51 +++++++++++++++------------------------------- radsecproxy.c | 2 +- radsecproxy.h | 4 ++-- tcp.c | 56 +++++++++++++++++---------------------------------- tls.c | 53 ++++++++++++++++-------------------------------- util.c | 27 +++++++++++++++++++++++++ util.h | 1 + 7 files changed, 83 insertions(+), 111 deletions(-) diff --git a/dtls.c b/dtls.c index 6ac1e16..c4d9fd8 100644 --- a/dtls.c +++ b/dtls.c @@ -35,7 +35,7 @@ static void setprotoopts(struct commonprotoopts *opts); static char **getlistenerargs(); void *dtlslistener(void *arg); -int dtlsconnect(struct server *server, struct timeval *when, int timeout, char *text); +int dtlsconnect(struct server *server, int timeout, char *text); void *dtlsclientrd(void *arg); int clientradputdtls(struct server *server, unsigned char *rad); void addserverextradtls(struct clsrvconf *conf); @@ -514,9 +514,10 @@ void *dtlslistener(void *arg) { return NULL; } -int dtlsconnect(struct server *server, struct timeval *when, int timeout, char *text) { - struct timeval socktimeout, now, start = {0,0}; +int dtlsconnect(struct server *server, int timeout, char *text) { + struct timeval socktimeout, now, start; time_t wait; + int firsttry = 1; X509 *cert; SSL_CTX *ctx = NULL; struct hostportres *hp; @@ -532,12 +533,7 @@ int dtlsconnect(struct server *server, struct timeval *when, int timeout, char * pthread_mutex_unlock(&server->lock); hp = (struct hostportres *)list_first(server->conf->hostports)->data; - - gettimeofday(&now, NULL); - if (when && (now.tv_sec - when->tv_sec) < 30 ) { - /* last connection was less than 30s ago. Delay next attempt */ - start.tv_sec = now.tv_sec + 30 - (now.tv_sec - when->tv_sec); - } + gettimeofday(&start, NULL); for (;;) { /* ensure previous connection is properly closed */ @@ -549,30 +545,18 @@ int dtlsconnect(struct server *server, struct timeval *when, int timeout, char * SSL_free(server->ssl); server->ssl = NULL; - /* no sleep at startup or at first try */ - if (start.tv_sec) { - gettimeofday(&now, NULL); - wait = abs(now.tv_sec - start.tv_sec); - wait = wait > 60 ? 60 : wait; + wait = connect_wait(start, server->connecttime, firsttry); + debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); + sleep(wait); + firsttry = 0; - if (timeout && (now.tv_sec - start.tv_sec) > timeout) { - debug(DBG_DBG, "tlsconnect: timeout"); - return 0; - } - - if (wait < 1) - sleep(2); - else { - debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); - sleep(wait); - } - debug(DBG_INFO, "tlsconnect: retry connecting to %s", server->conf->name); - } else { - gettimeofday(&start, NULL); + gettimeofday(&now, NULL); + if (timeout && (now.tv_sec - start.tv_sec) > timeout) { + debug(DBG_DBG, "tlsconnect: timeout"); + return 0; } - /* done sleeping */ - debug(DBG_WARN, "dtlsconnect: trying to open DTLS connection to %s port %s", hp->host, hp->port); + debug(DBG_INFO, "dtlsconnect: connecting to %s port %s", hp->host, hp->port); if ((server->sock = bindtoaddr(srcres, hp->addrinfo->ai_family, 0)) < 0) continue; @@ -617,7 +601,7 @@ int dtlsconnect(struct server *server, struct timeval *when, int timeout, char * pthread_mutex_lock(&server->lock); server->state = RSP_SERVER_STATE_CONNECTED; - gettimeofday(&server->lastconnecttry, NULL); + gettimeofday(&server->connecttime, NULL); pthread_mutex_unlock(&server->lock); pthread_mutex_lock(&server->newrq_mutex); server->conreset = 1; @@ -659,11 +643,8 @@ int clientradputdtls(struct server *server, unsigned char *rad) { void *dtlsclientrd(void *arg) { struct server *server = (struct server *)arg; unsigned char *buf; - struct timeval lastconnecttry; for (;;) { - /* yes, lastconnecttry is really necessary */ - lastconnecttry = server->lastconnecttry; buf = raddtlsget(server->ssl, 5, &server->lock); if (!buf) { if(SSL_get_shutdown(server->ssl) || server->lostrqs) { @@ -671,7 +652,7 @@ void *dtlsclientrd(void *arg) { debug (DBG_WARN, "tlscleintrd: connection to server %s lost", server->conf->name); else if (server->lostrqs) debug (DBG_WARN, "dtlsclientrd: server %s did not respond, closing connection.", server->conf->name); - dtlsconnect(server, &lastconnecttry, 0, "dtlsclientrd"); + dtlsconnect(server, 0, "dtlsclientrd"); server->lostrqs = 0; } continue; diff --git a/radsecproxy.c b/radsecproxy.c index 70a7d6a..38f2892 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -1823,7 +1823,7 @@ void *clientwr(void *arg) { gettimeofday(&server->lastreply, NULL); if (conf->pdef->connecter) { - if (!conf->pdef->connecter(server, NULL, server->dynamiclookuparg ? 5 : 0, "clientwr")) { + if (!conf->pdef->connecter(server, server->dynamiclookuparg ? 5 : 0, "clientwr")) { server->state = RSP_SERVER_STATE_FAILING; if (server->dynamiclookuparg) { debug(DBG_WARN, "%s: connect failed, sleeping %ds", diff --git a/radsecproxy.h b/radsecproxy.h index 681ba60..78b949a 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -183,7 +183,7 @@ struct server { pthread_mutex_t lock; pthread_t clientth; uint8_t clientrdgone; - struct timeval lastconnecttry; + struct timeval connecttime; struct timeval lastreply; enum rsp_server_state state; uint8_t lostrqs; @@ -237,7 +237,7 @@ struct protodefs { void (*setprotoopts)(struct commonprotoopts *); char **(*getlistenerargs)(); void *(*listener)(void*); - int (*connecter)(struct server *, struct timeval *, int, char *); + int (*connecter)(struct server *, int, char *); void *(*clientconnreader)(void*); int (*clientradput)(struct server *, unsigned char *); void (*addclient)(struct client *); diff --git a/tcp.c b/tcp.c index 803a549..500abb2 100644 --- a/tcp.c +++ b/tcp.c @@ -29,7 +29,7 @@ static void setprotoopts(struct commonprotoopts *opts); static char **getlistenerargs(); void *tcplistener(void *arg); -int tcpconnect(struct server *server, struct timeval *when, int timeout, char * text); +int tcpconnect(struct server *server, int timeout, char * text); void *tcpclientrd(void *arg); int clientradputtcp(struct server *server, unsigned char *rad); void tcpsetsrcres(); @@ -79,8 +79,9 @@ void tcpsetsrcres() { AF_UNSPEC, NULL, protodefs.socktype); } -int tcpconnect(struct server *server, struct timeval *when, int timeout, char *text) { - struct timeval now, start = {0,0}; +int tcpconnect(struct server *server, int timeout, char *text) { + struct timeval now, start; + int firsttry = 1; time_t wait; debug(DBG_DBG, "tcpconnect: called from %s", text); @@ -89,43 +90,27 @@ int tcpconnect(struct server *server, struct timeval *when, int timeout, char *t if (server->state == RSP_SERVER_STATE_CONNECTED) server->state = RSP_SERVER_STATE_RECONNECTING; - gettimeofday(&now, NULL); - if (when && (now.tv_sec - when->tv_sec) < 30 ) { - /* last connection was less than 30s ago. Delay next attempt */ - start.tv_sec = now.tv_sec + 30 - (now.tv_sec - when->tv_sec); - } + gettimeofday(&start, NULL); for (;;) { if (server->sock >= 0) close(server->sock); server->sock = -1; - /* no sleep at startup or at first try */ - if (start.tv_sec) { - gettimeofday(&now, NULL); - wait = abs(now.tv_sec - start.tv_sec); - wait = wait > 60 ? 60 : wait; - - if (timeout && (now.tv_sec - start.tv_sec) > timeout) { - debug(DBG_DBG, "tlsconnect: timeout"); - pthread_mutex_unlock(&server->lock); - return 0; - } - - /* give up lock while sleeping for next try */ - pthread_mutex_unlock(&server->lock); - if (wait < 1) - sleep(2); - else { - debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); - sleep(wait); - } - pthread_mutex_lock(&server->lock); - debug(DBG_INFO, "tlsconnect: retry connecting to %s", server->conf->name); - } else { - gettimeofday(&start, NULL); + pthread_mutex_unlock(&server->lock); + wait = connect_wait(start, server->connecttime, firsttry); + debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); + sleep(wait); + firsttry = 0; + + gettimeofday(&now, NULL); + if (timeout && (now.tv_sec - start.tv_sec) > timeout) { + debug(DBG_DBG, "tcpconnect: timeout"); + return 0; } + pthread_mutex_lock(&server->lock); + debug(DBG_INFO, "tcpconnect: connecting to %s", server->conf->name); if ((server->sock = connecttcphostlist(server->conf->hostports, srcres)) < 0) continue; if (server->conf->keepalive) @@ -133,7 +118,7 @@ int tcpconnect(struct server *server, struct timeval *when, int timeout, char *t break; } server->state = RSP_SERVER_STATE_CONNECTED; - gettimeofday(&server->lastconnecttry, NULL); + gettimeofday(&server->connecttime, NULL); server->lostrqs = 0; pthread_mutex_unlock(&server->lock); pthread_mutex_lock(&server->newrq_mutex); @@ -230,16 +215,13 @@ int clientradputtcp(struct server *server, unsigned char *rad) { void *tcpclientrd(void *arg) { struct server *server = (struct server *)arg; unsigned char *buf; - struct timeval lastconnecttry; for (;;) { - /* yes, lastconnecttry is really necessary */ - lastconnecttry = server->lastconnecttry; buf = radtcpget(server->sock, server->dynamiclookuparg ? IDLE_TIMEOUT : 0); if (!buf) { if (server->dynamiclookuparg) break; - tcpconnect(server, &lastconnecttry, 0, "tcpclientrd"); + tcpconnect(server, 0, "tcpclientrd"); continue; } diff --git a/tls.c b/tls.c index 158ca43..85390c4 100644 --- a/tls.c +++ b/tls.c @@ -31,7 +31,7 @@ static void setprotoopts(struct commonprotoopts *opts); static char **getlistenerargs(); void *tlslistener(void *arg); -int tlsconnect(struct server *server, struct timeval *when, int timeout, char *text); +int tlsconnect(struct server *server, int timeout, char *text); void *tlsclientrd(void *arg); int clientradputtls(struct server *server, unsigned char *rad); void tlssetsrcres(); @@ -82,9 +82,10 @@ void tlssetsrcres() { AF_UNSPEC, NULL, protodefs.socktype); } -int tlsconnect(struct server *server, struct timeval *when, int timeout, char *text) { - struct timeval now, start = {0,0}; +int tlsconnect(struct server *server, int timeout, char *text) { + struct timeval now, start; time_t wait; + int firsttry = 1; X509 *cert; SSL_CTX *ctx = NULL; unsigned long error; @@ -92,17 +93,10 @@ int tlsconnect(struct server *server, struct timeval *when, int timeout, char *t debug(DBG_DBG, "tlsconnect: called from %s", text); pthread_mutex_lock(&server->lock); - if (server->state == RSP_SERVER_STATE_CONNECTED) server->state = RSP_SERVER_STATE_RECONNECTING; - pthread_mutex_unlock(&server->lock); - - gettimeofday(&now, NULL); - if (when && (now.tv_sec - when->tv_sec) < 30 ) { - /* last connection was less than 30s ago. Delay next attempt */ - start.tv_sec = now.tv_sec + 30 - (now.tv_sec - when->tv_sec); - } + gettimeofday(&start, NULL); for (;;) { /* ensure previous connection is properly closed */ @@ -114,29 +108,18 @@ int tlsconnect(struct server *server, struct timeval *when, int timeout, char *t SSL_free(server->ssl); server->ssl = NULL; - /* no sleep at startup or at first try */ - if (start.tv_sec) { - gettimeofday(&now, NULL); - wait = abs(now.tv_sec - start.tv_sec); - wait = wait > 60 ? 60 : wait; - - if (timeout && (now.tv_sec - start.tv_sec) > timeout) { - debug(DBG_DBG, "tlsconnect: timeout"); - return 0; - } + wait = connect_wait(start, server->connecttime, firsttry); + debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); + sleep(wait); + firsttry = 0; - if (wait < 1) - sleep(2); - else { - debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); - sleep(wait); - } - debug(DBG_INFO, "tlsconnect: retry connecting to %s", server->conf->name); - } else { - gettimeofday(&start, NULL); + gettimeofday(&now, NULL); + if (timeout && (now.tv_sec - start.tv_sec) > timeout) { + debug(DBG_DBG, "tlsconnect: timeout"); + return 0; } - /* done sleeping */ + debug(DBG_INFO, "tlsconnect: connecting to %s", server->conf->name); if ((server->sock = connecttcphostlist(server->conf->hostports, srcres)) < 0) continue; if (server->conf->keepalive) @@ -181,7 +164,7 @@ int tlsconnect(struct server *server, struct timeval *when, int timeout, char *t pthread_mutex_lock(&server->lock); server->state = RSP_SERVER_STATE_CONNECTED; - gettimeofday(&server->lastconnecttry, NULL); + gettimeofday(&server->connecttime, NULL); server->lostrqs = 0; pthread_mutex_unlock(&server->lock); pthread_mutex_lock(&server->newrq_mutex); @@ -357,11 +340,9 @@ int clientradputtls(struct server *server, unsigned char *rad) { void *tlsclientrd(void *arg) { struct server *server = (struct server *)arg; unsigned char *buf; - struct timeval now, lastconnecttry; + struct timeval now; for (;;) { - /* yes, lastconnecttry is really necessary */ - lastconnecttry = server->lastconnecttry; buf = radtlsget(server->ssl, 10, &server->lock); if (!buf) { if (SSL_get_shutdown(server->ssl) || server->lostrqs) { @@ -371,7 +352,7 @@ void *tlsclientrd(void *arg) { debug (DBG_WARN, "tlsclientrd: server %s did not respond, closing connection.", server->conf->name); if (server->dynamiclookuparg) break; - tlsconnect(server, &lastconnecttry, 0, "tlsclientrd"); + tlsconnect(server, 0, "tlsclientrd"); } if (server->dynamiclookuparg) { gettimeofday(&now, NULL); diff --git a/util.c b/util.c index fd9f59c..eadce8c 100644 --- a/util.c +++ b/util.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "debug.h" #include "util.h" @@ -251,6 +252,32 @@ int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src, uint16_t timeout return s; } +time_t connect_wait(struct timeval attempt_start, struct timeval last_success, int firsttry) { + struct timeval now; + + gettimeofday(&now, NULL); + + if (attempt_start.tv_sec < last_success.tv_sec || + attempt_start.tv_sec > now.tv_sec) { + debug(DBG_WARN, "connect_wait: invalid timers detected!"); + return 60; + } + + if (now.tv_sec - last_success.tv_sec < 30) + return 30 - (attempt_start.tv_sec - last_success.tv_sec); + + if (firsttry) + return 0; + + if (now.tv_sec - attempt_start.tv_sec < 2) + return 2; + + if (now.tv_sec - attempt_start.tv_sec > 60) + return 60; + + return now.tv_sec - attempt_start.tv_sec; +} + /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ diff --git a/util.h b/util.h index 3daad3d..68b1f24 100644 --- a/util.h +++ b/util.h @@ -23,6 +23,7 @@ void disable_DF_bit(int socket, struct addrinfo *res); void enable_keepalive(int socket); int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse); int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src, uint16_t timeout); +time_t connect_wait(struct timeval attempt_start, struct timeval last_success, int firsttry); /* Local Variables: */