cifs: set resolved ip in sockaddr
authorPaulo Alcantara <pc@cjr.nz>
Tue, 4 Oct 2022 21:41:36 +0000 (18:41 -0300)
committerSteve French <stfrench@microsoft.com>
Mon, 19 Dec 2022 14:03:11 +0000 (08:03 -0600)
All callers from dns_resolve_server_name_to_ip() used to convert the
ip addr string back to sockaddr, so do that inside
dns_resolve_server_name_to_ip() and avoid duplicating code.

Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/connect.c
fs/cifs/dfs.c
fs/cifs/dfs_cache.c
fs/cifs/dns_resolve.c
fs/cifs/dns_resolve.h
fs/cifs/misc.c

index 94d1741..af386c5 100644 (file)
@@ -91,7 +91,8 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server)
 {
        int rc;
        int len;
-       char *unc, *ipaddr = NULL;
+       char *unc;
+       struct sockaddr_storage ss;
        time64_t expiry, now;
        unsigned long ttl = SMB_DNS_RESOLVE_INTERVAL_DEFAULT;
 
@@ -111,7 +112,11 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server)
        }
        scnprintf(unc, len, "\\\\%s", server->hostname);
 
-       rc = dns_resolve_server_name_to_ip(unc, &ipaddr, &expiry);
+       spin_lock(&server->srv_lock);
+       ss = server->dstaddr;
+       spin_unlock(&server->srv_lock);
+
+       rc = dns_resolve_server_name_to_ip(unc, (struct sockaddr *)&ss, &expiry);
        kfree(unc);
 
        if (rc < 0) {
@@ -121,22 +126,13 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server)
        }
 
        spin_lock(&server->srv_lock);
-       rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
-                                 strlen(ipaddr));
+       memcpy(&server->dstaddr, &ss, sizeof(server->dstaddr));
        spin_unlock(&server->srv_lock);
-       kfree(ipaddr);
 
-       /* rc == 1 means success here */
-       if (rc) {
-               now = ktime_get_real_seconds();
-               if (expiry && expiry > now)
-                       /*
-                        * To make sure we don't use the cached entry, retry 1s
-                        * after expiry.
-                        */
-                       ttl = max_t(unsigned long, expiry - now, SMB_DNS_RESOLVE_INTERVAL_MIN) + 1;
-       }
-       rc = !rc ? -1 : 0;
+       now = ktime_get_real_seconds();
+       if (expiry && expiry > now)
+               /* To make sure we don't use the cached entry, retry 1s */
+               ttl = max_t(unsigned long, expiry - now, SMB_DNS_RESOLVE_INTERVAL_MIN) + 1;
 
 requeue_resolve:
        cifs_dbg(FYI, "%s: next dns resolution scheduled for %lu seconds in the future\n",
index 0b15d7e..ce21438 100644 (file)
@@ -9,28 +9,6 @@
 #include "fs_context.h"
 #include "dfs.h"
 
-/* Resolve UNC server name and set destination ip address in fs context */
-static int resolve_unc(const char *path, struct smb3_fs_context *ctx)
-{
-       int rc;
-       char *ip = NULL;
-
-       rc = dns_resolve_server_name_to_ip(path, &ip, NULL);
-       if (rc < 0) {
-               cifs_dbg(FYI, "%s: failed to resolve UNC server name: %d\n", __func__, rc);
-               return rc;
-       }
-
-       if (!cifs_convert_address((struct sockaddr *)&ctx->dstaddr, ip, strlen(ip))) {
-               cifs_dbg(VFS, "%s: could not determinate destination address\n", __func__);
-               rc = -EHOSTUNREACH;
-       } else
-               rc = 0;
-
-       kfree(ip);
-       return rc;
-}
-
 /**
  * dfs_parse_target_referral - set fs context for dfs target referral
  *
@@ -68,7 +46,7 @@ int dfs_parse_target_referral(const char *full_path, const struct dfs_info3_para
        if (rc)
                goto out;
 
-       rc = resolve_unc(path, ctx);
+       rc = dns_resolve_server_name_to_ip(path, (struct sockaddr *)&ctx->dstaddr, NULL);
 
 out:
        kfree(path);
index e70915a..17b6d53 100644 (file)
@@ -1314,8 +1314,7 @@ static bool target_share_equal(struct TCP_Server_Info *server, const char *s1, c
        char unc[sizeof("\\\\") + SERVER_NAME_LENGTH] = {0};
        const char *host;
        size_t hostlen;
-       char *ip = NULL;
-       struct sockaddr sa;
+       struct sockaddr_storage ss;
        bool match;
        int rc;
 
@@ -1330,23 +1329,17 @@ static bool target_share_equal(struct TCP_Server_Info *server, const char *s1, c
        extract_unc_hostname(s1, &host, &hostlen);
        scnprintf(unc, sizeof(unc), "\\\\%.*s", (int)hostlen, host);
 
-       rc = dns_resolve_server_name_to_ip(unc, &ip, NULL);
+       rc = dns_resolve_server_name_to_ip(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);
                return true;
        }
 
-       if (!cifs_convert_address(&sa, ip, strlen(ip))) {
-               cifs_dbg(VFS, "%s: failed to convert address \'%s\'. skip address matching.\n",
-                        __func__, ip);
-       } else {
-               cifs_server_lock(server);
-               match = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, &sa);
-               cifs_server_unlock(server);
-       }
+       cifs_server_lock(server);
+       match = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss);
+       cifs_server_unlock(server);
 
-       kfree(ip);
        return match;
 }
 
index 0458d28..8bf8978 100644 (file)
@@ -12,6 +12,7 @@
  *
  */
 
+#include <linux/inet.h>
 #include <linux/slab.h>
 #include <linux/dns_resolver.h>
 #include "dns_resolve.h"
  * @ip_addr: Where to return the IP address.
  * @expiry: Where to return the expiry time for the dns record.
  *
- * The IP address will be returned in string form, and the caller is
- * responsible for freeing it.
- *
- * Returns length of result on success, -ve on error.
+ * Returns zero success, -ve on error.
  */
 int
-dns_resolve_server_name_to_ip(const char *unc, char **ip_addr, time64_t *expiry)
+dns_resolve_server_name_to_ip(const char *unc, struct sockaddr *ip_addr, time64_t *expiry)
 {
-       struct sockaddr_storage ss;
        const char *hostname, *sep;
-       char *name;
+       char *ip;
        int len, rc;
 
        if (!ip_addr || !unc)
@@ -60,30 +57,32 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr, time64_t *expiry)
                         __func__, unc);
 
        /* Try to interpret hostname as an IPv4 or IPv6 address */
