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

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