xref: /openbmc/linux/fs/smb/client/dns_resolve.c (revision 38c8a9a5)
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