| 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); |
| |