1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Copyright (c) 2002-2004 Brian Wellington (bwelling@xbill.org)
2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.xbill.DNS;
4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.*;
6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.*;
7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.net.*;
8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The Lookup object issues queries to caching DNS servers.  The input consists
11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * of a name, an optional type, and an optional class.  Caching is enabled
12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * by default and used when possible to reduce the number of DNS requests.
13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A Resolver, which defaults to an ExtendedResolver initialized with the
14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * resolvers located by the ResolverConfig class, performs the queries.  A
15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * search path of domain suffixes is used to resolve relative names, and is
16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * also determined by the ResolverConfig class.
17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A Lookup object may be reused, but should not be used by multiple threads.
19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Cache
21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Resolver
22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see ResolverConfig
23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Brian Wellington
25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic final class Lookup {
28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static Resolver defaultResolver;
30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static Name [] defaultSearchPath;
31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static Map defaultCaches;
32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static int defaultNdots;
33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate Resolver resolver;
35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate Name [] searchPath;
36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate Cache cache;
37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean temporary_cache;
38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int credibility;
39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate Name name;
40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int type;
41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int dclass;
42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean verbose;
43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int iterations;
44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean foundAlias;
45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean done;
46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean doneCurrent;
47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate List aliases;
48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate Record [] answers;
49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int result;
50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate String error;
51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean nxdomain;
52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean badresponse;
53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate String badresponse_error;
54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean networkerror;
55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean timedout;
56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean nametoolong;
57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean referral;
58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final Name [] noAliases = new Name[0];
60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** The lookup was successful. */
62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int SUCCESSFUL = 0;
63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The lookup failed due to a data or server error. Repeating the lookup
66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * would not be helpful.
67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int UNRECOVERABLE = 1;
69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The lookup failed due to a network error. Repeating the lookup may be
72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * helpful.
73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int TRY_AGAIN = 2;
75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** The host does not exist. */
77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int HOST_NOT_FOUND = 3;
78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** The host exists, but has no records associated with the queried type. */
80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int TYPE_NOT_FOUND = 4;
81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static synchronized void
83d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrefreshDefault() {
84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	try {
86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		defaultResolver = new ExtendedResolver();
87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	catch (UnknownHostException e) {
89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new RuntimeException("Failed to initialize resolver");
90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	defaultSearchPath = ResolverConfig.getCurrentConfig().searchPath();
92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	defaultCaches = new HashMap();
93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	defaultNdots = ResolverConfig.getCurrentConfig().ndots();
94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic {
97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	refreshDefault();
98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the Resolver that will be used as the default by future Lookups.
102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The default resolver.
103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static synchronized Resolver
105d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetDefaultResolver() {
106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return defaultResolver;
107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the default Resolver to be used as the default by future Lookups.
111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param resolver The default resolver.
112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static synchronized void
114d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetDefaultResolver(Resolver resolver) {
115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	defaultResolver = resolver;
116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the Cache that will be used as the default for the specified
120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * class by future Lookups.
121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The class whose cache is being retrieved.
122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The default cache for the specified class.
123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static synchronized Cache
125d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetDefaultCache(int dclass) {
126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	DClass.check(dclass);
127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Cache c = (Cache) defaultCaches.get(Mnemonic.toInteger(dclass));
128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (c == null) {
129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		c = new Cache(dclass);
130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		defaultCaches.put(Mnemonic.toInteger(dclass), c);
131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return c;
133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the Cache to be used as the default for the specified class by future
137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Lookups.
138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param cache The default cache for the specified class.
139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The class whose cache is being set.
140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static synchronized void
142d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetDefaultCache(Cache cache, int dclass) {
143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	DClass.check(dclass);
144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	defaultCaches.put(Mnemonic.toInteger(dclass), cache);
145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the search path that will be used as the default by future Lookups.
149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The default search path.
150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static synchronized Name []
152d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetDefaultSearchPath() {
153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return defaultSearchPath;
154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the search path to be used as the default by future Lookups.
158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param domains The default search path.
159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static synchronized void
161d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetDefaultSearchPath(Name [] domains) {
162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	defaultSearchPath = domains;
163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the search path that will be used as the default by future Lookups.
167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param domains The default search path.
168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException A name in the array is not a valid DNS name.
169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static synchronized void
171d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetDefaultSearchPath(String [] domains) throws TextParseException {
172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (domains == null) {
173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		defaultSearchPath = null;
174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return;
175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Name [] newdomains = new Name[domains.length];
177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = 0; i < domains.length; i++)
178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		newdomains[i] = Name.fromString(domains[i], Name.root);
179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	defaultSearchPath = newdomains;
180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate final void
183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenreset() {
184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	iterations = 0;
185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	foundAlias = false;
186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	done = false;
187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	doneCurrent = false;
188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	aliases = null;
189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	answers = null;
190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	result = -1;
191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	error = null;
192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	nxdomain = false;
193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	badresponse = false;
194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	badresponse_error = null;
195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	networkerror = false;
196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	timedout = false;
197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	nametoolong = false;
198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	referral = false;
199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (temporary_cache)
200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		cache.clearCache();
201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Create a Lookup object that will find records of the given name, type,
205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and class.  The lookup will use the default cache, resolver, and search
206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * path, and look for records that are reasonably credible.
207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The name of the desired records
208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The type of the desired records
209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The class of the desired records
210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IllegalArgumentException The type is a meta type other than ANY.
211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Cache
212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Resolver
213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Credibility
214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Name
215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Type
216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see DClass
217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic
219d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenLookup(Name name, int type, int dclass) {
220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Type.check(type);
221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	DClass.check(dclass);
222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!Type.isRR(type) && type != Type.ANY)
223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("Cannot query for " +
224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						   "meta-types other than ANY");
225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.name = name;
226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.type = type;
227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.dclass = dclass;
228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	synchronized (Lookup.class) {
229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.resolver = getDefaultResolver();
230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.searchPath = getDefaultSearchPath();
231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.cache = getDefaultCache(dclass);
232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.credibility = Credibility.NORMAL;
234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.verbose = Options.check("verbose");
235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.result = -1;
236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Create a Lookup object that will find records of the given name and type
240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * in the IN class.
241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The name of the desired records
242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The type of the desired records
243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IllegalArgumentException The type is a meta type other than ANY.
244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see #Lookup(Name,int,int)
245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic
247d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenLookup(Name name, int type) {
248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this(name, type, DClass.IN);
249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Create a Lookup object that will find records of type A at the given name
253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * in the IN class.
254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The name of the desired records
255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see #Lookup(Name,int,int)
256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic
258d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenLookup(Name name) {
259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this(name, Type.A, DClass.IN);
260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Create a Lookup object that will find records of the given name, type,
264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and class.
265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The name of the desired records
266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The type of the desired records
267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The class of the desired records
268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The name is not a valid DNS name
269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IllegalArgumentException The type is a meta type other than ANY.
270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see #Lookup(Name,int,int)
271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic
273d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenLookup(String name, int type, int dclass) throws TextParseException {
274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this(Name.fromString(name), type, dclass);
275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Create a Lookup object that will find records of the given name and type
279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * in the IN class.
280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The name of the desired records
281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The type of the desired records
282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The name is not a valid DNS name
283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IllegalArgumentException The type is a meta type other than ANY.
284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see #Lookup(Name,int,int)
285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic
287d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenLookup(String name, int type) throws TextParseException {
288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this(Name.fromString(name), type, DClass.IN);
289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Create a Lookup object that will find records of type A at the given name
293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * in the IN class.
294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The name of the desired records
295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException The name is not a valid DNS name
296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see #Lookup(Name,int,int)
297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic
299d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenLookup(String name) throws TextParseException {
300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this(Name.fromString(name), Type.A, DClass.IN);
301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the resolver to use when performing this lookup.  This overrides the
305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * default value.
306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param resolver The resolver to use.
307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void
309d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetResolver(Resolver resolver) {
310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.resolver = resolver;
311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the search path to use when performing this lookup.  This overrides the
315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * default value.
316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param domains An array of names containing the search path.
317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void
319d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetSearchPath(Name [] domains) {
320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.searchPath = domains;
321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the search path to use when performing this lookup. This overrides the
325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * default value.
326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param domains An array of names containing the search path.
327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws TextParseException A name in the array is not a valid DNS name.
328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void
330d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetSearchPath(String [] domains) throws TextParseException {
331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (domains == null) {
332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.searchPath = null;
333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return;
334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Name [] newdomains = new Name[domains.length];
336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = 0; i < domains.length; i++)
337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		newdomains[i] = Name.fromString(domains[i], Name.root);
338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.searchPath = newdomains;
339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the cache to use when performing this lookup.  This overrides the
343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * default value.  If the results of this lookup should not be permanently
344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * cached, null can be provided here.
345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param cache The cache to use.
346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void
348d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetCache(Cache cache) {
349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (cache == null) {
350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.cache = new Cache(dclass);
351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.temporary_cache = true;
352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} else {
353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.cache = cache;
354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.temporary_cache = false;
355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets ndots to use when performing this lookup, overriding the default value.
360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Specifically, this refers to the number of "dots" which, if present in a
361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * name, indicate that a lookup for the absolute name should be attempted
362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * before appending any search path elements.
363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ndots The ndots value to use, which must be greater than or equal to
364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 0.
365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void
367d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetNdots(int ndots) {
368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (ndots < 0)
369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("Illegal ndots value: " +
370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						   ndots);
371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	defaultNdots = ndots;
372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the minimum credibility level that will be accepted when performing
376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the lookup.  This defaults to Credibility.NORMAL.
377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param credibility The minimum credibility level.
378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void
380d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetCredibility(int credibility) {
381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.credibility = credibility;
382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void
385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenfollow(Name name, Name oldname) {
386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	foundAlias = true;
387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	badresponse = false;
388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	networkerror = false;
389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	timedout = false;
390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	nxdomain = false;
391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	referral = false;
392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	iterations++;
393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (iterations >= 6 || name.equals(oldname)) {
394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		result = UNRECOVERABLE;
395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		error = "CNAME loop";
396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		done = true;
397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return;
398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (aliases == null)
400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		aliases = new ArrayList();
401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	aliases.add(oldname);
402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	lookup(name);
403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void
406d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenprocessResponse(Name name, SetResponse response) {
407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (response.isSuccessful()) {
408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		RRset [] rrsets = response.answers();
409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		List l = new ArrayList();
410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Iterator it;
411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int i;
412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		for (i = 0; i < rrsets.length; i++) {
414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			it = rrsets[i].rrs();
415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			while (it.hasNext())
416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				l.add(it.next());
417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		result = SUCCESSFUL;
420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		answers = (Record []) l.toArray(new Record[l.size()]);
421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		done = true;
422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} else if (response.isNXDOMAIN()) {
423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		nxdomain = true;
424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		doneCurrent = true;
425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (iterations > 0) {
426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			result = HOST_NOT_FOUND;
427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			done = true;
428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} else if (response.isNXRRSET()) {
430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		result = TYPE_NOT_FOUND;
431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		answers = null;
432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		done = true;
433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} else if (response.isCNAME()) {
434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		CNAMERecord cname = response.getCNAME();
435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		follow(cname.getTarget(), name);
436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} else if (response.isDNAME()) {
437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		DNAMERecord dname = response.getDNAME();
438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		try {
439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			follow(name.fromDNAME(dname), name);
440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} catch (NameTooLongException e) {
441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			result = UNRECOVERABLE;
442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			error = "Invalid DNAME target";
443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			done = true;
444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} else if (response.isDelegation()) {
446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		// We shouldn't get a referral.  Ignore it.
447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		referral = true;
448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void
452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenlookup(Name current) {
453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	SetResponse sr = cache.lookupRecords(current, type, credibility);
454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (verbose) {
455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		System.err.println("lookup " + current + " " +
456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				   Type.string(type));
457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		System.err.println(sr);
458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	processResponse(current, sr);
460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (done || doneCurrent)
461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return;
462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Record question = Record.newRecord(current, type, dclass);
464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Message query = Message.newQuery(question);
465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Message response = null;
466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	try {
467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		response = resolver.send(query);
468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	catch (IOException e) {
470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		// A network error occurred.  Press on.
471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (e instanceof InterruptedIOException)
472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			timedout = true;
473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		else
474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			networkerror = true;
475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return;
476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int rcode = response.getHeader().getRcode();
478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (rcode != Rcode.NOERROR && rcode != Rcode.NXDOMAIN) {
479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		// The server we contacted is broken or otherwise unhelpful.
480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		// Press on.
481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		badresponse = true;
482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		badresponse_error = Rcode.string(rcode);
483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return;
484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!query.getQuestion().equals(response.getQuestion())) {
487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		// The answer doesn't match the question.  That's not good.
488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		badresponse = true;
489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		badresponse_error = "response does not match query";
490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return;
491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	sr = cache.addMessage(response);
494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (sr == null)
495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sr = cache.lookupRecords(current, type, credibility);
496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (verbose) {
497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		System.err.println("queried " + current + " " +
498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				   Type.string(type));
499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		System.err.println(sr);
500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	processResponse(current, sr);
502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void
505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenresolve(Name current, Name suffix) {
506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	doneCurrent = false;
507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Name tname = null;
508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (suffix == null)
509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		tname = current;
510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	else {
511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		try {
512d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			tname = Name.concatenate(current, suffix);
513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		catch (NameTooLongException e) {
515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			nametoolong = true;
516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return;
517d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	lookup(tname);
520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
521d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
522d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Performs the lookup, using the specified Cache, Resolver, and search path.
524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The answers, or null if none are found.
525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
526d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Record []
527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenrun() {
528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (done)
529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		reset();
530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (name.isAbsolute())
531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		resolve(name, null);
532d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	else if (searchPath == null)
533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		resolve(name, Name.root);
534d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	else {
535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (name.labels() > defaultNdots)
536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			resolve(name, Name.root);
537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (done)
538d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return answers;
539d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		for (int i = 0; i < searchPath.length; i++) {
541d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			resolve(name, searchPath[i]);
542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (done)
543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return answers;
544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			else if (foundAlias)
545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				break;
546d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!done) {
549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (badresponse) {
550d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			result = TRY_AGAIN;
551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			error = badresponse_error;
552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			done = true;
553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else if (timedout) {
554d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			result = TRY_AGAIN;
555d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			error = "timed out";
556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			done = true;
557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else if (networkerror) {
558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			result = TRY_AGAIN;
559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			error = "network error";
560d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			done = true;
561d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else if (nxdomain) {
562d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			result = HOST_NOT_FOUND;
563d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			done = true;
564d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else if (referral) {
565d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			result = UNRECOVERABLE;
566d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			error = "referral";
567d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			done = true;
568d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else if (nametoolong) {
569d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			result = UNRECOVERABLE;
570d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			error = "name too long";
571d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			done = true;
572d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
573d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
574d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return answers;
575d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
576d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
577d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void
578d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencheckDone() {
579d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (done && result != -1)
580d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return;
581d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	StringBuffer sb = new StringBuffer("Lookup of " + name + " ");
582d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (dclass != DClass.IN)
583d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append(DClass.string(dclass) + " ");
584d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	sb.append(Type.string(type) + " isn't done");
585d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	throw new IllegalStateException(sb.toString());
586d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
587d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
588d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
589d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the answers from the lookup.
590d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The answers, or null if none are found.
591d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IllegalStateException The lookup has not completed.
592d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
593d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Record []
594d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetAnswers() {
595d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	checkDone();
596d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return answers;
597d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
598d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
599d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
600d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns all known aliases for this name.  Whenever a CNAME/DNAME is
601d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * followed, an alias is added to this array.  The last element in this
602d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * array will be the owner name for records in the answer, if there are any.
603d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The aliases.
604d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IllegalStateException The lookup has not completed.
605d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
606d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Name []
607d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetAliases() {
608d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	checkDone();
609d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (aliases == null)
610d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return noAliases;
611d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return (Name []) aliases.toArray(new Name[aliases.size()]);
612d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
613d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
614d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
615d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the result code of the lookup.
616d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The result code, which can be SUCCESSFUL, UNRECOVERABLE, TRY_AGAIN,
617d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * HOST_NOT_FOUND, or TYPE_NOT_FOUND.
618d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IllegalStateException The lookup has not completed.
619d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
620d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int
621d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetResult() {
622d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	checkDone();
623d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return result;
624d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
625d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
626d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
627d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns an error string describing the result code of this lookup.
628d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return A string, which may either directly correspond the result code
629d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * or be more specific.
630d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IllegalStateException The lookup has not completed.
631d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
632d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic String
633d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetErrorString() {
634d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	checkDone();
635d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (error != null)
636d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return error;
637d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	switch (result) {
638d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		case SUCCESSFUL:	return "successful";
639d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		case UNRECOVERABLE:	return "unrecoverable error";
640d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		case TRY_AGAIN:		return "try again";
641d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		case HOST_NOT_FOUND:	return "host not found";
642d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		case TYPE_NOT_FOUND:	return "type not found";
643d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
644d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	throw new IllegalStateException("unknown result");
645d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
646d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
647d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
648