Message ID | 20180605192909.27578-1-kolga@netapp.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 06/05/2018 03:29 PM, Olga Kornievskaia wrote: > If the NFS client administrator supplies the clientaddr mount > option, it should be either a special value of either IPv4/IPv6 > any address or one of the machine's network addresses. Otherwise, > warn the administrator about the use of an arbitrary value for > the clientaddr value. > > Signed-off-by: Olga Kornievskaia <kolga@netapp.com> Committed... steved. > ` > --- > utils/mount/network.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ > utils/mount/network.h | 2 ++ > utils/mount/stropts.c | 24 ++++++++++++++++++++++-- > 3 files changed, 69 insertions(+), 2 deletions(-) > > diff --git a/utils/mount/network.c b/utils/mount/network.c > index e490399..2a54f82 100644 > --- a/utils/mount/network.c > +++ b/utils/mount/network.c > @@ -50,6 +50,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" > @@ -1759,3 +1761,46 @@ int nfs_umount_do_umnt(struct mount_options *options, > > 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; > + } > + case AF_INET6: > + if (!memcmp(&((struct sockaddr_in6 *)nfs_saddr)->sin6_addr, > + &in6addr_any, sizeof(in6addr_any))) > + return 1; > + } > + 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 --git a/utils/mount/network.h b/utils/mount/network.h > index ecaac33..0fc98ac 100644 > --- a/utils/mount/network.h > +++ b/utils/mount/network.h > @@ -54,6 +54,8 @@ int nfs_callback_address(const struct sockaddr *, const socklen_t, > 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 --git a/utils/mount/stropts.c b/utils/mount/stropts.c > index d1b0708..4d2e37e 100644 > --- a/utils/mount/stropts.c > +++ b/utils/mount/stropts.c > @@ -229,7 +229,8 @@ static int nfs_append_addr_option(const struct sockaddr *sap, > > /* > * 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(const struct sockaddr *sap, > 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); > > -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/utils/mount/network.c b/utils/mount/network.c index e490399..2a54f82 100644 --- a/utils/mount/network.c +++ b/utils/mount/network.c @@ -50,6 +50,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" @@ -1759,3 +1761,46 @@ int nfs_umount_do_umnt(struct mount_options *options, 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; + } + case AF_INET6: + if (!memcmp(&((struct sockaddr_in6 *)nfs_saddr)->sin6_addr, + &in6addr_any, sizeof(in6addr_any))) + return 1; + } + 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 --git a/utils/mount/network.h b/utils/mount/network.h index ecaac33..0fc98ac 100644 --- a/utils/mount/network.h +++ b/utils/mount/network.h @@ -54,6 +54,8 @@ int nfs_callback_address(const struct sockaddr *, const socklen_t, 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 --git a/utils/mount/stropts.c b/utils/mount/stropts.c index d1b0708..4d2e37e 100644 --- a/utils/mount/stropts.c +++ b/utils/mount/stropts.c @@ -229,7 +229,8 @@ static int nfs_append_addr_option(const struct sockaddr *sap, /* * 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(const struct sockaddr *sap, 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);
If the NFS client administrator supplies the clientaddr mount option, it should be either a special value of either IPv4/IPv6 any address or one of the machine's network addresses. Otherwise, warn the administrator about the use of an arbitrary value for the clientaddr value. Signed-off-by: Olga Kornievskaia <kolga@netapp.com> ` --- utils/mount/network.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ utils/mount/network.h | 2 ++ utils/mount/stropts.c | 24 ++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 2 deletions(-)