blob: 14d8adb6a2a3191578fc35ca01b4cfe1a9931de6 [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001// Copyright (c) 2005 Brian Wellington (bwelling@xbill.org)
2
3package org.xbill.DNS.spi;
4
5import java.lang.reflect.InvocationHandler;
6import java.lang.reflect.Method;
7import java.net.InetAddress;
8import java.net.UnknownHostException;
9import java.util.StringTokenizer;
10
11import org.xbill.DNS.AAAARecord;
12import org.xbill.DNS.ARecord;
13import org.xbill.DNS.ExtendedResolver;
14import org.xbill.DNS.Lookup;
15import org.xbill.DNS.Name;
16import org.xbill.DNS.PTRRecord;
17import org.xbill.DNS.Record;
18import org.xbill.DNS.Resolver;
19import org.xbill.DNS.ReverseMap;
20import org.xbill.DNS.TextParseException;
21import 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
37public class DNSJavaNameService implements InvocationHandler {
38
39private static final String nsProperty = "sun.net.spi.nameservice.nameservers";
40private static final String domainProperty = "sun.net.spi.nameservice.domain";
41private static final String v6Property = "java.net.preferIPv6Addresses";
42
43private 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 */
53protected
54DNSJavaNameService() {
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
90public Object
91invoke(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 */
128public InetAddress []
129lookupAllHostAddr(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 */
168public String
169getHostByAddr(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}