diff options
-rw-r--r-- | fs/smb/client/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/smb/client/connect.c | 27 | ||||
-rw-r--r-- | fs/smb/client/dfs.c | 8 | ||||
-rw-r--r-- | fs/smb/client/dfs_cache.c | 17 | ||||
-rw-r--r-- | fs/smb/client/dns_resolve.c | 44 | ||||
-rw-r--r-- | fs/smb/client/dns_resolve.h | 24 | ||||
-rw-r--r-- | fs/smb/client/misc.c | 23 |
7 files changed, 59 insertions, 86 deletions
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index d26f9bbb5382..c6c6acb9e206 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -680,7 +680,7 @@ static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, } int match_target_ip(struct TCP_Server_Info *server, - const char *share, size_t share_len, + const char *host, size_t hostlen, bool *result); int cifs_inval_name_dfs_link_error(const unsigned int xid, struct cifs_tcon *tcon, diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 99c018aec2eb..004fec33efab 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -72,10 +72,8 @@ static void cifs_prune_tlinks(struct work_struct *work); */ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server) { - int rc; - int len; - char *unc; struct sockaddr_storage ss; + int rc; if (!server->hostname) return -EINVAL; @@ -84,33 +82,18 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server) if (server->hostname[0] == '\0') return 0; - 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; - } - scnprintf(unc, len, "\\\\%s", server->hostname); - spin_lock(&server->srv_lock); ss = server->dstaddr; spin_unlock(&server->srv_lock); - rc = dns_resolve_server_name_to_ip(server->dns_dom, unc, - (struct sockaddr *)&ss, NULL); - kfree(unc); - - if (rc < 0) { - cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n", - __func__, server->hostname, rc); - } else { + rc = dns_resolve_name(server->dns_dom, server->hostname, + strlen(server->hostname), + (struct sockaddr *)&ss); + if (!rc) { spin_lock(&server->srv_lock); memcpy(&server->dstaddr, &ss, sizeof(server->dstaddr)); spin_unlock(&server->srv_lock); - rc = 0; } - return rc; } diff --git a/fs/smb/client/dfs.c b/fs/smb/client/dfs.c index 09d8808cd2e0..b7de814e39bd 100644 --- a/fs/smb/client/dfs.c +++ b/fs/smb/client/dfs.c @@ -48,9 +48,8 @@ int dfs_parse_target_referral(const char *full_path, const struct dfs_info3_para if (rc) goto out; - rc = dns_resolve_server_name_to_ip(DFS_DOM(ctx), path, - (struct sockaddr *)&ctx->dstaddr, - NULL); + rc = dns_resolve_unc(DFS_DOM(ctx), path, + (struct sockaddr *)&ctx->dstaddr); out: kfree(path); return rc; @@ -268,8 +267,7 @@ static int update_fs_context_dstaddr(struct smb3_fs_context *ctx) int rc = 0; if (!ctx->nodfs && ctx->dfs_automount) { - rc = dns_resolve_server_name_to_ip(NULL, ctx->source, - addr, NULL); + rc = dns_resolve_unc(NULL, ctx->source, addr); if (!rc) cifs_set_port(addr, ctx->port); ctx->dfs_automount = false; diff --git a/fs/smb/client/dfs_cache.c b/fs/smb/client/dfs_cache.c index c0a167c869fb..72527623f433 100644 --- a/fs/smb/client/dfs_cache.c +++ b/fs/smb/client/dfs_cache.c @@ -1096,11 +1096,8 @@ int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, static bool target_share_equal(struct cifs_tcon *tcon, const char *s1) { struct TCP_Server_Info *server = tcon->ses->server; - struct sockaddr_storage ss; - const char *host; const char *s2 = &tcon->tree_name[1]; - size_t hostlen; - char unc[sizeof("\\\\") + SERVER_NAME_LENGTH] = {0}; + struct sockaddr_storage ss; bool match; int rc; @@ -1111,19 +1108,13 @@ static bool target_share_equal(struct cifs_tcon *tcon, const char *s1) * Resolve share's hostname and check if server address matches. Otherwise just ignore it * as we could not have upcall to resolve hostname or failed to convert ip address. */ - extract_unc_hostname(s1, &host, &hostlen); - scnprintf(unc, sizeof(unc), "\\\\%.*s", (int)hostlen, host); - - rc = dns_resolve_server_name_to_ip(server->dns_dom, unc, - (struct sockaddr *)&ss, NULL); - if (rc < 0) { - cifs_dbg(FYI, "%s: could not resolve %.*s. assuming server address matches.\n", - __func__, (int)hostlen, host); + rc = dns_resolve_unc(server->dns_dom, s1, (struct sockaddr *)&ss); + if (rc < 0) return true; - } cifs_server_lock(server); match = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss); + cifs_dbg(FYI, "%s: [share=%s] ipaddr matched: %s\n", __func__, s1, str_yes_no(match)); cifs_server_unlock(server); return match; diff --git a/fs/smb/client/dns_resolve.c b/fs/smb/client/dns_resolve.c index 83db27f9c8f1..de7f4b384718 100644 --- a/fs/smb/client/dns_resolve.c +++ b/fs/smb/client/dns_resolve.c @@ -20,21 +20,19 @@ #include "cifsproto.h" #include "cifs_debug.h" -static int resolve_name(const char *name, size_t namelen, - struct sockaddr *addr, time64_t *expiry) +static int resolve_name(const char *name, size_t namelen, struct sockaddr *addr) { char *ip; int rc; rc = dns_query(current->nsproxy->net_ns, NULL, name, - namelen, NULL, &ip, expiry, false); + namelen, NULL, &ip, NULL, false); if (rc < 0) { cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n", __func__, (int)namelen, (int)namelen, name); } else { - cifs_dbg(FYI, "%s: resolved: %*.*s to %s expiry %llu\n", - __func__, (int)namelen, (int)namelen, name, ip, - expiry ? (*expiry) : 0); + cifs_dbg(FYI, "%s: resolved: %*.*s to %s\n", + __func__, (int)namelen, (int)namelen, name, ip); rc = cifs_convert_address(addr, ip, strlen(ip)); kfree(ip); @@ -50,31 +48,23 @@ static int resolve_name(const char *name, size_t namelen, } /** - * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address. - * @dom: optional DNS domain name - * @unc: UNC path specifying the server (with '/' as delimiter) - * @ip_addr: Where to return the IP address. - * @expiry: Where to return the expiry time for the dns record. + * dns_resolve_name - Perform an upcall to resolve hostname to an ip address. + * @dom: DNS domain name (or NULL) + * @name: Name to look up + * @namelen: Length of name + * @ip_addr: Where to return the IP address * - * Returns zero success, -ve on error. + * Returns zero on success, -ve code otherwise. */ -int dns_resolve_server_name_to_ip(const char *dom, const char *unc, - struct sockaddr *ip_addr, time64_t *expiry) +int dns_resolve_name(const char *dom, const char *name, + size_t namelen, struct sockaddr *ip_addr) { - const char *name; - size_t namelen, len; + size_t len; char *s; int rc; - if (!ip_addr || !unc) - return -EINVAL; - - cifs_dbg(FYI, "%s: dom=%s unc=%s\n", __func__, dom, unc); - if (strlen(unc) < 3) - return -EINVAL; - - extract_unc_hostname(unc, &name, &namelen); - if (!namelen) + cifs_dbg(FYI, "%s: dom=%s name=%.*s\n", __func__, dom, (int)namelen, name); + if (!ip_addr || !name || !*name || !namelen) return -EINVAL; cifs_dbg(FYI, "%s: hostname=%.*s\n", __func__, (int)namelen, name); @@ -97,10 +87,10 @@ int dns_resolve_server_name_to_ip(const char *dom, const char *unc, return -ENOMEM; scnprintf(s, len, "%.*s.%s", (int)namelen, name, dom); - rc = resolve_name(s, len - 1, ip_addr, expiry); + rc = resolve_name(s, len - 1, ip_addr); kfree(s); if (!rc) return 0; } - return resolve_name(name, namelen, ip_addr, expiry); + return resolve_name(name, namelen, ip_addr); } diff --git a/fs/smb/client/dns_resolve.h b/fs/smb/client/dns_resolve.h index 64c1dd2ad39b..0dc706f2c422 100644 --- a/fs/smb/client/dns_resolve.h +++ b/fs/smb/client/dns_resolve.h @@ -12,10 +12,30 @@ #define _DNS_RESOLVE_H #include <linux/net.h> +#include "cifsglob.h" +#include "cifsproto.h" #ifdef __KERNEL__ -int dns_resolve_server_name_to_ip(const char *dom, const char *unc, - struct sockaddr *ip_addr, time64_t *expiry); + +int dns_resolve_name(const char *dom, const char *name, + size_t namelen, struct sockaddr *ip_addr); + +static inline int dns_resolve_unc(const char *dom, const char *unc, + struct sockaddr *ip_addr) +{ + const char *name; + size_t namelen; + + if (!unc || strlen(unc) < 3) + return -EINVAL; + + extract_unc_hostname(unc, &name, &namelen); + if (!namelen) + return -EINVAL; + + return dns_resolve_name(dom, name, namelen, ip_addr); +} + #endif /* KERNEL */ #endif /* _DNS_RESOLVE_H */ diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index 0d483cd08354..a6efd3644e6a 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -1172,34 +1172,25 @@ void cifs_put_tcp_super(struct super_block *sb) #ifdef CONFIG_CIFS_DFS_UPCALL int match_target_ip(struct TCP_Server_Info *server, - const char *share, size_t share_len, + const char *host, size_t hostlen, bool *result) { - int rc; - char *target; struct sockaddr_storage ss; + int rc; - *result = false; - - target = kzalloc(share_len + 3, GFP_KERNEL); - if (!target) - return -ENOMEM; - - scnprintf(target, share_len + 3, "\\\\%.*s", (int)share_len, share); - - cifs_dbg(FYI, "%s: target name: %s\n", __func__, target + 2); + cifs_dbg(FYI, "%s: hostname=%.*s\n", __func__, (int)hostlen, host); - rc = dns_resolve_server_name_to_ip(server->dns_dom, target, - (struct sockaddr *)&ss, NULL); - kfree(target); + *result = false; + rc = dns_resolve_name(server->dns_dom, host, hostlen, + (struct sockaddr *)&ss); if (rc < 0) return rc; spin_lock(&server->srv_lock); *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss); spin_unlock(&server->srv_lock); - cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result); + cifs_dbg(FYI, "%s: ip addresses matched: %s\n", __func__, str_yes_no(*result)); return 0; } |