summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dtls.c11
-rw-r--r--radsecproxy.c84
-rw-r--r--radsecproxy.h21
-rw-r--r--tcp.c11
-rw-r--r--tls.c11
-rw-r--r--udp.c45
-rw-r--r--util.c21
-rw-r--r--util.h3
8 files changed, 105 insertions, 102 deletions
diff --git a/dtls.c b/dtls.c
index 01725e4..38edcb3 100644
--- a/dtls.c
+++ b/dtls.c
@@ -213,7 +213,7 @@ void *dtlsserverwr(void *arg) {
unsigned long error;
struct client *client = (struct client *)arg;
struct queue *replyq;
- struct reply *reply;
+ struct request *reply;
debug(DBG_DBG, "dtlsserverwr: starting for %s", client->conf->host);
replyq = client->replyq;
@@ -233,17 +233,16 @@ void *dtlsserverwr(void *arg) {
pthread_exit(NULL);
}
}
- reply = (struct reply *)list_shift(replyq->entries);
+ reply = (struct request *)list_shift(replyq->entries);
pthread_mutex_unlock(&replyq->mutex);
- cnt = SSL_write(client->ssl, reply->buf, RADLEN(reply->buf));
+ cnt = SSL_write(client->ssl, reply->replybuf, RADLEN(reply->replybuf));
if (cnt > 0)
debug(DBG_DBG, "dtlsserverwr: sent %d bytes, Radius packet of length %d",
- cnt, RADLEN(reply->buf));
+ cnt, RADLEN(reply->replybuf));
else
while ((error = ERR_get_error()))
debug(DBG_ERR, "dtlsserverwr: SSL: %s", ERR_error_string(error, NULL));
- free(reply->buf);
- free(reply);
+ freerq(reply);
}
}
diff --git a/radsecproxy.c b/radsecproxy.c
index 9e3cbe4..6e0c2c6 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -279,16 +279,8 @@ int resolvepeer(struct clsrvconf *conf, int ai_flags) {
debug(DBG_WARN, "resolvepeer: can't resolve (null) port (null)");
return 0;
}
- for (res = addrinfo; res; res = res->ai_next) {
- switch (res->ai_family) {
- case AF_INET:
- ((struct sockaddr_in *)res->ai_addr)->sin_port = 0;
- break;
- case AF_INET6:
- ((struct sockaddr_in6 *)res->ai_addr)->sin6_port = 0;
- break;
- }
- }
+ for (res = addrinfo; res; res = res->ai_next)
+ port_set(res->ai_addr, 0);
} else {
if (slash)
hints.ai_flags |= AI_NUMERICHOST;
@@ -541,7 +533,7 @@ void removequeue(struct queue *q) {
return;
pthread_mutex_lock(&q->mutex);
for (entry = list_first(q->entries); entry; entry = list_next(entry))
- free(((struct reply *)entry)->buf);
+ freerq((struct request *)entry);
list_destroy(q->entries);
pthread_cond_destroy(&q->cond);
pthread_mutex_unlock(&q->mutex);
@@ -940,10 +932,10 @@ void freerq(struct request *rq) {
free(rq->origusername);
if (rq->buf)
free(rq->buf);
- if (rq->msg) {
+ if (rq->replybuf)
+ free(rq->replybuf);
+ if (rq->msg)
radmsg_free(rq->msg);
- rq->msg = NULL;
- }
free(rq);
}
@@ -1013,38 +1005,26 @@ void sendrq(struct server *to, struct request *rq) {
pthread_mutex_unlock(&to->newrq_mutex);
}
-void sendreply(struct client *to, struct radmsg *msg, struct sockaddr_storage *tosa, int toudpsock) {
- uint8_t *buf;
- struct reply *reply;
+void sendreply(struct request *rq) {
uint8_t first;
-
- buf = radmsg2buf(msg, (uint8_t *)to->conf->secret);
- radmsg_free(msg);
- if (!buf) {
+ struct client *to = rq->from;
+
+ if (!rq->replybuf)
+ rq->replybuf = radmsg2buf(rq->msg, (uint8_t *)to->conf->secret);
+ radmsg_free(rq->msg);
+ rq->msg = NULL;
+ if (!rq->replybuf) {
+ freerq(rq);
debug(DBG_ERR, "sendreply: radmsg2buf failed");
return;
}
- reply = malloc(sizeof(struct reply));
- if (!reply) {
- free(buf);
- debug(DBG_ERR, "sendreply: malloc failed");
- return;
- }
- memset(reply, 0, sizeof(struct reply));
- reply->buf = buf;
- if (tosa)
- reply->tosa = *tosa;
- reply->toudpsock = toudpsock;
-
pthread_mutex_lock(&to->replyq->mutex);
-
first = list_first(to->replyq->entries) == NULL;
- if (!list_push(to->replyq->entries, reply)) {
+ if (!list_push(to->replyq->entries, rq)) {
pthread_mutex_unlock(&to->replyq->mutex);
- free(reply);
- free(buf);
+ freerq(rq);
debug(DBG_ERR, "sendreply: malloc failed");
return;
}
@@ -1652,8 +1632,10 @@ void respondaccounting(struct request *rq) {
msg = radmsg_init(RAD_Accounting_Response, rq->msg->id, rq->msg->auth);
if (msg) {
+ radmsg_free(rq->msg);
+ rq->msg = msg;
debug(DBG_DBG, "respondaccounting: responding to %s", rq->from->conf->host);
- sendreply(rq->from, msg, &rq->fromsa, rq->fromudpsock);
+ sendreply(rq);
} else
debug(DBG_ERR, "respondaccounting: malloc failed");
}
@@ -1663,8 +1645,10 @@ void respondstatusserver(struct request *rq) {
msg = radmsg_init(RAD_Access_Accept, rq->msg->id, rq->msg->auth);
if (msg) {
+ radmsg_free(rq->msg);
+ rq->msg = msg;
debug(DBG_DBG, "respondstatusserver: responding to %s", rq->from->conf->host);
- sendreply(rq->from, msg, &rq->fromsa, rq->fromudpsock);
+ sendreply(rq);
} else
debug(DBG_ERR, "respondstatusserver: malloc failed");
}
@@ -1688,8 +1672,10 @@ void respondreject(struct request *rq, char *message) {
}
}
+ radmsg_free(rq->msg);
+ rq->msg = msg;
debug(DBG_DBG, "respondreject: responding to %s", rq->from->conf->host);
- sendreply(rq->from, msg, &rq->fromsa, rq->fromudpsock);
+ sendreply(rq);
}
struct clsrvconf *choosesrvconf(struct list *srvconfs) {
@@ -1763,6 +1749,15 @@ int addclientrq(struct request *rq, uint8_t id) {
r = rq->from->rqs[id];
if (r) {
if (now.tv_sec - r->created.tv_sec < r->from->conf->dupinterval) {
+#if 0
+ later
+ if (r->replybuf) {
+ debug(DBG_INFO, "radsrv: already sent reply to request with id %d from %s, resending", id, r->from->conf->host);
+ r->refcount++;
+ sendreply(r);
+ } else
+#endif
+ debug(DBG_INFO, "radsrv: already got request with id %d from %s, ignoring", id, r->from->conf->host);
pthread_mutex_unlock(&rq->from->lock);
return 0;
}
@@ -1813,10 +1808,8 @@ int radsrv(struct request *rq) {
goto exit;
}
- if (!addclientrq(rq, msg->id)) {
- debug(DBG_INFO, "radsrv: already got request with id %d from %s, ignoring", msg->id, from->conf->host);
+ if (!addclientrq(rq, msg->id))
goto exit;
- }
if (msg->code == RAD_Status_Server) {
respondstatusserver(rq);
@@ -2026,7 +2019,10 @@ void replyh(struct server *server, unsigned char *buf) {
}
debug(DBG_INFO, "replyh: passing reply to client %s", from->conf->name);
- sendreply(from, msg, &rqout->rq->fromsa, rqout->rq->fromudpsock);
+ radmsg_free(rqout->rq->msg);
+ rqout->rq->msg = msg;
+ rqout->rq->refcount++;
+ sendreply(rqout->rq);
freerqoutdata(rqout);
pthread_mutex_unlock(rqout->lock);
return;
diff --git a/radsecproxy.h b/radsecproxy.h
index 5efe80b..a421c5e 100644
--- a/radsecproxy.h
+++ b/radsecproxy.h
@@ -45,14 +45,14 @@ struct options {
struct request {
struct timeval created;
uint8_t refcount;
- uint8_t *buf;
+ uint8_t *buf, *replybuf;
struct radmsg *msg;
struct client *from;
- struct sockaddr_storage fromsa; /* used by udpservwr */
- int fromudpsock; /* used by udpservwr */
char *origusername;
- char origauth[16]; /* used by servwr */
- uint8_t origid; /* used by servwr */
+ char origauth[16];
+ uint8_t origid;
+ int udpsock; /* only for UDP */
+ uint16_t udpport; /* only for UDP */
};
/* requests that our client will send */
@@ -63,13 +63,6 @@ struct rqout {
struct timeval expiry;
};
-/* replies that a server will send */
-struct reply {
- unsigned char *buf;
- struct sockaddr_storage tosa; /* used by udpservwr */
- int toudpsock; /* used by udpservwr */
-};
-
struct queue {
struct list *entries;
pthread_mutex_t mutex;
@@ -206,6 +199,10 @@ struct protodefs {
sizeof(struct sockaddr_in) : \
sizeof(struct sockaddr_in6))
+#define SOCKADDRP_SIZE(addr) ((addr)->sa_family == AF_INET ? \
+ sizeof(struct sockaddr_in) : \
+ sizeof(struct sockaddr_in6))
+
struct addrinfo *getsrcprotores(uint8_t type);
struct clsrvconf *find_clconf(uint8_t type, struct sockaddr *addr, struct list_node **cur);
struct clsrvconf *find_srvconf(uint8_t type, struct sockaddr *addr, struct list_node **cur);
diff --git a/tcp.c b/tcp.c
index d59efa5..24d75ae 100644
--- a/tcp.c
+++ b/tcp.c
@@ -190,7 +190,7 @@ void *tcpserverwr(void *arg) {
int cnt;
struct client *client = (struct client *)arg;
struct queue *replyq;
- struct reply *reply;
+ struct request *reply;
debug(DBG_DBG, "tcpserverwr: starting for %s", client->conf->host);
replyq = client->replyq;
@@ -209,16 +209,15 @@ void *tcpserverwr(void *arg) {
pthread_exit(NULL);
}
}
- reply = (struct reply *)list_shift(replyq->entries);
+ reply = (struct request *)list_shift(replyq->entries);
pthread_mutex_unlock(&replyq->mutex);
- cnt = write(client->sock, reply->buf, RADLEN(reply->buf));
+ cnt = write(client->sock, reply->replybuf, RADLEN(reply->replybuf));
if (cnt > 0)
debug(DBG_DBG, "tcpserverwr: sent %d bytes, Radius packet of length %d",
- cnt, RADLEN(reply->buf));
+ cnt, RADLEN(reply->replybuf));
else
debug(DBG_ERR, "tcpserverwr: write error for %s", client->conf->host);
- free(reply->buf);
- free(reply);
+ freerq(reply);
}
}
diff --git a/tls.c b/tls.c
index a9f91b3..e532211 100644
--- a/tls.c
+++ b/tls.c
@@ -241,7 +241,7 @@ void *tlsserverwr(void *arg) {
unsigned long error;
struct client *client = (struct client *)arg;
struct queue *replyq;
- struct reply *reply;
+ struct request *reply;
debug(DBG_DBG, "tlsserverwr: starting for %s", client->conf->host);
replyq = client->replyq;
@@ -261,17 +261,16 @@ void *tlsserverwr(void *arg) {
pthread_exit(NULL);
}
}
- reply = (struct reply *)list_shift(replyq->entries);
+ reply = (struct request *)list_shift(replyq->entries);
pthread_mutex_unlock(&replyq->mutex);
- cnt = SSL_write(client->ssl, reply->buf, RADLEN(reply->buf));
+ cnt = SSL_write(client->ssl, reply->replybuf, RADLEN(reply->replybuf));
if (cnt > 0)
debug(DBG_DBG, "tlsserverwr: sent %d bytes, Radius packet of length %d",
- cnt, RADLEN(reply->buf));
+ cnt, RADLEN(reply->replybuf));
else
while ((error = ERR_get_error()))
debug(DBG_ERR, "tlsserverwr: SSL: %s", ERR_error_string(error, NULL));
- free(reply->buf);
- free(reply);
+ freerq(reply);
}
}
diff --git a/udp.c b/udp.c
index 617f3cd..be61b0b 100644
--- a/udp.c
+++ b/udp.c
@@ -38,7 +38,7 @@ static struct queue *server_replyq = NULL;
/* exactly one of client and server must be non-NULL */
/* return who we received from in *client or *server */
/* return from in sa if not NULL */
-unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) {
+unsigned char *radudpget(int s, struct client **client, struct server **server, uint16_t *port) {
int cnt, len;
unsigned char buf[4], *rad = NULL;
struct sockaddr_storage from;
@@ -128,8 +128,8 @@ unsigned char *radudpget(int s, struct client **client, struct server **server,
*server = p->servers;
break;
}
- if (sa)
- *sa = from;
+ if (port)
+ *port = port_get((struct sockaddr *)&from);
return rad;
}
@@ -138,32 +138,20 @@ int clientradputudp(struct server *server, unsigned char *rad) {
struct sockaddr_storage sa;
struct sockaddr *sap;
struct clsrvconf *conf = server->conf;
- in_port_t *port = NULL;
+ uint16_t port;
len = RADLEN(rad);
+ port = port_get(conf->addrinfo->ai_addr);
if (*rad == RAD_Accounting_Request) {
sap = (struct sockaddr *)&sa;
memcpy(sap, conf->addrinfo->ai_addr, conf->addrinfo->ai_addrlen);
+ port_set(sap, ++port);
} else
sap = conf->addrinfo->ai_addr;
-
- switch (sap->sa_family) {
- case AF_INET:
- port = &((struct sockaddr_in *)sap)->sin_port;
- break;
- case AF_INET6:
- port = &((struct sockaddr_in6 *)sap)->sin6_port;
- break;
- default:
- return 0;
- }
- if (*rad == RAD_Accounting_Request)
- *port = htons(ntohs(*port) + 1);
-
if (sendto(server->sock, rad, len, 0, sap, conf->addrinfo->ai_addrlen) >= 0) {
- debug(DBG_DBG, "clienradputudp: sent UDP of length %d to %s port %d", len, conf->host, ntohs(*port));
+ debug(DBG_DBG, "clienradputudp: sent UDP of length %d to %s port %d", len, conf->host, port);
return 1;
}
@@ -193,8 +181,8 @@ void *udpserverrd(void *arg) {
sleep(5); /* malloc failed */
continue;
}
- rq->buf = radudpget(*sp, &rq->from, NULL, &rq->fromsa);
- rq->fromudpsock = *sp;
+ rq->buf = radudpget(*sp, &rq->from, NULL, &rq->udpport);
+ rq->udpsock = *sp;
radsrv(rq);
}
free(sp);
@@ -202,22 +190,23 @@ void *udpserverrd(void *arg) {
void *udpserverwr(void *arg) {
struct queue *replyq = (struct queue *)arg;
- struct reply *reply;
+ struct request *reply;
+ struct sockaddr_storage to;
for (;;) {
pthread_mutex_lock(&replyq->mutex);
- while (!(reply = (struct reply *)list_shift(replyq->entries))) {
+ while (!(reply = (struct request *)list_shift(replyq->entries))) {
debug(DBG_DBG, "udp server writer, waiting for signal");
pthread_cond_wait(&replyq->cond, &replyq->mutex);
debug(DBG_DBG, "udp server writer, got signal");
}
pthread_mutex_unlock(&replyq->mutex);
- if (sendto(reply->toudpsock, reply->buf, RADLEN(reply->buf), 0,
- (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0)
- debug(DBG_WARN, "sendudp: send failed");
- free(reply->buf);
- free(reply);
+ memcpy(&to, reply->from->addr, SOCKADDRP_SIZE(reply->from->addr));
+ port_set((struct sockaddr *)&to, reply->udpport);
+ if (sendto(reply->udpsock, reply->replybuf, RADLEN(reply->replybuf), 0, (struct sockaddr *)&to, SOCKADDR_SIZE(to)) < 0)
+ debug(DBG_WARN, "udpserverwr: send failed");
+ freerq(reply);
}
}
diff --git a/util.c b/util.c
index 5dc5f34..02614eb 100644
--- a/util.c
+++ b/util.c
@@ -72,6 +72,27 @@ void printfchars(char *prefixfmt, char *prefix, char *charfmt, char *chars, int
printf("\n");
}
+uint16_t port_get(struct sockaddr *sa) {
+ switch (sa->sa_family) {
+ case AF_INET:
+ return ntohs(((struct sockaddr_in *)sa)->sin_port);
+ case AF_INET6:
+ return ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
+ }
+ return 0;
+}
+
+void port_set(struct sockaddr *sa, uint16_t port) {
+ switch (sa->sa_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)sa)->sin_port = htons(port);
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
+ break;
+ }
+}
+
int addr_equal(struct sockaddr *a, struct sockaddr *b) {
switch (a->sa_family) {
case AF_INET:
diff --git a/util.h b/util.h
index 7bb8202..732902e 100644
--- a/util.h
+++ b/util.h
@@ -5,5 +5,8 @@ char *stringcopy(const char *s, int len);
char *addr2string(struct sockaddr *addr, socklen_t len);
int addr_equal(struct sockaddr *a, struct sockaddr *b);
struct sockaddr *addr_copy(struct sockaddr *in);
+uint16_t port_get(struct sockaddr *sa);
+void port_set(struct sockaddr *sa, uint16_t port);
+
void printfchars(char *prefixfmt, char *prefix, char *charfmt, char *chars, int len);
int connectport(int type, char *host, char *port);