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