diff options
author | Suresh Jayaraman <sjayaraman@suse.de> | 2009-08-20 03:33:34 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2009-09-01 13:08:48 -0400 |
commit | bdb97adcdf0993adbd2eef44b4533620d43792de (patch) | |
tree | 5d2a120233c93d6a372d26d5ce3fc6cb6525fa6e /fs/cifs/connect.c | |
parent | 1b3859bc9e20d764316346665fc93ecea2d2b176 (diff) |
PATCH] cifs: fix broken mounts when a SSH tunnel is used (try #4)
One more try..
It seems there is a regression that got introduced while Jeff fixed
all the mount/umount races. While attempting to find whether a tcp
session is already existing, we were not checking whether the "port"
used are the same. When a second mount is attempted with a different
"port=" option, it is being ignored. Because of this the cifs mounts
that uses a SSH tunnel appears to be broken.
Steps to reproduce:
1. create 2 shares
# SSH Tunnel a SMB session
2. ssh -f -L 6111:127.0.0.1:445 root@localhost "sleep 86400"
3. ssh -f -L 6222:127.0.0.1:445 root@localhost "sleep 86400"
4. tcpdump -i lo 6111 &
5. mkdir -p /mnt/mnt1
6. mkdir -p /mnt/mnt2
7. mount.cifs //localhost/a /mnt/mnt1 -o username=guest,ip=127.0.0.1,port=6111
#(shows tcpdump activity on port 6111)
8. mount.cifs //localhost/b /mnt/mnt2 -o username=guest,ip=127.0.0.1,port=6222
#(shows tcpdump activity only on port 6111 and not on 6222
Fix by adding a check to compare the port _only_ if the user tries to
override the tcp port with "port=" option, before deciding that an
existing tcp session is found. Also, clean up a bit by replacing
if-else if by a switch statment while at it as suggested by Jeff.
Reviewed-by: Jeff Layton <jlayton@redhat.com>
Reviewed-by: Shirish Pargaonkar <shirishp@us.ibm.com>
Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 1f3345d7fa79..4e47a9b800ce 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1377,7 +1377,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1377 | } | 1377 | } |
1378 | 1378 | ||
1379 | static struct TCP_Server_Info * | 1379 | static struct TCP_Server_Info * |
1380 | cifs_find_tcp_session(struct sockaddr_storage *addr) | 1380 | cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port) |
1381 | { | 1381 | { |
1382 | struct list_head *tmp; | 1382 | struct list_head *tmp; |
1383 | struct TCP_Server_Info *server; | 1383 | struct TCP_Server_Info *server; |
@@ -1397,16 +1397,37 @@ cifs_find_tcp_session(struct sockaddr_storage *addr) | |||
1397 | if (server->tcpStatus == CifsNew) | 1397 | if (server->tcpStatus == CifsNew) |
1398 | continue; | 1398 | continue; |
1399 | 1399 | ||
1400 | if (addr->ss_family == AF_INET && | 1400 | switch (addr->ss_family) { |
1401 | (addr4->sin_addr.s_addr != | 1401 | case AF_INET: |
1402 | server->addr.sockAddr.sin_addr.s_addr)) | 1402 | if (addr4->sin_addr.s_addr == |
1403 | continue; | 1403 | server->addr.sockAddr.sin_addr.s_addr) { |
1404 | else if (addr->ss_family == AF_INET6 && | 1404 | addr4->sin_port = htons(port); |
1405 | (!ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, | 1405 | /* user overrode default port? */ |
1406 | &addr6->sin6_addr) || | 1406 | if (addr4->sin_port) { |
1407 | server->addr.sockAddr6.sin6_scope_id != | 1407 | if (addr4->sin_port != |
1408 | addr6->sin6_scope_id)) | 1408 | server->addr.sockAddr.sin_port) |
1409 | continue; | 1409 | continue; |
1410 | } | ||
1411 | break; | ||
1412 | } else | ||
1413 | continue; | ||
1414 | |||
1415 | case AF_INET6: | ||
1416 | if (ipv6_addr_equal(&addr6->sin6_addr, | ||
1417 | &server->addr.sockAddr6.sin6_addr) && | ||
1418 | (addr6->sin6_scope_id == | ||
1419 | server->addr.sockAddr6.sin6_scope_id)) { | ||
1420 | addr6->sin6_port = htons(port); | ||
1421 | /* user overrode default port? */ | ||
1422 | if (addr6->sin6_port) { | ||
1423 | if (addr6->sin6_port != | ||
1424 | server->addr.sockAddr6.sin6_port) | ||
1425 | continue; | ||
1426 | } | ||
1427 | break; | ||
1428 | } else | ||
1429 | continue; | ||
1430 | } | ||
1410 | 1431 | ||
1411 | ++server->srv_count; | 1432 | ++server->srv_count; |
1412 | write_unlock(&cifs_tcp_ses_lock); | 1433 | write_unlock(&cifs_tcp_ses_lock); |
@@ -1475,7 +1496,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1475 | } | 1496 | } |
1476 | 1497 | ||
1477 | /* see if we already have a matching tcp_ses */ | 1498 | /* see if we already have a matching tcp_ses */ |
1478 | tcp_ses = cifs_find_tcp_session(&addr); | 1499 | tcp_ses = cifs_find_tcp_session(&addr, volume_info->port); |
1479 | if (tcp_ses) | 1500 | if (tcp_ses) |
1480 | return tcp_ses; | 1501 | return tcp_ses; |
1481 | 1502 | ||