1 // SPDX-License-Identifier: LGPL-2.1 2 /* 3 * 4 * Copyright (c) 2007 Igor Mammedov 5 * Author(s): Igor Mammedov (niallain@gmail.com) 6 * Steve French (sfrench@us.ibm.com) 7 * Wang Lei (wang840925@gmail.com) 8 * David Howells (dhowells@redhat.com) 9 * 10 * Contains the CIFS DFS upcall routines used for hostname to 11 * IP address translation. 12 * 13 */ 14 15 #include <linux/inet.h> 16 #include <linux/slab.h> 17 #include <linux/dns_resolver.h> 18 #include "dns_resolve.h" 19 #include "cifsglob.h" 20 #include "cifsproto.h" 21 #include "cifs_debug.h" 22 23 /** 24 * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address. 25 * @unc: UNC path specifying the server (with '/' as delimiter) 26 * @ip_addr: Where to return the IP address. 27 * @expiry: Where to return the expiry time for the dns record. 28 * 29 * Returns zero success, -ve on error. 30 */ 31 int 32 dns_resolve_server_name_to_ip(const char *unc, struct sockaddr *ip_addr, time64_t *expiry) 33 { 34 const char *hostname, *sep; 35 char *ip; 36 int len, rc; 37 38 if (!ip_addr || !unc) 39 return -EINVAL; 40 41 len = strlen(unc); 42 if (len < 3) { 43 cifs_dbg(FYI, "%s: unc is too short: %s\n", __func__, unc); 44 return -EINVAL; 45 } 46 47 /* Discount leading slashes for cifs */ 48 len -= 2; 49 hostname = unc + 2; 50 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); 58 59 /* Try to interpret hostname as an IPv4 or IPv6 address */ 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 } 66 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); 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; 88 } 89