about summary refs log tree commit diff
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/freeaddrinfo.c11
-rw-r--r--src/network/getaddrinfo.c10
-rw-r--r--src/network/lookup.h12
3 files changed, 25 insertions, 8 deletions
diff --git a/src/network/freeaddrinfo.c b/src/network/freeaddrinfo.c
index df3798ae..62241c23 100644
--- a/src/network/freeaddrinfo.c
+++ b/src/network/freeaddrinfo.c
@@ -1,7 +1,16 @@
 #include <stdlib.h>
+#include <stddef.h>
 #include <netdb.h>
+#include "lookup.h"
+#include "lock.h"
 
 void freeaddrinfo(struct addrinfo *p)
 {
-	free(p);
+	size_t cnt;
+	for (cnt=1; p->ai_next; cnt++, p=p->ai_next);
+	struct aibuf *b = (void *)((char *)p - offsetof(struct aibuf, ai));
+	b -= b->slot;
+	LOCK(b->lock);
+	if (!(b->ref -= cnt)) free(b);
+	else UNLOCK(b->lock);
 }
diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c
index e33bfa28..5ae8cbfb 100644
--- a/src/network/getaddrinfo.c
+++ b/src/network/getaddrinfo.c
@@ -16,13 +16,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
 	char canon[256], *outcanon;
 	int nservs, naddrs, nais, canon_len, i, j, k;
 	int family = AF_UNSPEC, flags = 0, proto = 0, socktype = 0;
-	struct aibuf {
-		struct addrinfo ai;
-		union sa {
-			struct sockaddr_in sin;
-			struct sockaddr_in6 sin6;
-		} sa;
-	} *out;
+	struct aibuf *out;
 
 	if (!host && !serv) return EAI_NONAME;
 
@@ -110,6 +104,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
 	}
 
 	for (k=i=0; i<naddrs; i++) for (j=0; j<nservs; j++, k++) {
+		out[k].slot = i;
 		out[k].ai = (struct addrinfo){
 			.ai_family = addrs[i].family,
 			.ai_socktype = ports[j].socktype,
@@ -134,6 +129,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
 			break;			
 		}
 	}
+	out[0].ref = nais;
 	out[nais-1].ai.ai_next = 0;
 	*res = &out->ai;
 	return 0;
diff --git a/src/network/lookup.h b/src/network/lookup.h
index f1952af5..ef662725 100644
--- a/src/network/lookup.h
+++ b/src/network/lookup.h
@@ -4,6 +4,18 @@
 #include <stdint.h>
 #include <stddef.h>
 #include <features.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+struct aibuf {
+	struct addrinfo ai;
+	union sa {
+		struct sockaddr_in sin;
+		struct sockaddr_in6 sin6;
+	} sa;
+	volatile int lock[1];
+	short slot, ref;
+};
 
 struct address {
 	int family;