From 085efd538b269e7d734040102c27df6c4f428174 Mon Sep 17 00:00:00 2001 From: venaas Date: Thu, 25 Jan 2007 15:18:26 +0000 Subject: implemented retries git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@41 e88ac4ed-0b26-0410-9574-a7f39faa03bf --- radsecproxy.c | 66 +++++++++++++++++++++++++++++++++++++++-------------------- radsecproxy.h | 7 ++++--- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/radsecproxy.c b/radsecproxy.c index d6affca..b61f1b9 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -7,7 +7,6 @@ */ /* TODO: - * make our server ignore client retrans and do its own instead? * accounting * radius keep alives (server status) * tls certificate validation, see below urls @@ -710,8 +709,6 @@ void sendrq(struct server *to, struct client *from, struct request *rq) { if (!createmessageauth(rq->buf, rq->messageauthattrval, to->peer.secret)) return; - gettimeofday(&rq->expiry, NULL); - rq->expiry.tv_sec += 30; to->requests[i] = *rq; if (!to->newrq) { @@ -1016,6 +1013,18 @@ struct server *id2server(char *id, uint8_t len) { return NULL; } +int rqinqueue(struct server *to, struct client *from, uint8_t id) { + int i; + + pthread_mutex_lock(&to->newrq_mutex); + for (i = 0; i < MAX_REQUESTS; i++) + if (to->requests[i].buf && to->requests[i].origid == id && to->requests[i].from == from) + break; + pthread_mutex_unlock(&to->newrq_mutex); + + return i < MAX_REQUESTS; +} + struct server *radsrv(struct request *rq, char *buf, struct client *from) { uint8_t code, id, *auth, *attr, attrvallen; uint8_t *usernameattr = NULL, *userpwdattr = NULL, *tunnelpwdattr = NULL, *messageauthattr = NULL; @@ -1077,6 +1086,11 @@ struct server *radsrv(struct request *rq, char *buf, struct client *from) { printf("radsrv: ignoring request, don't know where to send it\n"); return NULL; } + + if (rqinqueue(to, from, id)) { + printf("radsrv: ignoring request from host %s with id %d, already got one\n", from->peer.host, id); + return NULL; + } if (messageauthattr && (messageauthattr[RAD_Attr_Length] != 18 || !checkmessageauth(buf, &messageauthattr[RAD_Attr_Value], from->peer.secret))) { @@ -1300,6 +1314,7 @@ void *clientwr(void *arg) { pthread_t clientrdth; int i; struct timeval now; + struct timespec timeout; if (server->peer.type == 'U') { if ((server->sock = connecttoserver(server->peer.addrinfo)) < 0) { @@ -1314,12 +1329,17 @@ void *clientwr(void *arg) { for (;;) { pthread_mutex_lock(&server->newrq_mutex); - while (!server->newrq) { - printf("clientwr: waiting for signal\n"); - pthread_cond_wait(&server->newrq_cond, &server->newrq_mutex); - printf("clientwr: got signal\n"); + if (!server->newrq) { + gettimeofday(&now, NULL); + timeout.tv_sec = now.tv_sec + 1; + timeout.tv_nsec = 0; + printf("clientwr: waiting up to 1 sec for new request\n"); + pthread_cond_timedwait(&server->newrq_cond, &server->newrq_mutex, &timeout); + if (server->newrq) { + printf("clientwr: got new request\n"); + server->newrq = 0; + } } - server->newrq = 0; pthread_mutex_unlock(&server->newrq_mutex); for (i = 0; i < MAX_REQUESTS; i++) { @@ -1330,8 +1350,6 @@ void *clientwr(void *arg) { pthread_mutex_unlock(&server->newrq_mutex); break; } - - gettimeofday(&now, NULL); rq = server->requests + i; if (rq->received) { @@ -1342,22 +1360,26 @@ void *clientwr(void *arg) { pthread_mutex_unlock(&server->newrq_mutex); continue; } - if (now.tv_sec > rq->expiry.tv_sec) { + + gettimeofday(&now, NULL); + if (now.tv_sec <= rq->expiry.tv_sec) { + pthread_mutex_unlock(&server->newrq_mutex); + continue; + } + + if (rq->tries == (server->peer.type == 'T' ? 1 : REQUEST_RETRIES)) { printf("clientwr: removing expired packet from queue\n"); - free(rq->buf); - /* setting this to NULL means that it can be reused */ - rq->buf = NULL; - pthread_mutex_unlock(&server->newrq_mutex); - continue; - } + free(rq->buf); + /* setting this to NULL means that it can be reused */ + rq->buf = NULL; + pthread_mutex_unlock(&server->newrq_mutex); + continue; + } + pthread_mutex_unlock(&server->newrq_mutex); - if (rq->tries) - continue; // not re-sending (yet) - rq->tries++; - pthread_mutex_unlock(&server->newrq_mutex); - clientradput(server, server->requests[i].buf); + usleep(200000); } } /* should do more work to maintain TLS connections, keepalives etc */ diff --git a/radsecproxy.h b/radsecproxy.h index 5719070..dcf45ca 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -13,12 +13,13 @@ sizeof(struct sockaddr_in6)) #define MAX_PEERS 256 -/* MAX_REQUESTS is 256 due to Radius' 8 bit ID field */ +/* MAX_REQUESTS must be 256 due to Radius' 8 bit ID field */ #define MAX_REQUESTS 256 #define DEFAULT_TLS_SECRET "mysecret" #define DEFAULT_UDP_PORT "1812" #define DEFAULT_TLS_PORT "2083" -#define REQUEST_TIMEOUT 5 +#define REQUEST_EXPIRY 20 +#define REQUEST_RETRIES 3 #define MAX_CERT_DEPTH 5 #define RAD_Access_Request 1 @@ -51,7 +52,7 @@ struct options { char *udpserverport; }; -/* requests that a client will send */ +/* requests that our client will send */ struct request { unsigned char *buf; uint8_t tries; -- cgit v1.1