[please CC me on replies, I'm not subscribed] If the user configures an IPv6 protocol for nfs, autofs tries IPv4 too, and vice versa. The attached patch against autofs-5.1.1 prevents this. The additional tries for the wrong IP protocol can be quite costly if e.g. an IPSec tunnel must be brought up. -- Andreas Steinmetz SPAMmers use robotrap@xxxxxxxx
diff -rNu autofs-5.1.1/include/replicated.h autofs-5.1.1-new/include/replicated.h --- autofs-5.1.1/include/replicated.h 2015-04-21 11:37:45.000000000 +0200 +++ autofs-5.1.1-new/include/replicated.h 2016-01-17 21:33:38.514023914 +0100 @@ -72,7 +72,7 @@ unsigned int, unsigned int, unsigned int); void free_host_list(struct host **); int parse_location(unsigned, struct host **, const char *, unsigned int); -int prune_host_list(unsigned, struct host **, unsigned int, int); +int prune_host_list(unsigned, struct host **, unsigned int, int, int); void dump_host_list(struct host *); #endif diff -rNu autofs-5.1.1/modules/mount_nfs.c autofs-5.1.1-new/modules/mount_nfs.c --- autofs-5.1.1/modules/mount_nfs.c 2015-04-21 11:37:45.000000000 +0200 +++ autofs-5.1.1-new/modules/mount_nfs.c 2016-01-17 21:56:24.932039458 +0100 @@ -72,6 +72,7 @@ int port = -1; int ro = 0; /* Set if mount bind should be read-only */ int rdma = 0; + int v4v6 = 0; if (ap->flags & MOUNT_FLAG_REMOUNT) return 0; @@ -164,12 +165,22 @@ if (port < 0) port = 0; port_opt = cp; + } else if (_strncmp("proto=udp6", cp, o_len) == 0 || + _strncmp("udp6", cp, o_len) == 0) { + vers &= ~TCP_SUPPORTED; + v4v6 = 2; + } else if (_strncmp("proto=tcp6", cp, o_len) == 0 || + _strncmp("tcp6", cp, o_len) == 0) { + vers &= ~UDP_SUPPORTED; + v4v6 = 2; } else if (_strncmp("proto=udp", cp, o_len) == 0 || _strncmp("udp", cp, o_len) == 0) { vers &= ~TCP_SUPPORTED; + v4v6 = 1; } else if (_strncmp("proto=tcp", cp, o_len) == 0 || _strncmp("tcp", cp, o_len) == 0) { vers &= ~UDP_SUPPORTED; + v4v6 = 1; } /* Check for options that also make sense with bind mounts */ @@ -220,7 +231,8 @@ if (tmp) { tmp->rr = hosts->rr; prune_host_list(ap->logopt, &tmp, - NFS4_VERS_MASK|TCP_SUPPORTED, port); + NFS4_VERS_MASK|TCP_SUPPORTED, port, + v4v6); /* If probe succeeds just try the mount with host in hosts */ if (tmp) { v4_probe_ok = 1; @@ -228,9 +240,9 @@ } } if (!v4_probe_ok) - prune_host_list(ap->logopt, &hosts, vers, port); + prune_host_list(ap->logopt, &hosts, vers, port, v4v6); } else { - prune_host_list(ap->logopt, &hosts, vers, port); + prune_host_list(ap->logopt, &hosts, vers, port, v4v6); } dont_probe: diff -rNu autofs-5.1.1/modules/replicated.c autofs-5.1.1-new/modules/replicated.c --- autofs-5.1.1/modules/replicated.c 2015-04-21 11:37:45.000000000 +0200 +++ autofs-5.1.1-new/modules/replicated.c 2016-01-17 21:57:50.828401757 +0100 @@ -653,7 +653,7 @@ } int prune_host_list(unsigned logopt, struct host **list, - unsigned int vers, int port) + unsigned int vers, int port, int v4v6) { struct host *this, *last, *first; struct host *new = NULL; @@ -710,7 +710,14 @@ break; if (this->name) { - status = get_vers_and_cost(logopt, this, vers, port); + if ((v4v6 == 2 && this->addr_len == INET_ADDRSTRLEN) || + (v4v6 == 1 && + this->addr_len == INET6_ADDRSTRLEN)) { + status = 0; + } else { + status = get_vers_and_cost(logopt, this, + vers, port); + } if (!status) { if (this == first) { first = next; @@ -818,8 +825,14 @@ remove_host(list, this); add_host(&new, this); } else { - status = get_supported_ver_and_cost(logopt, this, - selected_version, port); + if ((v4v6 == 2 && this->addr_len == INET_ADDRSTRLEN) || + (v4v6 == 1 && + this->addr_len == INET6_ADDRSTRLEN)) { + status = 0; + } else { + status = get_supported_ver_and_cost(logopt, + this, selected_version, port); + } if (status) { this->version = selected_version; remove_host(list, this);