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

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