diff mbox

CIFS: Fix mounting share on non-standard ports

Message ID 1289321425-7860-1-git-send-email-piastryyy@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Pavel Shilovsky Nov. 9, 2010, 4:50 p.m. UTC
None
diff mbox

Patch

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 251a17c..6edf5ed 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1446,25 +1446,32 @@  match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
 {
 	struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
 	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
+	unsigned short int port;
+
+	/* search for a connection with the default port if user doesn't
+	   specify the port manually */
+	port = htons(CIFS_PORT);
 
 	switch (addr->sa_family) {
 	case AF_INET:
+		if (addr4->sin_port)
+			port = addr4->sin_port;
 		if (addr4->sin_addr.s_addr !=
 		    server->addr.sockAddr.sin_addr.s_addr)
 			return false;
-		if (addr4->sin_port &&
-		    addr4->sin_port != server->addr.sockAddr.sin_port)
+		if (port != server->addr.sockAddr.sin_port)
 			return false;
 		break;
 	case AF_INET6:
+		if (addr6->sin6_port)
+			port = addr6->sin6_port;
 		if (!ipv6_addr_equal(&addr6->sin6_addr,
 				     &server->addr.sockAddr6.sin6_addr))
 			return false;
 		if (addr6->sin6_scope_id !=
 		    server->addr.sockAddr6.sin6_scope_id)
 			return false;
-		if (addr6->sin6_port &&
-		    addr6->sin6_port != server->addr.sockAddr6.sin6_port)
+		if (port != server->addr.sockAddr6.sin6_port)
 			return false;
 		break;
 	}
@@ -2126,7 +2133,7 @@  ipv4_connect(struct TCP_Server_Info *server)
 	int rc = 0;
 	int val;
 	bool connected = false;
-	__be16 orig_port = 0;
+	bool orig_port_error = false;
 	struct socket *socket = server->ssocket;
 
 	if (socket == NULL) {
@@ -2148,32 +2155,30 @@  ipv4_connect(struct TCP_Server_Info *server)
 	if (rc < 0)
 		return rc;
 
-	/* user overrode default port */
+	/* user overrode default port or we perform reconnect */
 	if (server->addr.sockAddr.sin_port) {
 		rc = socket->ops->connect(socket, (struct sockaddr *)
 					  &server->addr.sockAddr,
 					  sizeof(struct sockaddr_in), 0);
 		if (rc >= 0)
 			connected = true;
+		else
+			orig_port_error = true;
+		/* in this case we don't have to try other port
+		   because we can mount another share */
 	}
 
-	if (!connected) {
-		/* save original port so we can retry user specified port
-			later if fall back ports fail this time  */
-		orig_port = server->addr.sockAddr.sin_port;
-
-		/* do not retry on the same port we just failed on */
-		if (server->addr.sockAddr.sin_port != htons(CIFS_PORT)) {
-			server->addr.sockAddr.sin_port = htons(CIFS_PORT);
-			rc = socket->ops->connect(socket,
-						(struct sockaddr *)
-						&server->addr.sockAddr,
-						sizeof(struct sockaddr_in), 0);
-			if (rc >= 0)
-				connected = true;
-		}
+	if (!orig_port_error && !connected) {
+		server->addr.sockAddr.sin_port = htons(CIFS_PORT);
+		rc = socket->ops->connect(socket,
+					(struct sockaddr *)
+					&server->addr.sockAddr,
+					sizeof(struct sockaddr_in), 0);
+		if (rc >= 0)
+			connected = true;
 	}
-	if (!connected) {
+
+	if (!orig_port_error && !connected) {
 		server->addr.sockAddr.sin_port = htons(RFC1001_PORT);
 		rc = socket->ops->connect(socket, (struct sockaddr *)
 					      &server->addr.sockAddr,
@@ -2185,15 +2190,12 @@  ipv4_connect(struct TCP_Server_Info *server)
 	/* give up here - unless we want to retry on different
 		protocol families some day */
 	if (!connected) {
-		if (orig_port)
-			server->addr.sockAddr.sin_port = orig_port;
 		cFYI(1, "Error %d connecting to server via ipv4", rc);
 		sock_release(socket);
 		server->ssocket = NULL;
 		return rc;
 	}
 
-
 	/*
 	 * Eventually check for other socket options to change from
 	 *  the default. sock_setsockopt not used because it expects
@@ -2291,7 +2293,7 @@  ipv6_connect(struct TCP_Server_Info *server)
 	int rc = 0;
 	int val;
 	bool connected = false;
-	__be16 orig_port = 0;
+	bool orig_port_error = false;
 	struct socket *socket = server->ssocket;
 
 	if (socket == NULL) {
@@ -2314,31 +2316,29 @@  ipv6_connect(struct TCP_Server_Info *server)
 	if (rc < 0)
 		return rc;
 
-	/* user overrode default port */
+	/* user overrode default port or we perform reconnect */
 	if (server->addr.sockAddr6.sin6_port) {
 		rc = socket->ops->connect(socket,
 				(struct sockaddr *) &server->addr.sockAddr6,
 				sizeof(struct sockaddr_in6), 0);
 		if (rc >= 0)
 			connected = true;
+		else
+			orig_port_error = true;
+		/* in this case we don't have to try other port
+		   because we can mount another share */
 	}
 
-	if (!connected) {
-		/* save original port so we can retry user specified port
-			later if fall back ports fail this time  */
-
-		orig_port = server->addr.sockAddr6.sin6_port;
-		/* do not retry on the same port we just failed on */
-		if (server->addr.sockAddr6.sin6_port != htons(CIFS_PORT)) {
-			server->addr.sockAddr6.sin6_port = htons(CIFS_PORT);
-			rc = socket->ops->connect(socket, (struct sockaddr *)
-					&server->addr.sockAddr6,
-					sizeof(struct sockaddr_in6), 0);
-			if (rc >= 0)
-				connected = true;
-		}
+	if (!orig_port_error && !connected) {
+		server->addr.sockAddr6.sin6_port = htons(CIFS_PORT);
+		rc = socket->ops->connect(socket, (struct sockaddr *)
+				&server->addr.sockAddr6,
+				sizeof(struct sockaddr_in6), 0);
+		if (rc >= 0)
+			connected = true;
 	}
-	if (!connected) {
+
+	if (!orig_port_error && !connected) {
 		server->addr.sockAddr6.sin6_port = htons(RFC1001_PORT);
 		rc = socket->ops->connect(socket, (struct sockaddr *)
 				&server->addr.sockAddr6,
@@ -2350,8 +2350,6 @@  ipv6_connect(struct TCP_Server_Info *server)
 	/* give up here - unless we want to retry on different
 		protocol families some day */
 	if (!connected) {
-		if (orig_port)
-			server->addr.sockAddr6.sin6_port = orig_port;
 		cFYI(1, "Error %d connecting to server via ipv6", rc);
 		sock_release(socket);
 		server->ssocket = NULL;