| From 28eb24ff75c5ac130eb326b3b4d0dcecfc0f427d Mon Sep 17 00:00:00 2001 |
| From: Paulo Alcantara <paulo@paulo.ac> |
| Date: Tue, 20 Nov 2018 15:16:36 -0200 |
| Subject: cifs: Always resolve hostname before reconnecting |
| |
| From: Paulo Alcantara <paulo@paulo.ac> |
| |
| commit 28eb24ff75c5ac130eb326b3b4d0dcecfc0f427d upstream. |
| |
| In case a hostname resolves to a different IP address (e.g. long |
| running mounts), make sure to resolve it every time prior to calling |
| generic_ip_connect() in reconnect. |
| |
| Suggested-by: Steve French <stfrench@microsoft.com> |
| Signed-off-by: Paulo Alcantara <palcantara@suse.de> |
| Signed-off-by: Steve French <stfrench@microsoft.com> |
| Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/cifs/connect.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 53 insertions(+) |
| |
| --- a/fs/cifs/connect.c |
| +++ b/fs/cifs/connect.c |
| @@ -48,6 +48,7 @@ |
| #include "cifs_unicode.h" |
| #include "cifs_debug.h" |
| #include "cifs_fs_sb.h" |
| +#include "dns_resolve.h" |
| #include "ntlmssp.h" |
| #include "nterr.h" |
| #include "rfc1002pdu.h" |
| @@ -304,6 +305,53 @@ static int cifs_setup_volume_info(struct |
| const char *devname); |
| |
| /* |
| + * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may |
| + * get their ip addresses changed at some point. |
| + * |
| + * This should be called with server->srv_mutex held. |
| + */ |
| +#ifdef CONFIG_CIFS_DFS_UPCALL |
| +static int reconn_set_ipaddr(struct TCP_Server_Info *server) |
| +{ |
| + int rc; |
| + int len; |
| + char *unc, *ipaddr = NULL; |
| + |
| + if (!server->hostname) |
| + return -EINVAL; |
| + |
| + len = strlen(server->hostname) + 3; |
| + |
| + unc = kmalloc(len, GFP_KERNEL); |
| + if (!unc) { |
| + cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__); |
| + return -ENOMEM; |
| + } |
| + snprintf(unc, len, "\\\\%s", server->hostname); |
| + |
| + rc = dns_resolve_server_name_to_ip(unc, &ipaddr); |
| + kfree(unc); |
| + |
| + if (rc < 0) { |
| + cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n", |
| + __func__, server->hostname, rc); |
| + return rc; |
| + } |
| + |
| + rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr, |
| + strlen(ipaddr)); |
| + kfree(ipaddr); |
| + |
| + return !rc ? -1 : 0; |
| +} |
| +#else |
| +static inline int reconn_set_ipaddr(struct TCP_Server_Info *server) |
| +{ |
| + return 0; |
| +} |
| +#endif |
| + |
| +/* |
| * cifs tcp session reconnection |
| * |
| * mark tcp session as reconnecting so temporarily locked |
| @@ -400,6 +448,11 @@ cifs_reconnect(struct TCP_Server_Info *s |
| rc = generic_ip_connect(server); |
| if (rc) { |
| cifs_dbg(FYI, "reconnect error %d\n", rc); |
| + rc = reconn_set_ipaddr(server); |
| + if (rc) { |
| + cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n", |
| + __func__, rc); |
| + } |
| mutex_unlock(&server->srv_mutex); |
| msleep(3000); |
| } else { |