• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2005 Brian Wellington (bwelling@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@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
DNSJavaNameService()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
invoke(Object proxy, Method method, Object[] args)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 []
lookupAllHostAddr(String host)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
getHostByAddr(byte [] addr)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