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