[PATCH] prevent autofs to try the wrong IP protocol

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Filesystem Development]     [Linux Ext4]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux