Commit 4b1b4c8b authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French
Browse files

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: default avatarPaulo Alcantara (Red Hat) <pc@manguebit.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 489d1523
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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,
+5 −22
Original line number Diff line number Diff line
@@ -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;
}

+3 −5
Original line number Diff line number Diff line
@@ -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;
+4 −13
Original line number Diff line number Diff line
@@ -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;
+17 −27
Original line number Diff line number Diff line
@@ -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);
}
Loading