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

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