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