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

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