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 <jeng...@inai.de>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to