Home | History | Annotate | Download | only in spi
      1 // Copyright (c) 2005 Brian Wellington (bwelling (at) xbill.org)
      2 
      3 package org.xbill.DNS.spi;
      4 
      5 import java.lang.reflect.InvocationHandler;
      6 import java.lang.reflect.Method;
      7 import java.net.InetAddress;
      8 import java.net.UnknownHostException;
      9 import java.util.StringTokenizer;
     10 
     11 import org.xbill.DNS.AAAARecord;
     12 import org.xbill.DNS.ARecord;
     13 import org.xbill.DNS.ExtendedResolver;
     14 import org.xbill.DNS.Lookup;
     15 import org.xbill.DNS.Name;
     16 import org.xbill.DNS.PTRRecord;
     17 import org.xbill.DNS.Record;
     18 import org.xbill.DNS.Resolver;
     19 import org.xbill.DNS.ReverseMap;
     20 import org.xbill.DNS.TextParseException;
     21 import org.xbill.DNS.Type;
     22 
     23 /**
     24  * This class implements a Name Service Provider, which Java can use
     25  * (starting with version 1.4), to perform DNS resolutions instead of using
     26  * the standard calls.
     27  * <p>
     28  * This Name Service Provider uses dnsjava.
     29  * <p>
     30  * To use this provider, you must set the following system property:
     31  * <b>sun.net.spi.nameservice.provider.1=dns,dnsjava</b>
     32  *
     33  * @author Brian Wellington
     34  * @author Paul Cowan (pwc21 (at) yahoo.com)
     35  */
     36 
     37 public class DNSJavaNameService implements InvocationHandler {
     38 
     39 private static final String nsProperty = "sun.net.spi.nameservice.nameservers";
     40 private static final String domainProperty = "sun.net.spi.nameservice.domain";
     41 private static final String v6Property = "java.net.preferIPv6Addresses";
     42 
     43 private boolean preferV6 = false;
     44 
     45 /**
     46  * Creates a DNSJavaNameService instance.
     47  * <p>
     48  * Uses the
     49  * <b>sun.net.spi.nameservice.nameservers</b>,
     50  * <b>sun.net.spi.nameservice.domain</b>, and
     51  * <b>java.net.preferIPv6Addresses</b> properties for configuration.
     52  */
     53 protected
     54 DNSJavaNameService() {
     55 	String nameServers = System.getProperty(nsProperty);
     56 	String domain = System.getProperty(domainProperty);
     57 	String v6 = System.getProperty(v6Property);
     58 
     59 	if (nameServers != null) {
     60 		StringTokenizer st = new StringTokenizer(nameServers, ",");
     61 		String [] servers = new String[st.countTokens()];
     62 		int n = 0;
     63 		while (st.hasMoreTokens())
     64 			servers[n++] = st.nextToken();
     65 		try {
     66 			Resolver res = new ExtendedResolver(servers);
     67 			Lookup.setDefaultResolver(res);
     68 		}
     69 		catch (UnknownHostException e) {
     70 			System.err.println("DNSJavaNameService: invalid " +
     71 					   nsProperty);
     72 		}
     73 	}
     74 
     75 	if (domain != null) {
     76 		try {
     77 			Lookup.setDefaultSearchPath(new String[] {domain});
     78 		}
     79 		catch (TextParseException e) {
     80 			System.err.println("DNSJavaNameService: invalid " +
     81 					   domainProperty);
     82 		}
     83 	}
     84 
     85 	if (v6 != null && v6.equalsIgnoreCase("true"))
     86 		preferV6 = true;
     87 }
     88 
     89 
     90 public Object
     91 invoke(Object proxy, Method method, Object[] args) throws Throwable {
     92 	try {
     93 		if (method.getName().equals("getHostByAddr")) {
     94 			return this.getHostByAddr((byte[]) args[0]);
     95 		} else if (method.getName().equals("lookupAllHostAddr")) {
     96 			InetAddress[] addresses;
     97 			addresses = this.lookupAllHostAddr((String) args[0]);
     98 			Class returnType = method.getReturnType();
     99 			if (returnType.equals(InetAddress[].class)) {
    100 				// method for Java >= 1.6
    101 				return addresses;
    102 			} else if (returnType.equals(byte[][].class)) {
    103 				// method for Java <= 1.5
    104 				int naddrs = addresses.length;
    105 				byte [][] byteAddresses = new byte[naddrs][];
    106 				byte [] addr;
    107 				for (int i = 0; i < naddrs; i++) {
    108 					addr = addresses[i].getAddress();
    109 					byteAddresses[i] = addr;
    110 				}
    111 				return byteAddresses;
    112 			}
    113 		}
    114 	} catch (Throwable e) {
    115 		System.err.println("DNSJavaNameService: Unexpected error.");
    116 		e.printStackTrace();
    117 		throw e;
    118 	}
    119 	throw new IllegalArgumentException(
    120 					"Unknown function name or arguments.");
    121 }
    122 
    123 /**
    124  * Performs a forward DNS lookup for the host name.
    125  * @param host The host name to resolve.
    126  * @return All the ip addresses found for the host name.
    127  */
    128 public InetAddress []
    129 lookupAllHostAddr(String host) throws UnknownHostException {
    130 	Name name = null;
    131 
    132 	try {
    133 		name = new Name(host);
    134 	}
    135 	catch (TextParseException e) {
    136 		throw new UnknownHostException(host);
    137 	}
    138 
    139 	Record [] records = null;
    140 	if (preferV6)
    141 		records = new Lookup(name, Type.AAAA).run();
    142 	if (records == null)
    143 		records = new Lookup(name, Type.A).run();
    144 	if (records == null && !preferV6)
    145 		records = new Lookup(name, Type.AAAA).run();
    146 	if (records == null)
    147 		throw new UnknownHostException(host);
    148 
    149 	InetAddress[] array = new InetAddress[records.length];
    150 	for (int i = 0; i < records.length; i++) {
    151 		Record record = records[i];
    152 		if (records[i] instanceof ARecord) {
    153 			ARecord a = (ARecord) records[i];
    154 			array[i] = a.getAddress();
    155 		} else {
    156 			AAAARecord aaaa = (AAAARecord) records[i];
    157 			array[i] = aaaa.getAddress();
    158 		}
    159 	}
    160 	return array;
    161 }
    162 
    163 /**
    164  * Performs a reverse DNS lookup.
    165  * @param addr The ip address to lookup.
    166  * @return The host name found for the ip address.
    167  */
    168 public String
    169 getHostByAddr(byte [] addr) throws UnknownHostException {
    170 	Name name = ReverseMap.fromAddress(InetAddress.getByAddress(addr));
    171 	Record [] records = new Lookup(name, Type.PTR).run();
    172 	if (records == null)
    173 		throw new UnknownHostException();
    174 	return ((PTRRecord) records[0]).getTarget().toString();
    175 }
    176 }
    177