|
20 | 20 | #include "cifsproto.h" |
21 | 21 | #include "cifs_debug.h" |
22 | 22 |
|
| 23 | +static int resolve_name(const char *name, size_t namelen, |
| 24 | + struct sockaddr *addr, time64_t *expiry) |
| 25 | +{ |
| 26 | + char *ip; |
| 27 | + int rc; |
| 28 | + |
| 29 | + rc = dns_query(current->nsproxy->net_ns, NULL, name, |
| 30 | + namelen, NULL, &ip, expiry, false); |
| 31 | + if (rc < 0) { |
| 32 | + cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n", |
| 33 | + __func__, (int)namelen, (int)namelen, name); |
| 34 | + } else { |
| 35 | + cifs_dbg(FYI, "%s: resolved: %*.*s to %s expiry %llu\n", |
| 36 | + __func__, (int)namelen, (int)namelen, name, ip, |
| 37 | + expiry ? (*expiry) : 0); |
| 38 | + |
| 39 | + rc = cifs_convert_address(addr, ip, strlen(ip)); |
| 40 | + kfree(ip); |
| 41 | + if (!rc) { |
| 42 | + cifs_dbg(FYI, "%s: unable to determine ip address\n", |
| 43 | + __func__); |
| 44 | + rc = -EHOSTUNREACH; |
| 45 | + } else { |
| 46 | + rc = 0; |
| 47 | + } |
| 48 | + } |
| 49 | + return rc; |
| 50 | +} |
| 51 | + |
23 | 52 | /** |
24 | 53 | * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address. |
| 54 | + * @dom: optional DNS domain name |
25 | 55 | * @unc: UNC path specifying the server (with '/' as delimiter) |
26 | 56 | * @ip_addr: Where to return the IP address. |
27 | 57 | * @expiry: Where to return the expiry time for the dns record. |
28 | 58 | * |
29 | 59 | * Returns zero success, -ve on error. |
30 | 60 | */ |
31 | | -int |
32 | | -dns_resolve_server_name_to_ip(const char *unc, struct sockaddr *ip_addr, time64_t *expiry) |
| 61 | +int dns_resolve_server_name_to_ip(const char *dom, const char *unc, |
| 62 | + struct sockaddr *ip_addr, time64_t *expiry) |
33 | 63 | { |
34 | | - const char *hostname, *sep; |
35 | | - char *ip; |
36 | | - int len, rc; |
| 64 | + const char *name; |
| 65 | + size_t namelen, len; |
| 66 | + char *s; |
| 67 | + int rc; |
37 | 68 |
|
38 | 69 | if (!ip_addr || !unc) |
39 | 70 | return -EINVAL; |
40 | 71 |
|
41 | | - len = strlen(unc); |
42 | | - if (len < 3) { |
43 | | - cifs_dbg(FYI, "%s: unc is too short: %s\n", __func__, unc); |
| 72 | + cifs_dbg(FYI, "%s: dom=%s unc=%s\n", __func__, dom, unc); |
| 73 | + if (strlen(unc) < 3) |
44 | 74 | return -EINVAL; |
45 | | - } |
46 | | - |
47 | | - /* Discount leading slashes for cifs */ |
48 | | - len -= 2; |
49 | | - hostname = unc + 2; |
50 | 75 |
|
51 | | - /* Search for server name delimiter */ |
52 | | - sep = memchr(hostname, '/', len); |
53 | | - if (sep) |
54 | | - len = sep - hostname; |
55 | | - else |
56 | | - cifs_dbg(FYI, "%s: probably server name is whole unc: %s\n", |
57 | | - __func__, unc); |
| 76 | + extract_unc_hostname(unc, &name, &namelen); |
| 77 | + if (!namelen) |
| 78 | + return -EINVAL; |
58 | 79 |
|
| 80 | + cifs_dbg(FYI, "%s: hostname=%.*s\n", __func__, (int)namelen, name); |
59 | 81 | /* Try to interpret hostname as an IPv4 or IPv6 address */ |
60 | | - rc = cifs_convert_address(ip_addr, hostname, len); |
| 82 | + rc = cifs_convert_address(ip_addr, name, namelen); |
61 | 83 | if (rc > 0) { |
62 | | - cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %*.*s\n", __func__, len, len, |
63 | | - hostname); |
| 84 | + cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %*.*s\n", |
| 85 | + __func__, (int)namelen, (int)namelen, name); |
64 | 86 | return 0; |
65 | 87 | } |
66 | 88 |
|
67 | | - /* Perform the upcall */ |
68 | | - rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len, |
69 | | - NULL, &ip, expiry, false); |
70 | | - if (rc < 0) { |
71 | | - cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n", |
72 | | - __func__, len, len, hostname); |
73 | | - } else { |
74 | | - cifs_dbg(FYI, "%s: resolved: %*.*s to %s expiry %llu\n", |
75 | | - __func__, len, len, hostname, ip, |
76 | | - expiry ? (*expiry) : 0); |
77 | | - |
78 | | - rc = cifs_convert_address(ip_addr, ip, strlen(ip)); |
79 | | - kfree(ip); |
| 89 | + /* |
| 90 | + * If @name contains a NetBIOS name and @dom has been specified, then |
| 91 | + * convert @name to an FQDN and try resolving it first. |
| 92 | + */ |
| 93 | + if (dom && *dom && cifs_netbios_name(name, namelen)) { |
| 94 | + len = strnlen(dom, CIFS_MAX_DOMAINNAME_LEN) + namelen + 2; |
| 95 | + s = kmalloc(len, GFP_KERNEL); |
| 96 | + if (!s) |
| 97 | + return -ENOMEM; |
80 | 98 |
|
81 | | - if (!rc) { |
82 | | - cifs_dbg(FYI, "%s: unable to determine ip address\n", __func__); |
83 | | - rc = -EHOSTUNREACH; |
84 | | - } else |
85 | | - rc = 0; |
| 99 | + scnprintf(s, len, "%.*s.%s", (int)namelen, name, dom); |
| 100 | + rc = resolve_name(s, len - 1, ip_addr, expiry); |
| 101 | + kfree(s); |
| 102 | + if (!rc) |
| 103 | + return 0; |
86 | 104 | } |
87 | | - return rc; |
| 105 | + return resolve_name(name, namelen, ip_addr, expiry); |
88 | 106 | } |
0 commit comments