1 From: Suresh Jayaraman <sjayaraman@suse.de>
2 Subject: [PATCH] cifs: fix broken mounts when a SSH tunnel is used (try #4)
4 Patch-mainline: in cifs-2.6.git (merge expected in 2.6.32-rcX)
6 It seems there is a regression that got introduced while Jeff fixed
7 all the mount/umount races. While attempting to find whether a tcp
8 session is already existing, we were not checking whether the "port"
9 used are the same. When a second mount is attempted with a different
10 "port=" option, it is being ignored. Because of this the cifs mounts
11 that uses a SSH tunnel appears to be broken.
16 # SSH Tunnel a SMB session
17 2. ssh -f -L 6111:127.0.0.1:445 root@localhost "sleep 86400"
18 3. ssh -f -L 6222:127.0.0.1:445 root@localhost "sleep 86400"
19 4. tcpdump -i lo 6111 &
22 7. mount.cifs //localhost/a /mnt/mnt1 -o username=guest,ip=127.0.0.1,port=6111
23 #(shows tcpdump activity on port 6111)
24 8. mount.cifs //localhost/b /mnt/mnt2 -o username=guest,ip=127.0.0.1,port=6222
25 #(shows tcpdump activity only on port 6111 and not on 6222
27 Fix by adding a check to compare the port _only_ if the user tries to
28 override the tcp port with "port=" option, before deciding that an
29 existing tcp session is found. Also, clean up a bit by replacing
30 if-else if by a switch statment while at it as suggested by Jeff.
32 Reviewed-by: Jeff Layton <jlayton@redhat.com>
33 Reviewed-by: Shirish Pargaonkar <shirishp@us.ibm.com>
34 Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
35 Signed-off-by: Steve French <sfrench@us.ibm.com>
37 fs/cifs/connect.c | 44 ++++++++++++++++++++++++++++++++++----------
38 1 file changed, 34 insertions(+), 10 deletions(-)
40 Index: linux-2.6.27-SLE11_BRANCH/fs/cifs/connect.c
41 ===================================================================
42 --- linux-2.6.27-SLE11_BRANCH.orig/fs/cifs/connect.c
43 +++ linux-2.6.27-SLE11_BRANCH/fs/cifs/connect.c
45 #include <linux/freezer.h>
46 #include <asm/uaccess.h>
47 #include <asm/processor.h>
48 +#include <net/ipv6.h>
51 #include "cifsproto.h"
52 @@ -1349,7 +1350,7 @@ cifs_parse_mount_options(char *options,
55 static struct TCP_Server_Info *
56 -cifs_find_tcp_session(struct sockaddr_storage *addr)
57 +cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port)
59 struct list_head *tmp;
60 struct TCP_Server_Info *server;
61 @@ -1369,14 +1370,37 @@ cifs_find_tcp_session(struct sockaddr_st
62 if (server->tcpStatus == CifsNew)
65 - if (addr->ss_family == AF_INET &&
66 - (addr4->sin_addr.s_addr !=
67 - server->addr.sockAddr.sin_addr.s_addr))
69 - else if (addr->ss_family == AF_INET6 &&
70 - memcmp(&server->addr.sockAddr6.sin6_addr,
71 - &addr6->sin6_addr, sizeof(addr6->sin6_addr)))
73 + switch (addr->ss_family) {
75 + if (addr4->sin_addr.s_addr ==
76 + server->addr.sockAddr.sin_addr.s_addr) {
77 + addr4->sin_port = htons(port);
78 + /* user overrode default port? */
79 + if (addr4->sin_port) {
80 + if (addr4->sin_port !=
81 + server->addr.sockAddr.sin_port)
89 + if (ipv6_addr_equal(&addr6->sin6_addr,
90 + &server->addr.sockAddr6.sin6_addr) &&
91 + (addr6->sin6_scope_id ==
92 + server->addr.sockAddr6.sin6_scope_id)) {
93 + addr6->sin6_port = htons(port);
94 + /* user overrode default port? */
95 + if (addr6->sin6_port) {
96 + if (addr6->sin6_port !=
97 + server->addr.sockAddr6.sin6_port)
106 write_unlock(&cifs_tcp_ses_lock);
107 @@ -2111,7 +2135,7 @@ cifs_mount(struct super_block *sb, struc
111 - srvTcp = cifs_find_tcp_session(&addr);
112 + srvTcp = cifs_find_tcp_session(&addr, volume_info.port);
113 if (!srvTcp) { /* create socket */
114 if (addr.ss_family == AF_INET6) {
115 cFYI(1, ("attempting ipv6 connect"));