summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvenaas <venaas>2007-01-25 15:18:26 +0000
committervenaas <venaas@e88ac4ed-0b26-0410-9574-a7f39faa03bf>2007-01-25 15:18:26 +0000
commit085efd538b269e7d734040102c27df6c4f428174 (patch)
tree17ce0ecd67e1199f28b44ec1ad89ab83c2ab3673
parentd1fd8449df7f12c6798849a13f1474fd40d66c32 (diff)
implemented retries
git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@41 e88ac4ed-0b26-0410-9574-a7f39faa03bf
-rw-r--r--radsecproxy.c66
-rw-r--r--radsecproxy.h7
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;