summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--list.c18
-rw-r--r--list.h5
-rw-r--r--radsecproxy.c106
-rw-r--r--radsecproxy.h8
4 files changed, 79 insertions, 58 deletions
diff --git a/list.c b/list.c
index 578c61a..e9dcebb 100644
--- a/list.c
+++ b/list.c
@@ -23,7 +23,7 @@ void list_destroy(struct list *list) {
}
/* appends entry to list; returns 1 if ok, 0 if malloc fails */
-int list_add(struct list *list, void *data) {
+int list_push(struct list *list, void *data) {
struct list_node *node;
node = malloc(sizeof(struct list_node));
@@ -42,6 +42,22 @@ int list_add(struct list *list, void *data) {
return 1;
}
+/* removes first entry from list and returns data */
+void *list_shift(struct list *list) {
+ struct list_node *node;
+ void *data;
+
+ if (!list->first)
+ return NULL;
+
+ node = list->first;
+ list->first = node->next;
+ data = node->data;
+ free(node);
+
+ return data;
+}
+
/* returns first node */
struct list_node *list_first(struct list *list) {
return list->first;
diff --git a/list.h b/list.h
index 876d345..c89f902 100644
--- a/list.h
+++ b/list.h
@@ -14,7 +14,10 @@ struct list *list_create();
void list_destroy(struct list *list);
/* appends entry to list; returns 1 if ok, 0 if malloc fails */
-int list_add(struct list *list, void *data);
+int list_push(struct list *list, void *data);
+
+/* removes first entry from list and returns data */
+void *list_shift(struct list *list);
/* returns first node */
struct list_node *list_first(struct list *list);
diff --git a/radsecproxy.c b/radsecproxy.c
index 93f4b6b..973fee6 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -233,19 +233,17 @@ struct clsrvconf *find_peer(char type, struct sockaddr *addr, struct list *confs
return NULL;
}
-struct replyq *newreplyq(int size) {
+struct replyq *newreplyq() {
struct replyq *replyq;
replyq = malloc(sizeof(struct replyq));
if (!replyq)
debugx(1, DBG_ERR, "malloc failed");
- replyq->replies = calloc(MAX_REQUESTS, sizeof(struct reply));
+ replyq->replies = list_create();
if (!replyq->replies)
debugx(1, DBG_ERR, "malloc failed");
- replyq->count = 0;
- replyq->size = size;
- pthread_mutex_init(&replyq->count_mutex, NULL);
- pthread_cond_init(&replyq->count_cond, NULL);
+ pthread_mutex_init(&replyq->mutex, NULL);
+ pthread_cond_init(&replyq->cond, NULL);
return replyq;
}
@@ -261,7 +259,7 @@ void addclient(struct clsrvconf *conf) {
}
memset(conf->clients, 0, sizeof(struct client));
conf->clients->conf = conf;
- conf->clients->replyq = conf->type == 'T' ? newreplyq(MAX_REQUESTS) : udp_server_replyq;
+ conf->clients->replyq = conf->type == 'T' ? newreplyq() : udp_server_replyq;
}
void addserver(struct clsrvconf *conf) {
@@ -709,32 +707,43 @@ void sendrq(struct server *to, struct request *rq) {
}
void sendreply(struct client *to, unsigned char *buf, struct sockaddr_storage *tosa) {
- struct replyq *replyq = to->replyq;
+ struct reply *reply;
+ uint8_t first;
if (!radsign(buf, (unsigned char *)to->conf->secret)) {
free(buf);
debug(DBG_WARN, "sendreply: failed to sign message");
return;
}
-
- pthread_mutex_lock(&replyq->count_mutex);
- if (replyq->count == replyq->size) {
- debug(DBG_WARN, "No room in queue, dropping request");
- pthread_mutex_unlock(&replyq->count_mutex);
+
+ reply = malloc(sizeof(struct reply));
+ if (!reply) {
free(buf);
+ debug(DBG_ERR, "sendreply: malloc failed");
return;
}
-
- replyq->replies[replyq->count].buf = buf;
+ memset(reply, 0, sizeof(struct reply));
+ reply->buf = buf;
if (tosa)
- replyq->replies[replyq->count].tosa = *tosa;
- replyq->count++;
+ reply->tosa = *tosa;
+
+ pthread_mutex_lock(&to->replyq->mutex);
- if (replyq->count == 1) {
+ first = list_first(to->replyq->replies) == NULL;
+
+ if (!list_push(to->replyq->replies, reply)) {
+ pthread_mutex_unlock(&to->replyq->mutex);
+ free(reply);
+ free(buf);
+ debug(DBG_ERR, "sendreply: malloc failed");
+ return;
+ }
+
+ if (first) {
debug(DBG_DBG, "signalling server writer");
- pthread_cond_signal(&replyq->count_cond);
+ pthread_cond_signal(&to->replyq->cond);
}
- pthread_mutex_unlock(&replyq->count_mutex);
+ pthread_mutex_unlock(&to->replyq->mutex);
}
int pwdencrypt(uint8_t *in, uint8_t len, char *shared, uint8_t sharedlen, uint8_t *auth) {
@@ -1527,26 +1536,22 @@ void *clientwr(void *arg) {
void *udpserverwr(void *arg) {
struct replyq *replyq = udp_server_replyq;
- struct reply *reply = replyq->replies;
+ struct reply *reply;
- pthread_mutex_lock(&replyq->count_mutex);
for (;;) {
- while (!replyq->count) {
+ pthread_mutex_lock(&replyq->mutex);
+ while (!(reply = (struct reply *)list_shift(replyq->replies))) {
debug(DBG_DBG, "udp server writer, waiting for signal");
- pthread_cond_wait(&replyq->count_cond, &replyq->count_mutex);
+ pthread_cond_wait(&replyq->cond, &replyq->mutex);
debug(DBG_DBG, "udp server writer, got signal");
}
- pthread_mutex_unlock(&replyq->count_mutex);
-
+ pthread_mutex_unlock(&replyq->mutex);
+
if (sendto(udp_server_sock, reply->buf, RADLEN(reply->buf), 0,
(struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0)
debug(DBG_WARN, "sendudp: send failed");
free(reply->buf);
-
- pthread_mutex_lock(&replyq->count_mutex);
- replyq->count--;
- memmove(replyq->replies, replyq->replies + 1,
- replyq->count * sizeof(struct reply));
+ free(reply);
}
}
@@ -1575,37 +1580,36 @@ void *tlsserverwr(void *arg) {
unsigned long error;
struct client *client = (struct client *)arg;
struct replyq *replyq;
+ struct reply *reply;
debug(DBG_DBG, "tlsserverwr starting for %s", client->conf->host);
replyq = client->replyq;
- pthread_mutex_lock(&replyq->count_mutex);
for (;;) {
- while (!replyq->count) {
+ pthread_mutex_lock(&replyq->mutex);
+ while (!list_first(replyq->replies)) {
if (client->ssl) {
debug(DBG_DBG, "tls server writer, waiting for signal");
- pthread_cond_wait(&replyq->count_cond, &replyq->count_mutex);
+ pthread_cond_wait(&replyq->cond, &replyq->mutex);
debug(DBG_DBG, "tls server writer, got signal");
}
if (!client->ssl) {
/* ssl might have changed while waiting */
- pthread_mutex_unlock(&replyq->count_mutex);
+ pthread_mutex_unlock(&replyq->mutex);
debug(DBG_DBG, "tlsserverwr: exiting as requested");
pthread_exit(NULL);
}
}
- pthread_mutex_unlock(&replyq->count_mutex);
- cnt = SSL_write(client->ssl, replyq->replies->buf, RADLEN(replyq->replies->buf));
+ reply = (struct reply *)list_shift(replyq->replies);
+ pthread_mutex_unlock(&replyq->mutex);
+ cnt = SSL_write(client->ssl, reply->buf, RADLEN(reply->buf));
if (cnt > 0)
debug(DBG_DBG, "tlsserverwr: Sent %d bytes, Radius packet of length %d",
- cnt, RADLEN(replyq->replies->buf));
+ cnt, RADLEN(reply->buf));
else
while ((error = ERR_get_error()))
debug(DBG_ERR, "tlsserverwr: SSL: %s", ERR_error_string(error, NULL));
- free(replyq->replies->buf);
-
- pthread_mutex_lock(&replyq->count_mutex);
- replyq->count--;
- memmove(replyq->replies, replyq->replies + 1, replyq->count * sizeof(struct reply));
+ free(reply->buf);
+ free(reply);
}
}
@@ -1643,9 +1647,9 @@ void *tlsserverrd(void *arg) {
debug(DBG_ERR, "tlsserverrd: connection lost");
/* stop writer by setting ssl to NULL and give signal in case waiting for data */
client->ssl = NULL;
- pthread_mutex_lock(&client->replyq->count_mutex);
- pthread_cond_signal(&client->replyq->count_cond);
- pthread_mutex_unlock(&client->replyq->count_mutex);
+ pthread_mutex_lock(&client->replyq->mutex);
+ pthread_cond_signal(&client->replyq->cond);
+ pthread_mutex_unlock(&client->replyq->mutex);
debug(DBG_DBG, "tlsserverrd: waiting for writer to end");
pthread_join(tlsserverwrth, NULL);
}
@@ -1767,7 +1771,7 @@ void tlsadd(char *value, char *cacertfile, char *cacertpath, char *certfile, cha
SSL_CTX_set_verify_depth(ctx, MAX_CERT_DEPTH + 1);
new = malloc(sizeof(struct tls));
- if (!new || !list_add(tls, new))
+ if (!new || !list_push(tls, new))
debugx(1, DBG_ERR, "malloc failed");
memset(new, 0, sizeof(struct tls));
@@ -1860,7 +1864,7 @@ void addrealm(char *value, char *server, char *message) {
}
realm = malloc(sizeof(struct realm));
- if (!realm || !list_add(realms, realm))
+ if (!realm || !list_push(realms, realm))
debugx(1, DBG_ERR, "malloc failed");
memset(realm, 0, sizeof(struct realm));
@@ -2121,7 +2125,7 @@ void confclient_cb(FILE *f, char *block, char *opt, char *val) {
debug(DBG_DBG, "confclient_cb called for %s", block);
conf = malloc(sizeof(struct clsrvconf));
- if (!conf || !list_add(clconfs, conf))
+ if (!conf || !list_push(clconfs, conf))
debugx(1, DBG_ERR, "malloc failed");
memset(conf, 0, sizeof(struct clsrvconf));
@@ -2169,7 +2173,7 @@ void confserver_cb(FILE *f, char *block, char *opt, char *val) {
debug(DBG_DBG, "confserver_cb called for %s", block);
conf = malloc(sizeof(struct clsrvconf));
- if (!conf || !list_add(srvconfs, conf))
+ if (!conf || !list_push(srvconfs, conf))
debugx(1, DBG_ERR, "malloc failed");
memset(conf, 0, sizeof(struct clsrvconf));
@@ -2374,7 +2378,7 @@ int main(int argc, char **argv) {
if (client_udp_count) {
udp_server_listen = server_create('U');
- udp_server_replyq = newreplyq(client_udp_count * MAX_REQUESTS);
+ udp_server_replyq = newreplyq();
if (pthread_create(&udpserverth, NULL, udpserverrd, NULL))
debugx(1, DBG_ERR, "pthread_create failed");
}
diff --git a/radsecproxy.h b/radsecproxy.h
index 05050d9..004a269 100644
--- a/radsecproxy.h
+++ b/radsecproxy.h
@@ -67,11 +67,9 @@ struct reply {
};
struct replyq {
- struct reply *replies;
- int count;
- int size;
- pthread_mutex_t count_mutex;
- pthread_cond_t count_cond;
+ struct list *replies;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
};
struct clsrvconf {