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);