From patchwork Tue Nov 9 16:50:25 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 311582 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oA9GqXor015974 for ; Tue, 9 Nov 2010 16:52:34 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753635Ab0KIQwB (ORCPT ); Tue, 9 Nov 2010 11:52:01 -0500 Received: from mail-ew0-f46.google.com ([209.85.215.46]:35991 "EHLO mail-ew0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753618Ab0KIQv7 (ORCPT ); Tue, 9 Nov 2010 11:51:59 -0500 Received: by ewy7 with SMTP id 7so3686021ewy.19 for ; Tue, 09 Nov 2010 08:51:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:subject:date :message-id:x-mailer; bh=XkezzCqaZEFm3/Eh3Zp3R3qkE+CmWFAVTQPxTk4R/k8=; b=S08im5ibK7fqywUZbTwHWeO1/FjU0f7/zluSkD/IPqjhR0bPWmGJpVYJxGaPD+qVOM QzkOvoC8OLqQ2cSR6HX3KZqL1dEFGVs1SbnipnCk25WgAWsn+W3FX8DpPMmSYTpqJtcd vX9ap1tk/Ijz3z+qLpEbalXRqP81gblLSBVdw= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:subject:date:message-id:x-mailer; b=aoHkJUuoPXlPJmcw0D55BYZRoAdLlKC1Ixum1w81XXP+jPSK72YxLLaHt4TwlTJUOq 2fe7IFYcD658BiNaVj8d+z/3nLsHpwg59scGyEVjNdcuDgHaqyuPo/dGVeKWTp40K4jo g9sXEgdcDi8q55DzmZ/SqegOGgKCGRL7btZS8= Received: by 10.213.113.141 with SMTP id a13mr961119ebq.49.1289321515726; Tue, 09 Nov 2010 08:51:55 -0800 (PST) Received: from localhost.localdomain ([95.84.57.9]) by mx.google.com with ESMTPS id v51sm1322955eeh.22.2010.11.09.08.51.53 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 09 Nov 2010 08:51:54 -0800 (PST) From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [PATCH] CIFS: Fix mounting share on non-standard ports Date: Tue, 9 Nov 2010 19:50:25 +0300 Message-Id: <1289321425-7860-1-git-send-email-piastryyy@gmail.com> X-Mailer: git-send-email 1.7.2.3 Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Tue, 09 Nov 2010 16:52:34 +0000 (UTC) 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;