]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
smb: client: provide dns_resolve_{unc,name} helpers
authorPaulo Alcantara <pc@manguebit.com>
Tue, 7 Jan 2025 15:22:50 +0000 (12:22 -0300)
committerSteve French <stfrench@microsoft.com>
Mon, 20 Jan 2025 01:34:00 +0000 (19:34 -0600)
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>
fs/smb/client/cifsproto.h
fs/smb/client/connect.c
fs/smb/client/dfs.c
fs/smb/client/dfs_cache.c
fs/smb/client/dns_resolve.c
fs/smb/client/dns_resolve.h
fs/smb/client/misc.c

index d26f9bbb53829a789578ca9a393b8fb12fb44315..c6c6acb9e206efac759771638a7175e40ed16c26 100644 (file)
@@ -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,
index 99c018aec2eb19fddf0026c595666e22e4182ab3..004fec33efab73d32df946ea24022bf76c5f2b92 100644 (file)
@@ -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;
 }
 
index 09d8808cd2e040331359ac04f87b6ef36d8e6cbc..b7de814e39bddeec354b33870a1ca22fa06adfc3 100644 (file)
@@ -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;
index c0a167c869fbee4561c2fe78e3c0d019a1a26484..72527623f4330b7d71a993050d6d8d14fb011fd1 100644 (file)
@@ -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;
index 83db27f9c8f1ea7e01fa38a9c6d357170ae0af4c..de7f4b384718184a09a15cde9758c2f5b9ac5006 100644 (file)
 #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);
 }
index 64c1dd2ad39b723d01d66efad7b46e3f879dd47a..0dc706f2c42259be0acea5d6e924c93cf99c1611 100644 (file)
 #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 */
index 0d483cd083542bb6753c8a7f95bc083a3f5f8c34..a6efd3644e6a831e5591f73dae8c3d1501aaaf20 100644 (file)
@@ -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;
 }