changing to use a separate client structure for each udp client
authorvenaas <venaas>
Sun, 14 Sep 2008 17:16:03 +0000 (17:16 +0000)
committervenaas <venaas@e88ac4ed-0b26-0410-9574-a7f39faa03bf>
Sun, 14 Sep 2008 17:16:03 +0000 (17:16 +0000)
git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@378 e88ac4ed-0b26-0410-9574-a7f39faa03bf

dtls.c
radsecproxy.c
radsecproxy.h
udp.c
util.c
util.h

diff --git a/dtls.c b/dtls.c
index 6d605cb..a80c8fd 100644 (file)
--- a/dtls.c
+++ b/dtls.c
@@ -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);
index 2ffae31..cdf9fbb 100644 (file)
@@ -581,6 +581,7 @@ void removeclient(struct client *client) {
        return;
     removequeue(client->replyq);
     list_removedata(client->conf->clients, client);
+    free(client->addr);
     free(client);
 }
 
index eeefaed..d37967f 100644 (file)
@@ -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 {
diff --git a/udp.c b/udp.c
index c2302d4..4d27425 100644 (file)
--- a/udp.c
+++ b/udp.c
@@ -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;
diff --git a/util.c b/util.c
index d551cf0..5dc5f34 100644 (file)
--- a/util.c
+++ b/util.c
@@ -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;
diff --git a/util.h b/util.h
index c151b90..7bb8202 100644 (file)
--- a/util.h
+++ b/util.h
@@ -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);