/*1* fs/cifs/dns_resolve.c2*3* Copyright (c) 2007 Igor Mammedov4* Author(s): Igor Mammedov ([email protected])5* Steve French ([email protected])6* Wang Lei ([email protected])7* David Howells ([email protected])8*9* Contains the CIFS DFS upcall routines used for hostname to10* IP address translation.11*12* This library is free software; you can redistribute it and/or modify13* it under the terms of the GNU Lesser General Public License as published14* by the Free Software Foundation; either version 2.1 of the License, or15* (at your option) any later version.16*17* This library is distributed in the hope that it will be useful,18* but WITHOUT ANY WARRANTY; without even the implied warranty of19* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See20* the GNU Lesser General Public License for more details.21*22* You should have received a copy of the GNU Lesser General Public License23* along with this library; if not, write to the Free Software24* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA25*/2627#include <linux/slab.h>28#include <linux/dns_resolver.h>29#include "dns_resolve.h"30#include "cifsglob.h"31#include "cifsproto.h"32#include "cifs_debug.h"3334/**35* dns_resolve_server_name_to_ip - Resolve UNC server name to ip address.36* @unc: UNC path specifying the server37* @ip_addr: Where to return the IP address.38*39* The IP address will be returned in string form, and the caller is40* responsible for freeing it.41*42* Returns length of result on success, -ve on error.43*/44int45dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)46{47struct sockaddr_storage ss;48const char *hostname, *sep;49char *name;50int len, rc;5152if (!ip_addr || !unc)53return -EINVAL;5455len = strlen(unc);56if (len < 3) {57cFYI(1, "%s: unc is too short: %s", __func__, unc);58return -EINVAL;59}6061/* Discount leading slashes for cifs */62len -= 2;63hostname = unc + 2;6465/* Search for server name delimiter */66sep = memchr(hostname, '\\', len);67if (sep)68len = sep - hostname;69else70cFYI(1, "%s: probably server name is whole unc: %s",71__func__, unc);7273/* Try to interpret hostname as an IPv4 or IPv6 address */74rc = cifs_convert_address((struct sockaddr *)&ss, hostname, len);75if (rc > 0)76goto name_is_IP_address;7778/* Perform the upcall */79rc = dns_query(NULL, hostname, len, NULL, ip_addr, NULL);80if (rc < 0)81cERROR(1, "%s: unable to resolve: %*.*s",82__func__, len, len, hostname);83else84cFYI(1, "%s: resolved: %*.*s to %s",85__func__, len, len, hostname, *ip_addr);86return rc;8788name_is_IP_address:89name = kmalloc(len + 1, GFP_KERNEL);90if (!name)91return -ENOMEM;92memcpy(name, hostname, len);93name[len] = 0;94cFYI(1, "%s: unc is IP, skipping dns upcall: %s", __func__, name);95*ip_addr = name;96return 0;97}9899100