[PATCH iptables 2/2] libxtables: pass AI_ADDRCONFIG flag to getaddrinfo()

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

 



According to man getaddrinfo(3):

If hints.ai_flags includes the AI_ADDRCONFIG flag, then IPv4 addresses
are returned in the list pointed to by res only if the local system has
at least one IPv4 address configured, and IPv6 addresses are only
returned if the local system has at least one IPv6 address configured.
The loopback address is not considered for this case as valid as a
configured address.

This patch removes AI_CANONNAME since we don't need the ->ai_canonname
field set in this code.

hints.ai_family has been changed to AF_UNSPEC otherwise the
AI_ADDRCONFIG flag is ignored.

Originally reported as a problem for iptables-translate, but this also
affects iptables and ip6tables.

 $ iptables-translate -A INPUT -s localhost -j ACCEPT

gives duplicated rules:

 nft add rule ip filter INPUT ip saddr 127.0.0.1 counter accept
 nft add rule ip filter INPUT ip saddr 127.0.0.1 counter accept

Reported-by: Alexander Alemayhu <alexander@xxxxxxxxxxxx>
Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
 libxtables/xtables.c | 32 ++++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/libxtables/xtables.c b/libxtables/xtables.c
index d43f97066ea9..aa0b1eb71c0c 100644
--- a/libxtables/xtables.c
+++ b/libxtables/xtables.c
@@ -1367,21 +1367,29 @@ static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr)
 	unsigned int i;
 
 	memset(&hints, 0, sizeof(hints));
-	hints.ai_flags    = AI_CANONNAME;
-	hints.ai_family   = AF_INET;
+	hints.ai_flags    = AI_ADDRCONFIG;
+	hints.ai_family   = AF_UNSPEC;
 	hints.ai_socktype = SOCK_RAW;
 
 	*naddr = 0;
 	if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) {
 		return NULL;
 	} else {
-		for (p = res; p != NULL; p = p->ai_next)
+		for (p = res; p != NULL; p = p->ai_next) {
+			if (p->ai_family != AF_INET)
+				continue;
+
 			++*naddr;
+		}
 		addr = xtables_calloc(*naddr, sizeof(struct in_addr));
-		for (i = 0, p = res; p != NULL; p = p->ai_next)
+		for (i = 0, p = res; p != NULL; p = p->ai_next) {
+			if (p->ai_family != AF_INET)
+				continue;
+
 			memcpy(&addr[i++],
 			       &((const struct sockaddr_in *)p->ai_addr)->sin_addr,
 			       sizeof(struct in_addr));
+		}
 		freeaddrinfo(res);
 		return addr;
 	}
@@ -1657,8 +1665,8 @@ host_to_ip6addr(const char *name, unsigned int *naddr)
 	unsigned int i;
 
 	memset(&hints, 0, sizeof(hints));
-	hints.ai_flags    = AI_CANONNAME;
-	hints.ai_family   = AF_INET6;
+	hints.ai_flags    = AI_ADDRCONFIG;
+	hints.ai_family   = AF_UNSPEC;
 	hints.ai_socktype = SOCK_RAW;
 
 	*naddr = 0;
@@ -1666,14 +1674,22 @@ host_to_ip6addr(const char *name, unsigned int *naddr)
 		return NULL;
 	} else {
 		/* Find length of address chain */
-		for (p = res; p != NULL; p = p->ai_next)
+		for (p = res; p != NULL; p = p->ai_next) {
+			if (p->ai_family != AF_INET6)
+				continue;
+
 			++*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)
+		for (i = 0, p = res; p != NULL; p = p->ai_next) {
+			if (p->ai_family != AF_INET6)
+				continue;
+
 			memcpy(&addr[i++],
 			       &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr,
 			       sizeof(struct in6_addr));
+		}
 		freeaddrinfo(res);
 		return addr;
 	}
-- 
2.1.4

--
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