0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/slab.h>
0016 #include <linux/dns_resolver.h>
0017 #include "dns_resolve.h"
0018 #include "cifsglob.h"
0019 #include "cifsproto.h"
0020 #include "cifs_debug.h"
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 int
0034 dns_resolve_server_name_to_ip(const char *unc, char **ip_addr, time64_t *expiry)
0035 {
0036 struct sockaddr_storage ss;
0037 const char *hostname, *sep;
0038 char *name;
0039 int len, rc;
0040
0041 if (!ip_addr || !unc)
0042 return -EINVAL;
0043
0044 len = strlen(unc);
0045 if (len < 3) {
0046 cifs_dbg(FYI, "%s: unc is too short: %s\n", __func__, unc);
0047 return -EINVAL;
0048 }
0049
0050
0051 len -= 2;
0052 hostname = unc + 2;
0053
0054
0055 sep = memchr(hostname, '/', len);
0056 if (sep)
0057 len = sep - hostname;
0058 else
0059 cifs_dbg(FYI, "%s: probably server name is whole unc: %s\n",
0060 __func__, unc);
0061
0062
0063 rc = cifs_convert_address((struct sockaddr *)&ss, hostname, len);
0064 if (rc > 0)
0065 goto name_is_IP_address;
0066
0067
0068 rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len,
0069 NULL, ip_addr, expiry, false);
0070 if (rc < 0)
0071 cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n",
0072 __func__, len, len, hostname);
0073 else
0074 cifs_dbg(FYI, "%s: resolved: %*.*s to %s expiry %llu\n",
0075 __func__, len, len, hostname, *ip_addr,
0076 expiry ? (*expiry) : 0);
0077 return rc;
0078
0079 name_is_IP_address:
0080 name = kmalloc(len + 1, GFP_KERNEL);
0081 if (!name)
0082 return -ENOMEM;
0083 memcpy(name, hostname, len);
0084 name[len] = 0;
0085 cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %s\n",
0086 __func__, name);
0087 *ip_addr = name;
0088 return 0;
0089 }