summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@cjr.nz>2022-10-05 00:41:36 +0300
committerSteve French <stfrench@microsoft.com>2022-12-19 17:03:11 +0300
commit6d740164d8903e6a0e98c30f80fac6af19ce0a21 (patch)
tree9861e8bfcac455a3a51dba53cc4208351c44837b /fs
parent2301bc103ac4acb6d6b6e5860eeed448c4ba2df0 (diff)
downloadlinux-6d740164d8903e6a0e98c30f80fac6af19ce0a21.tar.xz
cifs: set resolved ip in sockaddr
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/connect.c28
-rw-r--r--fs/cifs/dfs.c24
-rw-r--r--fs/cifs/dfs_cache.c17
-rw-r--r--fs/cifs/dns_resolve.c49
-rw-r--r--fs/cifs/dns_resolve.h4
-rw-r--r--fs/cifs/misc.c36
6 files changed, 55 insertions, 103 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 94d1741ced21..af386c5f019e 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -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",
diff --git a/fs/cifs/dfs.c b/fs/cifs/dfs.c
index 0b15d7e9f818..ce21438cadec 100644
--- a/fs/cifs/dfs.c
+++ b/fs/cifs/dfs.c
@@ -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);
diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c
index e70915ad7541..17b6d533c966 100644
--- a/fs/cifs/dfs_cache.c
+++ b/fs/cifs/dfs_cache.c
@@ -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;
}
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
index 0458d28d71aa..8bf8978bc5d6 100644
--- a/fs/cifs/dns_resolve.c
+++ b/fs/cifs/dns_resolve.c
@@ -12,6 +12,7 @@
*
*/
+#include <linux/inet.h>
#include <linux/slab.h>
#include <linux/dns_resolver.h>
#include "dns_resolve.h"
@@ -25,17 +26,13 @@
* @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;
}
diff --git a/fs/cifs/dns_resolve.h b/fs/cifs/dns_resolve.h
index afc0df381246..6eb0c15a2440 100644
--- a/fs/cifs/dns_resolve.h
+++ b/fs/cifs/dns_resolve.h
@@ -11,8 +11,10 @@
#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 */
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 062175994e87..4d3c586785a5 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -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)