diff options
-rw-r--r-- | dtls.c | 1 | ||||
-rw-r--r-- | radsecproxy.c | 1 | ||||
-rw-r--r-- | radsecproxy.h | 2 | ||||
-rw-r--r-- | udp.c | 19 | ||||
-rw-r--r-- | util.c | 37 | ||||
-rw-r--r-- | util.h | 2 |
6 files changed, 57 insertions, 5 deletions
@@ -312,7 +312,6 @@ void *dtlsservernew(void *arg) { if (client) { client->sock = params->sock; client->rbios = params->sesscache->rbios; - client->addr = params->addr; client->ssl = ssl; dtlsserverrd(client); removeclient(client); diff --git a/radsecproxy.c b/radsecproxy.c index 2ffae31..cdf9fbb 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -581,6 +581,7 @@ void removeclient(struct client *client) { return; removequeue(client->replyq); list_removedata(client->conf->clients, client); + free(client->addr); free(client); } diff --git a/radsecproxy.h b/radsecproxy.h index eeefaed..d37967f 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -104,7 +104,7 @@ struct client { SSL *ssl; struct queue *replyq; struct queue *rbios; /* for dtls */ - struct sockaddr_storage addr; /* for dtls */ + struct sockaddr *addr; /* for udp */ }; struct server { @@ -42,6 +42,7 @@ unsigned char *radudpget(int s, struct client **client, struct server **server, int cnt, len; unsigned char buf[4], *rad = NULL; struct sockaddr_storage from; + struct sockaddr *fromcopy; socklen_t fromlen = sizeof(from); struct clsrvconf *p; struct list_node *node; @@ -101,10 +102,22 @@ unsigned char *radudpget(int s, struct client **client, struct server **server, debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len); if (client) { - node = list_first(p->clients); - *client = node ? (struct client *)node->data : addclient(p); - if (!*client) + for (node = list_first(p->clients); node; node = list_next(node)) + if (addr_equal((struct sockaddr *)&from, ((struct client *)node->data)->addr)) + break; + if (node) { + *client = (struct client *)node->data; + break; + } + fromcopy = addr_copy((struct sockaddr *)&from); + if (!fromcopy) continue; + *client = addclient(p); + if (!*client) { + free(fromcopy); + continue; + } + (*client)->addr = fromcopy; } else if (server) *server = p->servers; break; @@ -72,6 +72,43 @@ void printfchars(char *prefixfmt, char *prefix, char *charfmt, char *chars, int printf("\n"); } +int addr_equal(struct sockaddr *a, struct sockaddr *b) { + switch (a->sa_family) { + case AF_INET: + return !memcmp(&((struct sockaddr_in*)a)->sin_addr, + &((struct sockaddr_in*)b)->sin_addr, + sizeof(struct in_addr)); + case AF_INET6: + return IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6*)a)->sin6_addr, + &((struct sockaddr_in6*)b)->sin6_addr); + default: + /* Must not reach */ + return 0; + } +} + +struct sockaddr *addr_copy(struct sockaddr *in) { + struct sockaddr *out = NULL; + + switch (in->sa_family) { + case AF_INET: + out = malloc(sizeof(struct sockaddr_in)); + if (out) { + memset(out, 0, sizeof(struct sockaddr_in)); + ((struct sockaddr_in *)out)->sin_addr = ((struct sockaddr_in *)in)->sin_addr; + } + break; + case AF_INET6: + out = malloc(sizeof(struct sockaddr_in6)); + if (out) { + memset(out, 0, sizeof(struct sockaddr_in6)); + ((struct sockaddr_in6 *)out)->sin6_addr = ((struct sockaddr_in6 *)in)->sin6_addr; + } + break; + } + return out; +} + char *addr2string(struct sockaddr *addr, socklen_t len) { struct sockaddr_in6 *sa6; struct sockaddr_in sa4; @@ -3,5 +3,7 @@ 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); void printfchars(char *prefixfmt, char *prefix, char *charfmt, char *chars, int len); int connectport(int type, char *host, char *port); |