Commit 6d740164 authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French

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: default avatarPaulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 2301bc10
...@@ -91,7 +91,8 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server) ...@@ -91,7 +91,8 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server)
{ {
int rc; int rc;
int len; int len;
char *unc, *ipaddr = NULL; char *unc;
struct sockaddr_storage ss;
time64_t expiry, now; time64_t expiry, now;
unsigned long ttl = SMB_DNS_RESOLVE_INTERVAL_DEFAULT; unsigned long ttl = SMB_DNS_RESOLVE_INTERVAL_DEFAULT;
...@@ -111,7 +112,11 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server) ...@@ -111,7 +112,11 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server)
} }
scnprintf(unc, len, "\\\\%s", server->hostname); 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); kfree(unc);
if (rc < 0) { if (rc < 0) {
...@@ -121,22 +126,13 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server) ...@@ -121,22 +126,13 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server)
} }
spin_lock(&server->srv_lock); spin_lock(&server->srv_lock);
rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr, memcpy(&server->dstaddr, &ss, sizeof(server->dstaddr));
strlen(ipaddr));
spin_unlock(&server->srv_lock); spin_unlock(&server->srv_lock);
kfree(ipaddr);
/* rc == 1 means success here */ now = ktime_get_real_seconds();
if (rc) { if (expiry && expiry > now)
now = ktime_get_real_seconds(); /* To make sure we don't use the cached entry, retry 1s */
if (expiry && expiry > now) ttl = max_t(unsigned long, expiry - now, SMB_DNS_RESOLVE_INTERVAL_MIN) + 1;
/*
* 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;
requeue_resolve: requeue_resolve:
cifs_dbg(FYI, "%s: next dns resolution scheduled for %lu seconds in the future\n", cifs_dbg(FYI, "%s: next dns resolution scheduled for %lu seconds in the future\n",
......
...@@ -9,28 +9,6 @@ ...@@ -9,28 +9,6 @@
#include "fs_context.h" #include "fs_context.h"
#include "dfs.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 * 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 ...@@ -68,7 +46,7 @@ int dfs_parse_target_referral(const char *full_path, const struct dfs_info3_para
if (rc) if (rc)
goto out; goto out;
rc = resolve_unc(path, ctx); rc = dns_resolve_server_name_to_ip(path, (struct sockaddr *)&ctx->dstaddr, NULL);
out: out:
kfree(path); kfree(path);
......
...@@ -1314,8 +1314,7 @@ static bool target_share_equal(struct TCP_Server_Info *server, const char *s1, 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}; char unc[sizeof("\\\\") + SERVER_NAME_LENGTH] = {0};
const char *host; const char *host;
size_t hostlen; size_t hostlen;
char *ip = NULL; struct sockaddr_storage ss;
struct sockaddr sa;
bool match; bool match;
int rc; int rc;
...@@ -1330,23 +1329,17 @@ static bool target_share_equal(struct TCP_Server_Info *server, const char *s1, c ...@@ -1330,23 +1329,17 @@ static bool target_share_equal(struct TCP_Server_Info *server, const char *s1, c
extract_unc_hostname(s1, &host, &hostlen); extract_unc_hostname(s1, &host, &hostlen);
scnprintf(unc, sizeof(unc), "\\\\%.*s", (int)hostlen, host); 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) { if (rc < 0) {
cifs_dbg(FYI, "%s: could not resolve %.*s. assuming server address matches.\n", cifs_dbg(FYI, "%s: could not resolve %.*s. assuming server address matches.\n",
__func__, (int)hostlen, host); __func__, (int)hostlen, host);
return true; return true;
} }
if (!cifs_convert_address(&sa, ip, strlen(ip))) { cifs_server_lock(server);
cifs_dbg(VFS, "%s: failed to convert address \'%s\'. skip address matching.\n", match = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss);
__func__, ip); cifs_server_unlock(server);
} else {
cifs_server_lock(server);
match = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, &sa);
cifs_server_unlock(server);
}
kfree(ip);
return match; return match;
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* *
*/ */
#include <linux/inet.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/dns_resolver.h> #include <linux/dns_resolver.h>
#include "dns_resolve.h" #include "dns_resolve.h"
...@@ -25,17 +26,13 @@ ...@@ -25,17 +26,13 @@
* @ip_addr: Where to return the IP address. * @ip_addr: Where to return the IP address.
* @expiry: Where to return the expiry time for the dns record. * @expiry: Where to return the expiry time for the dns record.
* *
* The IP address will be returned in string form, and the caller is * Returns zero success, -ve on error.
* responsible for freeing it.
*
* Returns length of result on success, -ve on error.
*/ */
int 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; const char *hostname, *sep;
char *name; char *ip;
int len, rc; int len, rc;
if (!ip_addr || !unc) if (!ip_addr || !unc)
...@@ -60,30 +57,32 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr, time64_t *expiry) ...@@ -60,30 +57,32 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr, time64_t *expiry)
__func__, unc); __func__, unc);
/* Try to interpret hostname as an IPv4 or IPv6 address */ /* Try to interpret hostname as an IPv4 or IPv6 address */
rc = cifs_convert_address((struct sockaddr *)&ss, hostname, len); rc = cifs_convert_address(ip_addr, hostname, len);
if (rc > 0) if (rc > 0) {
goto name_is_IP_address; cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %*.*s\n", __func__, len, len,
hostname);
return 0;
}
/* Perform the upcall */ /* Perform the upcall */
rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len, rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len,
NULL, ip_addr, expiry, false); NULL, &ip, expiry, false);
if (rc < 0) if (rc < 0) {
cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n", cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n",
__func__, len, len, hostname); __func__, len, len, hostname);
else } else {
cifs_dbg(FYI, "%s: resolved: %*.*s to %s expiry %llu\n", 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); expiry ? (*expiry) : 0);
return rc;
name_is_IP_address: rc = cifs_convert_address(ip_addr, ip, strlen(ip));
name = kmalloc(len + 1, GFP_KERNEL); kfree(ip);
if (!name)
return -ENOMEM; if (!rc) {
memcpy(name, hostname, len); cifs_dbg(FYI, "%s: unable to determine ip address\n", __func__);
name[len] = 0; rc = -EHOSTUNREACH;
cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %s\n", } else
__func__, name); rc = 0;
*ip_addr = name; }
return 0; return rc;
} }
...@@ -11,8 +11,10 @@ ...@@ -11,8 +11,10 @@
#ifndef _DNS_RESOLVE_H #ifndef _DNS_RESOLVE_H
#define _DNS_RESOLVE_H #define _DNS_RESOLVE_H
#include <linux/net.h>
#ifdef __KERNEL__ #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 /* KERNEL */
#endif /* _DNS_RESOLVE_H */ #endif /* _DNS_RESOLVE_H */
...@@ -1258,44 +1258,28 @@ int match_target_ip(struct TCP_Server_Info *server, ...@@ -1258,44 +1258,28 @@ int match_target_ip(struct TCP_Server_Info *server,
bool *result) bool *result)
{ {
int rc; int rc;
char *target, *tip = NULL; char *target;
struct sockaddr tipaddr; struct sockaddr_storage ss;
*result = false; *result = false;
target = kzalloc(share_len + 3, GFP_KERNEL); target = kzalloc(share_len + 3, GFP_KERNEL);
if (!target) { if (!target)
rc = -ENOMEM; return -ENOMEM;
goto out;
}
scnprintf(target, share_len + 3, "\\\\%.*s", (int)share_len, share); 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: target name: %s\n", __func__, target + 2);
rc = dns_resolve_server_name_to_ip(target, &tip, NULL); rc = dns_resolve_server_name_to_ip(target, (struct sockaddr *)&ss, NULL);
if (rc < 0) kfree(target);
goto out;
cifs_dbg(FYI, "%s: target ip: %s\n", __func__, tip);
if (!cifs_convert_address(&tipaddr, tip, strlen(tip))) { if (rc < 0)
cifs_dbg(VFS, "%s: failed to convert target ip address\n", return rc;
__func__);
rc = -EINVAL;
goto out;
}
*result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, (struct sockaddr *)&ss);
&tipaddr);
cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result); cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result);
rc = 0; return 0;
out:
kfree(target);
kfree(tip);
return rc;
} }
int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix) int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment