On 8:23 12/01, Ian Kent wrote: > On Fri, 2019-01-11 at 12:18 -0600, Goldwyn Rodrigues wrote: > > When an NFS server is specified by an IPv6 address and no mount > > options, the mount fails because check_address_proto() > > receives vers with TCP_REQUESTED set but the host.addr_len is > > INET6_ADDRSTRLEN. Removing the check for INET_ADDRSTRLEN > > fixes this issue. > > Thanks for the patch Goldwyn. > > Shouldn't that be "Removing the check for INET6_ADDRSTRLEN fixes > this issue". Correct. > > > > > However, this would allow mount from "proto=tcp" for an IPv6 > > addressed server. > > This statement is a bit confusing, Isn't this the point of the > change? > Yes, I was mentioning the side-effects of the patch :) The other way would be not to set TCP_REQUESTED at all, and set it later by returning version from check_address_proto. I have another bigger patch [attached] but decided against it. It kinda looked too ugly for resolving this. Take your pick ;) > I need to try and find the reason I added this check in the > first place to work out if removing the check could introduce > a problem ... > > > > > Fixes: 9053214 ("autofs-5.1.3 - fix ipv6 proto option handling") > > Can I have a look at the bug, couldn't find it by searching for > it? Add this entry in relevant auto file. local-dir -fstype=nfs [IP:v6:address]:/export-dir/on/server and try to access it. > > > Signed-off-by: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx> > > --- > > modules/replicated.c | 3 --- > > 1 file changed, 3 deletions(-) > > > > diff --git a/modules/replicated.c b/modules/replicated.c > > index 740270e..e99e32a 100644 > > --- a/modules/replicated.c > > +++ b/modules/replicated.c > > @@ -497,9 +497,6 @@ static int check_address_proto(unsigned logopt, > > if (ipv6_requested) { > > if (host->addr_len == INET_ADDRSTRLEN) > > ret = 0; > > - } else { > > - if (host->addr_len == INET6_ADDRSTRLEN) > > - ret = 0; > > } > > > > if (!ret) > -- Goldwyn
commit 4e05949c3e140b0d66ccd78fe74d9974eeff9cf2 Author: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx> Date: Fri Jan 11 06:36:13 2019 -0600 Fix NFS mounts with IPv6 address and no options When a NFS server is specified by an IPv6 address and no mount options, the mount fails because check_address_proto() receives vers with TCP_REQUESTED set but the host.add_len is set to INET6_ADDRSTRLEN. Fix it by not setting TCP_SUPPORTED before options are parsed. This is eventually set at check_address_proto(), if not set. Also check for UDP6_REQUESTED when denying NFSv4 over UDP. Fixes: 9053214 ("autofs-5.1.3 - fix ipv6 proto option handling") Signed-off-by: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx> diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c index 426c27b..90668e4 100644 --- a/modules/mount_nfs.c +++ b/modules/mount_nfs.c @@ -88,7 +88,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int mount_default_proto = defaults_get_mount_nfs_default_proto(); vers = NFS_VERS_DEFAULT | NFS_PROTO_DEFAULT; if (strcmp(fstype, "nfs4") == 0) - vers = NFS4_VERS_DEFAULT | TCP_SUPPORTED; + vers = NFS4_VERS_DEFAULT; else if (mount_default_proto == 4) vers = vers | NFS4_VERS_DEFAULT; @@ -154,7 +154,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int /* Is any version of NFSv4 in the options */ if (_strncmp("vers=4", cp, 6) == 0 || _strncmp("nfsvers=4", cp, 9) == 0) - vers = NFS4_VERS_MASK | TCP_SUPPORTED; + vers = NFS4_VERS_MASK; else if (_strncmp("vers=3", cp, o_len) == 0 || _strncmp("nfsvers=3", cp, o_len) == 0) { vers &= ~(NFS4_VERS_MASK | NFS_VERS_MASK); @@ -174,17 +174,15 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int port = 0; } else if (_strncmp("proto=udp", cp, o_len) == 0 || _strncmp("udp", cp, o_len) == 0) { - vers &= ~TCP_SUPPORTED; + vers |= UDP_REQUESTED; } else if (_strncmp("proto=udp6", cp, o_len) == 0 || _strncmp("udp6", cp, o_len) == 0) { - vers &= ~TCP_SUPPORTED; vers |= UDP6_REQUESTED; } else if (_strncmp("proto=tcp", cp, o_len) == 0 || _strncmp("tcp", cp, o_len) == 0) { - vers &= ~UDP_SUPPORTED; + vers |= TCP_REQUESTED; } else if (_strncmp("proto=tcp6", cp, o_len) == 0 || _strncmp("tcp6", cp, o_len) == 0) { - vers &= ~UDP_SUPPORTED; vers |= TCP6_REQUESTED; } /* Check for options that also make sense @@ -199,10 +197,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int } } - /* In case both tcp and udp options were given */ - if ((vers & NFS_PROTO_MASK) == 0) - vers |= NFS_PROTO_MASK; - debug(ap->logopt, MODPREFIX "nfs options=\"%s\", nobind=%d, nosymlink=%d, ro=%d", nfsoptions, nobind, nosymlink, ro); @@ -234,7 +228,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int mount_default_proto == 4 && (vers & NFS_VERS_MASK) != 0 && (vers & NFS4_VERS_MASK) != 0 && - !(vers & UDP6_REQUESTED)) { + !(vers & (UDP6_REQUESTED | UDP_REQUESTED))) { unsigned int v4_probe_ok = 0; struct host *tmp = new_host(hosts->name, 0, hosts->addr, hosts->addr_len, diff --git a/modules/replicated.c b/modules/replicated.c index 740270e..9819c22 100644 --- a/modules/replicated.c +++ b/modules/replicated.c @@ -486,22 +486,32 @@ done_ver: } static int check_address_proto(unsigned logopt, - struct host *host, unsigned int version) + struct host *host, unsigned int *version) { - int ipv6_requested = version & (TCP6_REQUESTED | UDP6_REQUESTED); + unsigned int ver = *version; int ret = 1; /* If a protocol has been explicitly requested then don't * consider addresses that don't match the requested protocol. */ - if (ipv6_requested) { - if (host->addr_len == INET_ADDRSTRLEN) - ret = 0; - } else { - if (host->addr_len == INET6_ADDRSTRLEN) - ret = 0; + if (host->addr_len == INET6_ADDRSTRLEN) { + if (ver & (TCP_REQUESTED | UDP_REQUESTED)) { + ret = 1; + goto out; + } + if (!(ver & (TCP6_REQUESTED | UDP6_REQUESTED))) + *version |= TCP6_REQUESTED; + + } else if (host->addr_len == INET_ADDRSTRLEN) { + if (ver & (TCP6_REQUESTED | UDP6_REQUESTED)) { + ret = 1; + goto out; + } + if (!(ver & (TCP_REQUESTED | UDP_REQUESTED))) + *version |= TCP_REQUESTED; } +out: if (!ret) debug(logopt, "requested protocol does not match address"); @@ -516,7 +526,7 @@ static int get_vers_and_cost(unsigned logopt, struct host *host, unsigned int supported, vers = (NFS_VERS_MASK | NFS4_VERS_MASK); int ret = 0; - if (!check_address_proto(logopt, host, version)) + if (!check_address_proto(logopt, host, &version)) return 0; memset(&pm_info, 0, sizeof(struct conn_info)); @@ -588,7 +598,7 @@ static int get_supported_ver_and_cost(unsigned logopt, struct host *host, debug(logopt, "called with host %s version 0x%x", host->name, version); - if (!check_address_proto(logopt, host, version)) + if (!check_address_proto(logopt, host, &version)) return 0; memset(&pm_info, 0, sizeof(struct conn_info));