summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@manguebit.com>2025-01-07 12:22:50 -0300
committerSteve French <stfrench@microsoft.com>2025-01-19 19:34:00 -0600
commit4b1b4c8be9dee9aa1a751cfa3954b2fcfdfe9c3d (patch)
tree0c230c8c7abcf70e6aac040138fa4d54e0de67a6
parent489d1523105e14e7a2c6e68205e05397e3b714fb (diff)
smb: client: provide dns_resolve_{unc,name} helpers
Some places pass hostnames rather than UNC paths to resolve them to ip addresses, so provide helpers to handle both cases and then stop converting hostnames to UNC paths by inserting path delimiters into them. Also kill @expiry parameter as it's not used anywhere. Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r--fs/smb/client/cifsproto.h2
-rw-r--r--fs/smb/client/connect.c27
-rw-r--r--fs/smb/client/dfs.c8
-rw-r--r--fs/smb/client/dfs_cache.c17
-rw-r--r--fs/smb/client/dns_resolve.c44
-rw-r--r--fs/smb/client/dns_resolve.h24
-rw-r--r--fs/smb/client/misc.c23
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;
}