Blame SOURCES/autofs-5.0.7-fix-ipv6-proximity-calculation.patch

4d476f
autofs-5.0.7 - fix ipv6 proximity calculation
4d476f
4d476f
From: Ian Kent <ikent@redhat.com>
4d476f
4d476f
The socket based ioctl used to get interface information only
4d476f
return IPv4 information. Change get_proximity() function to use
4d476f
getifaddrs(3) instead.
4d476f
---
4d476f
4d476f
 CHANGELOG            |    1 
4d476f
 modules/replicated.c |  149 ++++++++++++++------------------------------------
4d476f
 2 files changed, 42 insertions(+), 108 deletions(-)
4d476f
4d476f
4d476f
diff --git a/CHANGELOG b/CHANGELOG
4d476f
index dc38580..34c70fa 100644
4d476f
--- a/CHANGELOG
4d476f
+++ b/CHANGELOG
4d476f
@@ -2,6 +2,7 @@
4d476f
 =======================
4d476f
 - fix nobind sun escaped map entries.
4d476f
 - fix use cache entry after free in lookup_prune_one_cache().
4d476f
+- fix ipv6 proximity calculation.
4d476f
 
4d476f
 25/07/2012 autofs-5.0.7
4d476f
 =======================
4d476f
diff --git a/modules/replicated.c b/modules/replicated.c
4d476f
index 78046c6..bd6003b 100644
4d476f
--- a/modules/replicated.c
4d476f
+++ b/modules/replicated.c
4d476f
@@ -52,6 +52,7 @@
4d476f
 #include <net/if.h>
4d476f
 #include <netinet/in.h>
4d476f
 #include <netdb.h>
4d476f
+#include <ifaddrs.h>
4d476f
 
4d476f
 #include "rpc_subs.h"
4d476f
 #include "replicated.h"
4d476f
@@ -110,58 +111,18 @@ void seed_random(void)
4d476f
 	return;
4d476f
 }
4d476f
 
4d476f
-static int alloc_ifreq(struct ifconf *ifc, int sock)
4d476f
-{
4d476f
-	int ret, lastlen = ifc_last_len, len = ifc_buf_len;
4d476f
-	char err_buf[MAX_ERR_BUF], *buf;
4d476f
-
4d476f
-	while (1) {
4d476f
-		buf = malloc(len);
4d476f
-		if (!buf) {
4d476f
-			char *estr = strerror_r(errno, err_buf, MAX_ERR_BUF);
4d476f
-			logerr("malloc: %s", estr);
4d476f
-			return 0;
4d476f
-		}
4d476f
-
4d476f
-		ifc->ifc_len = len;
4d476f
-		ifc->ifc_req = (struct ifreq *) buf;
4d476f
-
4d476f
-		ret = ioctl(sock, SIOCGIFCONF, ifc);
4d476f
-		if (ret == -1) {
4d476f
-			char *estr = strerror_r(errno, err_buf, MAX_ERR_BUF);
4d476f
-			logerr("ioctl: %s", estr);
4d476f
-			free(buf);
4d476f
-			return 0;
4d476f
-		}
4d476f
-
4d476f
-		if (ifc->ifc_len <= lastlen)
4d476f
-			break;
4d476f
-
4d476f
-		lastlen = ifc->ifc_len;
4d476f
-		len += MAX_IFC_BUF;
4d476f
-		free(buf);
4d476f
-	}
4d476f
-
4d476f
-	if (lastlen != ifc_last_len) {
4d476f
-		ifc_last_len = lastlen;
4d476f
-		ifc_buf_len = len;
4d476f
-	}
4d476f
-
4d476f
-	return 1;
4d476f
-}
4d476f
-
4d476f
 static unsigned int get_proximity(struct sockaddr *host_addr)
