162306a36Sopenharmony_ci// SPDX-License-Identifier: LGPL-2.1 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (c) 2007 Igor Mammedov 562306a36Sopenharmony_ci * Author(s): Igor Mammedov (niallain@gmail.com) 662306a36Sopenharmony_ci * Steve French (sfrench@us.ibm.com) 762306a36Sopenharmony_ci * Wang Lei (wang840925@gmail.com) 862306a36Sopenharmony_ci * David Howells (dhowells@redhat.com) 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Contains the CIFS DFS upcall routines used for hostname to 1162306a36Sopenharmony_ci * IP address translation. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/inet.h> 1662306a36Sopenharmony_ci#include <linux/slab.h> 1762306a36Sopenharmony_ci#include <linux/dns_resolver.h> 1862306a36Sopenharmony_ci#include "dns_resolve.h" 1962306a36Sopenharmony_ci#include "cifsglob.h" 2062306a36Sopenharmony_ci#include "cifsproto.h" 2162306a36Sopenharmony_ci#include "cifs_debug.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/** 2462306a36Sopenharmony_ci * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address. 2562306a36Sopenharmony_ci * @unc: UNC path specifying the server (with '/' as delimiter) 2662306a36Sopenharmony_ci * @ip_addr: Where to return the IP address. 2762306a36Sopenharmony_ci * @expiry: Where to return the expiry time for the dns record. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * Returns zero success, -ve on error. 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_ciint 3262306a36Sopenharmony_cidns_resolve_server_name_to_ip(const char *unc, struct sockaddr *ip_addr, time64_t *expiry) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci const char *hostname, *sep; 3562306a36Sopenharmony_ci char *ip; 3662306a36Sopenharmony_ci int len, rc; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci if (!ip_addr || !unc) 3962306a36Sopenharmony_ci return -EINVAL; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci len = strlen(unc); 4262306a36Sopenharmony_ci if (len < 3) { 4362306a36Sopenharmony_ci cifs_dbg(FYI, "%s: unc is too short: %s\n", __func__, unc); 4462306a36Sopenharmony_ci return -EINVAL; 4562306a36Sopenharmony_ci } 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci /* Discount leading slashes for cifs */ 4862306a36Sopenharmony_ci len -= 2; 4962306a36Sopenharmony_ci hostname = unc + 2; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /* Search for server name delimiter */ 5262306a36Sopenharmony_ci sep = memchr(hostname, '/', len); 5362306a36Sopenharmony_ci if (sep) 5462306a36Sopenharmony_ci len = sep - hostname; 5562306a36Sopenharmony_ci else 5662306a36Sopenharmony_ci cifs_dbg(FYI, "%s: probably server name is whole unc: %s\n", 5762306a36Sopenharmony_ci __func__, unc); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* Try to interpret hostname as an IPv4 or IPv6 address */ 6062306a36Sopenharmony_ci rc = cifs_convert_address(ip_addr, hostname, len); 6162306a36Sopenharmony_ci if (rc > 0) { 6262306a36Sopenharmony_ci cifs_dbg(FYI, "%s: unc is IP, skipping dns upcall: %*.*s\n", __func__, len, len, 6362306a36Sopenharmony_ci hostname); 6462306a36Sopenharmony_ci return 0; 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* Perform the upcall */ 6862306a36Sopenharmony_ci rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len, 6962306a36Sopenharmony_ci NULL, &ip, expiry, false); 7062306a36Sopenharmony_ci if (rc < 0) { 7162306a36Sopenharmony_ci cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n", 7262306a36Sopenharmony_ci __func__, len, len, hostname); 7362306a36Sopenharmony_ci } else { 7462306a36Sopenharmony_ci cifs_dbg(FYI, "%s: resolved: %*.*s to %s expiry %llu\n", 7562306a36Sopenharmony_ci __func__, len, len, hostname, ip, 7662306a36Sopenharmony_ci expiry ? (*expiry) : 0); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci rc = cifs_convert_address(ip_addr, ip, strlen(ip)); 7962306a36Sopenharmony_ci kfree(ip); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci if (!rc) { 8262306a36Sopenharmony_ci cifs_dbg(FYI, "%s: unable to determine ip address\n", __func__); 8362306a36Sopenharmony_ci rc = -EHOSTUNREACH; 8462306a36Sopenharmony_ci } else 8562306a36Sopenharmony_ci rc = 0; 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci return rc; 8862306a36Sopenharmony_ci} 89