dns_resolve.c (2338B)
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/slab.h> 16#include <linux/dns_resolver.h> 17#include "dns_resolve.h" 18#include "cifsglob.h" 19#include "cifsproto.h" 20#include "cifs_debug.h" 21 22/** 23 * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address. 24 * @unc: UNC path specifying the server (with '/' as delimiter) 25 * @ip_addr: Where to return the IP address. 26 * @expiry: Where to return the expiry time for the dns record. 27 * 28 * The IP address will be returned in string form, and the caller is 29 * responsible for freeing it. 30 * 31 * Returns length of result on success, -ve on error. 32 */ 33int 34dns_resolve_server_name_to_ip(const char *unc, char **ip_addr, time64_t *expiry) 35{ 36 struct sockaddr_storage ss; 37 const char *hostname, *sep; 38 char *name; 39 int len, rc; 40 41 if (!ip_addr || !unc) 42 return -EINVAL; 43 44 len = strlen(unc); 45 if (len < 3) { 46 cifs_dbg(FYI, "%s: unc is too short: %s\n", __func__, unc); 47 return -EINVAL; 48 } 49 50 /* Discount leading slashes for cifs */ 51 len -= 2; 52 hostname = unc + 2; 53 54 /* Search for server name delimiter */ 55 sep = memchr(hostname, '/', len); 56 if (sep) 57 len = sep - hostname; 58 else 59 cifs_dbg(FYI, "%s: probably server name is whole unc: %s\n", 60 __func__, unc); 61 62 /* Try to interpret hostname as an IPv4 or IPv6 address */ 63 rc = cifs_convert_address((struct sockaddr *)&ss, hostname, len); 64 if (rc > 0) 65 goto name_is_IP_address; 66 67 /* Perform the upcall */ 68 rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len, 69 NULL, ip_addr, 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_addr, 76 expiry ? (*expiry) : 0); 77 return rc; 78 79name_is_IP_address: 80 name = kmalloc(len + 1, GFP_KERNEL); 81 if (!name) 82 return -ENOMEM; 83 memcpy(name, hostname, len); 84 name[len] = 0; 85 cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %s\n", 86 __func__, name); 87 *ip_addr = name; 88 return 0; 89}