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: */