Commit ce2faa29 authored by venaas's avatar venaas Committed by venaas
Browse files

expiry of udp clients

git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@412 e88ac4ed-0b26-0410-9574-a7f39faa03bf
parent 9059151d
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
/* Bugs: /* Bugs:
* May segfault when dtls connections go down? More testing needed * May segfault when dtls connections go down? More testing needed
* Need to remove UDP clients when no activity for a while...
* Remove expired stuff from clients request list? * Remove expired stuff from clients request list?
* Multiple outgoing connections if not enough IDs? (multiple servers per conf?) * Multiple outgoing connections if not enough IDs? (multiple servers per conf?)
* Useful for TCP accounting? Now we require separate server config for alt port * Useful for TCP accounting? Now we require separate server config for alt port
...@@ -574,13 +573,10 @@ void removeclientrqs(struct client *client) { ...@@ -574,13 +573,10 @@ void removeclientrqs(struct client *client) {
removeclientrqs_sendrq_freeserver_lock(0); removeclientrqs_sendrq_freeserver_lock(0);
} }
void removeclient(struct client *client) { void removelockedclient(struct client *client) {
struct clsrvconf *conf; struct clsrvconf *conf;
if (!client)
return;
conf = client->conf; conf = client->conf;
pthread_mutex_lock(conf->lock);
if (conf->clients) { if (conf->clients) {
removeclientrqs(client); removeclientrqs(client);
removequeue(client->replyq); removequeue(client->replyq);
...@@ -588,6 +584,17 @@ void removeclient(struct client *client) { ...@@ -588,6 +584,17 @@ void removeclient(struct client *client) {
free(client->addr); free(client->addr);
free(client); free(client);
} }
}
void removeclient(struct client *client) {
struct clsrvconf *conf;
if (!client)
return;
conf = client->conf;
pthread_mutex_lock(conf->lock);
removelockedclient(client);
pthread_mutex_unlock(conf->lock); pthread_mutex_unlock(conf->lock);
} }
...@@ -2037,7 +2044,7 @@ void replyh(struct server *server, unsigned char *buf) { ...@@ -2037,7 +2044,7 @@ void replyh(struct server *server, unsigned char *buf) {
goto errunlock; goto errunlock;
} }
debug(DBG_INFO, "replyh: passing reply to client %s", from->conf->name); debug(DBG_INFO, "replyh: passing reply to client %s (%s)", from->conf->name, addr2string(from->addr));
radmsg_free(rqout->rq->msg); radmsg_free(rqout->rq->msg);
rqout->rq->msg = msg; rqout->rq->msg = msg;
sendreply(newrqref(rqout->rq)); sendreply(newrqref(rqout->rq));
......
...@@ -110,6 +110,7 @@ struct client { ...@@ -110,6 +110,7 @@ struct client {
struct queue *replyq; struct queue *replyq;
struct queue *rbios; /* for dtls */ struct queue *rbios; /* for dtls */
struct sockaddr *addr; struct sockaddr *addr;
time_t expiry; /* for udp */
}; };
struct server { struct server {
...@@ -206,6 +207,7 @@ struct clsrvconf *find_clconf(uint8_t type, struct sockaddr *addr, struct list_n ...@@ -206,6 +207,7 @@ struct clsrvconf *find_clconf(uint8_t type, struct sockaddr *addr, struct list_n
struct clsrvconf *find_srvconf(uint8_t type, struct sockaddr *addr, struct list_node **cur); struct clsrvconf *find_srvconf(uint8_t type, struct sockaddr *addr, struct list_node **cur);
struct clsrvconf *find_clconf_type(uint8_t type, struct list_node **cur); struct clsrvconf *find_clconf_type(uint8_t type, struct list_node **cur);
struct client *addclient(struct clsrvconf *conf, uint8_t lock); struct client *addclient(struct clsrvconf *conf, uint8_t lock);
void removelockedclient(struct client *client);
void removeclient(struct client *client); void removeclient(struct client *client);
struct queue *newqueue(); struct queue *newqueue();
void freebios(struct queue *q); void freebios(struct queue *q);
......
...@@ -35,6 +35,20 @@ static int client4_sock = -1; ...@@ -35,6 +35,20 @@ static int client4_sock = -1;
static int client6_sock = -1; static int client6_sock = -1;
static struct queue *server_replyq = NULL; static struct queue *server_replyq = NULL;
void removeudpclientfromreplyq(struct client *c) {
struct list_node *n;
struct request *r;
/* lock the common queue and remove replies for this client */
pthread_mutex_lock(&c->replyq->mutex);
for (n = list_first(c->replyq->entries); n; n = list_next(n)) {
r = (struct request *)n->data;
if (r->from == c)
r->from = NULL;
}
pthread_mutex_unlock(&c->replyq->mutex);
}
/* exactly one of client and server must be non-NULL */ /* exactly one of client and server must be non-NULL */
/* return who we received from in *client or *server */ /* return who we received from in *client or *server */
/* return from in sa if not NULL */ /* return from in sa if not NULL */
...@@ -48,6 +62,7 @@ unsigned char *radudpget(int s, struct client **client, struct server **server, ...@@ -48,6 +62,7 @@ unsigned char *radudpget(int s, struct client **client, struct server **server,
struct list_node *node; struct list_node *node;
fd_set readfds; fd_set readfds;
struct client *c = NULL; struct client *c = NULL;
struct timeval now;
for (;;) { for (;;) {
if (rad) { if (rad) {
...@@ -103,13 +118,28 @@ unsigned char *radudpget(int s, struct client **client, struct server **server, ...@@ -103,13 +118,28 @@ unsigned char *radudpget(int s, struct client **client, struct server **server,
debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len); debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len);
if (client) { if (client) {
*client = NULL;
pthread_mutex_lock(p->lock); pthread_mutex_lock(p->lock);
for (node = list_first(p->clients); node; node = list_next(node)) { for (node = list_first(p->clients); node;) {
c = (struct client *)node->data; c = (struct client *)node->data;
if (s == c->sock && addr_equal((struct sockaddr *)&from, c->addr)) node = list_next(node);
break; if (s != c->sock)
continue;
gettimeofday(&now, NULL);
if (!*client && addr_equal((struct sockaddr *)&from, c->addr)) {
c->expiry = now.tv_sec + 60;
*client = c;
}
if (c->expiry >= now.tv_sec)
continue;
debug(DBG_DBG, "radudpget: removing expired client (%s)", addr2string(c->addr));
removeudpclientfromreplyq(c);
c->replyq = NULL; /* stop removeclient() from removing common udp replyq */
removelockedclient(c);
break;
} }
if (!node) { if (!*client) {
fromcopy = addr_copy((struct sockaddr *)&from); fromcopy = addr_copy((struct sockaddr *)&from);
if (!fromcopy) { if (!fromcopy) {
pthread_mutex_unlock(p->lock); pthread_mutex_unlock(p->lock);
...@@ -123,8 +153,10 @@ unsigned char *radudpget(int s, struct client **client, struct server **server, ...@@ -123,8 +153,10 @@ unsigned char *radudpget(int s, struct client **client, struct server **server,
} }
c->sock = s; c->sock = s;
c->addr = fromcopy; c->addr = fromcopy;
gettimeofday(&now, NULL);
c->expiry = now.tv_sec + 60;
*client = c;
} }
*client = c;
pthread_mutex_unlock(p->lock); pthread_mutex_unlock(p->lock);
} else if (server) } else if (server)
*server = p->servers; *server = p->servers;
...@@ -202,12 +234,15 @@ void *udpserverwr(void *arg) { ...@@ -202,12 +234,15 @@ void *udpserverwr(void *arg) {
pthread_cond_wait(&replyq->cond, &replyq->mutex); pthread_cond_wait(&replyq->cond, &replyq->mutex);
debug(DBG_DBG, "udp server writer, got signal"); debug(DBG_DBG, "udp server writer, got signal");
} }
/* do this with lock, udpserverrd may set from = NULL if from expires */
if (reply->from)
memcpy(&to, reply->from->addr, SOCKADDRP_SIZE(reply->from->addr));
pthread_mutex_unlock(&replyq->mutex); pthread_mutex_unlock(&replyq->mutex);
if (reply->from) {
memcpy(&to, reply->from->addr, SOCKADDRP_SIZE(reply->from->addr)); port_set((struct sockaddr *)&to, reply->udpport);
port_set((struct sockaddr *)&to, reply->udpport); if (sendto(reply->udpsock, reply->replybuf, RADLEN(reply->replybuf), 0, (struct sockaddr *)&to, SOCKADDR_SIZE(to)) < 0)
if (sendto(reply->udpsock, reply->replybuf, RADLEN(reply->replybuf), 0, (struct sockaddr *)&to, SOCKADDR_SIZE(to)) < 0) debug(DBG_WARN, "udpserverwr: send failed");
debug(DBG_WARN, "udpserverwr: send failed"); }
debug(DBG_DBG, "udpserverwr: refcount %d", reply->refcount); debug(DBG_DBG, "udpserverwr: refcount %d", reply->refcount);
freerq(reply); freerq(reply);
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment