Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add basic alternative DNS library (and drop xbill)

  • Loading branch information...
commit b6854f595657ca99ca40047c4c6668f50661c1f1 1 parent a042df2
Rene Treffer authored
Showing with 1,362 additions and 21,321 deletions.
  1. +37 −32 src/com/googlecode/asmack/connection/impl/XmppConnection.java
  2. +160 −0 src/com/googlecode/asmack/dns/Client.java
  3. +507 −0 src/com/googlecode/asmack/dns/DNSMessage.java
  4. +62 −0 src/com/googlecode/asmack/dns/Question.java
  5. +293 −0 src/com/googlecode/asmack/dns/Record.java
  6. +37 −0 src/com/googlecode/asmack/dns/record/A.java
  7. +43 −0 src/com/googlecode/asmack/dns/record/AAAA.java
  8. +44 −0 src/com/googlecode/asmack/dns/record/CNAME.java
  9. +16 −0 src/com/googlecode/asmack/dns/record/Data.java
  10. +12 −0 src/com/googlecode/asmack/dns/record/NS.java
  11. +74 −0 src/com/googlecode/asmack/dns/record/SRV.java
  12. +77 −0 src/com/googlecode/asmack/dns/util/NameUtil.java
  13. +0 −127 src/org/xbill/DNS/A6Record.java
  14. +0 −66 src/org/xbill/DNS/AAAARecord.java
  15. +0 −46 src/org/xbill/DNS/AFSDBRecord.java
  16. +0 −287 src/org/xbill/DNS/APLRecord.java
  17. +0 −89 src/org/xbill/DNS/ARecord.java
  18. +0 −372 src/org/xbill/DNS/Address.java
  19. +0 −224 src/org/xbill/DNS/CERTRecord.java
  20. +0 −45 src/org/xbill/DNS/CNAMERecord.java
  21. +0 −848 src/org/xbill/DNS/Cache.java
  22. +0 −58 src/org/xbill/DNS/Client.java
  23. +0 −72 src/org/xbill/DNS/Compression.java
  24. +0 −50 src/org/xbill/DNS/Credibility.java
  25. +0 −92 src/org/xbill/DNS/DClass.java
  26. +0 −65 src/org/xbill/DNS/DHCIDRecord.java
  27. +0 −132 src/org/xbill/DNS/DLVRecord.java
  28. +0 −45 src/org/xbill/DNS/DNAMERecord.java
  29. +0 −216 src/org/xbill/DNS/DNSInput.java
  30. +0 −91 src/org/xbill/DNS/DNSKEYRecord.java
  31. +0 −188 src/org/xbill/DNS/DNSOutput.java
  32. +0 −795 src/org/xbill/DNS/DNSSEC.java
  33. +0 −155 src/org/xbill/DNS/DSRecord.java
  34. +0 −42 src/org/xbill/DNS/EmptyRecord.java
  35. +0 −45 src/org/xbill/DNS/ExtendedFlags.java
  36. +0 −419 src/org/xbill/DNS/ExtendedResolver.java
  37. +0 −81 src/org/xbill/DNS/Flags.java
  38. +0 −79 src/org/xbill/DNS/FormattedTime.java
  39. +0 −178 src/org/xbill/DNS/GPOSRecord.java
  40. +0 −264 src/org/xbill/DNS/Generator.java
  41. +0 −95 src/org/xbill/DNS/HINFORecord.java
  42. +0 −286 src/org/xbill/DNS/Header.java
  43. +0 −231 src/org/xbill/DNS/IPSECKEYRecord.java
  44. +0 −105 src/org/xbill/DNS/ISDNRecord.java
  45. +0 −18 src/org/xbill/DNS/InvalidDClassException.java
  46. +0 −18 src/org/xbill/DNS/InvalidTTLException.java
  47. +0 −18 src/org/xbill/DNS/InvalidTypeException.java
  48. +0 −161 src/org/xbill/DNS/KEYBase.java
  49. +0 −352 src/org/xbill/DNS/KEYRecord.java
  50. +0 −51 src/org/xbill/DNS/KXRecord.java
  51. +0 −314 src/org/xbill/DNS/LOCRecord.java
  52. +0 −629 src/org/xbill/DNS/Lookup.java
  53. +0 −42 src/org/xbill/DNS/MBRecord.java
  54. +0 −43 src/org/xbill/DNS/MDRecord.java
  55. +0 −43 src/org/xbill/DNS/MFRecord.java
  56. +0 −38 src/org/xbill/DNS/MGRecord.java
  57. +0 −90 src/org/xbill/DNS/MINFORecord.java
  58. +0 −38 src/org/xbill/DNS/MRRecord.java
  59. +0 −57 src/org/xbill/DNS/MXRecord.java
  60. +0 −427 src/org/xbill/DNS/Master.java
  61. +0 −607 src/org/xbill/DNS/Message.java
  62. +0 −210 src/org/xbill/DNS/Mnemonic.java
  63. +0 −154 src/org/xbill/DNS/NAPTRRecord.java
  64. +0 −106 src/org/xbill/DNS/NSAPRecord.java
  65. +0 −38 src/org/xbill/DNS/NSAP_PTRRecord.java
  66. +0 −165 src/org/xbill/DNS/NSEC3PARAMRecord.java
  67. +0 −266 src/org/xbill/DNS/NSEC3Record.java
  68. +0 −98 src/org/xbill/DNS/NSECRecord.java
  69. +0 −42 src/org/xbill/DNS/NSRecord.java
  70. +0 −67 src/org/xbill/DNS/NULLRecord.java
  71. +0 −111 src/org/xbill/DNS/NXTRecord.java
  72. +0 −822 src/org/xbill/DNS/Name.java
  73. +0 −24 src/org/xbill/DNS/NameTooLongException.java
  74. +0 −217 src/org/xbill/DNS/OPTRecord.java
  75. +0 −60 src/org/xbill/DNS/Opcode.java
  76. +0 −123 src/org/xbill/DNS/Options.java
  77. +0 −38 src/org/xbill/DNS/PTRRecord.java
  78. +0 −96 src/org/xbill/DNS/PXRecord.java
  79. +0 −82 src/org/xbill/DNS/RPRecord.java
  80. +0 −50 src/org/xbill/DNS/RRSIGRecord.java
  81. +0 −258 src/org/xbill/DNS/RRset.java
  82. +0 −48 src/org/xbill/DNS/RTRecord.java
  83. +0 −123 src/org/xbill/DNS/Rcode.java
  84. +0 −730 src/org/xbill/DNS/Record.java
  85. +0 −24 src/org/xbill/DNS/RelativeNameException.java
  86. +0 −45 src/org/xbill/DNS/ResolveThread.java
  87. +0 −95 src/org/xbill/DNS/Resolver.java
  88. +0 −456 src/org/xbill/DNS/ResolverConfig.java
  89. +0 −30 src/org/xbill/DNS/ResolverListener.java
  90. +0 −130 src/org/xbill/DNS/ReverseMap.java
  91. +0 −79 src/org/xbill/DNS/SIG0.java
  92. +0 −193 src/org/xbill/DNS/SIGBase.java
  93. +0 −50 src/org/xbill/DNS/SIGRecord.java
  94. +0 −162 src/org/xbill/DNS/SOARecord.java
  95. +0 −44 src/org/xbill/DNS/SPFRecord.java
  96. +0 −113 src/org/xbill/DNS/SRVRecord.java
  97. +0 −108 src/org/xbill/DNS/SSHFPRecord.java
  98. +0 −92 src/org/xbill/DNS/Section.java
  99. +0 −61 src/org/xbill/DNS/Serial.java
  100. +0 −202 src/org/xbill/DNS/SetResponse.java
  101. +0 −346 src/org/xbill/DNS/SimpleResolver.java
  102. +0 −31 src/org/xbill/DNS/SingleCompressedNameBase.java
  103. +0 −61 src/org/xbill/DNS/SingleNameBase.java
  104. +0 −132 src/org/xbill/DNS/TCPClient.java
  105. +0 −225 src/org/xbill/DNS/TKEYRecord.java
  106. +0 −539 src/org/xbill/DNS/TSIG.java
  107. +0 −220 src/org/xbill/DNS/TSIGRecord.java
  108. +0 −113 src/org/xbill/DNS/TTL.java
  109. +0 −123 src/org/xbill/DNS/TXTBase.java
  110. +0 −44 src/org/xbill/DNS/TXTRecord.java
  111. +0 −25 src/org/xbill/DNS/TextParseException.java
  112. +0 −713 src/org/xbill/DNS/Tokenizer.java
  113. +0 −356 src/org/xbill/DNS/Type.java
  114. +0 −146 src/org/xbill/DNS/TypeBitmap.java
  115. +0 −75 src/org/xbill/DNS/U16NameBase.java
  116. +0 −170 src/org/xbill/DNS/UDPClient.java
  117. +0 −54 src/org/xbill/DNS/UNKRecord.java
  118. +0 −300 src/org/xbill/DNS/Update.java
  119. +0 −719 src/org/xbill/DNS/WKSRecord.java
  120. +0 −25 src/org/xbill/DNS/WireParseException.java
  121. +0 −86 src/org/xbill/DNS/X25Record.java
  122. +0 −559 src/org/xbill/DNS/Zone.java
  123. +0 −23 src/org/xbill/DNS/ZoneTransferException.java
  124. +0 −583 src/org/xbill/DNS/ZoneTransferIn.java
  125. +0 −176 src/org/xbill/DNS/spi/DNSJavaNameService.java
  126. +0 −1  src/org/xbill/DNS/spi/services/sun.net.spi.nameservice.NameServiceDescriptor
  127. +0 −59 src/org/xbill/DNS/tests/primary.java
  128. +0 −109 src/org/xbill/DNS/tests/xfrin.java
  129. +0 −123 src/org/xbill/DNS/utils/HMAC.java
  130. +0 −73 src/org/xbill/DNS/utils/base16.java
  131. +0 −213 src/org/xbill/DNS/utils/base32.java
  132. +0 −145 src/org/xbill/DNS/utils/base64.java
  133. +0 −56 src/org/xbill/DNS/utils/hexdump.java
  134. +0 −4 src/org/xbill/DNS/windows/DNSServer.properties
  135. +0 −4 src/org/xbill/DNS/windows/DNSServer_de.properties
  136. +0 −4 src/org/xbill/DNS/windows/DNSServer_fr.properties
  137. +0 −4 src/org/xbill/DNS/windows/DNSServer_ja.properties
  138. +0 −4 src/org/xbill/DNS/windows/DNSServer_pl.properties
