org.xbill.DNS.spi.DNSJavaNameService Maven / Gradle / Ivy
Show all versions of org.apache.servicemix.bundles.dnsjava
// SPDX-License-Identifier: BSD-2-Clause
// Copyright (c) 2005 Brian Wellington ([email protected])
package org.xbill.DNS.spi;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.StringTokenizer;
import lombok.extern.slf4j.Slf4j;
import org.xbill.DNS.AAAARecord;
import org.xbill.DNS.ARecord;
import org.xbill.DNS.ExtendedResolver;
import org.xbill.DNS.Lookup;
import org.xbill.DNS.Name;
import org.xbill.DNS.PTRRecord;
import org.xbill.DNS.Record;
import org.xbill.DNS.Resolver;
import org.xbill.DNS.ReverseMap;
import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;
import sun.net.spi.nameservice.NameService;
/**
* This class implements a Name Service Provider, which Java can use (starting with version 1.4), to
* perform DNS resolutions instead of using the standard calls.
*
* This Name Service Provider uses dnsjava.
*
*
To use this provider, you must set the following system property:
* sun.net.spi.nameservice.provider.1=dns,dnsjava
*
* @author Brian Wellington
* @author Paul Cowan ([email protected])
*/
@Slf4j
public class DNSJavaNameService implements NameService {
private static final String nsProperty = "sun.net.spi.nameservice.nameservers";
private static final String domainProperty = "sun.net.spi.nameservice.domain";
private static final String v6Property = "java.net.preferIPv6Addresses";
private boolean preferV6 = false;
private Name localhostName = null;
private InetAddress[] localhostNamedAddresses = null;
private InetAddress[] localhostAddresses = null;
private boolean addressesLoaded = false;
/**
* Creates a DNSJavaNameService instance.
*
*
Uses the sun.net.spi.nameservice.nameservers, sun.net.spi.nameservice.domain,
* and java.net.preferIPv6Addresses properties for configuration.
*/
protected DNSJavaNameService() {
String nameServers = System.getProperty(nsProperty);
String domain = System.getProperty(domainProperty);
String v6 = System.getProperty(v6Property);
if (nameServers != null) {
StringTokenizer st = new StringTokenizer(nameServers, ",");
String[] servers = new String[st.countTokens()];
int n = 0;
while (st.hasMoreTokens()) {
servers[n++] = st.nextToken();
}
try {
Resolver res = new ExtendedResolver(servers);
Lookup.setDefaultResolver(res);
} catch (UnknownHostException e) {
log.error("DNSJavaNameService: invalid {}", nsProperty);
}
}
if (domain != null) {
try {
Lookup.setDefaultSearchPath(new String[] {domain});
} catch (TextParseException e) {
log.error("DNSJavaNameService: invalid {}", domainProperty);
}
}
if (v6 != null && v6.equalsIgnoreCase("true")) {
preferV6 = true;
}
try {
// retrieve the name from the system that is used as localhost
Class> inetAddressImplFactoryClass = Class.forName("java.net.InetAddressImplFactory");
Method createMethod = inetAddressImplFactoryClass.getDeclaredMethod("create");
createMethod.setAccessible(true);
Object inetAddressImpl = createMethod.invoke(null);
Class> inetAddressImplClass = Class.forName("java.net.InetAddressImpl");
Method hostnameMethod = inetAddressImplClass.getMethod("getLocalHostName");
hostnameMethod.setAccessible(true);
localhostName = Name.fromString((String) hostnameMethod.invoke(inetAddressImpl));
Method lookupAllHostAddrMethod =
inetAddressImplClass.getMethod("lookupAllHostAddr", String.class);
lookupAllHostAddrMethod.setAccessible(true);
localhostNamedAddresses =
(InetAddress[]) lookupAllHostAddrMethod.invoke(inetAddressImpl, localhostName.toString());
localhostAddresses =
(InetAddress[]) lookupAllHostAddrMethod.invoke(inetAddressImpl, "localhost");
addressesLoaded = true;
} catch (Exception e) {
log.error("Could not obtain localhost", e);
}
}
/**
* Performs a forward DNS lookup for the host name.
*
* @param host The host name to resolve.
* @return All the ip addresses found for the host name.
*/
@Override
public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
Name name;
try {
name = new Name(host);
} catch (TextParseException e) {
throw new UnknownHostException(host);
}
// avoid asking a dns server (causing a probable timeout) when host is the name of the local
// host
if (addressesLoaded) {
if (name.equals(localhostName)) {
return localhostNamedAddresses;
} else if ("localhost".equalsIgnoreCase(host)) {
return localhostAddresses;
}
}
Record[] records = null;
if (preferV6) {
records = new Lookup(name, Type.AAAA).run();
}
if (records == null) {
records = new Lookup(name, Type.A).run();
}
if (records == null && !preferV6) {
records = new Lookup(name, Type.AAAA).run();
}
if (records == null) {
throw new UnknownHostException(host);
}
InetAddress[] array = new InetAddress[records.length];
for (int i = 0; i < records.length; i++) {
if (records[i] instanceof ARecord) {
ARecord a = (ARecord) records[i];
array[i] = a.getAddress();
} else {
AAAARecord aaaa = (AAAARecord) records[i];
array[i] = aaaa.getAddress();
}
}
return array;
}
/**
* Performs a reverse DNS lookup.
*
* @param addr The ip address to lookup.
* @return The host name found for the ip address.
*/
@Override
public String getHostByAddr(byte[] addr) throws UnknownHostException {
Name name = ReverseMap.fromAddress(InetAddress.getByAddress(addr));
Record[] records = new Lookup(name, Type.PTR).run();
if (records == null) {
throw new UnknownHostException("Unknown address: " + name);
}
return ((PTRRecord) records[0]).getTarget().toString();
}
}