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

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