69 src/com/googlecode/asmack/connection/impl/XmppConnection.java
View
@@ -37,16 +37,23 @@
package com.googlecode.asmack.connection.impl;
-import org.xbill.DNS.Lookup;
-import org.xbill.DNS.Record;
-import org.xbill.DNS.SRVRecord;
-import org.xbill.DNS.TextParseException;
-import org.xbill.DNS.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import android.util.Log;
import com.googlecode.asmack.StanzaSink;
import com.googlecode.asmack.XMPPUtils;
import com.googlecode.asmack.XmppAccount;
import com.googlecode.asmack.XmppException;
+import com.googlecode.asmack.dns.Client;
+import com.googlecode.asmack.dns.DNSMessage;
+import com.googlecode.asmack.dns.Record;
+import com.googlecode.asmack.dns.Record.CLASS;
+import com.googlecode.asmack.dns.Record.TYPE;
+import com.googlecode.asmack.dns.record.SRV;
/**
* Xmpp compliant connection, resolving the XMPP server via DNS/SRV lookups.
@@ -90,39 +97,37 @@ public void connect(StanzaSink sink) throws XmppException {
* @return String[] A host/port pair.
*/
private static String[] resolveSRV(String domain) {
+ Client client = new Client();
+
+ DNSMessage reply = client.query(domain, TYPE.SRV, CLASS.IN);
+
+ if (reply == null) {
+ Log.w("XMPPConnection", "Resolving SRV " + domain + " failed");
+ return null;
+ }
+
String bestHost = null;
int bestPort = -1;
int bestPriority = Integer.MAX_VALUE;
int bestWeight = 0;
- Lookup lookup;
- try {
- lookup = new Lookup(domain, Type.SRV);
- Record recs[] = lookup.run();
- if (recs == null) {
- return null;
+
+ List<Record> list = new ArrayList<Record>();
+ list.addAll(Arrays.asList(reply.getAnswers()));
+ Collections.shuffle(list);
+ for (Record rec : list) {
+ SRV srv = (SRV)rec.getPayload();
+ int weight = (int) (srv.getWeight() * srv.getWeight() *
+ Math.random());
+ int priority = (int) (srv.getPriority() * srv.getPriority() *
+ Math.random());
+ if (priority < bestPriority && weight >= bestWeight) {
+ bestPriority = priority;
+ bestWeight = weight;
+ bestHost = srv.getName();
+ bestPort = srv.getPort();
}
- for (Record rec : recs) {
- SRVRecord record = (SRVRecord) rec;
- if (record != null && record.getTarget() != null) {
- int weight = (int) (record.getWeight() * record.getWeight() * Math.random());
- if (record.getPriority() < bestPriority) {
- bestPriority = record.getPriority();
- bestWeight = weight;
- bestHost = record.getTarget().toString();
- bestPort = record.getPort();
- } else if (record.getPriority() == bestPriority) {
- if (weight > bestWeight) {
- bestPriority = record.getPriority();
- bestWeight = weight;
- bestHost = record.getTarget().toString();
- bestPort = record.getPort();
- }
- }
- }
}
- } catch (TextParseException e) {
- } catch (NullPointerException e) {
- }
+
if (bestHost == null) {
return null;
}
160 src/com/googlecode/asmack/dns/Client.java
View
@@ -0,0 +1,160 @@
+package com.googlecode.asmack.dns;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.HashSet;
+import java.util.Random;
+
+import com.googlecode.asmack.dns.Record.CLASS;
+import com.googlecode.asmack.dns.Record.TYPE;
+
+/**
+ * A minimal DNS client for SRV/A/AAAA/NS and CNAME lookups, with IDN support.
+ * This circumvents the missing javax.naming package on android.
+ */
+public class Client {
+
+ /**
+ * The internal random class for sequence generation.
+ */
+ protected Random random;
+
+ /**
+ * Create a new DNS client.
+ */
+ public Client() {
+ try {
+ random = SecureRandom.getInstance("SHA1PRNG");
+ } catch (NoSuchAlgorithmException e1) {
+ random = new SecureRandom();
+ }
+ }
+
+ /**
+ * Query a nameserver for a single entry.
+ * @param name The DNS name to request.
+ * @param type The DNS type to request (SRV, A, AAAA, ...).
+ * @param clazz The class of the request (usually IN for Internet).
+ * @param host The DNS server host.
+ * @return
+ * @throws IOException On IO Errors.
+ */
+ public DNSMessage query(String name, TYPE type, CLASS clazz, String host)
+ throws IOException
+ {
+ Question q = new Question();
+ q.setClazz(clazz);
+ q.setType(type);
+ q.setName(name);
+ return query(q, host);
+ }
+
+ /**
+ * Query the system nameserver for a single entry.
+ * @param name The DNS name to request.
+ * @param type The DNS type to request (SRV, A, AAAA, ...).
+ * @param clazz The class of the request (usually IN for Internet).
+ * @return The DNSMessage reply or null.
+ */
+ public DNSMessage query(String name, TYPE type, CLASS clazz)
+ {
+ Question q = new Question();
+ q.setClazz(clazz);
+ q.setType(type);
+ q.setName(name);
+ return query(q);
+ }
+
+ /**
+ * Query a specific server for one entry.
+ * @param q The question section of the DNS query.
+ * @param host The dns server host.
+ * @throws IOException On IOErrors.
+ */
+ public DNSMessage query(Question q, String host) throws IOException {
+ DNSMessage message = new DNSMessage();
+ message.setQuestions(new Question[]{q});
+ message.setRecursionDesired(true);
+ message.setId(random.nextInt());
+ byte[] buf = message.toArray();
+ DatagramSocket socket = new DatagramSocket();
+ DatagramPacket packet = new DatagramPacket(
+ buf, buf.length, InetAddress.getByName(host), 53);
+ socket.setSoTimeout(5000);
+ socket.send(packet);
+ packet = new DatagramPacket(new byte[513], 513);
+ socket.receive(packet);
+ DNSMessage dnsMessage = DNSMessage.parse(packet.getData());
+ if (dnsMessage.getId() != message.getId()) {
+ return null;
+ }
+ return dnsMessage;
+ }
+
+ /**
+ * Query the system DNS server for one entry.
+ * @param q The question section of the DNS query.
+ */
+ public DNSMessage query(Question q) {
+ String dnsServer[] = findDNS();
+ for (String dns : dnsServer) {
+ try {
+ DNSMessage message = query(q, dns);
+ if (message == null) {
+ continue;
+ }
+ if (message.getResponseCode() !=
+ DNSMessage.RESPONSE_CODE.NO_ERROR) {
+ continue;
+ }
+ for (Record record: message.getAnswers()) {
+ if (record.isAnswer(q)) {
+ return message;
+ }
+ }
+ } catch (IOException ioe) {
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Retrieve a list of currently configured DNS servers.
+ * @return The server array.
+ */
+ public String[] findDNS() {
+ try {
+ Process process = Runtime.getRuntime().exec("getprop");
+ InputStream inputStream = process.getInputStream();
+ LineNumberReader lnr = new LineNumberReader(
+ new InputStreamReader(inputStream));
+ String line = null;
+ HashSet<String> server = new HashSet<String>(6);
+ while ((line = lnr.readLine()) != null) {
+ int split = line.indexOf("]: [");
+ if (split == -1) {
+ continue;
+ }
+ String property = line.substring(1, split);
+ String value = line.substring(split + 4, line.length() - 1);
+ if (property.endsWith(".dns") || property.endsWith(".dns1") ||
+ property.endsWith(".dns2")) {
+ server.add(value);
+ }
+ }
+ if (server.size() > 0) {
+ return server.toArray(new String[server.size()]);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
507 src/com/googlecode/asmack/dns/DNSMessage.java
View
@@ -0,0 +1,507 @@
+package com.googlecode.asmack.dns;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * A DNS message as defined by rfc1035. The message consists of a header and
+ * 4 sections: question, answer, nameserver and addition resource record
+ * section.
+ * A message can either be parsed ({@see #parse(byte[])}) or serialized
+ * ({@see #toArray()}).
+ */
+public class DNSMessage {
+
+ /**
+ * Possible DNS reply codes.
+ */
+ public static enum RESPONSE_CODE {
+ NO_ERROR(0), FORMAT_ERR(1), SERVER_FAIL(2), NX_DOMAIN(3),
+ NO_IMP(4), REFUSED(5), YXDOMAIN(6), YXRRSET(7),
+ NXRRSET(8), NOT_AUTH(9),NOT_ZONE(10);
+
+ /**
+ * Reverse lookup table for response codes.
+ */
+ private final static RESPONSE_CODE INVERSE_LUT[] = new RESPONSE_CODE[]{
+ NO_ERROR, FORMAT_ERR, SERVER_FAIL, NX_DOMAIN, NO_IMP,
+ REFUSED, YXDOMAIN, YXRRSET, NXRRSET, NOT_AUTH, NOT_ZONE,
+ null, null, null, null, null
+ };
+
+ /**
+ * The response code value.
+ */
+ private final byte value;
+
+ /**
+ * Create a new response code.
+ * @param value The response code value.
+ */
+ private RESPONSE_CODE(int value) {
+ this.value = (byte)value;
+ }
+
+ /**
+ * Retrieve the byte value of the response code.
+ * @return
+ */
+ public byte getValue() {
+ return (byte) value;
+ }
+
+ /**
+ * Retrieve the response code for a byte value.
+ * @param value The byte value.
+ * @return The symbolic response code or null.
+ * @throws IllegalArgumentException if the value is not in the range of
+ * 0..15.
+ */
+ public static RESPONSE_CODE getResponseCode(int value) {
+ if (value < 0 || value > 15) {
+ throw new IllegalArgumentException();
+ }
+ return INVERSE_LUT[value];
+ }
+
+ };
+
+ /**
+ * Symbolic DNS Opcode values.
+ */
+ public static enum OPCODE {
+ QUERY(0),
+ INVERSE_QUERY(1),
+ STATUS(2),
+ NOTIFY(4),
+ UPDATE(5);
+
+ /**
+ * Lookup table for for obcode reolution.
+ */
+ private final static OPCODE INVERSE_LUT[] = new OPCODE[]{
+ QUERY, INVERSE_QUERY, STATUS, null, NOTIFY, UPDATE, null,
+ null, null, null, null, null, null, null, null
+ };
+
+ /**
+ * The value of this opcode.
+ */
+ private final byte value;
+
+ /**
+ * Create a new opcode for a given byte value.
+ * @param value The byte value of the opcode.
+ */
+ private OPCODE(int value) {
+ this.value = (byte)value;
+ }
+
+ /**
+ * Retrieve the byte value of this opcode.
+ * @return The byte value of this opcode.
+ */
+ public byte getValue() {
+ return value;
+ }
+
+ /**
+ * Retrieve the symbolic name of an opcode byte.
+ * @param value The byte value of the opcode.
+ * @return The symbolic opcode or null.
+ * @throws IllegalArgumentException If the byte value is not in the
+ * range 0..15.
+ */
+ public static OPCODE getOpcode(int value) {
+ if (value < 0 || value > 15) {
+ throw new IllegalArgumentException();
+ }
+ return INVERSE_LUT[value];
+ }
+
+ };
+
+ /**
+ * The DNS message id.
+ */
+ protected int id;
+
+ /**
+ * The DNS message opcode.
+ */
+ protected OPCODE opcode;
+
+ /**
+ * The response code of this dns message.
+ */
+ protected RESPONSE_CODE responseCode;
+
+ /**
+ * True if this is a query.
+ */
+ protected boolean query;
+
+ /**
+ * True if this is a authorative response.
+ */
+ protected boolean authoritativeAnswer;
+
+ /**
+ * True on truncate, tcp should be used.
+ */
+ protected boolean truncated;
+
+ /**
+ * True if the server should recurse.
+ */
+ protected boolean recursionDesired;
+
+ /**
+ * True if recursion is possible.
+ */
+ protected boolean recursionAvailable;
+
+ /**
+ * True if the server regarded the response as authentic.
+ */
+ protected boolean authenticData;
+
+ /**
+ * True if the server should not check the replies.
+ */
+ protected boolean checkDisabled;
+
+ /**
+ * The question section content.
+ */
+ protected Question questions[];
+
+ /**
+ * The answers section content.
+ */
+ protected Record answers[];
+
+ /**
+ * The nameserver records.
+ */
+ protected Record nameserverRecords[];
+
+ /**
+ * Additional resousrce records.
+ */
+ protected Record additionalResourceRecords[];
+
+ /**
+ * Retrieve the current DNS message id.
+ * @return The current DNS message id.
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Set the current DNS message id.
+ * @param id The new DNS message id.
+ */
+ public void setId(int id) {
+ this.id = id & 0xffff;
+ }
+
+ /**
+ * Retrieve the query type (true or false;
+ * @return True if this DNS message is a query.
+ */
+ public boolean isQuery() {
+ return query;
+ }
+
+ /**
+ * Set the query status of this message.
+ * @param query The new query status.
+ */
+ public void setQuery(boolean query) {
+ this.query = query;
+ }
+
+ /**
+ * True if the DNS message is an authoritative answer.
+ * @return True if this an authoritative DNS message.
+ */
+ public boolean isAuthoritativeAnswer() {
+ return authoritativeAnswer;
+ }
+
+ /**
+ * Set the authoritative answer flag.
+ * @param authoritativeAnswer Tge new authoritative answer value.
+ */
+ public void setAuthoritativeAnswer(boolean authoritativeAnswer) {
+ this.authoritativeAnswer = authoritativeAnswer;
+ }
+
+ /**
+ * Retrieve the truncation status of this message. True means that the
+ * client should try a tcp lookup.
+ * @return True if this message was truncated.
+ */
+ public boolean isTruncated() {
+ return truncated;
+ }
+
+ /**
+ * Set the truncation bit on this DNS message.
+ * @param truncated The new truncated bit status.
+ */
+ public void setTruncated(boolean truncated) {
+ this.truncated = truncated;
+ }
+
+ /**
+ * Check if this message preferes recursion.
+ * @return True if recursion is desired.
+ */
+ public boolean isRecursionDesired() {
+ return recursionDesired;
+ }
+
+ /**
+ * Set the recursion desired flag on this message.
+ * @param recursionDesired The new recusrion setting.
+ */
+ public void setRecursionDesired(boolean recursionDesired) {
+ this.recursionDesired = recursionDesired;
+ }
+
+ /**
+ * Retrieve the recursion available flag of this DNS message.
+ * @return The recursion available flag of this message.
+ */
+ public boolean isRecursionAvailable() {
+ return recursionAvailable;
+ }
+
+ /**
+ * Set the recursion available flog from this DNS message.
+ * @param recursionAvailable The new recursion available status.
+ */
+ public void setRecursionAvailable(boolean recursionAvailable) {
+ this.recursionAvailable = recursionAvailable;
+ }
+
+ /**
+ * Retrieve the authentic data flag of this message.
+ * @return The authentic data flag.
+ */
+ public boolean isAuthenticData() {
+ return authenticData;
+ }
+
+ /**
+ * Set the authentic data flag on this DNS message.
+ * @param authenticData The new authentic data flag value.
+ */
+ public void setAuthenticData(boolean authenticData) {
+ this.authenticData = authenticData;
+ }
+
+ /**
+ * Check if checks are disabled.
+ * @return The status of the CheckDisabled flag.
+ */
+ public boolean isCheckDisabled() {
+ return checkDisabled;
+ }
+
+ /**
+ * Change the check status of this packet.
+ * @param checkDisabled
+ */
+ public void setCheckDisabled(boolean checkDisabled) {
+ this.checkDisabled = checkDisabled;
+ }
+
+ /**
+ * Generate a binary dns packet out of this message.
+ * @return byte[] the binary representation.
+ * @throws IOException Should never happen.
+ */
+ public byte[] toArray() throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
+ DataOutputStream dos = new DataOutputStream(baos);
+ int header = 0;
+ if (query) {
+ header += 1 << 15;
+ }
+ if (opcode != null) {
+ header += opcode.getValue() << 11;
+ }
+ if (authoritativeAnswer) {
+ header += 1 << 10;
+ }
+ if (truncated) {
+ header += 1 << 9;
+ }
+ if (recursionDesired) {
+ header += 1 << 8;
+ }
+ if (recursionAvailable) {
+ header += 1 << 7;
+ }
+ if (authenticData) {
+ header += 1 << 5;
+ }
+ if (checkDisabled) {
+ header += 1 << 4;
+ }
+ if (responseCode != null) {
+ header += responseCode.getValue();
+ }
+ dos.writeShort((short)id);
+ dos.writeShort((short)header);
+ if (questions == null) {
+ dos.writeShort(0);
+ } else {
+ dos.writeShort((short)questions.length);
+ }
+ if (answers == null) {
+ dos.writeShort(0);
+ } else {
+ dos.writeShort((short)answers.length);
+ }
+ if (nameserverRecords == null) {
+ dos.writeShort(0);
+ } else {
+ dos.writeShort((short)nameserverRecords.length);
+ }
+ if (additionalResourceRecords == null) {
+ dos.writeShort(0);
+ } else {
+ dos.writeShort((short)additionalResourceRecords.length);
+ }
+ for (Question question: questions) {
+ dos.write(question.toByteArray());
+ }
+ dos.flush();
+ return baos.toByteArray();
+ }
+
+ /**
+ * Build a DNS Message based on a binary DNS message.
+ * @param data The DNS message data.
+ * @return Parsed DNSMessage message.
+ * @throws IOException On read errors.
+ */
+ public static DNSMessage parse(byte data[]) throws IOException {
+ ByteArrayInputStream bis = new ByteArrayInputStream(data);
+ DataInputStream dis = new DataInputStream(bis);
+ DNSMessage message = new DNSMessage();
+ message.id = dis.readUnsignedShort();
+ int header = dis.readUnsignedShort();
+ message.query = ((header >> 15) & 1) == 0;
+ message.opcode = OPCODE.getOpcode((header >> 11) & 0xf);
+ message.authoritativeAnswer = ((header >> 10) & 1) == 1;
+ message.truncated = ((header >> 9) & 1) == 1;
+ message.recursionDesired = ((header >> 8) & 1) == 1;
+ message.recursionAvailable = ((header >> 7) & 1) == 1;
+ message.authenticData = ((header >> 5) & 1) == 1;
+ message.checkDisabled = ((header >> 4) & 1) == 1;
+ message.responseCode = RESPONSE_CODE.getResponseCode(header & 0xf);
+ int questionCount = dis.readUnsignedShort();
+ int answerCount = dis.readUnsignedShort();
+ int nameserverCount = dis.readUnsignedShort();
+ int additionalResourceRecordCount = dis.readUnsignedShort();
+ message.questions = new Question[questionCount];
+ while (questionCount-- > 0) {
+ Question q = new Question();
+ q.parse(dis, data);
+ message.questions[questionCount] = q;
+ }
+ message.answers = new Record[answerCount];
+ while (answerCount-- > 0) {
+ Record rr = new Record();
+ rr.parse(dis, data);
+ message.answers[answerCount] = rr;
+ }
+ message.nameserverRecords = new Record[nameserverCount];
+ while (nameserverCount-- > 0) {
+ Record rr = new Record();
+ rr.parse(dis, data);
+ message.nameserverRecords[nameserverCount] = rr;
+ }
+ message.additionalResourceRecords =
+ new Record[additionalResourceRecordCount];
+ while (additionalResourceRecordCount-- > 0) {
+ Record rr = new Record();
+ rr.parse(dis, data);
+ message.additionalResourceRecords[additionalResourceRecordCount] =
+ rr;
+ }
+ return message;
+ }
+
+ /**
+ * Set the question part of this message.
+ * @param questions The questions.
+ */
+ public void setQuestions(Question ... questions) {
+ this.questions = questions;
+ }
+
+ /**
+ * Retrieve the opcode of this message.
+ * @return The opcode of this message.
+ */
+ public OPCODE getOpcode() {
+ return opcode;
+ }
+
+ /**
+ * Retrieve the response code of this message.
+ * @return The response code.
+ */
+ public RESPONSE_CODE getResponseCode() {
+ return responseCode;
+ }
+
+ /**
+ * Retrieve the question section of this message.
+ * @return The DNS question section.
+ */
+ public Question[] getQuestions() {
+ return questions;
+ }
+
+ /**
+ * Retrieve the answer records of this DNS message.
+ * @return The answer section of this DNS message.
+ */
+ public Record[] getAnswers() {
+ return answers;
+ }
+
+ /**
+ * Retrieve the nameserver records of this DNS message.
+ * @return The nameserver section of this DNS message.
+ */
+ public Record[] getNameserverRecords() {
+ return nameserverRecords;
+ }
+
+ /**
+ * Retrieve the additional resource records attached to this DNS message.
+ * @return The additional resource record section of this DNS message.
+ */
+ public Record[] getAdditionalResourceRecords() {
+ return additionalResourceRecords;
+ }
+
+ public String toString() {
+ return "-- DNSMessage " + id + " --\n" +
+ Arrays.toString(answers);
+ }
+
+}
62 src/com/googlecode/asmack/dns/Question.java
View
@@ -0,0 +1,62 @@
+package com.googlecode.asmack.dns;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import com.googlecode.asmack.dns.Record.CLASS;
+import com.googlecode.asmack.dns.Record.TYPE;
+import com.googlecode.asmack.dns.util.NameUtil;
+
+public class Question {
+
+ private String name;
+
+ private TYPE type;
+
+ private CLASS clazz = CLASS.IN;
+
+ public TYPE getType() {
+ return type;
+ }
+
+ public void setType(TYPE type) {
+ this.type = type;
+ }
+
+ public CLASS getClazz() {
+ return clazz;
+ }
+
+ public void setClazz(CLASS clazz) {
+ this.clazz = clazz;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void parse(DataInputStream dis, byte[] data) throws IOException {
+ this.name = NameUtil.parse(dis, data);
+ this.type = TYPE.getType(dis.readUnsignedShort());
+ this.clazz = CLASS.getClass(dis.readUnsignedShort());
+ }
+
+ public byte[] toByteArray() throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
+ DataOutputStream dos = new DataOutputStream(baos);
+
+ dos.write(NameUtil.toByteArray(this.name));
+ dos.writeShort(type.getValue());
+ dos.writeShort(clazz.getValue());
+
+ dos.flush();
+ return baos.toByteArray();
+ }
+
+}
293 src/com/googlecode/asmack/dns/Record.java
View
@@ -0,0 +1,293 @@
+package com.googlecode.asmack.dns;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+
+import com.googlecode.asmack.dns.record.A;
+import com.googlecode.asmack.dns.record.AAAA;
+import com.googlecode.asmack.dns.record.CNAME;
+import com.googlecode.asmack.dns.record.Data;
+import com.googlecode.asmack.dns.record.NS;
+import com.googlecode.asmack.dns.record.SRV;
+import com.googlecode.asmack.dns.util.NameUtil;
+
+/**
+ * A generic DNS record.
+ */
+public class Record {
+
+ /**
+ * The record type.
+ * {@see http://www.iana.org/assignments/dns-parameters}
+ */
+ public static enum TYPE {
+ A(1),
+ NS(2),
+ MD(3),
+ MF(4),
+ CNAME(5),
+ SOA(6),
+ MB(7),
+ MG(8),
+ MR(9),
+ NULL(10),
+ WKS(11),
+ PTR(12),
+ HINFO(13),
+ MINFO(14),
+ MX(15),
+ TXT(16),
+ RP(17),
+ AFSDB(18),
+ X25(19),
+ ISDN(20),
+ RT(21),
+ NSAP(22),
+ NSAP_PTR(23),
+ SIG(24),
+ KEY(25),
+ PX(26),
+ GPOS(27),
+ AAAA(28),
+ LOC(29),
+ NXT(30),
+ EID(31),
+ NIMLOC(32),
+ SRV(33),
+ ATMA(34),
+ NAPTR(35),
+ KX(36),
+ CERT(37),
+ A6(38),
+ DNAME(39),
+ SINK(40),
+ OPT(41),
+ APL(42),
+ DS(43),
+ SSHFP(44),
+ IPSECKEY(45),
+ RRSIG(46),
+ NSEC(47),
+ DNSKEY(48),
+ DHCID(49),
+ NSEC3(50),
+ NSEC3PARAM(51),
+ HIP(55),
+ NINFO(56),
+ RKEY(57),
+ TALINK(58),
+ SPF(99),
+ UINFO(100),
+ UID(101),
+ GID(102),
+ TKEY(249),
+ TSIG(250),
+ IXFR(251),
+ AXFR(252),
+ MAILB(253),
+ MAILA(254),
+ ANY(255),
+ TA(32768),
+ DLV(32769);
+
+ /**
+ * The value of this DNS record type.
+ */
+ private final int value;
+
+ /**
+ * Internal lookup table to map values to types.
+ */
+ private final static HashMap<Integer, TYPE> INVERSE_LUT =
+ new HashMap<Integer, TYPE>();
+
+ /**
+ * Initialize the reverse lookup table.
+ */
+ static {
+ for(TYPE t: TYPE.values()) {
+ INVERSE_LUT.put(t.getValue(), t);
+ }
+ }
+
+ /**
+ * Create a new record type.
+ * @param value The binary value of this type.
+ */
+ private TYPE(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Retrieve the binary value of this type.
+ * @return The binary value.
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Retrieve the symbolic type of the binary value.
+ * @param value The binary type value.
+ * @return The symbolic tpye.
+ */
+ public static TYPE getType(int value) {
+ return INVERSE_LUT.get(value);
+ }
+ };
+
+ /**
+ * The symbolic class of a DNS record (usually IN for Internet).
+ */
+ public static enum CLASS {
+ IN(1),
+ CH(3),
+ HS(4),
+ NONE(254),
+ ANY(255);
+
+ /**
+ * Internal reverse lookup table to map binary class values to symbolic
+ * names.
+ */
+ private final static HashMap<Integer, CLASS> INVERSE_LUT =
+ new HashMap<Integer, CLASS>();
+
+ /**
+ * Initialize the interal reverse lookup table.
+ */
+ static {
+ for(CLASS c: CLASS.values()) {
+ INVERSE_LUT.put(c.getValue(), c);
+ }
+ }
+
+ /**
+ * The binary value of this dns class.
+ */
+ private final int value;
+
+ /**
+ * Create a new DNS class based on a binary value.
+ * @param value The binary value of this DNS class.
+ */
+ private CLASS(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Retrieve the binary value of this DNS class.
+ * @return The binary value of this DNS class.
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Retrieve the symbolic DNS class for a binary class value.
+ * @param value The binary DNS class value.
+ * @return The symbolic class instance.
+ */
+ public static CLASS getClass(int value) {
+ return INVERSE_LUT.get(value);
+ }
+
+ }
+
+ /**
+ * The generic name of this record.
+ */
+ protected String name;
+
+ /**
+ * The type (and payload type) of this record.
+ */
+ protected TYPE type;
+
+ /**
+ * The record class (usually CLASS.IN).
+ */
+ protected CLASS clazz;
+
+ /**
+ * The ttl of this record.
+ */
+ protected long ttl;
+
+ /**
+ * The payload object of this record.
+ */
+ protected Data payloadData;
+
+ /**
+ * Parse a given record based on the full message data and the current
+ * stream position.
+ * @param dis The DataInputStream positioned at the first record byte.
+ * @param data The full message data.
+ * @throws IOException In case of malformed replies.
+ */
+ public void parse(DataInputStream dis, byte[] data) throws IOException {
+ this.name = NameUtil.parse(dis, data);
+ this.type = TYPE.getType(dis.readUnsignedShort());
+ this.clazz = CLASS.getClass(dis.readUnsignedShort());
+ this.ttl = (((long)dis.readUnsignedShort()) << 32) +
+ dis.readUnsignedShort();
+ int payloadLength = dis.readUnsignedShort();
+ switch (this.type) {
+ case SRV:
+ this.payloadData = new SRV();
+ break;
+ case AAAA:
+ this.payloadData = new AAAA();
+ break;
+ case A:
+ this.payloadData = new A();
+ break;
+ case NS:
+ this.payloadData = new NS();
+ break;
+ case CNAME:
+ this.payloadData = new CNAME();
+ break;
+ default:
+ System.out.println("Unparsed type " + type);
+ this.payloadData = null;
+ for (int i = 0; i < payloadLength; i++) {
+ dis.readByte();
+ }
+ break;
+ }
+ if (this.payloadData != null) {
+ this.payloadData.parse(dis, data, payloadLength);
+ }
+ }
+
+ /**
+ * Retrieve a textual representation of this resource record.
+ * @return String
+ */
+ @Override
+ public String toString() {
+ if (payloadData == null) {
+ return "RR " + type + "/" + clazz;
+ }
+ return "RR " + type + "/" + clazz + ": " + payloadData.toString();
+ };
+
+ /**
+ * Check if this record answers a given query.
+ * @param q The query.
+ * @return True if this record is a valid answer.
+ */
+ public boolean isAnswer(Question q) {
+ return ((q.getType() == type) || (q.getType() == TYPE.ANY)) &&
+ ((q.getClazz() == clazz) || (q.getClazz() == CLASS.ANY)) &&
+ (q.getName().equals(name));
+ }
+
+ public Data getPayload() {
+ return payloadData;
+ }
+
+}
37 src/com/googlecode/asmack/dns/record/A.java
View
@@ -0,0 +1,37 @@
+package com.googlecode.asmack.dns.record;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import com.googlecode.asmack.dns.Record.TYPE;
+
+public class A implements Data {
+
+ private byte[] ip;
+
+ @Override
+ public TYPE getType() {
+ return TYPE.A;
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ return ip;
+ }
+
+ @Override
+ public void parse(DataInputStream dis, byte[] data, int length)
+ throws IOException {
+ ip = new byte[4];
+ dis.readFully(ip);
+ }
+
+ @Override
+ public String toString() {
+ return Integer.toString(ip[0] & 0xff) + "." +
+ Integer.toString(ip[1] & 0xff) + "." +
+ Integer.toString(ip[2] & 0xff) + "." +
+ Integer.toString(ip[3] & 0xff);
+ }
+
+}
43 src/com/googlecode/asmack/dns/record/AAAA.java
View
@@ -0,0 +1,43 @@
+package com.googlecode.asmack.dns.record;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import com.googlecode.asmack.dns.Record.TYPE;
+
+public class AAAA implements Data {
+
+ private byte[] ip;
+
+ @Override
+ public TYPE getType() {
+ return TYPE.AAAA;
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ return ip;
+ }
+
+ @Override
+ public void parse(DataInputStream dis, byte[] data, int length)
+ throws IOException {
+ ip = new byte[16];
+ dis.readFully(ip);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < ip.length; i += 2) {
+ if (i != 0) {
+ sb.append(':');
+ }
+ sb.append(Integer.toHexString(
+ ((ip[i] & 0xff) << 8) + (ip[i + 1] & 0xff)
+ ));
+ }
+ return sb.toString();
+ }
+
+}
44 src/com/googlecode/asmack/dns/record/CNAME.java
View
@@ -0,0 +1,44 @@
+package com.googlecode.asmack.dns.record;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import com.googlecode.asmack.dns.Record.TYPE;
+import com.googlecode.asmack.dns.util.NameUtil;
+
+public class CNAME implements Data {
+
+ protected String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void parse(DataInputStream dis, byte[] data, int length)
+ throws IOException
+ {
+ this.name = NameUtil.parse(dis, data);
+ }
+
+ @Override
+ public TYPE getType() {
+ return TYPE.CNAME;
+ }
+
+ @Override
+ public String toString() {
+ return "to \"" + name + "\"";
+ }
+
+}
16 src/com/googlecode/asmack/dns/record/Data.java
View
@@ -0,0 +1,16 @@
+package com.googlecode.asmack.dns.record;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import com.googlecode.asmack.dns.Record.TYPE;
+
+public interface Data {
+
+ TYPE getType();
+
+ byte[] toByteArray();
+
+ void parse(DataInputStream dis, byte data[], int length) throws IOException;
+
+}
12 src/com/googlecode/asmack/dns/record/NS.java
View
@@ -0,0 +1,12 @@
+package com.googlecode.asmack.dns.record;
+
+import com.googlecode.asmack.dns.Record.TYPE;
+
+public class NS extends CNAME {
+
+ @Override
+ public TYPE getType() {
+ return TYPE.NS;
+ }
+
+}
74 src/com/googlecode/asmack/dns/record/SRV.java
View
@@ -0,0 +1,74 @@
+package com.googlecode.asmack.dns.record;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import com.googlecode.asmack.dns.Record.TYPE;
+import com.googlecode.asmack.dns.util.NameUtil;
+
+public class SRV implements Data {
+
+ protected int priority;
+ protected int weight;
+ protected int port;
+ protected String name;
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public void setPriority(int priority) {
+ this.priority = priority;
+ }
+
+ public int getWeight() {
+ return weight;
+ }
+
+ public void setWeight(int weight) {
+ this.weight = weight;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void parse(DataInputStream dis, byte[] data, int length)
+ throws IOException
+ {
+ this.priority = dis.readUnsignedShort();
+ this.weight = dis.readUnsignedShort();
+ this.port = dis.readUnsignedShort();
+ this.name = NameUtil.parse(dis, data);
+ }
+
+ @Override
+ public String toString() {
+ return "SRV " + name + ":" + port + " p:" + priority + " w:" + weight;
+ }
+
+ @Override
+ public TYPE getType() {
+ return TYPE.SRV;
+ }
+
+}
77 src/com/googlecode/asmack/dns/util/NameUtil.java
View
@@ -0,0 +1,77 @@
+package com.googlecode.asmack.dns.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.IDN;
+import java.util.HashSet;
+
+public class NameUtil {
+
+ public static int size(String name) {
+ return name.length() + 2;
+ }
+
+ public static byte[] toByteArray(String name) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(64);
+ DataOutputStream dos = new DataOutputStream(baos);
+ for (String s: name.split("[.\u3002\uFF0E\uFF61]")) {
+ byte[] buffer = IDN.toASCII(s).getBytes();
+ dos.writeByte(buffer.length);
+ dos.write(buffer);
+ }
+ dos.writeByte(0);
+ dos.flush();
+ return baos.toByteArray();
+ }
+
+ public static String parse(DataInputStream dis, byte data[])
+ throws IOException
+ {
+ int c = dis.readUnsignedByte();
+ if ((c & 0xc0) == 0xc0) {
+ c = ((c & 0x3f) << 8) + dis.readUnsignedByte();
+ HashSet<Integer> jumps = new HashSet<Integer>();
+ jumps.add(c);
+ return parse(data, c, jumps);
+ }
+ if (c == 0) {
+ return "";
+ }
+ byte b[] = new byte[c];
+ dis.readFully(b);
+ String s = IDN.toUnicode(new String(b));
+ String t = parse(dis, data);
+ if (t.length() > 0) {
+ s = s + "." + t;
+ }
+ return s;
+ }
+
+ public static String parse(
+ byte data[],
+ int offset,
+ HashSet<Integer> jumps
+ ) {
+ int c = data[offset] & 0xff;
+ if ((c & 0xc0) == 0xc0) {
+ c = ((c & 0x3f) << 8) + data[offset + 1];
+ if (jumps.contains(c)) {
+ throw new IllegalStateException("Cyclic offsets detected.");
+ }
+ jumps.add(c);
+ return parse(data, c, jumps);
+ }
+ if (c == 0) {
+ return "";
+ }
+ String s = new String(data,offset + 1, c);
+ String t = parse(data, offset + 1 + c, jumps);
+ if (t.length() > 0) {
+ s = s + "." + t;
+ }
+ return s;
+ }
+
+}
127 src/org/xbill/DNS/A6Record.java
View
@@ -1,127 +0,0 @@
-// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
-
-package org.xbill.DNS;
-
-import java.io.*;
-import java.net.*;
-
-/**
- * A6 Record - maps a domain name to an IPv6 address (experimental)
- *
- * @author Brian Wellington
- */
-
-public class A6Record extends Record {
-
-private static final long serialVersionUID = -8815026887337346789L;
-
-private int prefixBits;
-private InetAddress suffix;
-private Name prefix;
-
-A6Record() {}
-
-Record
-getObject() {
- return new A6Record();
-}
-
-/**
- * Creates an A6 Record from the given data
- * @param prefixBits The number of bits in the address prefix
- * @param suffix The address suffix
- * @param prefix The name of the prefix
- */
-public
-A6Record(Name name, int dclass, long ttl, int prefixBits,
- InetAddress suffix, Name prefix)
-{
- super(name, Type.A6, dclass, ttl);
- this.prefixBits = checkU8("prefixBits", prefixBits);
- if (suffix != null && Address.familyOf(suffix) != Address.IPv6)
- throw new IllegalArgumentException("invalid IPv6 address");
- this.suffix = suffix;
- if (prefix != null)
- this.prefix = checkName("prefix", prefix);
-}
-
-void
-rrFromWire(DNSInput in) throws IOException {
- prefixBits = in.readU8();
- int suffixbits = 128 - prefixBits;
- int suffixbytes = (suffixbits + 7) / 8;
- if (prefixBits < 128) {
- byte [] bytes = new byte[16];
- in.readByteArray(bytes, 16 - suffixbytes, suffixbytes);
- suffix = InetAddress.getByAddress(bytes);
- }
- if (prefixBits > 0)
- prefix = new Name(in);
-}
-
-void
-rdataFromString(Tokenizer st, Name origin) throws IOException {
- prefixBits = st.getUInt8();
- if (prefixBits > 128) {
- throw st.exception("prefix bits must be [0..128]");
- } else if (prefixBits < 128) {
- String s = st.getString();
- try {
- suffix = Address.getByAddress(s, Address.IPv6);
- }
- catch (UnknownHostException e) {
- throw st.exception("invalid IPv6 address: " + s);
- }
- }
- if (prefixBits > 0)
- prefix = st.getName(origin);
-}
-
-/** Converts rdata to a String */
-String
-rrToString() {
- StringBuffer sb = new StringBuffer();
- sb.append(prefixBits);
- if (suffix != null) {
- sb.append(" ");
- sb.append(suffix.getHostAddress());
- }
- if (prefix != null) {
- sb.append(" ");
- sb.append(prefix);
- }
- return sb.toString();
-}
-
-/** Returns the number of bits in the prefix */
-public int
-getPrefixBits() {
- return prefixBits;
-}
-
-/** Returns the address suffix */
-public InetAddress
-getSuffix() {
- return suffix;
-}
-
-/** Returns the address prefix */
-public Name
-getPrefix() {
- return prefix;
-}
-
-void
-rrToWire(DNSOutput out, Compression c, boolean canonical) {
- out.writeU8(prefixBits);
- if (suffix != null) {
- int suffixbits = 128 - prefixBits;
- int suffixbytes = (suffixbits + 7) / 8;
- byte [] data = suffix.getAddress();
- out.writeByteArray(data, 16 - suffixbytes, suffixbytes);
- }
- if (prefix != null)
- prefix.toWire(out, null, canonical);
-}
-
-}
66 src/org/xbill/DNS/AAAARecord.java
View
@@ -1,66 +0,0 @@
-// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
-
-package org.xbill.DNS;
-
-import java.io.*;
-import java.net.*;
-
-/**
- * IPv6 Address Record - maps a domain name to an IPv6 address
- *
- * @author Brian Wellington
- */
-
-public class AAAARecord extends Record {
-
-private static final long serialVersionUID = -4588601512069748050L;
-
-private InetAddress address;
-
-AAAARecord() {}
-
-Record
-getObject() {
- return new AAAARecord();
-}
-
-/**
- * Creates an AAAA Record from the given data
- * @param address The address suffix
- */
-public
-AAAARecord(Name name, int dclass, long ttl, InetAddress address) {
- super(name, Type.AAAA, dclass, ttl);
- if (Address.familyOf(address) != Address.IPv6)
- throw new IllegalArgumentException("invalid IPv6 address");
- this.address = address;
-}
-
-void
-rrFromWire(DNSInput in) throws IOException {
- address = InetAddress.getByAddress(in.readByteArray(16));
-}
-
-void
-rdataFromString(Tokenizer st, Name origin) throws IOException {
- address = st.getAddress(Address.IPv6);
-}
-
-/** Converts rdata to a String */
-String
-rrToString() {
- return address.getHostAddress();
-}
-
-/** Returns the address */
-public InetAddress
-getAddress() {
- return address;
-}
-
-void
-rrToWire(DNSOutput out, Compression c, boolean canonical) {
- out.writeByteArray(address.getAddress());
-}
-
-}
46 src/org/xbill/DNS/AFSDBRecord.java
View
@@ -1,46 +0,0 @@
-// Copyright (c) 2004 Brian Wellington (bwelling@xbill.org)
-
-package org.xbill.DNS;
-
-/**
- * AFS Data Base Record - maps a domain name to the name of an AFS cell
- * database server.
- *
- *
- * @author Brian Wellington
- */
-
-public class AFSDBRecord extends U16NameBase {
-
-private static final long serialVersionUID = 3034379930729102437L;
-
-AFSDBRecord() {}
-
-Record
-getObject() {
- return new AFSDBRecord();
-}
-
-/**
- * Creates an AFSDB Record from the given data.
- * @param subtype Indicates the type of service provided by the host.
- * @param host The host providing the service.
- */
-public
-AFSDBRecord(Name name, int dclass, long ttl, int subtype, Name host) {
- super(name, Type.AFSDB, dclass, ttl, subtype, "subtype", host, "host");
-}
-
-/** Gets the subtype indicating the service provided by the host. */
-public int
-getSubtype() {
- return getU16Field();
-}
-
-/** Gets the host providing service for the domain. */
-public Name
-getHost() {
- return getNameField();
-}
-
-}
287 src/org/xbill/DNS/APLRecord.java
View
@@ -1,287 +0,0 @@
-// Copyright (c) 2004 Brian Wellington (bwelling@xbill.org)
-
-package org.xbill.DNS;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import org.xbill.DNS.utils.*;
-
-/**
- * APL - Address Prefix List. See RFC 3123.
- *
- * @author Brian Wellington
- */
-
-/*
- * Note: this currently uses the same constants as the Address class;
- * this could change if more constants are defined for APL records.
- */
-
-public class APLRecord extends Record {
-
-public static class Element {
- public final int family;
- public final boolean negative;
- public final int prefixLength;
- public final Object address;
-
- private
- Element(int family, boolean negative, Object address, int prefixLength)
- {
- this.family = family;
- this.negative = negative;
- this.address = address;
- this.prefixLength = prefixLength;
- if (!validatePrefixLength(family, prefixLength)) {
- throw new IllegalArgumentException("invalid prefix " +
- "length");
- }
- }
-
- /**
- * Creates an APL element corresponding to an IPv4 or IPv6 prefix.
- * @param negative Indicates if this prefix is a negation.
- * @param address The IPv4 or IPv6 address.
- * @param prefixLength The length of this prefix, in bits.
- * @throws IllegalArgumentException The prefix length is invalid.
- */
- public
- Element(boolean negative, InetAddress address, int prefixLength) {
- this(Address.familyOf(address), negative, address,
- prefixLength);
- }
-
- public String
- toString() {
- StringBuffer sb = new StringBuffer();
- if (negative)
- sb.append("!");
- sb.append(family);
- sb.append(":");
- if (family == Address.IPv4 || family == Address.IPv6)
- sb.append(((InetAddress) address).getHostAddress());
- else
- sb.append(base16.toString((byte []) address));
- sb.append("/");
- sb.append(prefixLength);
- return sb.toString();
- }
-
- public boolean
- equals(Object arg) {
- if (arg == null || !(arg instanceof Element))
- return false;
- Element elt = (Element) arg;
- return (family == elt.family &&
- negative == elt.negative &&
- prefixLength == elt.prefixLength &&
- address.equals(elt.address));
- }
-
- public int
- hashCode() {
- return address.hashCode() + prefixLength + (negative ? 1 : 0);
- }
-}
-
-private static final long serialVersionUID = -1348173791712935864L;
-
-private List elements;
-
-APLRecord() {}
-
-Record
-getObject() {
- return new APLRecord();
-}
-
-private static boolean
-validatePrefixLength(int family, int prefixLength) {
- if (prefixLength < 0 || prefixLength >= 256)
- return false;
- if ((family == Address.IPv4 && prefixLength > 32) ||
- (family == Address.IPv6 && prefixLength > 128))
- return false;
- return true;
-}
-
-/**
- * Creates an APL Record from the given data.
- * @param elements The list of APL elements.
- */
-public
-APLRecord(Name name, int dclass, long ttl, List elements) {
- super(name, Type.APL, dclass, ttl);
- this.elements = new ArrayList(elements.size());
- for (Iterator it = elements.iterator(); it.hasNext(); ) {
- Object o = it.next();
- if (!(o instanceof Element)) {
- throw new IllegalArgumentException("illegal element");
- }
- Element element = (Element) o;
- if (element.family != Address.IPv4 &&
- element.family != Address.IPv6)
- {
- throw new IllegalArgumentException("unknown family");
- }
- this.elements.add(element);
-
- }
-}
-
-private static byte []
-parseAddress(byte [] in, int length) throws WireParseException {
- if (in.length > length)
- throw new WireParseException("invalid address length");
- if (in.length == length)
- return in;
- byte [] out = new byte[length];
- System.arraycopy(in, 0, out, 0, in.length);
- return out;
-}
-
-void
-rrFromWire(DNSInput in) throws IOException {
- elements = new ArrayList(1);
- while (in.remaining() != 0) {
- int family = in.readU16();
- int prefix = in.readU8();
- int length = in.readU8();
- boolean negative = (length & 0x80) != 0;
- length &= ~0x80;
-
- byte [] data = in.readByteArray(length);
- Element element;
- if (!validatePrefixLength(family, prefix)) {
- throw new WireParseException("invalid prefix length");
- }
-
- if (family == Address.IPv4 || family == Address.IPv6) {
- data = parseAddress(data,
- Address.addressLength(family));
- InetAddress addr = InetAddress.getByAddress(data);
- element = new Element(negative, addr, prefix);
- } else {
- element = new Element(family, negative, data, prefix);
- }
- elements.add(element);
-
- }
-}
-
-void
-rdataFromString(Tokenizer st, Name origin) throws IOException {
- elements = new ArrayList(1);
- while (true) {
- Tokenizer.Token t = st.get();
- if (!t.isString())
- break;
-
- boolean negative = false;
- int family = 0;
- int prefix = 0;
-
- String s = t.value;
- int start = 0;
- if (s.startsWith("!")) {
- negative = true;
- start = 1;
- }
- int colon = s.indexOf(':', start);
- if (colon < 0)
- throw st.exception("invalid address prefix element");
- int slash = s.indexOf('/', colon);
- if (slash < 0)
- throw st.exception("invalid address prefix element");
-
- String familyString = s.substring(start, colon);
- String addressString = s.substring(colon + 1, slash);
- String prefixString = s.substring(slash + 1);
-
- try {
- family = Integer.parseInt(familyString);
- }
- catch (NumberFormatException e) {
- throw st.exception("invalid family");
- }
- if (family != Address.IPv4 && family != Address.IPv6)
- throw st.exception("unknown family");
-
- try {
- prefix = Integer.parseInt(prefixString);
- }
- catch (NumberFormatException e) {
- throw st.exception("invalid prefix length");
- }
-
- if (!validatePrefixLength(family, prefix)) {
- throw st.exception("invalid prefix length");
- }
-
- byte [] bytes = Address.toByteArray(addressString, family);
- if (bytes == null)
- throw st.exception("invalid IP address " +
- addressString);
-
- InetAddress address = InetAddress.getByAddress(bytes);
- elements.add(new Element(negative, address, prefix));
- }
- st.unget();
-}
-
-String
-rrToString() {
- StringBuffer sb = new StringBuffer();
- for (Iterator it = elements.iterator(); it.hasNext(); ) {
- Element element = (Element) it.next();
- sb.append(element);
- if (it.hasNext())
- sb.append(" ");
- }
- return sb.toString();
-}
-
-/** Returns the list of APL elements. */
-public List
-getElements() {
- return elements;
-}
-
-private static int
-addressLength(byte [] addr) {
- for (int i = addr.length - 1; i >= 0; i--) {
- if (addr[i] != 0)
- return i + 1;
- }
- return 0;
-}
-
-void
-rrToWire(DNSOutput out, Compression c, boolean canonical) {
- for (Iterator it = elements.iterator(); it.hasNext(); ) {
- Element element = (Element) it.next();
- int length = 0;
- byte [] data;
- if (element.family == Address.IPv4 ||
- element.family == Address.IPv6)
- {
- InetAddress addr = (InetAddress) element.address;
- data = addr.getAddress();
- length = addressLength(data);
- } else {
- data = (byte []) element.address;
- length = data.length;
- }
- int wlength = length;
- if (element.negative) {
- wlength |= 0x80;
- }
- out.writeU16(element.family);
- out.writeU8(element.prefixLength);
- out.writeU8(wlength);
- out.writeByteArray(data, 0, length);
- }
-}
-
-}
89 src/org/xbill/DNS/ARecord.java
View
@@ -1,89 +0,0 @@
-// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
-
-package org.xbill.DNS;
-
-import java.net.*;
-import java.io.*;
-
-/**
- * Address Record - maps a domain name to an Internet address
- *
- * @author Brian Wellington
- */
-
-public class ARecord extends Record {
-
-private static final long serialVersionUID = -2172609200849142323L;
-
-private int addr;
-
-ARecord() {}
-
-Record
-getObject() {
- return new ARecord();
-}
-
-private static final int
-fromArray(byte [] array) {
- return (((array[0] & 0xFF) << 24) |
- ((array[1] & 0xFF) << 16) |
- ((array[2] & 0xFF) << 8) |
- (array[3] & 0xFF));
-}
-
-private static final byte []
-toArray(int addr) {
- byte [] bytes = new byte[4];
- bytes[0] = (byte) ((addr >>> 24) & 0xFF);
- bytes[1] = (byte) ((addr >>> 16) & 0xFF);
- bytes[2] = (byte) ((addr >>> 8) & 0xFF);
- bytes[3] = (byte) (addr & 0xFF);
- return bytes;
-}
-
-/**
- * Creates an A Record from the given data
- * @param address The address that the name refers to
- */
-public
-ARecord(Name name, int dclass, long ttl, InetAddress address) {
- super(name, Type.A, dclass, ttl);
- if (Address.familyOf(address) != Address.IPv4)
- throw new IllegalArgumentException("invalid IPv4 address");
- addr = fromArray(address.getAddress());
-}
-
-void
-rrFromWire(DNSInput in) throws IOException {
- addr = fromArray(in.readByteArray(4));
-}
-
-void
-rdataFromString(Tokenizer st, Name origin) throws IOException {
- InetAddress address = st.getAddress(Address.IPv4);
- addr = fromArray(address.getAddress());
-}
-
-/** Converts rdata to a String */
-String
-rrToString() {
- return (Address.toDottedQuad(toArray(addr)));
-}
-
-/** Returns the Internet address */
-public InetAddress
-getAddress() {
- try {
- return InetAddress.getByAddress(toArray(addr));
- } catch (UnknownHostException e) {
- return null;
- }
-}
-
-void
-rrToWire(DNSOutput out, Compression c, boolean canonical) {
- out.writeU32(((long)addr) & 0xFFFFFFFFL);
-}
-
-}
372 src/org/xbill/DNS/Address.java
View
@@ -1,372 +0,0 @@
-// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
-
-package org.xbill.DNS;
-
-import java.net.*;
-import java.net.Inet6Address;
-
-/**
- * Routines dealing with IP addresses. Includes functions similar to
- * those in the java.net.InetAddress class.
- *
- * @author Brian Wellington
- */
-
-public final class Address {
-
-public static final int IPv4 = 1;
-public static final int IPv6 = 2;
-
-private
-Address() {}
-
-private static byte []
-parseV4(String s) {
- int numDigits;
- int currentOctet;
- byte [] values = new byte[4];
- int currentValue;
- int length = s.length();
-
- currentOctet = 0;
- currentValue = 0;
- numDigits = 0;
- for (int i = 0; i < length; i++) {
- char c = s.charAt(i);
- if (c >= '0' && c <= '9') {
- /* Can't have more than 3 digits per octet. */
- if (numDigits == 3)
- return null;
- /* Octets shouldn't start with 0, unless they are 0. */
- if (numDigits > 0 && currentValue == 0)
- return null;
- numDigits++;
- currentValue *= 10;
- currentValue += (c - '0');
- /* 255 is the maximum value for an octet. */
- if (currentValue > 255)
- return null;
- } else if (c == '.') {
- /* Can't have more than 3 dots. */
- if (currentOctet == 3)
- return null;
- /* Two consecutive dots are bad. */
- if (numDigits == 0)
- return null;
- values[currentOctet++] = (byte) currentValue;
- currentValue = 0;
- numDigits = 0;
- } else
- return null;
- }
- /* Must have 4 octets. */
- if (currentOctet != 3)
- return null;
- /* The fourth octet can't be empty. */
- if (numDigits == 0)
- return null;
- values[currentOctet] = (byte) currentValue;
- return values;
-}
-
-private static byte []
-parseV6(String s) {
- int range = -1;
- byte [] data = new byte[16];
-
- String [] tokens = s.split(":", -1);
-
- int first = 0;
- int last = tokens.length - 1;
-
- if (tokens[0].length() == 0) {
- // If the first two tokens are empty, it means the string
- // started with ::, which is fine. If only the first is
- // empty, the string started with :, which is bad.
- if (last - first > 0 && tokens[1].length() == 0)
- first++;
- else
- return null;
- }
-
- if (tokens[last].length() == 0) {
- // If the last two tokens are empty, it means the string
- // ended with ::, which is fine. If only the last is
- // empty, the string ended with :, which is bad.
- if (last - first > 0 && tokens[last - 1].length() == 0)
- last--;
- else
- return null;
- }
-
- if (last - first + 1 > 8)
- return null;
-
- int i, j;
- for (i = first, j = 0; i <= last; i++) {
- if (tokens[i].length() == 0) {
- if (range >= 0)
- return null;
- range = j;
- continue;
- }
-
- if (tokens[i].indexOf('.') >= 0) {
- // An IPv4 address must be the last component
- if (i < last)
- return null;
- // There can't have been more than 6 components.
- if (i > 6)
- return null;
- byte [] v4addr = Address.toByteArray(tokens[i], IPv4);
- if (v4addr == null)
- return null;
- for (int k = 0; k < 4; k++)
- data[j++] = v4addr[k];
- break;
- }
-
- try {
- for (int k = 0; k < tokens[i].length(); k++) {
- char c = tokens[i].charAt(k);
- if (Character.digit(c, 16) < 0)
- return null;
- }
- int x = Integer.parseInt(tokens[i], 16);
- if (x > 0xFFFF || x < 0)
- return null;
- data[j++] = (byte)(x >>> 8);
- data[j++] = (byte)(x & 0xFF);
- }
- catch (NumberFormatException e) {
- return null;
- }
- }
-
- if (j < 16 && range < 0)
- return null;
-
- if (range >= 0) {
- int empty = 16 - j;
- System.arraycopy(data, range, data, range + empty, j - range);
- for (i = range; i < range + empty; i++)
- data[i] = 0;
- }
-
- return data;
-}
-
-/**
- * Convert a string containing an IP address to an array of 4 or 16 integers.
- * @param s The address, in text format.
- * @param family The address family.
- * @return The address
- */
-public static int []
-toArray(String s, int family) {
- byte [] byteArray = toByteArray(s, family);
- if (byteArray == null)
- return null;
- int [] intArray = new int[byteArray.length];
- for (int i = 0; i < byteArray.length; i++)
- intArray[i] = byteArray[i] & 0xFF;
- return intArray;
-}
-
-/**
- * Convert a string containing an IPv4 address to an array of 4 integers.
- * @param s The address, in text format.
- * @return The address
- */
-public static int []
-toArray(String s) {
- return toArray(s, IPv4);
-}
-
-/**
- * Convert a string containing an IP address to an array of 4 or 16 bytes.
- * @param s The address, in text format.
- * @param family The address family.
- * @return The address
- */
-public static byte []
-toByteArray(String s, int family) {
- if (family == IPv4)
- return parseV4(s);
- else if (family == IPv6)
- return parseV6(s);
- else
- throw new IllegalArgumentException("unknown address family");
-}
-
-/**
- * Determines if a string contains a valid IP address.
- * @param s The string
- * @return Whether the string contains a valid IP address
- */
-public static boolean
-isDottedQuad(String s) {
- byte [] address = Address.toByteArray(s, IPv4);
- return (address != null);
-}
-
-/**
- * Converts a byte array containing an IPv4 address into a dotted quad string.
- * @param addr The array
- * @return The string representation
- */
-public static String
-toDottedQuad(byte [] addr) {
- return ((addr[0] & 0xFF) + "." + (addr[1] & 0xFF) + "." +
- (addr[2] & 0xFF) + "." + (addr[3] & 0xFF));
-}
-
-/**
- * Converts an int array containing an IPv4 address into a dotted quad string.
- * @param addr The array
- * @return The string representation
- */
-public static String
-toDottedQuad(int [] addr) {
- return (addr[0] + "." + addr[1] + "." + addr[2] + "." + addr[3]);
-}
-
-private static Record []
-lookupHostName(String name) throws UnknownHostException {
- try {
- Record [] records = new Lookup(name).run();
- if (records == null)
- throw new UnknownHostException("unknown host");
- return records;
- }
- catch (TextParseException e) {
- throw new UnknownHostException("invalid name");
- }
-}
-
-private static InetAddress
-addrFromRecord(String name, Record r) throws UnknownHostException {
- ARecord a = (ARecord) r;
- return InetAddress.getByAddress(name, a.getAddress().getAddress());
-}
-
-/**
- * Determines the IP address of a host
- * @param name The hostname to look up
- * @return The first matching IP address
- * @exception UnknownHostException The hostname does not have any addresses
- */
-public static InetAddress
-getByName(String name) throws UnknownHostException {
- try {
- return getByAddress(name);
- } catch (UnknownHostException e) {
- Record [] records = lookupHostName(name);
- return addrFromRecord(name, records[0]);
- }
-}
-
-/**
- * Determines all IP address of a host
- * @param name The hostname to look up
- * @return All matching IP addresses
- * @exception UnknownHostException The hostname does not have any addresses
- */
-public static InetAddress []
-getAllByName(String name) throws UnknownHostException {
- try {
- InetAddress addr = getByAddress(name);
- return new InetAddress[] {addr};
- } catch (UnknownHostException e) {
- Record [] records = lookupHostName(name);
- InetAddress [] addrs = new InetAddress[records.length];
- for (int i = 0; i < records.length; i++)
- addrs[i] = addrFromRecord(name, records[i]);
- return addrs;
- }
-}
-
-/**
- * Converts an address from its string representation to an IP address.
- * The address can be either IPv4 or IPv6.
- * @param addr The address, in string form
- * @return The IP addresses
- * @exception UnknownHostException The address is not a valid IP address.
- */
-public static InetAddress
-getByAddress(String addr) throws UnknownHostException {
- byte [] bytes;
- bytes = toByteArray(addr, IPv4);