You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
4.4 KiB

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