From: Paulo Alcantara Date: Tue, 7 Jan 2025 15:22:50 +0000 (-0300) Subject: smb: client: provide dns_resolve_{unc,name} helpers X-Git-Tag: v6.14-rc1~127^2~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4b1b4c8be9dee9aa1a751cfa3954b2fcfdfe9c3d;p=thirdparty%2Fkernel%2Flinux.git 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: Paulo Alcantara (Red Hat) Signed-off-by: Steve French --- diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index d26f9bbb53829..c6c6acb9e206e 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -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, diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 99c018aec2eb1..004fec33efab7 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -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; } diff --git a/fs/smb/client/dfs.c b/fs/smb/client/dfs.c index 09d8808cd2e04..b7de814e39bdd 100644 --- a/fs/smb/client/dfs.c +++ b/fs/smb/client/dfs.c @@ -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; diff --git a/fs/smb/client/dfs_cache.c b/fs/smb/client/dfs_cache.c index c0a167c869fbe..72527623f4330 100644 --- a/fs/smb/client/dfs_cache.c +++ b/fs/smb/client/dfs_cache.c @@ -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; diff --git a/fs/smb/client/dns_resolve.c b/fs/smb/client/dns_resolve.c index 83db27f9c8f1e..de7f4b3847181 100644 --- a/fs/smb/client/dns_resolve.c +++ b/fs/smb/client/dns_resolve.c @@ -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); } diff --git a/fs/smb/client/dns_resolve.h b/fs/smb/client/dns_resolve.h index 64c1dd2ad39b7..0dc706f2c4225 100644 --- a/fs/smb/client/dns_resolve.h +++ b/fs/smb/client/dns_resolve.h @@ -12,10 +12,30 @@ #define _DNS_RESOLVE_H #include +#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 */ diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index 0d483cd083542..a6efd3644e6a8 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -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; }