From d0675120761d8cd58fd621501f88b3fa5a1df49f Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Mon, 17 Sep 2018 07:36:02 +0200 Subject: [PATCH 1/3] add options for statusserver: minimal: only send statusserver if request lost auto: try autodetecting statusserver capability --- radsecproxy.c | 122 +++++++++++++++++++++++++++++++------------------- radsecproxy.h | 9 +++- 2 files changed, 85 insertions(+), 46 deletions(-) diff --git a/radsecproxy.c b/radsecproxy.c index 1c6fd54..9bd6453 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -472,7 +472,7 @@ void sendrq(struct request *rq) { if (!to) goto errexit; - start = to->conf->statusserver ? 1 : 0; + start = to->conf->statusserver == RSP_STATSRV_OFF ? 0 : 1; pthread_mutex_lock(&to->newrq_mutex); if (start && rq->msg->code == RAD_Status_Server) { if (!_internal_sendrq(to, 0, rq)) { @@ -1669,9 +1669,11 @@ void replyh(struct server *server, unsigned char *buf) { gettimeofday(&server->lastrcv, NULL); if (rqout->rq->msg->code == RAD_Status_Server) { - freerqoutdata(rqout); - debug(DBG_NOTICE, "replyh: got status server response from %s", server->conf->name); - goto errunlock; + freerqoutdata(rqout); + debug(DBG_NOTICE, "replyh: got status server response from %s", server->conf->name); + if (server->conf->statusserver == RSP_STATSRV_AUTO) + server->conf->statusserver = RSP_STATSRV_MINIMAL; + goto errunlock; } gettimeofday(&server->lastreply, NULL); @@ -1784,7 +1786,7 @@ void *clientwr(void *arg) { pthread_t clientrdth; int i, dynconffail = 0; time_t secs; - uint8_t rnd, do_resend = 0; + uint8_t rnd, do_resend = 0, statusserver_requested = 0; struct timeval now, laststatsrv; struct timespec timeout; struct request *statsrvrq; @@ -1816,7 +1818,7 @@ void *clientwr(void *arg) { memset(&timeout, 0, sizeof(struct timespec)); - if (conf->statusserver) { + if (conf->statusserver != RSP_STATSRV_OFF) { gettimeofday(&server->lastrcv, NULL); gettimeofday(&laststatsrv, NULL); } @@ -1840,6 +1842,9 @@ void *clientwr(void *arg) { } server->state = RSP_SERVER_STATE_CONNECTED; + if (conf->statusserver == RSP_STATSRV_AUTO) + statusserver_requested = 1; + for (;;) { pthread_mutex_lock(&server->newrq_mutex); if (!server->newrq) { @@ -1847,7 +1852,7 @@ void *clientwr(void *arg) { /* random 0-7 seconds */ RAND_bytes(&rnd, 1); rnd /= 32; - if (conf->statusserver) { + if (conf->statusserver != RSP_STATSRV_OFF) { secs = server->lastrcv.tv_sec > laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec; if (now.tv_sec - secs > STATUS_SERVER_PERIOD) secs = now.tv_sec; @@ -1911,24 +1916,33 @@ void *clientwr(void *arg) { continue; } - if (rqout->tries == (*rqout->rq->buf == RAD_Status_Server ? 1 : conf->retrycount + 1)) { - debug(DBG_DBG, "clientwr: removing expired packet from queue"); - replylog(rqout->rq->msg, server, rqout->rq); - if (conf->statusserver) { - if (*rqout->rq->buf == RAD_Status_Server) { - debug(DBG_WARN, "clientwr: no status server response, %s dead?", conf->name); - if (server->lostrqs < 255) - server->lostrqs++; - } + if (rqout->tries > 0 && now.tv_sec - server->lastrcv.tv_sec > conf->retryinterval) + statusserver_requested = 1; + if (rqout->tries == (*rqout->rq->buf == RAD_Status_Server ? 1 : conf->retrycount + 1)) { + debug(DBG_DBG, "clientwr: removing expired packet from queue"); + replylog(rqout->rq->msg, server, rqout->rq); + if (conf->statusserver == RSP_STATSRV_ON || conf->statusserver == RSP_STATSRV_MINIMAL) { + if (*rqout->rq->buf == RAD_Status_Server) { + debug(DBG_WARN, "clientwr: no status server response, %s dead?", conf->name); + if (server->lostrqs < 255) + server->lostrqs++; + } + } else { + if (conf->statusserver == RSP_STATSRV_AUTO && *rqout->rq->buf == RAD_Status_Server) { + if (server->lastrcv.tv_sec >= laststatsrv.tv_sec) { + debug(DBG_DBG, "clientwr: status server autodetect faild, disabling status server for %s", conf->name); + conf->statusserver = RSP_STATSRV_OFF; + } } else { - debug(DBG_WARN, "clientwr: no server response, %s dead?", conf->name); - if (server->lostrqs < 255) - server->lostrqs++; - } - freerqoutdata(rqout); - pthread_mutex_unlock(rqout->lock); - continue; - } + debug(DBG_WARN, "clientwr: no server response, %s dead?", conf->name); + if (server->lostrqs < 255) + server->lostrqs++; + } + } + freerqoutdata(rqout); + pthread_mutex_unlock(rqout->lock); + continue; + } rqout->expiry.tv_sec = now.tv_sec + conf->retryinterval; if (!timeout.tv_sec || rqout->expiry.tv_sec < timeout.tv_sec) @@ -1941,19 +1955,23 @@ void *clientwr(void *arg) { pthread_mutex_unlock(rqout->lock); } do_resend = 0; - if (conf->statusserver && server->state == RSP_SERVER_STATE_CONNECTED) { - secs = server->lastrcv.tv_sec > laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec; - gettimeofday(&now, NULL); - if (now.tv_sec - secs > STATUS_SERVER_PERIOD) { - laststatsrv = now; - statsrvrq = createstatsrvrq(); - if (statsrvrq) { - statsrvrq->to = server; - debug(DBG_DBG, "clientwr: sending %s to %s", radmsgtype2string(RAD_Status_Server), conf->name); - sendrq(statsrvrq); - } - } - } + if (server->state == RSP_SERVER_STATE_CONNECTED && !conf->statusserver == RSP_STATSRV_OFF) { + secs = server->lastrcv.tv_sec > laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec; + gettimeofday(&now, NULL); + if ((conf->statusserver == RSP_STATSRV_ON && now.tv_sec - secs > STATUS_SERVER_PERIOD) || + ((conf->statusserver == RSP_STATSRV_MINIMAL || conf->statusserver == RSP_STATSRV_AUTO) && + statusserver_requested && now.tv_sec - laststatsrv.tv_sec > STATUS_SERVER_PERIOD)) { + + laststatsrv = now; + statsrvrq = createstatsrvrq(); + if (statsrvrq) { + statsrvrq->to = server; + debug(DBG_DBG, "clientwr: sending %s to %s", radmsgtype2string(RAD_Status_Server), conf->name); + sendrq(statsrvrq); + } + statusserver_requested = 0; + } + } } errexit: if (server->dynamiclookuparg) { @@ -2936,7 +2954,7 @@ int compileserverconfig(struct clsrvconf *conf, const char *block) { int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { struct clsrvconf *conf, *resconf; - char *conftype = NULL, *rewriteinalias = NULL; + char *conftype = NULL, *rewriteinalias = NULL, *statusserver = NULL; long int retryinterval = LONG_MIN, retrycount = LONG_MIN, addttl = LONG_MIN; uint8_t ipv4only = 0, ipv6only = 0, confmerged = 0; @@ -2951,10 +2969,11 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char conf->loopprevention = UCHAR_MAX; /* Uninitialized. */ resconf = (struct clsrvconf *)arg; if (resconf) { - conf->statusserver = resconf->statusserver; - conf->certnamecheck = resconf->certnamecheck; - } else - conf->certnamecheck = 1; + conf->statusserver = resconf->statusserver; + conf->certnamecheck = resconf->certnamecheck; + } else { + conf->certnamecheck = 1; + } if (!getgenericconfig(cf, block, "type", CONF_STR, &conftype, @@ -2973,7 +2992,7 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char "rewrite", CONF_STR, &rewriteinalias, "rewriteIn", CONF_STR, &conf->confrewritein, "rewriteOut", CONF_STR, &conf->confrewriteout, - "StatusServer", CONF_BLN, &conf->statusserver, + "StatusServer", CONF_STR, &statusserver, "RetryInterval", CONF_LINT, &retryinterval, "RetryCount", CONF_LINT, &retrycount, "DynamicLookupCommand", CONF_STR, &conf->dynamiclookupcommand, @@ -3049,6 +3068,19 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char conf->addttl = (uint8_t)addttl; } + if (statusserver) { + if (strcasecmp(statusserver, "Off") == 0) + conf->statusserver = RSP_STATSRV_OFF; + else if (strcasecmp(statusserver, "On") == 0) + conf->statusserver = RSP_STATSRV_ON; + else if (strcasecmp(statusserver, "Minimal") == 0) + conf->statusserver = RSP_STATSRV_MINIMAL; + else if (strcasecmp(statusserver, "Auto") == 0) + conf->statusserver = RSP_STATSRV_AUTO; + else + debugx(1, DBG_ERR, "config error in blocck %s: invalid StatusServer value: %s", block, statusserver); + } + if (resconf) { if (!mergesrvconf(resconf, conf)) goto errexit; @@ -3222,8 +3254,8 @@ void getmainconfig(const char *configfile) { "FTicksKey", CONF_STR, &fticks_key_str, "FTicksSyslogFacility", CONF_STR, &options.ftickssyslogfacility, "FTicksPrefix", CONF_STR, &options.fticksprefix, - "IPv4Only", CONF_BLN, &options.ipv4only, - "IPv6Only", CONF_BLN, &options.ipv6only, + "IPv4Only", CONF_BLN, &options.ipv4only, + "IPv6Only", CONF_BLN, &options.ipv6only, NULL )) debugx(1, DBG_ERR, "configuration error"); diff --git a/radsecproxy.h b/radsecproxy.h index 681ba60..230dcdd 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -72,6 +72,13 @@ enum rsp_server_state { RSP_SERVER_STATE_FAILING }; +enum rsp_statsrv { + RSP_STATSRV_OFF = 0, + RSP_STATSRV_ON, + RSP_STATSRV_MINIMAL, + RSP_STATSRV_AUTO +}; + struct options { char *pidfile; char *logdestination; @@ -145,7 +152,7 @@ struct clsrvconf { char *confrewriteusername; struct modattr *rewriteusername; char *dynamiclookupcommand; - uint8_t statusserver; + enum rsp_statsrv statusserver; uint8_t retryinterval; uint8_t retrycount; uint8_t dupinterval; From 719094b985f953afda42927aea7756ca7fcb5bf3 Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Mon, 17 Sep 2018 17:34:49 +0200 Subject: [PATCH 2/3] only retry statusserver-autodetect after successful traffic --- radsecproxy.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/radsecproxy.c b/radsecproxy.c index 9bd6453..61d9470 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -1818,11 +1818,9 @@ void *clientwr(void *arg) { memset(&timeout, 0, sizeof(struct timespec)); - if (conf->statusserver != RSP_STATSRV_OFF) { - gettimeofday(&server->lastrcv, NULL); - gettimeofday(&laststatsrv, NULL); - } gettimeofday(&server->lastreply, NULL); + server->lastrcv = server->lastreply; + laststatsrv = server->lastreply; if (conf->pdef->connecter) { if (!conf->pdef->connecter(server, NULL, server->dynamiclookuparg ? 5 : 0, "clientwr")) { @@ -1842,9 +1840,6 @@ void *clientwr(void *arg) { } server->state = RSP_SERVER_STATE_CONNECTED; - if (conf->statusserver == RSP_STATSRV_AUTO) - statusserver_requested = 1; - for (;;) { pthread_mutex_lock(&server->newrq_mutex); if (!server->newrq) { @@ -1929,7 +1924,7 @@ void *clientwr(void *arg) { } } else { if (conf->statusserver == RSP_STATSRV_AUTO && *rqout->rq->buf == RAD_Status_Server) { - if (server->lastrcv.tv_sec >= laststatsrv.tv_sec) { + if (server->lastreply.tv_sec >= laststatsrv.tv_sec) { debug(DBG_DBG, "clientwr: status server autodetect faild, disabling status server for %s", conf->name); conf->statusserver = RSP_STATSRV_OFF; } @@ -1956,11 +1951,10 @@ void *clientwr(void *arg) { } do_resend = 0; if (server->state == RSP_SERVER_STATE_CONNECTED && !conf->statusserver == RSP_STATSRV_OFF) { - secs = server->lastrcv.tv_sec > laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec; gettimeofday(&now, NULL); - if ((conf->statusserver == RSP_STATSRV_ON && now.tv_sec - secs > STATUS_SERVER_PERIOD) || - ((conf->statusserver == RSP_STATSRV_MINIMAL || conf->statusserver == RSP_STATSRV_AUTO) && - statusserver_requested && now.tv_sec - laststatsrv.tv_sec > STATUS_SERVER_PERIOD)) { + if ((conf->statusserver == RSP_STATSRV_ON && now.tv_sec - (laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec) > STATUS_SERVER_PERIOD) || + (conf->statusserver == RSP_STATSRV_MINIMAL && statusserver_requested && now.tv_sec - laststatsrv.tv_sec > STATUS_SERVER_PERIOD) || + (conf->statusserver == RSP_STATSRV_AUTO && server->lastreply.tv_sec >= laststatsrv.tv_sec)) { laststatsrv = now; statsrvrq = createstatsrvrq(); From b732bdbffa5ea950c973cc93865a3f0b23785ccb Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Sat, 10 Nov 2018 13:20:55 +0100 Subject: [PATCH 3/3] update manpage and changelog --- ChangeLog | 4 ++++ radsecproxy.conf.5 | 19 ++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 228a532..c5f21a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ changes since 1.7.2 + New features: + - Autodetect status-server capability of servers + - Minimalistic status-server + Misc: - No longer require docbook2x tools, but include plain manpages - Fail on startup if overlapping clients with different tls blocks diff --git a/radsecproxy.conf.5 b/radsecproxy.conf.5 index 1916f1e..ff3ca73 100644 --- a/radsecproxy.conf.5 +++ b/radsecproxy.conf.5 @@ -543,13 +543,18 @@ for the realm and then the SRV records for each NAPTR matching \&'x-eduroam:radius.tls' is provided in \fItools/naptr\-eduroam.sh\fR. .RE -.BR "StatusServer (" on | off ) -.RS -Enable the use of status-server messages for this server (default off). If -statusserver is enabled, the proxy will send regular status-server messages to -the server to verify that it is alive. Status tracking of the server will solely -depend on status-server message and ignore lost requests. This should only be -enabled if the server supports it. +.BR "StatusServer (" on | off | minimal | auto ) +.RS +Enable the use of status-server messages for this server (default \fBoff\fR). If +statusserver is enabled (\fBon\fR), the proxy will send regular status-server +messages to the server to verify that it is alive. Status tracking of the server +will solely depend on status-server message and ignore lost requests. This +should only be enabled if the server supports it. With the option \fBminimal\fR +status-server messages are only sent when regular requests have been lost and no +other replies have been received. + +The option \fBauto\fR tries to detect whether the other server supports +status-server. If so, status-server messages are enabled in \fBminimal\fR mode. .RE .BI "RetryCount " count