timps (0.25-4) naf/conn.c

Summary

 naf/conn.c |   68 +++++++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 53 insertions(+), 15 deletions(-)

    
download this patch

Patch contents

--- timps-0.25.orig/naf/conn.c
+++ timps-0.25/naf/conn.c
@@ -62,6 +62,7 @@
 #ifdef HAVE_TIME_H
 #include <time.h>
 #endif
+#include <limits.h>
 #ifdef HAVE_LINUX_NETFILTER_IPV4_H
 #include <linux/netfilter_ipv4.h> /* XXX */
 #endif
@@ -1110,12 +1111,12 @@
 	return;
 }
 
-static struct nafconn *listenestablish(struct nafmodule *mod, unsigned short portnum, struct nafmodule *nowner)
+static struct nafconn *listenestablish(struct nafmodule *mod, const char *addr, unsigned short portnum, struct nafmodule *nowner)
 {
 	nbio_sockfd_t sfd;
 	struct nafconn *retconn = NULL;
 
-	if ((sfd = nbio_sfd_newlistener(&gnb, portnum)) == -1) {
+	if ((sfd = nbio_sfd_newlistener(&gnb, addr, portnum)) == -1) {
 		dprintf(mod, "unable to create listener socket\n");
 		return NULL;
 	}
@@ -1131,25 +1132,38 @@
 
 static int findlistenport_matcher(struct nafmodule *mod, struct nafconn *conn, const void *data)
 {
-	unsigned short port;
+	struct sockaddr_in *insin;
+	struct sockaddr_in *testsin;
 
 	if (!(conn->type & NAF_CONN_TYPE_LISTENER))
 		return 0;
 
-	port = ntohs(((struct sockaddr_in *)&conn->localendpoint)->sin_port);
+	insin = (struct sockaddr_in *)data;
+	testsin = (struct sockaddr_in *)&conn->localendpoint;
 
-	if (port == *(unsigned short *)data)
+	if ((testsin->sin_family == insin->sin_family) &&
+	    (testsin->sin_addr.s_addr == insin->sin_addr.s_addr) &&
+	    (testsin->sin_port == insin->sin_port))
 		return 1;
-
 	return 0;
 }
 
-static struct nafconn *findlistenport(struct nafmodule *mod, unsigned short port)
+static struct nafconn *findlistenport(struct nafmodule *mod, const char *addr, unsigned short port)
 {
-	return naf_conn_find(mod, findlistenport_matcher, (const void *)&port);
+	struct sockaddr_in sin;
+
+	memset(&sin, 0, sizeof(sin));
+	sin.sin_family = AF_INET;
+	if (addr) {
+		if (inet_pton(AF_INET, addr, &sin.sin_addr.s_addr) != 1)
+			return NULL;
+	}
+	sin.sin_port = htons(port);
+
+	return naf_conn_find(mod, findlistenport_matcher, (const void *)&sin);
 }
 
-static int listenport_isconfigured(struct nafmodule *mod, unsigned short port)
+static int listenport_isconfigured(struct nafmodule *mod, const char *inaddr, unsigned short inport)
 {
 	char *conf, *cur;
 
@@ -1158,10 +1172,22 @@
 
 	cur = strtok(conf, ",");
 	do {
+		char *colon;
+		char *addr = NULL;
+
 		if (!cur)
 			break;
 
-		if (port == atoi(cur)) {
+		colon = strchr(cur, ':');
+		if (colon) {
+			addr = cur;
+			*(colon++) = '\0';
+			cur = colon;
+		}
+
+		if ((inport == atoi(cur)) &&
+		    (!!addr == !!inaddr) &&
+		    (addr && (strcmp(addr, inaddr) == 0))) {
 			naf_free(mod, conf);
 			return 1;
 		}
@@ -1175,15 +1201,20 @@
 
 static int cleanlisteners_matcher(struct nafmodule *mod, struct nafconn *conn, const void *data)
 {
+	struct sockaddr_in *testsin;
 	unsigned short port;
+	char addr[128];
 
 	if (!(conn->type & NAF_CONN_TYPE_LISTENER))
 		return 0;
 
-	port = ntohs(((struct sockaddr_in *)&conn->localendpoint)->sin_port);
+	testsin = (struct sockaddr_in *)&conn->localendpoint;
+	port = ntohs(testsin->sin_port);
+	if (!inet_ntop(AF_INET, &testsin->sin_addr, addr, sizeof(addr)))
+		return 0;
 
-	if (!listenport_isconfigured(mod, port)) {
-		dvprintf(mod, "removing unconfigured listen port %u\n", port);
+	if (!listenport_isconfigured(mod, addr, port)) {
+		dvprintf(mod, "removing unconfigured listen port %s:%u\n", addr ? addr : "any", port);
 		naf_conn_free(conn);
 	}
 
@@ -1218,12 +1249,19 @@
 		struct nafconn *nconn = NULL;
 		struct nafmodule *nconnowner = NULL;
 		const char *owner = NULL;
+		char *addr = NULL;
+		char *colon;
 		int portnum = -1;
 		int goahead = 1;
 
 		if (!cur)
 			break;
 
+		if ((colon = strchr(cur, ':'))) {
+			addr = cur;
+			*(colon++) = '\0';
+			cur = colon;
+		}
 		portnum = atoi(cur);
 
 		owner = strchr(cur, '/');
@@ -1242,13 +1280,13 @@
 			goahead = 0;
 		}
 
-		if (findlistenport(mod, (naf_u16_t)atoi(cur))) {
+		if (findlistenport(mod, addr, (naf_u16_t)atoi(cur))) {
 			dvprintf(mod, "duplicate listener specified on port %d\n", portnum);
 			goahead = 0;
 		}
 
 		if (goahead)
-			nconn = listenestablish(mod, (naf_u16_t)portnum, nconnowner);
+			nconn = listenestablish(mod, addr, (naf_u16_t)portnum, nconnowner);
 
 		if (nconn) {
 			dvprintf(mod, "listening on port %d (for %s)\n",