13742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman// /Copyright 2003-2005 Arthur van Hoff, Rick Blair 23742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman// Licensed under Apache License version 2.0 33742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman// Original license LGPL 43742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 53742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanpackage javax.jmdns.impl; 63742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 73742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.io.ByteArrayInputStream; 83742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.io.IOException; 93742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.net.DatagramPacket; 103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.net.InetAddress; 113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.HashMap; 123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.Map; 133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.logging.Level; 143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport java.util.logging.Logger; 153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSConstants; 173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSLabel; 183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSOptionCode; 193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSRecordClass; 203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSRecordType; 213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanimport javax.jmdns.impl.constants.DNSResultCode; 223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman/** 243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * Parse an incoming DNS message into its components. 253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * 263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @author Arthur van Hoff, Werner Randelshofer, Pierre Frisch, Daniel Bobbert 273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Romanpublic final class DNSIncoming extends DNSMessage { 293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman private static Logger logger = Logger.getLogger(DNSIncoming.class.getName()); 303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // This is a hack to handle a bug in the BonjourConformanceTest 323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // It is sending out target strings that don't follow the "domain name" format. 333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public static boolean USE_DOMAIN_NAME_FORMAT_FOR_SRV_TARGET = true; 343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public static class MessageInputStream extends ByteArrayInputStream { 363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman private static Logger logger1 = Logger.getLogger(MessageInputStream.class.getName()); 373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman final Map<Integer, String> _names; 393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public MessageInputStream(byte[] buffer, int length) { 413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this(buffer, 0, length); 423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /** 453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @param buffer 463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @param offset 473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @param length 483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public MessageInputStream(byte[] buffer, int offset, int length) { 503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman super(buffer, offset, length); 513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman _names = new HashMap<Integer, String>(); 523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public int readByte() { 553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return this.read(); 563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public int readUnsignedShort() { 593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return (this.read() << 8) | this.read(); 603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public int readInt() { 633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return (this.readUnsignedShort() << 16) | this.readUnsignedShort(); 643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public byte[] readBytes(int len) { 673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman byte bytes[] = new byte[len]; 683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this.read(bytes, 0, len); 693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return bytes; 703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public String readUTF(int len) { 733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman StringBuilder buffer = new StringBuilder(len); 743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (int index = 0; index < len; index++) { 753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int ch = this.read(); 763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman switch (ch >> 4) { 773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case 0: 783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case 1: 793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case 2: 803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case 3: 813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case 4: 823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case 5: 833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case 6: 843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case 7: 853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // 0xxxxxxx 863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case 12: 883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case 13: 893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // 110x xxxx 10xx xxxx 903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman ch = ((ch & 0x1F) << 6) | (this.read() & 0x3F); 913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman index++; 923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case 14: 943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // 1110 xxxx 10xx xxxx 10xx xxxx 953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman ch = ((ch & 0x0f) << 12) | ((this.read() & 0x3F) << 6) | (this.read() & 0x3F); 963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman index++; 973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman index++; 983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman default: 1003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // 10xx xxxx, 1111 xxxx 1013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman ch = ((ch & 0x3F) << 4) | (this.read() & 0x0f); 1023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman index++; 1033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 1043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buffer.append((char) ch); 1063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return buffer.toString(); 1083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman protected synchronized int peek() { 1113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return (pos < count) ? (buf[pos] & 0xff) : -1; 1123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public String readName() { 1153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman Map<Integer, StringBuilder> names = new HashMap<Integer, StringBuilder>(); 1163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman StringBuilder buffer = new StringBuilder(); 1173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman boolean finished = false; 1183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman while (!finished) { 1193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int len = this.read(); 1203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (len == 0) { 1213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman finished = true; 1223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 1233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman switch (DNSLabel.labelForByte(len)) { 1253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case Standard: 1263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int offset = pos - 1; 1273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman String label = this.readUTF(len) + "."; 1283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buffer.append(label); 1293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (StringBuilder previousLabel : names.values()) { 1303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman previousLabel.append(label); 1313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman names.put(Integer.valueOf(offset), new StringBuilder(label)); 1333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 1343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case Compressed: 1353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int index = (DNSLabel.labelValue(len) << 8) | this.read(); 1363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman String compressedLabel = _names.get(Integer.valueOf(index)); 1373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (compressedLabel == null) { 1383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger1.severe("bad domain name: possible circular name detected. Bad offset: 0x" + Integer.toHexString(index) + " at 0x" + Integer.toHexString(pos - 2)); 1393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman compressedLabel = ""; 1403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buffer.append(compressedLabel); 1423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (StringBuilder previousLabel : names.values()) { 1433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman previousLabel.append(compressedLabel); 1443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman finished = true; 1463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 1473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case Extended: 1483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // int extendedLabelClass = DNSLabel.labelValue(len); 1493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger1.severe("Extended label are not currently supported."); 1503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 1513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case Unknown: 1523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman default: 1533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger1.severe("unsupported dns label type: '" + Integer.toHexString(len & 0xC0) + "'"); 1543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (Integer index : names.keySet()) { 1573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman _names.put(index, names.get(index).toString()); 1583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return buffer.toString(); 1603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public String readNonNameString() { 1633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int len = this.read(); 1643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return this.readUTF(len); 1653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 1683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman private final DatagramPacket _packet; 1703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman private final long _receivedTime; 1723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman private final MessageInputStream _messageInputStream; 1743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman private int _senderUDPPayload; 1763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /** 1783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * Parse a message from a datagram packet. 1793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * 1803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @param packet 1813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @exception IOException 1823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 1833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public DNSIncoming(DatagramPacket packet) throws IOException { 1843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman super(0, 0, packet.getPort() == DNSConstants.MDNS_PORT); 1853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this._packet = packet; 1863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman InetAddress source = packet.getAddress(); 1873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this._messageInputStream = new MessageInputStream(packet.getData(), packet.getLength()); 1883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this._receivedTime = System.currentTimeMillis(); 1893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this._senderUDPPayload = DNSConstants.MAX_MSG_TYPICAL; 1903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman try { 1923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this.setId(_messageInputStream.readUnsignedShort()); 1933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this.setFlags(_messageInputStream.readUnsignedShort()); 1943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int numQuestions = _messageInputStream.readUnsignedShort(); 1953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int numAnswers = _messageInputStream.readUnsignedShort(); 1963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int numAuthorities = _messageInputStream.readUnsignedShort(); 1973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int numAdditionals = _messageInputStream.readUnsignedShort(); 1983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 1993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // parse questions 2003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (numQuestions > 0) { 2013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (int i = 0; i < numQuestions; i++) { 2023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman _questions.add(this.readQuestion()); 2033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 2063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // parse answers 2073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (numAnswers > 0) { 2083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (int i = 0; i < numAnswers; i++) { 2093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSRecord rec = this.readAnswer(source); 2103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (rec != null) { 2113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // Add a record, if we were able to create one. 2123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman _answers.add(rec); 2133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 2173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (numAuthorities > 0) { 2183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (int i = 0; i < numAuthorities; i++) { 2193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSRecord rec = this.readAnswer(source); 2203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (rec != null) { 2213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // Add a record, if we were able to create one. 2223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman _authoritativeAnswers.add(rec); 2233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 2273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (numAdditionals > 0) { 2283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (int i = 0; i < numAdditionals; i++) { 2293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSRecord rec = this.readAnswer(source); 2303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (rec != null) { 2313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // Add a record, if we were able to create one. 2323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman _additionals.add(rec); 2333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } catch (Exception e) { 2373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.log(Level.WARNING, "DNSIncoming() dump " + print(true) + "\n exception ", e); 2383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // This ugly but some JVM don't implement the cause on IOException 2393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman IOException ioe = new IOException("DNSIncoming corrupted message"); 2403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman ioe.initCause(e); 2413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman throw ioe; 2423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 2453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman private DNSIncoming(int flags, int id, boolean multicast, DatagramPacket packet, long receivedTime) { 2463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman super(flags, id, multicast); 2473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this._packet = packet; 2483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this._messageInputStream = new MessageInputStream(packet.getData(), packet.getLength()); 2493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this._receivedTime = receivedTime; 2503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 2523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 2533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /* 2543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * (non-Javadoc) 2553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * 2563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @see java.lang.Object#clone() 2573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 2583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 2593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public DNSIncoming clone() { 2603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSIncoming in = new DNSIncoming(this.getFlags(), this.getId(), this.isMulticast(), this._packet, this._receivedTime); 2613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman in._senderUDPPayload = this._senderUDPPayload; 2623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman in._questions.addAll(this._questions); 2633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman in._answers.addAll(this._answers); 2643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman in._authoritativeAnswers.addAll(this._authoritativeAnswers); 2653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman in._additionals.addAll(this._additionals); 2663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return in; 2673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 2693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 2703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman private DNSQuestion readQuestion() { 2713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman String domain = _messageInputStream.readName(); 2723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSRecordType type = DNSRecordType.typeForIndex(_messageInputStream.readUnsignedShort()); 2733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (type == DNSRecordType.TYPE_IGNORE) { 2743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.log(Level.SEVERE, "Could not find record type: " + this.print(true)); 2753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int recordClassIndex = _messageInputStream.readUnsignedShort(); 2773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSRecordClass recordClass = DNSRecordClass.classForIndex(recordClassIndex); 2783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman boolean unique = recordClass.isUnique(recordClassIndex); 2793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return DNSQuestion.newQuestion(domain, type, recordClass, unique); 2803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 2823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman private DNSRecord readAnswer(InetAddress source) { 2833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman String domain = _messageInputStream.readName(); 2843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSRecordType type = DNSRecordType.typeForIndex(_messageInputStream.readUnsignedShort()); 2853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (type == DNSRecordType.TYPE_IGNORE) { 2863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.log(Level.SEVERE, "Could not find record type. domain: " + domain + "\n" + this.print(true)); 2873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int recordClassIndex = _messageInputStream.readUnsignedShort(); 2893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSRecordClass recordClass = (type == DNSRecordType.TYPE_OPT ? DNSRecordClass.CLASS_UNKNOWN : DNSRecordClass.classForIndex(recordClassIndex)); 2903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if ((recordClass == DNSRecordClass.CLASS_UNKNOWN) && (type != DNSRecordType.TYPE_OPT)) { 2913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.log(Level.SEVERE, "Could not find record class. domain: " + domain + " type: " + type + "\n" + this.print(true)); 2923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 2933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman boolean unique = recordClass.isUnique(recordClassIndex); 2943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int ttl = _messageInputStream.readInt(); 2953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int len = _messageInputStream.readUnsignedShort(); 2963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSRecord rec = null; 2973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 2983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman switch (type) { 2993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case TYPE_A: // IPv4 3003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman rec = new DNSRecord.IPv4Address(domain, recordClass, unique, ttl, _messageInputStream.readBytes(len)); 3013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 3023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case TYPE_AAAA: // IPv6 3033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman rec = new DNSRecord.IPv6Address(domain, recordClass, unique, ttl, _messageInputStream.readBytes(len)); 3043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 3053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case TYPE_CNAME: 3063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case TYPE_PTR: 3073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman String service = ""; 3083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman service = _messageInputStream.readName(); 3093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (service.length() > 0) { 3103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman rec = new DNSRecord.Pointer(domain, recordClass, unique, ttl, service); 3113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } else { 3123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.log(Level.WARNING, "PTR record of class: " + recordClass + ", there was a problem reading the service name of the answer for domain:" + domain); 3133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 3143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 3153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case TYPE_TXT: 3163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman rec = new DNSRecord.Text(domain, recordClass, unique, ttl, _messageInputStream.readBytes(len)); 3173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 3183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case TYPE_SRV: 3193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int priority = _messageInputStream.readUnsignedShort(); 3203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int weight = _messageInputStream.readUnsignedShort(); 3213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int port = _messageInputStream.readUnsignedShort(); 3223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman String target = ""; 3233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // This is a hack to handle a bug in the BonjourConformanceTest 3243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // It is sending out target strings that don't follow the "domain name" format. 3253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (USE_DOMAIN_NAME_FORMAT_FOR_SRV_TARGET) { 3263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman target = _messageInputStream.readName(); 3273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } else { 3283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // [PJYF Nov 13 2010] Do we still need this? This looks really bad. All label are supposed to start by a length. 3293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman target = _messageInputStream.readNonNameString(); 3303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 3313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman rec = new DNSRecord.Service(domain, recordClass, unique, ttl, priority, weight, port, target); 3323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 3333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case TYPE_HINFO: 3343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman StringBuilder buf = new StringBuilder(); 3353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(_messageInputStream.readUTF(len)); 3363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int index = buf.indexOf(" "); 3373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman String cpu = (index > 0 ? buf.substring(0, index) : buf.toString()).trim(); 3383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman String os = (index > 0 ? buf.substring(index + 1) : "").trim(); 3393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman rec = new DNSRecord.HostInformation(domain, recordClass, unique, ttl, cpu, os); 3403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 3413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case TYPE_OPT: 3423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSResultCode extendedResultCode = DNSResultCode.resultCodeForFlags(this.getFlags(), ttl); 3433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int version = (ttl & 0x00ff0000) >> 16; 3443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (version == 0) { 3453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman _senderUDPPayload = recordClassIndex; 3463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman while (_messageInputStream.available() > 0) { 3473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // Read RDData 3483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int optionCodeInt = 0; 3493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman DNSOptionCode optionCode = null; 3503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (_messageInputStream.available() >= 2) { 3513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman optionCodeInt = _messageInputStream.readUnsignedShort(); 3523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman optionCode = DNSOptionCode.resultCodeForFlags(optionCodeInt); 3533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } else { 3543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.log(Level.WARNING, "There was a problem reading the OPT record. Ignoring."); 3553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 3563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 3573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int optionLength = 0; 3583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (_messageInputStream.available() >= 2) { 3593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman optionLength = _messageInputStream.readUnsignedShort(); 3603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } else { 3613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.log(Level.WARNING, "There was a problem reading the OPT record. Ignoring."); 3623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 3633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 3643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman byte[] optiondata = new byte[0]; 3653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (_messageInputStream.available() >= optionLength) { 3663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman optiondata = _messageInputStream.readBytes(optionLength); 3673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 3683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // 3693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // We should really do something with those options. 3703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman switch (optionCode) { 3713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case Owner: 3723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // Valid length values are 8, 14, 18 and 20 3733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 3743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // |Opt|Len|V|S|Primary MAC|Wakeup MAC | Password | 3753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 3763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // 3773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int ownerVersion = 0; 3783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int ownerSequence = 0; 3793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman byte[] ownerPrimaryMacAddress = null; 3803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman byte[] ownerWakeupMacAddress = null; 3813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman byte[] ownerPassword = null; 3823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman try { 3833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman ownerVersion = optiondata[0]; 3843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman ownerSequence = optiondata[1]; 3853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman ownerPrimaryMacAddress = new byte[] { optiondata[2], optiondata[3], optiondata[4], optiondata[5], optiondata[6], optiondata[7] }; 3863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman ownerWakeupMacAddress = ownerPrimaryMacAddress; 3873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (optiondata.length > 8) { 3883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // We have a wakeupMacAddress. 3893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman ownerWakeupMacAddress = new byte[] { optiondata[8], optiondata[9], optiondata[10], optiondata[11], optiondata[12], optiondata[13] }; 3903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 3913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (optiondata.length == 18) { 3923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // We have a short password. 3933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman ownerPassword = new byte[] { optiondata[14], optiondata[15], optiondata[16], optiondata[17] }; 3943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 3953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (optiondata.length == 22) { 3963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // We have a long password. 3973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman ownerPassword = new byte[] { optiondata[14], optiondata[15], optiondata[16], optiondata[17], optiondata[18], optiondata[19], optiondata[20], optiondata[21] }; 3983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 3993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } catch (Exception exception) { 4003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.warning("Malformed OPT answer. Option code: Owner data: " + this._hexString(optiondata)); 4013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (logger.isLoggable(Level.FINE)) { 4033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.fine("Unhandled Owner OPT version: " + ownerVersion + " sequence: " + ownerSequence + " MAC address: " + this._hexString(ownerPrimaryMacAddress) 4043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman + (ownerWakeupMacAddress != ownerPrimaryMacAddress ? " wakeup MAC address: " + this._hexString(ownerWakeupMacAddress) : "") + (ownerPassword != null ? " password: " + this._hexString(ownerPassword) : "")); 4053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 4073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case LLQ: 4083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case NSID: 4093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case UL: 4103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (logger.isLoggable(Level.FINE)) { 4113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.log(Level.FINE, "There was an OPT answer. Option code: " + optionCode + " data: " + this._hexString(optiondata)); 4123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 4143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman case Unknown: 4153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.log(Level.WARNING, "There was an OPT answer. Not currently handled. Option code: " + optionCodeInt + " data: " + this._hexString(optiondata)); 4163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 4173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman default: 4183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman // This is to keep the compiler happy. 4193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 4203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } else { 4233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.log(Level.WARNING, "There was an OPT answer. Wrong version number: " + version + " result code: " + extendedResultCode); 4243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 4263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman default: 4273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (logger.isLoggable(Level.FINER)) { 4283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman logger.finer("DNSIncoming() unknown type:" + type); 4293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman _messageInputStream.skip(len); 4313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman break; 4323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (rec != null) { 4343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman rec.setRecordSource(source); 4353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return rec; 4373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 4393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /** 4403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * Debugging. 4413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 4423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman String print(boolean dump) { 4433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman StringBuilder buf = new StringBuilder(); 4443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(this.print()); 4453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (dump) { 4463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman byte[] data = new byte[_packet.getLength()]; 4473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman System.arraycopy(_packet.getData(), 0, data, 0, data.length); 4483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(this.print(data)); 4493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return buf.toString(); 4513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 4533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman @Override 4543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public String toString() { 4553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman StringBuilder buf = new StringBuilder(); 4563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(isQuery() ? "dns[query," : "dns[response,"); 4573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (_packet.getAddress() != null) { 4583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(_packet.getAddress().getHostAddress()); 4593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(':'); 4613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(_packet.getPort()); 4623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(", length="); 4633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(_packet.getLength()); 4643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(", id=0x"); 4653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(Integer.toHexString(this.getId())); 4663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (this.getFlags() != 0) { 4673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(", flags=0x"); 4683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(Integer.toHexString(this.getFlags())); 4693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if ((this.getFlags() & DNSConstants.FLAGS_QR_RESPONSE) != 0) { 4703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(":r"); 4713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if ((this.getFlags() & DNSConstants.FLAGS_AA) != 0) { 4733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(":aa"); 4743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if ((this.getFlags() & DNSConstants.FLAGS_TC) != 0) { 4763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(":tc"); 4773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4793742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (this.getNumberOfQuestions() > 0) { 4803742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(", questions="); 4813742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(this.getNumberOfQuestions()); 4823742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4833742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (this.getNumberOfAnswers() > 0) { 4843742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(", answers="); 4853742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(this.getNumberOfAnswers()); 4863742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4873742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (this.getNumberOfAuthorities() > 0) { 4883742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(", authorities="); 4893742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(this.getNumberOfAuthorities()); 4903742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4913742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (this.getNumberOfAdditionals() > 0) { 4923742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(", additionals="); 4933742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(this.getNumberOfAdditionals()); 4943742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 4953742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (this.getNumberOfQuestions() > 0) { 4963742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append("\nquestions:"); 4973742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (DNSQuestion question : _questions) { 4983742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append("\n\t"); 4993742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(question); 5003742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5013742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5023742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (this.getNumberOfAnswers() > 0) { 5033742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append("\nanswers:"); 5043742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (DNSRecord record : _answers) { 5053742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append("\n\t"); 5063742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(record); 5073742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5083742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5093742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (this.getNumberOfAuthorities() > 0) { 5103742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append("\nauthorities:"); 5113742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (DNSRecord record : _authoritativeAnswers) { 5123742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append("\n\t"); 5133742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(record); 5143742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5153742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5163742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (this.getNumberOfAdditionals() > 0) { 5173742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append("\nadditionals:"); 5183742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (DNSRecord record : _additionals) { 5193742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append("\n\t"); 5203742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append(record); 5213742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5223742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5233742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman buf.append("]"); 5243742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return buf.toString(); 5253742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5263742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 5273742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /** 5283742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * Appends answers to this Incoming. 5293742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * 5303742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @exception IllegalArgumentException 5313742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * If not a query or if Truncated. 5323742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 5333742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman void append(DNSIncoming that) { 5343742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman if (this.isQuery() && this.isTruncated() && that.isQuery()) { 5353742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this._questions.addAll(that.getQuestions()); 5363742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this._answers.addAll(that.getAnswers()); 5373742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this._authoritativeAnswers.addAll(that.getAuthorities()); 5383742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman this._additionals.addAll(that.getAdditionals()); 5393742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } else { 5403742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman throw new IllegalArgumentException(); 5413742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5423742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5433742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 5443742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public int elapseSinceArrival() { 5453742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return (int) (System.currentTimeMillis() - _receivedTime); 5463742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5473742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 5483742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /** 5493742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * This will return the default UDP payload except if an OPT record was found with a different size. 5503742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * 5513742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @return the senderUDPPayload 5523742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 5533742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman public int getSenderUDPPayload() { 5543742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return this._senderUDPPayload; 5553742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5563742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 5573742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman private static final char[] _nibbleToHex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 5583742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 5593742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman /** 5603742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * Returns a hex-string for printing 5613742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * 5623742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @param bytes 5633742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman * @return Returns a hex-string which can be used within a SQL expression 5643742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman */ 5653742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman private String _hexString(byte[] bytes) { 5663742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 5673742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman StringBuilder result = new StringBuilder(2 * bytes.length); 5683742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 5693742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman for (int i = 0; i < bytes.length; i++) { 5703742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman int b = bytes[i] & 0xFF; 5713742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman result.append(_nibbleToHex[b / 16]); 5723742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman result.append(_nibbleToHex[b % 16]); 5733742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5743742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 5753742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman return result.toString(); 5763742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman } 5773742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman 5783742d9db8b6edb10627b0f89336cca5249f1d15aManuel Roman} 579