1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Copyright (c) 1999-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 * An implementation of Resolver that sends one query to one server. 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * SimpleResolver handles TCP retries, transaction security (TSIG), and 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * EDNS 0. 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Resolver 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see TSIG 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see OPTRecord 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Brian Wellington 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class SimpleResolver implements Resolver { 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** The default port to send queries to */ 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int DEFAULT_PORT = 53; 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** The default EDNS payload size */ 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int DEFAULT_EDNS_PAYLOADSIZE = 1280; 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate InetSocketAddress address; 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate InetSocketAddress localAddress; 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean useTCP, ignoreTruncation; 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate OPTRecord queryOPT; 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate TSIG tsig; 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate long timeoutValue = 10 * 1000; 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final short DEFAULT_UDPSIZE = 512; 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static String defaultResolver = "localhost"; 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static int uniqueID = 0; 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a SimpleResolver that will query the specified host 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @exception UnknownHostException Failure occurred while finding the host 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenSimpleResolver(String hostname) throws UnknownHostException { 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (hostname == null) { 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen hostname = ResolverConfig.getCurrentConfig().server(); 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (hostname == null) 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen hostname = defaultResolver; 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen InetAddress addr; 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (hostname.equals("0")) 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen addr = InetAddress.getLocalHost(); 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen addr = InetAddress.getByName(hostname); 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen address = new InetSocketAddress(addr, DEFAULT_PORT); 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a SimpleResolver. The host to query is either found by using 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * ResolverConfig, or the default host is used. 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see ResolverConfig 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @exception UnknownHostException Failure occurred while finding the host 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenSimpleResolver() throws UnknownHostException { 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this(null); 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Gets the destination address associated with this SimpleResolver. 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Messages sent using this SimpleResolver will be sent to this address. 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The destination address associated with this SimpleResolver. 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenInetSocketAddress 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetAddress() { 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return address; 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Sets the default host (initially localhost) to query */ 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static void 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetDefaultResolver(String hostname) { 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen defaultResolver = hostname; 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetPort(int port) { 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen address = new InetSocketAddress(address.getAddress(), port); 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the address of the server to communicate with. 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addr The address of the DNS server 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetAddress(InetSocketAddress addr) { 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen address = addr; 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the address of the server to communicate with (on the default 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * DNS port) 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addr The address of the DNS server 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetAddress(InetAddress addr) { 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen address = new InetSocketAddress(addr, address.getPort()); 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the local address to bind to when sending messages. 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addr The local address to send messages from. 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetLocalAddress(InetSocketAddress addr) { 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen localAddress = addr; 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the local address to bind to when sending messages. A random port 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * will be used. 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addr The local address to send messages from. 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetLocalAddress(InetAddress addr) { 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen localAddress = new InetSocketAddress(addr, 0); 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetTCP(boolean flag) { 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.useTCP = flag; 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetIgnoreTruncation(boolean flag) { 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.ignoreTruncation = flag; 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetEDNS(int level, int payloadSize, int flags, List options) { 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (level != 0 && level != -1) 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException("invalid EDNS level - " + 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "must be 0 or -1"); 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (payloadSize == 0) 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen payloadSize = DEFAULT_EDNS_PAYLOADSIZE; 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen queryOPT = new OPTRecord(payloadSize, 0, level, flags, options); 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetEDNS(int level) { 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setEDNS(level, 0, 0, null); 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetTSIGKey(TSIG key) { 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen tsig = key; 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenTSIG 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetTSIGKey() { 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return tsig; 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetTimeout(int secs, int msecs) { 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen timeoutValue = (long)secs * 1000 + msecs; 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetTimeout(int secs) { 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen setTimeout(secs, 0); 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenlong 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetTimeout() { 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return timeoutValue; 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate Message 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenparseMessage(byte [] b) throws WireParseException { 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (new Message(b)); 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (IOException e) { 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (Options.check("verbose")) 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!(e instanceof WireParseException)) 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e = new WireParseException("Error parsing message"); 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw (WireParseException) e; 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenverifyTSIG(Message query, Message response, byte [] b, TSIG tsig) { 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (tsig == null) 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int error = tsig.verify(response, b, query.getTSIG()); 199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (Options.check("verbose")) 200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.err.println("TSIG verify: " + Rcode.TSIGstring(error)); 201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void 204d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenapplyEDNS(Message query) { 205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (queryOPT == null || query.getOPT() != null) 206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return; 207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen query.addRecord(queryOPT, Section.ADDITIONAL); 208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int 211d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenmaxUDPSize(Message query) { 212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen OPTRecord opt = query.getOPT(); 213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (opt == null) 214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return DEFAULT_UDPSIZE; 215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return opt.getPayloadSize(); 217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sends a message to a single server and waits for a response. No checking 221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is done to ensure that the response is associated with the query. 222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param query The query to send. 223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The response. 224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException An error occurred while sending or receiving. 225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Message 227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chensend(Message query) throws IOException { 228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (Options.check("verbose")) 229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.err.println("Sending to " + 230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen address.getAddress().getHostAddress() + 231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ":" + address.getPort()); 232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (query.getHeader().getOpcode() == Opcode.QUERY) { 234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record question = query.getQuestion(); 235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (question != null && question.getType() == Type.AXFR) 236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return sendAXFR(query); 237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen query = (Message) query.clone(); 240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen applyEDNS(query); 241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (tsig != null) 242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen tsig.apply(query, null); 243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] out = query.toWire(Message.MAXLENGTH); 245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int udpSize = maxUDPSize(query); 246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean tcp = false; 247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen long endTime = System.currentTimeMillis() + timeoutValue; 248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen do { 249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] in; 250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (useTCP || out.length > udpSize) 252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen tcp = true; 253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (tcp) 254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen in = TCPClient.sendrecv(localAddress, address, out, 255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen endTime); 256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen in = UDPClient.sendrecv(localAddress, address, out, 258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen udpSize, endTime); 259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* 261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Check that the response is long enough. 262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (in.length < Header.LENGTH) { 264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new WireParseException("invalid DNS header - " + 265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "too short"); 266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /* 268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Check that the response ID matches the query ID. We want 269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to check this before actually parsing the message, so that 270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * if there's a malformed response that's not ours, it 271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * doesn't confuse us. 272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int id = ((in[0] & 0xFF) << 8) + (in[1] & 0xFF); 274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int qid = query.getHeader().getID(); 275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (id != qid) { 276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String error = "invalid message id: expected " + qid + 277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "; got id " + id; 278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (tcp) { 279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new WireParseException(error); 280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (Options.check("verbose")) { 282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.err.println(error); 283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen continue; 285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message response = parseMessage(in); 288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen verifyTSIG(query, response, in, tsig); 289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!tcp && !ignoreTruncation && 290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.getHeader().getFlag(Flags.TC)) 291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen tcp = true; 293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen continue; 294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return response; 296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } while (true); 297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Asynchronously sends a message to a single server, registering a listener 301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to receive a callback on success or exception. Multiple asynchronous 302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * lookups can be performed in parallel. Since the callback may be invoked 303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * before the function returns, external synchronization is necessary. 304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param query The query to send 305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param listener The object containing the callbacks. 306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return An identifier, which is also a parameter in the callback 307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Object 309d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensendAsync(final Message query, final ResolverListener listener) { 310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen final Object id; 311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen synchronized (this) { 312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen id = new Integer(uniqueID++); 313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record question = query.getQuestion(); 315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String qname; 316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (question != null) 317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen qname = question.getName().toString(); 318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen qname = "(none)"; 320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String name = this.getClass() + ": " + qname; 321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Thread thread = new ResolveThread(this, query, id, listener); 322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen thread.setName(name); 323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen thread.setDaemon(true); 324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen thread.start(); 325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return id; 326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate Message 329d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensendAXFR(Message query) throws IOException { 330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Name qname = query.getQuestion().getName(); 331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ZoneTransferIn xfrin = ZoneTransferIn.newAXFR(qname, address, tsig); 332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen xfrin.setTimeout((int)(getTimeout() / 1000)); 333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen xfrin.setLocalAddress(localAddress); 334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen xfrin.run(); 336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (ZoneTransferException e) { 338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new WireParseException(e.getMessage()); 339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List records = xfrin.getAXFR(); 341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message response = new Message(query.getHeader().getID()); 342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.getHeader().setFlag(Flags.AA); 343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.getHeader().setFlag(Flags.QR); 344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.addRecord(query.getQuestion(), Section.QUESTION); 345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Iterator it = records.iterator(); 346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (it.hasNext()) 347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.addRecord((Record)it.next(), Section.ANSWER); 348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return response; 349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 352