diff --git a/ChangeLog b/ChangeLog index c5f21a3..979193c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -275,7 +275,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/dtls.c b/dtls.c index 7c2c315..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); @@ -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))); @@ -502,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; @@ -520,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 */ @@ -537,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; - - 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_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; @@ -605,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; @@ -647,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) { @@ -659,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 0ba0006..86f4c4c 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -1823,7 +1823,7 @@ void *clientwr(void *arg) { laststatsrv = server->lastreply; 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", @@ -2009,8 +2009,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)) { diff --git a/radsecproxy.conf.5 b/radsecproxy.conf.5 index ff3ca73..706e9b6 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 / @@ -581,7 +581,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) @@ -811,7 +811,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/radsecproxy.h b/radsecproxy.h index 230dcdd..cb20d76 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -190,7 +190,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; @@ -244,7 +244,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 10622ac..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); @@ -276,7 +259,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); @@ -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/tlscommon.c b/tlscommon.c index e429d12..7362309 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -44,9 +44,16 @@ static uint8_t cookie_secret_initialized = 0; #if OPENSSL_VERSION_NUMBER < 0x10100000 static pthread_mutex_t *ssl_locks = NULL; +#if OPENSSL_VERSION_NUMBER < 0x10000000 unsigned long ssl_thread_id() { return (unsigned long)pthread_self(); } +#else +void ssl_thread_id(CRYPTO_THREADID *id) { + CRYPTO_THREADID_set_numeric(id, (unsigned long)pthread_self()); +} +#endif + void ssl_locking_callback(int mode, int type, const char *file, int line) { if (mode & CRYPTO_LOCK) @@ -69,7 +76,11 @@ void sslinit() { for (i = 0; i < CRYPTO_num_locks(); i++) { pthread_mutex_init(&ssl_locks[i], NULL); } +#if OPENSSL_VERSION_NUMBER < 0x10000000 CRYPTO_set_id_callback(ssl_thread_id); +#else + CRYPTO_THREADID_set_callback(ssl_thread_id); +#endif CRYPTO_set_locking_callback(ssl_locking_callback); SSL_load_error_strings(); #else 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} " diff --git a/util.c b/util.c index df6f821..eadce8c 100644 --- a/util.c +++ b/util.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "debug.h" #include "util.h" @@ -129,15 +130,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 @@ -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: */