4d476f
 {
4d476f
+	struct ifaddrs *ifa = NULL;
4d476f
+	struct ifaddrs *this;
4d476f
 	struct sockaddr_in *addr, *msk_addr, *if_addr;
4d476f
 	struct sockaddr_in6 *addr6, *msk6_addr, *if6_addr;
4d476f
 	struct in_addr *hst_addr;
4d476f
 	struct in6_addr *hst6_addr;
4d476f
 	int addr_len;
4d476f
-	char buf[MAX_ERR_BUF], *ptr;
4d476f
-	struct ifconf ifc;
4d476f
-	struct ifreq *ifr, nmptr;
4d476f
-	int sock, ret, i;
4d476f
+	char buf[MAX_ERR_BUF];
4d476f
 	uint32_t mask, ha, ia, *mask6, *ha6, *ia6;
4d476f
+	int ret;
4d476f
 
4d476f
 	addr = NULL;
4d476f
 	addr6 = NULL;
4d476f
@@ -170,13 +131,14 @@ static unsigned int get_proximity(struct sockaddr *host_addr)
4d476f
 	mask6 = NULL;
4d476f
 	ha6 = NULL;
4d476f
 	ia6 = NULL;
4d476f
+	ha = 0;
4d476f
 
4d476f
 	switch (host_addr->sa_family) {
4d476f
 	case AF_INET:
4d476f
 		addr = (struct sockaddr_in *) host_addr;
4d476f
 		hst_addr = (struct in_addr *) &addr->sin_addr;
4d476f
 		ha = ntohl((uint32_t) hst_addr->s_addr);
4d476f
-		addr_len = sizeof(hst_addr);
4d476f
+		addr_len = sizeof(*hst_addr);
4d476f
 		break;
4d476f
 
4d476f
 	case AF_INET6:
4d476f
@@ -186,7 +148,7 @@ static unsigned int get_proximity(struct sockaddr *host_addr)
4d476f
 		addr6 = (struct sockaddr_in6 *) host_addr;
4d476f
 		hst6_addr = (struct in6_addr *) &addr6->sin6_addr;
4d476f
 		ha6 = &hst6_addr->s6_addr32[0];
4d476f
-		addr_len = sizeof(hst6_addr);
4d476f
+		addr_len = sizeof(*hst6_addr);
4d476f
 		break;
4d476f
 #endif
4d476f
 
4d476f
@@ -194,36 +156,29 @@ static unsigned int get_proximity(struct sockaddr *host_addr)
4d476f
 		return PROXIMITY_ERROR;
4d476f
 	}
4d476f
 
4d476f
-	sock = open_sock(AF_INET, SOCK_DGRAM, 0);
4d476f
-	if (sock < 0) {
4d476f
+	ret = getifaddrs(&ifa;;
4d476f
+	if (ret) {
4d476f
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
4d476f
-		logerr("socket creation failed: %s", estr);
4d476f
+		logerr("getifaddrs: %s", estr);
4d476f
 		return PROXIMITY_ERROR;
4d476f
 	}
4d476f
 
4d476f
-	if (!alloc_ifreq(&ifc, sock)) {
4d476f
-		close(sock);
4d476f
-		return PROXIMITY_ERROR;
4d476f
-	}
4d476f
-
4d476f
-	/* For each interface */
4d476f
-
4d476f
-	/* Is the address a local interface */
4d476f
-	i = 0;
4d476f
-	ptr = (char *) &ifc.ifc_buf[0];
4d476f
-
4d476f
-	while (ptr < (char *) ifc.ifc_req + ifc.ifc_len) {
4d476f
-		ifr = (struct ifreq *) ptr;
4d476f
+	this = ifa;
4d476f
+	while (this) {
4d476f
+		if (this->ifa_flags & IFF_POINTOPOINT ||
4d476f
+		    this->ifa_addr->sa_data == NULL) {
4d476f
+			this = this->ifa_next;
4d476f
+			continue;
4d476f
+		}
4d476f
 
4d476f
-		switch (ifr->ifr_addr.sa_family) {
4d476f
+		switch (this->ifa_addr->sa_family) {
4d476f
 		case AF_INET:
4d476f
 			if (host_addr->sa_family == AF_INET6)
4d476f
 				break;
4d476f
-			if_addr = (struct sockaddr_in *) &ifr->ifr_addr;
4d476f
+			if_addr = (struct sockaddr_in *) this->ifa_addr;
4d476f
 			ret = memcmp(&if_addr->sin_addr, hst_addr, addr_len);
4d476f
 			if (!ret) {
4d476f
-				close(sock);
4d476f
-				free(ifc.ifc_req);
4d476f
+				freeifaddrs(ifa);
4d476f
 				return PROXIMITY_LOCAL;
4d476f
 			}
4d476f
 			break;
4d476f
@@ -234,55 +189,41 @@ static unsigned int get_proximity(struct sockaddr *host_addr)
4d476f
 #else
4d476f
 			if (host_addr->sa_family == AF_INET)
4d476f
 				break;
4d476f
-
4d476f
-			if6_addr = (struct sockaddr_in6 *) &ifr->ifr_addr;
4d476f
+			if6_addr = (struct sockaddr_in6 *) this->ifa_addr;
4d476f
 			ret = memcmp(&if6_addr->sin6_addr, hst6_addr, addr_len);
4d476f
 			if (!ret) {
4d476f
-				close(sock);
4d476f
-				free(ifc.ifc_req);
4d476f
+				freeifaddrs(ifa);
4d476f
 				return PROXIMITY_LOCAL;
4d476f
 			}
4d476f
 #endif
4d476f
-
4d476f
 		default:
4d476f
 			break;
4d476f
 		}
4d476f
-
4d476f
-		i++;
4d476f
-		ptr = (char *) &ifc.ifc_req[i];
4d476f
+		this = this->ifa_next;
4d476f
 	}
4d476f
 
4d476f
-	i = 0;
4d476f
-	ptr = (char *) &ifc.ifc_buf[0];
4d476f
-
4d476f
-	while (ptr < (char *) ifc.ifc_req + ifc.ifc_len) {
4d476f
-		ifr = (struct ifreq *) ptr;
4d476f
-
4d476f
-		nmptr = *ifr;
4d476f
-		ret = ioctl(sock, SIOCGIFNETMASK, &nmptr);
4d476f
-		if (ret == -1) {
4d476f
-			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
4d476f
-			logerr("ioctl: %s", estr);
4d476f
-			close(sock);
4d476f
-			free(ifc.ifc_req);
4d476f
-			return PROXIMITY_ERROR;
4d476f
+	this = ifa;
4d476f
+	while (this) {
4d476f
+		if (this->ifa_flags & IFF_POINTOPOINT ||
4d476f
+		    this->ifa_addr->sa_data == NULL) {
4d476f
+			this = this->ifa_next;
4d476f
+			continue;
4d476f
 		}
4d476f
 
4d476f
-		switch (ifr->ifr_addr.sa_family) {
4d476f
+		switch (this->ifa_addr->sa_family) {
4d476f
 		case AF_INET:
4d476f
 			if (host_addr->sa_family == AF_INET6)
4d476f
 				break;
4d476f
-			if_addr = (struct sockaddr_in *) &ifr->ifr_addr;
4d476f
+			if_addr = (struct sockaddr_in *) this->ifa_addr;
4d476f
 			ia =  ntohl((uint32_t) if_addr->sin_addr.s_addr);
4d476f
 
4d476f
-			/* Is the address within a localiy attached subnet */
4d476f
+			/* Is the address within a localy attached subnet */
4d476f
 
4d476f
-			msk_addr = (struct sockaddr_in *) &nmptr.ifr_netmask;
4d476f
+			msk_addr = (struct sockaddr_in *) this->ifa_netmask;
4d476f
 			mask = ntohl((uint32_t) msk_addr->sin_addr.s_addr);
4d476f
 
4d476f
 			if ((ia & mask) == (ha & mask)) {
4d476f
-				close(sock);
4d476f
-				free(ifc.ifc_req);
4d476f
+				freeifaddrs(ifa);
4d476f
 				return PROXIMITY_SUBNET;
4d476f
 			}
4d476f
 
4d476f
@@ -304,8 +245,7 @@ static unsigned int get_proximity(struct sockaddr *host_addr)
4d476f
 				break;
4d476f
 
4d476f
 			if ((ia & mask) == (ha & mask)) {
4d476f
-				close(sock);
4d476f
-				free(ifc.ifc_req);
4d476f
+				freeifaddrs(ifa);
4d476f
 				return PROXIMITY_NET;
4d476f
 			}
4d476f
 			break;
4d476f
@@ -316,35 +256,28 @@ static unsigned int get_proximity(struct sockaddr *host_addr)
4d476f
 #else
4d476f
 			if (host_addr->sa_family == AF_INET)
4d476f
 				break;
4d476f
-
4d476f
-			if6_addr = (struct sockaddr_in6 *) &ifr->ifr_addr;
4d476f
+			if6_addr = (struct sockaddr_in6 *) this->ifa_addr;
4d476f
 			ia6 = &if6_addr->sin6_addr.s6_addr32[0];
4d476f
 
4d476f
 			/* Is the address within the network of the interface */
4d476f
 
4d476f
-			msk6_addr = (struct sockaddr_in6 *) &nmptr.ifr_netmask;
4d476f
+			msk6_addr = (struct sockaddr_in6 *) this->ifa_netmask;
4d476f
 			mask6 = &msk6_addr->sin6_addr.s6_addr32[0];
4d476f
 
4d476f
 			if (ipv6_mask_cmp(ha6, ia6, mask6)) {
4d476f
-				close(sock);
4d476f
-				free(ifc.ifc_req);
4d476f
+				freeifaddrs(ifa);
4d476f
 				return PROXIMITY_SUBNET;
4d476f
 			}
4d476f
 
4d476f
 			/* How do we define "local network" in ipv6? */
4d476f
 #endif
4d476f
-			break;
4d476f
-
4d476f
 		default:
4d476f
 			break;
4d476f
 		}
4d476f
-
4d476f
-		i++;
4d476f
-		ptr = (char *) &ifc.ifc_req[i];
4d476f
+		this = this->ifa_next;
4d476f
 	}
4d476f
 
4d476f
-	close(sock);
4d476f
-	free(ifc.ifc_req);
4d476f
+	freeifaddrs(ifa);
4d476f
 
4d476f
 	return PROXIMITY_OTHER;
4d476f
 }