diff --git a/radsecproxy.c b/radsecproxy.c
index 142d069..c7a50ec 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -2725,6 +2725,7 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
#endif
"DuplicateInterval", CONF_LINT, &dupinterval,
"addTTL", CONF_LINT, &addttl,
+ "tcpKeepalive", CONF_BLN, &conf->keepalive,
"rewrite", CONF_STR, &rewriteinalias,
"rewriteIn", CONF_STR, &conf->confrewritein,
"rewriteOut", CONF_STR, &conf->confrewriteout,
@@ -2908,6 +2909,7 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
"CertificateNameCheck", CONF_BLN, &conf->certnamecheck,
#endif
"addTTL", CONF_LINT, &addttl,
+ "tcpKeepalive", CONF_BLN, &conf->keepalive,
"rewrite", CONF_STR, &rewriteinalias,
"rewriteIn", CONF_STR, &conf->confrewritein,
"rewriteOut", CONF_STR, &conf->confrewriteout,
diff --git a/radsecproxy.conf.5.xml b/radsecproxy.conf.5.xml
index a2ab67c..d14ed3c 100644
--- a/radsecproxy.conf.5.xml
+++ b/radsecproxy.conf.5.xml
@@ -510,6 +510,7 @@ blocktype name {
certificateNameCheck,
matchCertificateAttribute,
duplicateInterval, AddTTL,
+ tcpKeepalive
fticksVISCOUNTRY,
fticksVISINST, rewrite,
rewriteIn, rewriteOut, and
@@ -587,6 +588,11 @@ blocktype name {
that for details. Any value configured here overrides the basic
one when sending messages to this client.
+
+ The tcpKeepalive option enables TCP keepalives. If
+ keepalives are not answered within 30s the connection is considered
+ lost.
+
The fticksVISCOUNTRY option configures
clients eligible to F-Ticks logging as defined by the
@@ -682,7 +688,8 @@ blocktype name {
type, secret,
tls, certificateNameCheck,
matchCertificateAttribute,
- AddTTL, rewrite,
+ AddTTL, tcpKeepalive,
+ rewrite,
rewriteIn, rewriteOut,
statusServer, retryCount,
dynamicLookupCommand and
@@ -704,7 +711,8 @@ blocktype name {
type, secret,
tls, certificateNameCheck,
matchCertificateAttribute,
- AddTTL, rewrite,
+ AddTTL, tcpKeepalive,
+ rewrite,
rewriteIn and rewriteOut
are just as specified for the client block
above, except that defaultServer (and not
diff --git a/radsecproxy.h b/radsecproxy.h
index c96cc69..78eafcd 100644
--- a/radsecproxy.h
+++ b/radsecproxy.h
@@ -132,6 +132,7 @@ struct clsrvconf {
uint8_t dupinterval;
uint8_t certnamecheck;
uint8_t addttl;
+ uint8_t keepalive;
uint8_t loopprevention;
struct rewrite *rewritein;
struct rewrite *rewriteout;
diff --git a/tcp.c b/tcp.c
index 77a6044..d52edff 100644
--- a/tcp.c
+++ b/tcp.c
@@ -118,8 +118,11 @@ int tcpconnect(struct server *server, struct timeval *when, int timeout, char *t
if (server->sock >= 0)
close(server->sock);
- if ((server->sock = connecttcphostlist(server->conf->hostports, srcres)) >= 0)
+ if ((server->sock = connecttcphostlist(server->conf->hostports, srcres)) >= 0) {
+ if (server->conf->keepalive)
+ enable_keepalive(server->sock);
break;
+ }
}
server->connectionok = 1;
gettimeofday(&server->lastconnecttry, NULL);
@@ -221,8 +224,10 @@ void *tcpclientrd(void *arg) {
for (;;) {
/* yes, lastconnecttry is really necessary */
lastconnecttry = server->lastconnecttry;
- buf = radtcpget(server->sock, 0);
+ buf = radtcpget(server->sock, server->dynamiclookuparg ? IDLE_TIMEOUT : 0);
if (!buf) {
+ if (server->dynamiclookuparg)
+ break;
tcpconnect(server, &lastconnecttry, 0, "tcpclientrd");
continue;
}
@@ -230,6 +235,9 @@ void *tcpclientrd(void *arg) {
replyh(server, buf);
}
server->clientrdgone = 1;
+ pthread_mutex_lock(&server->newrq_mutex);
+ pthread_cond_signal(&server->newrq_cond);
+ pthread_mutex_unlock(&server->newrq_mutex);
return NULL;
}
@@ -328,6 +336,8 @@ void *tcpservernew(void *arg) {
if (conf) {
client = addclient(conf, 1);
if (client) {
+ if(conf->keepalive)
+ enable_keepalive(s);
client->sock = s;
client->addr = addr_copy((struct sockaddr *)&from);
tcpserverrd(client);
diff --git a/tls.c b/tls.c
index bbf9da3..2932b7b 100644
--- a/tls.c
+++ b/tls.c
@@ -130,6 +130,9 @@ int tlsconnect(struct server *server, struct timeval *when, int timeout, char *t
if ((server->sock = connecttcphostlist(server->conf->hostports, srcres)) < 0)
continue;
+ if (server->conf->keepalive)
+ enable_keepalive(server->sock);
+
SSL_free(server->ssl);
server->ssl = NULL;
ctx = tlsgetctx(handle, server->conf->tlsconf);
@@ -422,7 +425,7 @@ void *tlsservernew(void *arg) {
cert = verifytlscert(ssl);
if (!cert)
goto exit;
- accepted_tls = conf->tlsconf;
+ accepted_tls = conf->tlsconf;
}
while (conf) {
@@ -430,6 +433,8 @@ void *tlsservernew(void *arg) {
X509_free(cert);
client = addclient(conf, 1);
if (client) {
+ if (conf->keepalive)
+ enable_keepalive(s);
client->ssl = ssl;
client->addr = addr_copy((struct sockaddr *)&from);
tlsserverrd(client);
diff --git a/util.c b/util.c
index 6db7112..cce7432 100644
--- a/util.c
+++ b/util.c
@@ -4,6 +4,7 @@
#include
#include
+#include
#include
#include
#include
@@ -123,6 +124,28 @@ void disable_DF_bit(int socket, struct addrinfo *res) {
}
}
+void enable_keepalive(int socket) {
+ int optval;
+ socklen_t optlen = sizeof(optval);
+
+ optval = 3;
+ if(setsockopt(socket, SOL_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) {
+ debug(DBG_ERR, "enable_keepalive: setsockopt TCP_KEEPIDLE %d failed", optval);
+ }
+ optval = 10;
+ if(setsockopt(socket, SOL_TCP, TCP_KEEPINTVL, &optval, optlen) < 0) {
+ debug(DBG_ERR, "enable_keepalive: setsockopt TCP_KEEPINTVL failed");
+ }
+ optval = 1;
+ if(setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
+ debug(DBG_ERR, "enable_keepalive: setsockopt SO_KEEPALIVE failed");
+ }
+}
+
int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse) {
int s, on = 1;
struct addrinfo *res;
diff --git a/util.h b/util.h
index 5784eb9..bd66d18 100644
--- a/util.h
+++ b/util.h
@@ -20,6 +20,7 @@ void port_set(struct sockaddr *sa, uint16_t port);
void printfchars(char *prefixfmt, char *prefix, char *charfmt, uint8_t *chars, int len);
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);