-       rc = cifs_convert_address((struct sockaddr *)&ss, hostname, len);
-       if (rc > 0)
-               goto name_is_IP_address;
+       rc = cifs_convert_address(ip_addr, hostname, len);
+       if (rc > 0) {
+               cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %*.*s\n", __func__, len, len,
+                        hostname);
+               return 0;
+       }
 
        /* Perform the upcall */
        rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len,
-                      NULL, ip_addr, expiry, false);
-       if (rc < 0)
+                      NULL, &ip, expiry, false);
+       if (rc < 0) {
                cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n",
                         __func__, len, len, hostname);
-       else
+       } else {
                cifs_dbg(FYI, "%s: resolved: %*.*s to %s expiry %llu\n",
-                        __func__, len, len, hostname, *ip_addr,
+                        __func__, len, len, hostname, ip,
                         expiry ? (*expiry) : 0);
-       return rc;
 
-name_is_IP_address:
-       name = kmalloc(len + 1, GFP_KERNEL);
-       if (!name)
-               return -ENOMEM;
-       memcpy(name, hostname, len);
-       name[len] = 0;
-       cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %s\n",
-                __func__, name);
-       *ip_addr = name;
-       return 0;
+               rc = cifs_convert_address(ip_addr, ip, strlen(ip));
+               kfree(ip);
+
+               if (!rc) {
+                       cifs_dbg(FYI, "%s: unable to determine ip address\n", __func__);
+                       rc = -EHOSTUNREACH;
+               } else
+                       rc = 0;
+       }
+       return rc;
 }
index afc0df3..6eb0c15 100644 (file)
 #ifndef _DNS_RESOLVE_H
 #define _DNS_RESOLVE_H
 
+#include <linux/net.h>
+
 #ifdef __KERNEL__
-extern int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr, time64_t *expiry);
+int dns_resolve_server_name_to_ip(const char *unc, struct sockaddr *ip_addr, time64_t *expiry);
 #endif /* KERNEL */
 
 #endif /* _DNS_RESOLVE_H */
index 0621759..4d3c586 100644 (file)
@@ -1258,44 +1258,28 @@ int match_target_ip(struct TCP_Server_Info *server,
                    bool *result)
 {
        int rc;
-       char *target, *tip = NULL;
-       struct sockaddr tipaddr;
+       char *target;
+       struct sockaddr_storage ss;
 
        *result = false;
 
        target = kzalloc(share_len + 3, GFP_KERNEL);
-       if (!target) {
-               rc = -ENOMEM;
-               goto out;
-       }
+       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);
 
-       rc = dns_resolve_server_name_to_ip(target, &tip, NULL);
-       if (rc < 0)
-               goto out;
-
-       cifs_dbg(FYI, "%s: target ip: %s\n", __func__, tip);
+       rc = dns_resolve_server_name_to_ip(target, (struct sockaddr *)&ss, NULL);
+       kfree(target);
 
-       if (!cifs_convert_address(&tipaddr, tip, strlen(tip))) {
-               cifs_dbg(VFS, "%s: failed to convert target ip address\n",
-                        __func__);
-               rc = -EINVAL;
-               goto out;
-       }
+       if (rc < 0)
+               return rc;
 
-       *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr,
-                                   &tipaddr);
+       *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss);
        cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result);
-       rc = 0;
-
-out:
-       kfree(target);
-       kfree(tip);
-
-       return rc;
+       return 0;
 }
 
 int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix)