Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 290314bcd05f8d672d45e72918073e43 > files > 72

autofs-5.0.1-0.rc2.102.src.rpm

diff --git a/CHANGELOG b/CHANGELOG
index 43dadcf..02ca9e1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -14,6 +14,7 @@
 - fix "-fstype=nfs4" handling.
 - fix get_query_dn not looking in subtree for LDAP search.
 - allow syntax "--timeout <secs>" for backward compatibility.
+- make masked_match independent of hostname for exports comparison.
 
 1/9/2006 autofs-5.0.1 rc2
 -------------------------
diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c
index d07ea71..da2a396 100644
--- a/lib/rpc_subs.c
+++ b/lib/rpc_subs.c
@@ -24,11 +24,13 @@ #include <rpc/pmap_prot.h>
 #include <unistd.h>
 #include <sys/socket.h>
 #include <netdb.h>
+#include <net/if.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <sys/fcntl.h>
 #include <rpcsvc/ypclnt.h>
 #include <errno.h>
+#include <sys/ioctl.h>
 
 #include "mount.h"
 #include "rpc_subs.h"
@@ -40,6 +42,8 @@ #else
 #include "log.h"
 #endif
 
+#define MAX_ERR_BUF	512
+
 /*
  * Create a UDP RPC client
  */
@@ -717,50 +721,99 @@ void rpc_exports_free(exports list)
 	return;
 }
 
-static int masked_match(const char *myname, const char *addr, const char *mask)
+static int masked_match(const char *addr, const char *mask)
 {
-	struct hostent he;
-	struct hostent *phe = &he;
-	struct hostent *result;
-	char buf[HOST_ENT_BUF_SIZE], **haddr;
-	struct sockaddr_in saddr, maddr;
-	int ghn_errno, ret;
-
-	memset(buf, 0, HOST_ENT_BUF_SIZE);
-	memset(&he, 0, sizeof(struct hostent));
-
-	ret = gethostbyname_r(myname, phe,
-			buf, HOST_ENT_BUF_SIZE, &result, &ghn_errno);
-	if (ret || !result)
+	char buf[MAX_ERR_BUF], *ptr;
+	struct sockaddr_in saddr;
+	struct sockaddr_in6 saddr6;
+	struct ifconf ifc;
+	struct ifreq *ifr;
+	int sock, ret, i, is_ipv4, is_ipv6;
+	unsigned int msize;
+
+	sock = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sock < 0) {
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		error(LOGOPT_ANY, "socket creation failed: %s", estr);
 		return 0;
+	}
 
-	ret = inet_aton(addr, &saddr.sin_addr);
-	if (!ret)
+	ifc.ifc_len = sizeof(buf);
+	ifc.ifc_req = (struct ifreq *) buf;
+	ret = ioctl(sock, SIOCGIFCONF, &ifc);
+	if (ret == -1) {
+		close(sock);
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		error(LOGOPT_ANY, "ioctl: %s", estr);
 		return 0;
+	}
+
+	is_ipv4 = is_ipv6 = 0;
+	is_ipv4 = inet_pton(AF_INET, addr, &saddr.sin_addr);
+	if (!is_ipv4)
+		is_ipv6 = inet_pton(AF_INET6, addr, &saddr6.sin6_addr);
 
 	if (strchr(mask, '.')) {
+		struct sockaddr_in maddr;
+		uint32_t ma;
+		int i = 0;
+
 		ret = inet_aton(mask, &maddr.sin_addr);
 		if (!ret)
 			return 0;
-	} else {
-		uint32_t m = (uint32_t) -1;
-		int msize = atoi(mask);
 
-		m = m << (32 - msize);
-		maddr.sin_addr.s_addr = htonl(m);
-	}
+		ma = ntohl((uint32_t) maddr.sin_addr.s_addr);
+		while (!(ma & 1)) {
+			i++;
+			ma = ma >> 1;
+		}
+
+		msize = i;
+	} else
+		msize = atoi(mask);
 
-	for (haddr = phe->h_addr_list; *haddr; haddr++) {
-		uint32_t ca, ma, ha;
+	i = 0;
+	ptr = (char *) &ifc.ifc_buf[0];
 
-		ca = (uint32_t) saddr.sin_addr.s_addr;
-		ma = (uint32_t) maddr.sin_addr.s_addr;
-		ha = (uint32_t) ((struct in_addr *) *haddr)->s_addr;
+	while (ptr < buf + ifc.ifc_len) {
+		ifr = (struct ifreq *) ptr;
 
-		ret = ((ca & ma) == (ha & ma));
-		if (ret)
-			return 1;
+		switch (ifr->ifr_addr.sa_family) {
+		case AF_INET:
+		{
+			struct sockaddr_in *if_addr;
+			uint32_t m, ia, ha;
+
+			if (!is_ipv4 || msize > 32)
+				break;
+
+			m = -1;
+			m = m << (32 - msize);
+			ha = ntohl((uint32_t) saddr.sin_addr.s_addr);
+
+			if_addr = (struct sockaddr_in *) &ifr->ifr_addr;
+			ia = ntohl((uint32_t) if_addr->sin_addr.s_addr);
+
+			if ((ia & m) == (ha & m)) {
+				close(sock);
+				return 1;
+			}
+			break;
+		}
+
+		/* glibc rpc only understands IPv4 atm */
+		case AF_INET6:
+			break;
+
+		default:
+			break;
+		}
+
+		i++;
+		ptr = (char *) &ifc.ifc_req[i];
 	}
+
+	close(sock);
 	return 0;
 }
 
@@ -892,9 +945,9 @@ static int host_match(char *pattern)
 		mask = strchr(addr, '/');
 		if (mask) {
 			*mask++ = '\0';
-			ret = masked_match(myname, addr, mask);
+			ret = masked_match(addr, mask);
 		} else
-			ret = masked_match(myname, addr, "32");
+			ret = masked_match(addr, "32");
 	} else if (!strcmp(pattern, "gss/krb5")) {
 		/* Leave this to the GSS layer */
 		ret = 1;