Blame SOURCES/nfs-utils-1.3.0-mount-clientaddr.patch

5fd2c0
diff -up nfs-utils-1.3.0/utils/mount/network.c.orig nfs-utils-1.3.0/utils/mount/network.c
5fd2c0
--- nfs-utils-1.3.0/utils/mount/network.c.orig	2018-07-30 14:14:01.242771732 -0400
5fd2c0
+++ nfs-utils-1.3.0/utils/mount/network.c	2018-07-30 14:15:36.918075978 -0400
5fd2c0
@@ -44,6 +44,8 @@
5fd2c0
 #include <rpc/rpc.h>
5fd2c0
 #include <rpc/pmap_prot.h>
5fd2c0
 #include <rpc/pmap_clnt.h>
5fd2c0
+#include <net/if.h>
5fd2c0
+#include <ifaddrs.h>
5fd2c0
 
5fd2c0
 #include "sockaddr.h"
5fd2c0
 #include "xcommon.h"
5fd2c0
@@ -1736,3 +1738,48 @@ int nfs_umount_do_umnt(struct mount_opti
5fd2c0
 
5fd2c0
 	return EX_SUCCESS;
5fd2c0
 }
5fd2c0
+
5fd2c0
+int nfs_is_inaddr_any(struct sockaddr *nfs_saddr)
5fd2c0
+{
5fd2c0
+	switch (nfs_saddr->sa_family) {
5fd2c0
+	case AF_INET: {
5fd2c0
+		if (((struct sockaddr_in *)nfs_saddr)->sin_addr.s_addr ==
5fd2c0
+				INADDR_ANY)
5fd2c0
+			return 1;
5fd2c0
+		break;
5fd2c0
+	}
5fd2c0
+	case AF_INET6:
5fd2c0
+		if (!memcmp(&((struct sockaddr_in6 *)nfs_saddr)->sin6_addr,
5fd2c0
+				&in6addr_any, sizeof(in6addr_any)))
5fd2c0
+			return 1;
5fd2c0
+		break;
5fd2c0
+	}
5fd2c0
+	return 0;
5fd2c0
+}
5fd2c0
+
5fd2c0
+int nfs_addr_matches_localips(struct sockaddr *nfs_saddr)
5fd2c0
+{
5fd2c0
+	struct ifaddrs *myaddrs, *ifa;
5fd2c0
+	int found = 0;
5fd2c0
+
5fd2c0
+	/* acquire exiting network interfaces */
5fd2c0
+	if (getifaddrs(&myaddrs) != 0)
5fd2c0
+		return 0;
5fd2c0
+
5fd2c0
+	/* interate over the available interfaces and check if we
5fd2c0
+	 * we find a match to the supplied clientaddr value
5fd2c0
+	 */
5fd2c0
+	for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) {
5fd2c0
+		if (ifa->ifa_addr == NULL)
5fd2c0
+			continue;
5fd2c0
+		if (!(ifa->ifa_flags & IFF_UP))
5fd2c0
+			continue;
5fd2c0
+		if (!memcmp(ifa->ifa_addr, nfs_saddr,
5fd2c0
+				sizeof(struct sockaddr))) {
5fd2c0
+			found = 1;
5fd2c0
+			break;
5fd2c0
+		}
5fd2c0
+	}
5fd2c0
+	freeifaddrs(myaddrs);
5fd2c0
+	return found;
5fd2c0
+}
5fd2c0
diff -up nfs-utils-1.3.0/utils/mount/network.h.orig nfs-utils-1.3.0/utils/mount/network.h
5fd2c0
--- nfs-utils-1.3.0/utils/mount/network.h.orig	2018-07-30 14:14:01.242771732 -0400
5fd2c0
+++ nfs-utils-1.3.0/utils/mount/network.h	2018-07-30 14:15:36.918075978 -0400
5fd2c0
@@ -54,6 +54,8 @@ int nfs_callback_address(const struct so
5fd2c0
 int clnt_ping(struct sockaddr_in *, const unsigned long,
5fd2c0
 		const unsigned long, const unsigned int,
5fd2c0
 		struct sockaddr_in *);
5fd2c0
+int nfs_is_inaddr_any(struct sockaddr *);
5fd2c0
+int nfs_addr_matches_localips(struct sockaddr *);
5fd2c0
 
5fd2c0
 struct mount_options;
5fd2c0
 
5fd2c0
diff -up nfs-utils-1.3.0/utils/mount/nfs.man.orig nfs-utils-1.3.0/utils/mount/nfs.man
5fd2c0
--- nfs-utils-1.3.0/utils/mount/nfs.man.orig	2018-07-30 14:14:01.240771705 -0400
5fd2c0
+++ nfs-utils-1.3.0/utils/mount/nfs.man	2018-07-30 14:15:43.365163864 -0400
5fd2c0
@@ -825,6 +825,9 @@ to perform NFS version 4.0 callback requ
5fd2c0
 files on this mount point. If  the  server is unable to
5fd2c0
 establish callback connections to clients, performance
5fd2c0
 may degrade, or accesses to files may temporarily hang.
5fd2c0
+Can specify a value of IPv4_ANY (0.0.0.0) or equivalent
5fd2c0
+IPv6 any address which will signal to the NFS server that
5fd2c0
+this NFS client does not want delegations.
5fd2c0
 .IP
5fd2c0
 If this option is not specified, the
5fd2c0
 .BR mount (8)
5fd2c0
diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
5fd2c0
--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2018-07-30 14:14:01.243771746 -0400
5fd2c0
+++ nfs-utils-1.3.0/utils/mount/stropts.c	2018-07-30 14:15:36.918075978 -0400
5fd2c0
@@ -229,7 +229,8 @@ static int nfs_append_addr_option(const
5fd2c0
 
5fd2c0
 /*
5fd2c0
  * Called to discover our address and append an appropriate 'clientaddr='
5fd2c0
- * option to the options string.
5fd2c0
+ * option to the options string. If the supplied 'clientaddr=' value does
5fd2c0
+ * not match either IPV4/IPv6 any or a local address, then fail the mount.
5fd2c0
  *
5fd2c0
  * Returns 1 if 'clientaddr=' option created successfully or if
5fd2c0
  * 'clientaddr=' option is already present; otherwise zero.
5fd2c0
@@ -242,8 +243,27 @@ static int nfs_append_clientaddr_option(
5fd2c0
 	struct sockaddr *my_addr = &address.sa;
5fd2c0
 	socklen_t my_len = sizeof(address);
5fd2c0
 
5fd2c0
-	if (po_contains(options, "clientaddr") == PO_FOUND)
5fd2c0
+	if (po_contains(options, "clientaddr") == PO_FOUND) {
5fd2c0
+		char *addr = po_get(options, "clientaddr");
5fd2c0
+		union nfs_sockaddr nfs_address;
5fd2c0
+		struct sockaddr *nfs_saddr = &nfs_address.sa;
5fd2c0
+		socklen_t nfs_salen = sizeof(nfs_address);
5fd2c0
+
5fd2c0
+		/* translate the input for clientaddr to nfs_sockaddr */
5fd2c0
+		if (!nfs_string_to_sockaddr(addr, nfs_saddr, &nfs_salen))
5fd2c0
+			return 0;
5fd2c0
+
5fd2c0
+		/* check for IPV4_ANY and IPV6_ANY */
5fd2c0
+		if (nfs_is_inaddr_any(nfs_saddr))
5fd2c0
+			return 1;
5fd2c0
+
5fd2c0
+		/* check if ip matches local network addresses */
5fd2c0
+		if (!nfs_addr_matches_localips(nfs_saddr))
5fd2c0
+			nfs_error(_("%s: [warning] supplied clientaddr=%s "
5fd2c0
+				"does not match any existing network "
5fd2c0
+				"addresses"), progname, addr);
5fd2c0
 		return 1;
5fd2c0
+	}
5fd2c0
 
5fd2c0
 	nfs_callback_address(sap, salen, my_addr, &my_len);
5fd2c0