[PATCH 2/2] autofs-5.1.8 - dont probe interface that cant send packet

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

 



When calculating the proximity add checks for basic reachability.

If an interface doesn't have an address of the family of the target
host, or the interface address is the IPv6 link local address, or
the target host address is the IPv6 link local address then don't
add it to the list of hosts to probe.

Reported-by: Salvatore Bonaccorso <carnil@xxxxxxxxxx>
Tested-by: Salvatore Bonaccorso <carnil@xxxxxxxxxx>
Cc: Goldwyn Rodrigues <rgoldwyn@xxxxxxx>
Cc: Mike Gabriel <sunweaver@xxxxxxxxxx>
Signed-off-by: Ian Kent <raven@xxxxxxxxxx>
---
 CHANGELOG            |    1 +
 lib/parse_subs.c     |   36 +++++++++++++++++++++++++++++++++++-
 modules/replicated.c |   19 +++++++++++--------
 3 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 2f0b9dee..3885474c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -91,6 +91,7 @@
 - add ioctlfd open helper.
 - make open files limit configurable.
 - use correct reference for IN6 macro call.
+- dont probe interface that cant send packet.
 
 19/10/2021 autofs-5.1.8
 - add xdr_exports().
diff --git a/lib/parse_subs.c b/lib/parse_subs.c
index 0ee00d51..3c95996e 100644
--- a/lib/parse_subs.c
+++ b/lib/parse_subs.c
@@ -218,7 +218,7 @@ unsigned int get_proximity(struct sockaddr *host_addr)
 	int addr_len;
 	char buf[MAX_ERR_BUF];
 	uint32_t mask, ha, ia, *mask6, *ha6, *ia6;
-	int ret;
+	int ret, at_least_one;
 
 	addr = NULL;
 	addr6 = NULL;
@@ -228,6 +228,7 @@ unsigned int get_proximity(struct sockaddr *host_addr)
 	ha6 = NULL;
 	ia6 = NULL;
 	ha = 0;
+	at_least_one = 0;
 
 	switch (host_addr->sa_family) {
 	case AF_INET:
@@ -245,6 +246,14 @@ unsigned int get_proximity(struct sockaddr *host_addr)
 		hst6_addr = (struct in6_addr *) &addr6->sin6_addr;
 		ha6 = &hst6_addr->s6_addr32[0];
 		addr_len = sizeof(*hst6_addr);
+
+		/* The link-local address always seems to be a problem so
+		 * ignore it when trying to work out if the address we have
+		 * is reachable.
+		 */
+		if (IN6_IS_ADDR_LINKLOCAL(hst6_addr))
+			return PROXIMITY_UNSUPPORTED;
+
 		break;
 #endif
 
@@ -278,6 +287,14 @@ unsigned int get_proximity(struct sockaddr *host_addr)
 				freeifaddrs(ifa);
 				return PROXIMITY_LOCAL;
 			}
+
+			/* If the target address is the loopback address it will
+			 * have matched above so we can ignore it when trying to
+			 * work out if the address we have is reachable.
+			 */
+			if (addr->sin_addr.s_addr != INADDR_LOOPBACK)
+				at_least_one = 1;
+
 			break;
 
 		case AF_INET6:
@@ -290,6 +307,15 @@ unsigned int get_proximity(struct sockaddr *host_addr)
 				freeifaddrs(ifa);
 				return PROXIMITY_LOCAL;
 			}
+
+			/* If the interface address is the loopback address it will
+			 * have matched above so we can ignore it and the link-local
+			 * address always seems to be a problem so ignore it too when
+			 * trying to work out if the address we have is reachable.
+			 */
+			if (!IN6_IS_ADDR_LINKLOCAL(&if6_addr->sin6_addr) &&
+			    !IN6_IS_ADDR_LOOPBACK(&if6_addr->sin6_addr))
+				at_least_one = 1;
 #endif
 		default:
 			break;
@@ -297,6 +323,11 @@ unsigned int get_proximity(struct sockaddr *host_addr)
 		this = this->ifa_next;
 	}
 
+	if (!at_least_one) {
+		freeifaddrs(ifa);
+		return PROXIMITY_UNSUPPORTED;
+	}
+
 	this = ifa;
 	while (this) {
 		if (!(this->ifa_flags & IFF_UP) ||
@@ -353,6 +384,9 @@ unsigned int get_proximity(struct sockaddr *host_addr)
 			if6_addr = (struct sockaddr_in6 *) this->ifa_addr;
 			ia6 = &if6_addr->sin6_addr.s6_addr32[0];
 
+			if (IN6_IS_ADDR_LINKLOCAL(&if6_addr->sin6_addr))
+				break;
+
 			/* Is the address within the network of the interface */
 
 			msk6_addr = (struct sockaddr_in6 *) this->ifa_netmask;
diff --git a/modules/replicated.c b/modules/replicated.c
index 2e628123..5e2f8b17 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -926,6 +926,15 @@ static int add_new_host(struct host **list,
 
 	prx = get_proximity(host_addr->ai_addr);
 
+	/*
+	 * If we tried to add an IPv6 address and we don't have IPv6
+	 * support (or the host_addr type doesn't match that of any
+	 * of the interface addresses or looks unreachable) return
+	 * success in the hope of getting a valid address later.
+	 */
+	if (prx == PROXIMITY_UNSUPPORTED)
+		return 1;
+
 	/*
 	 * If we want the weight to be the determining factor
 	 * when selecting a host, or we are using random selection,
@@ -938,13 +947,6 @@ static int add_new_host(struct host **list,
 		       MOUNT_FLAG_RANDOM_SELECT)))
 		prx = PROXIMITY_SUBNET;
 
-	/*
-	 * If we tried to add an IPv6 address and we don't have IPv6
-	 * support return success in the hope of getting an IPv4
-	 * address later.
-	 */
-	if (prx == PROXIMITY_UNSUPPORTED)
-		return 1;
 	if (prx == PROXIMITY_ERROR)
 		return 0;
 
@@ -1038,7 +1040,8 @@ try_name:
 		} else if (this->ai_family == AF_INET6) {
 			struct sockaddr_in6 *addr = (struct sockaddr_in6 *) this->ai_addr;
 
-			if (!IN6_IS_ADDR_LOOPBACK(&addr->sin6_addr))
+			if (!IN6_IS_ADDR_LOOPBACK(&addr->sin6_addr) &&
+			    !IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr))
 				rr6++;
 		}
 		this = this->ai_next;





[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