Commit | Line | Data |
---|---|---|
929be906 | 1 | // SPDX-License-Identifier: LGPL-2.1 |
197c183f | 2 | /* |
197c183f SF |
3 | * |
4 | * Copyright (c) 2007 Igor Mammedov | |
5 | * Author(s): Igor Mammedov (niallain@gmail.com) | |
6 | * Steve French (sfrench@us.ibm.com) | |
1a4240f4 WL |
7 | * Wang Lei (wang840925@gmail.com) |
8 | * David Howells (dhowells@redhat.com) | |
197c183f SF |
9 | * |
10 | * Contains the CIFS DFS upcall routines used for hostname to | |
11 | * IP address translation. | |
12 | * | |
197c183f SF |
13 | */ |
14 | ||
6d740164 | 15 | #include <linux/inet.h> |
5a0e3ad6 | 16 | #include <linux/slab.h> |
1a4240f4 | 17 | #include <linux/dns_resolver.h> |
197c183f SF |
18 | #include "dns_resolve.h" |
19 | #include "cifsglob.h" | |
20 | #include "cifsproto.h" | |
21 | #include "cifs_debug.h" | |
22 | ||
1a4240f4 WL |
23 | /** |
24 | * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address. | |
d9deef0a | 25 | * @unc: UNC path specifying the server (with '/' as delimiter) |
1a4240f4 | 26 | * @ip_addr: Where to return the IP address. |
506c1da4 | 27 | * @expiry: Where to return the expiry time for the dns record. |
1a4240f4 | 28 | * |
6d740164 | 29 | * Returns zero success, -ve on error. |
197c183f SF |
30 | */ |
31 | int | |
6d740164 | 32 | dns_resolve_server_name_to_ip(const char *unc, struct sockaddr *ip_addr, time64_t *expiry) |
366781c1 | 33 | { |
1a4240f4 | 34 | const char *hostname, *sep; |
6d740164 | 35 | char *ip; |
1a4240f4 | 36 | int len, rc; |
197c183f | 37 | |
366781c1 | 38 | if (!ip_addr || !unc) |
197c183f SF |
39 | return -EINVAL; |
40 | ||
197c183f SF |
41 | len = strlen(unc); |
42 | if (len < 3) { | |
f96637be | 43 | cifs_dbg(FYI, "%s: unc is too short: %s\n", __func__, unc); |
197c183f SF |
44 | return -EINVAL; |
45 | } | |
d09e860c | 46 | |
1a4240f4 WL |
47 | /* Discount leading slashes for cifs */ |
48 | len -= 2; | |
49 | hostname = unc + 2; | |
197c183f | 50 | |
1a4240f4 | 51 | /* Search for server name delimiter */ |
d9deef0a | 52 | sep = memchr(hostname, '/', len); |
1a4240f4 | 53 | if (sep) |
ba038648 | 54 | len = sep - hostname; |
1a4240f4 | 55 | else |
f96637be JP |
56 | cifs_dbg(FYI, "%s: probably server name is whole unc: %s\n", |
57 | __func__, unc); | |
1a4240f4 WL |
58 | |
59 | /* Try to interpret hostname as an IPv4 or IPv6 address */ | |
6d740164 PA |
60 | rc = cifs_convert_address(ip_addr, hostname, len); |
61 | if (rc > 0) { | |
62 | cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %*.*s\n", __func__, len, len, | |
63 | hostname); | |
64 | return 0; | |
65 | } | |
1a4240f4 WL |
66 | |
67 | /* Perform the upcall */ | |
a58946c1 | 68 | rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len, |
6d740164 PA |
69 | NULL, &ip, expiry, false); |
70 | if (rc < 0) { | |
f96637be JP |
71 | cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n", |
72 | __func__, len, len, hostname); | |
6d740164 | 73 | } else { |
506c1da4 | 74 | cifs_dbg(FYI, "%s: resolved: %*.*s to %s expiry %llu\n", |
6d740164 | 75 | __func__, len, len, hostname, ip, |
506c1da4 | 76 | expiry ? (*expiry) : 0); |
197c183f | 77 | |
6d740164 PA |
78 | rc = cifs_convert_address(ip_addr, ip, strlen(ip)); |
79 | kfree(ip); | |
80 | ||
81 | if (!rc) { | |
82 | cifs_dbg(FYI, "%s: unable to determine ip address\n", __func__); | |
83 | rc = -EHOSTUNREACH; | |
84 | } else | |
85 | rc = 0; | |
86 | } | |
87 | return rc; | |
4c0c03ca | 88 | } |