[PATCH 3/3] libxtables: avoid returning duplicate address for host resolution

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



A long-standing problem has been that `iptables -s any_host_here`
could yield multiple rules with the same address if the DNS was
indeed so populated.

Signed-off-by: Jan Engelhardt <jengelh@xxxxxxx>
---
 libxtables/xtables.c | 44 ++++++++++++++++++++++++++++++++------------
 1 file changed, 32 insertions(+), 12 deletions(-)

diff --git a/libxtables/xtables.c b/libxtables/xtables.c
index 891d81a..d994306 100644
--- a/libxtables/xtables.c
+++ b/libxtables/xtables.c
@@ -1364,7 +1364,7 @@ static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
 	struct addrinfo hints;
 	struct addrinfo *res, *p;
 	int err;
-	unsigned int i;
+	size_t i, j;
 
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_family   = AF_INET;
@@ -1374,14 +1374,23 @@ static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
 	err = getaddrinfo(name, NULL, &hints, &res);
 	if (err != 0)
 		return NULL;
-	for (p = res; p != NULL; p = p->ai_next)
-		++*naddr;
 	addr = xtables_calloc(*naddr, sizeof(struct in_addr));
-	for (i = 0, p = res; p != NULL; p = p->ai_next)
-		memcpy(&addr[i++],
-		       &((const struct sockaddr_in *)p->ai_addr)->sin_addr,
-		       sizeof(struct in_addr));
+	for (i = 0, p = res; p != NULL; p = p->ai_next) {
+		const struct sockaddr_in *newaddr = (const void *)p->ai_addr;
+		bool seen = false;
+
+		for (j = 0; j < i; ++j) {
+			if (memcmp(newaddr, &addr[j], sizeof(*newaddr)) == 0) {
+				seen = true;
+				break;
+			}
+		}
+		if (seen)
+			continue;
+		memcpy(&addr[i++], &newaddr->sin_addr, sizeof(newaddr->sin_addr));
+	}
 	freeaddrinfo(res);
+	*naddr = i;
 	return addr;
 }
 
@@ -1650,7 +1659,7 @@ host_to_ip6addr(const char *name, unsigned int *naddr)
 	struct addrinfo hints;
 	struct addrinfo *res, *p;
 	int err;
-	unsigned int i;
+	size_t i, j;
 
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_family   = AF_INET6;
@@ -1665,11 +1674,22 @@ host_to_ip6addr(const char *name, unsigned int *naddr)
 		++*naddr;
 	/* Copy each element of the address chain */
 	addr = xtables_calloc(*naddr, sizeof(struct in6_addr));
-	for (i = 0, p = res; p != NULL; p = p->ai_next)
-		memcpy(&addr[i++],
-		       &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr,
-		       sizeof(struct in6_addr));
+	for (i = 0, p = res; p != NULL; p = p->ai_next) {
+		const struct sockaddr_in6 *newaddr = (const void *)p->ai_addr;
+		bool seen = false;
+
+		for (j = 0; j < i; ++j) {
+			if (memcmp(newaddr, &addr[j], sizeof(*newaddr)) == 0) {
+				seen = true;
+				break;
+			}
+		}
+		if (seen)
+			continue;
+		memcpy(&addr[i++], &newaddr->sin6_addr, sizeof(newaddr->sin6_addr));
+	}
 	freeaddrinfo(res);
+	*naddr = i;
 	return addr;
 }
 
-- 
2.10.2

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux