/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package util;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Set;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import play.Logger;
import com.emc.vipr.client.exceptions.ViPRException;
import com.google.common.net.InetAddresses;
/**
* Utility class to deal with dynamic dns host resolution.
*
* @author logelj
*
*/
public final class DnsUtils {
private static final String CONTEXT_ATTRIBUTE_A = "A";
private static final String NAMING_FACTORY_KEY = "java.naming.factory.initial";
private static final String NAMING_FACTORY_VALUE = "com.sun.jndi.dns.DnsContextFactory";
private static final String NAMING_PROVIDER_URL_KEY = "java.naming.provider.url";
private static final String DNS_URL_FORMAT = "dns://%s";
/**
* Resolves a host IP address given DNS servers and FQDN host
*
* @param dnsServers
* set of DNS server IP addresses.
* @param hostname
* the fully qualified hostname to lookup.
* @return the ip address of the fully qualified host
*/
public static final InetAddress getHostIpAddress(Set<String> dnsServers, String hostname) {
if (dnsServers.isEmpty()) {
throw new ViPRException(String.format("No nameservers provided to lookup IP address of '%s'", hostname));
}
ViPRException error = null;
for (String dnsServer : dnsServers) {
try {
Attribute attr = getAttribute(dnsServer, hostname, CONTEXT_ATTRIBUTE_A);
return InetAddress.getByName((String) attr.get());
} catch (Exception e) {
Logger.error(e, "Could not lookup IP address of '%s' using nameserver '%s'", hostname, dnsServer);
error = new ViPRException(e.getMessage(), e);
}
}
if (error != null) {
throw error;
}
else {
throw new ViPRException(String.format("Could not lookup IP address of '%s' using nameservers %s", hostname,
dnsServers));
}
}
/**
* Validates the hostname against a number of DNS servers.
*
* @param dnsServers
* the collection of DNS servers.
* @param hostname
* the hostname to validate.
* @return true if the hostname is valid.
*/
public static boolean validateHostname(Collection<String> dnsServers, String hostname) {
for (String dnsServer : dnsServers) {
if (validateHostname(dnsServer, hostname)) {
return true;
}
}
return false;
}
/**
* Validates the existence of a fully qualified host via a name server
*
* @param dnsServer Domain Name Server ip address
* @param hostname Fully qualified hostname
* @return Flag indicating if the host is resolvable on the domain name server
*/
public static boolean validateHostname(final String dnsServer, final String hostname) {
try {
getAttribute(dnsServer, hostname, CONTEXT_ATTRIBUTE_A);
} catch (NamingException e) {
Logger.error(e, e.getMessage());
return false;
} catch (UnknownHostException e) {
Logger.error(e, e.getMessage());
return false;
}
return true;
}
private static DirContext getContext(final String dnsServer) throws UnknownHostException, NamingException {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(NAMING_FACTORY_KEY, NAMING_FACTORY_VALUE);
String urlString = String.format(DNS_URL_FORMAT, InetAddresses.toUriString(InetAddress.getByName(dnsServer)));
env.put(NAMING_PROVIDER_URL_KEY, urlString);
return new InitialDirContext(env);
}
private static Attribute getAttribute(String dnsServer, String hostname, String attrId)
throws UnknownHostException, NamingException {
Attributes attributes = getContext(dnsServer).getAttributes(hostname, new String[] { attrId });
return attributes.get(attrId);
}
}