1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org) 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.xbill.DNS; 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.*; 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.*; 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A DNS Message. A message is the basic unit of communication between 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the client and server of a DNS operation. A message consists of a Header 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and 4 message sections. 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Resolver 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Header 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Brian Wellington 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class Message implements Cloneable { 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** The maximum length of a message in wire format. */ 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int MAXLENGTH = 65535; 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate Header header; 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate List [] sections; 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int size; 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate TSIG tsigkey; 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate TSIGRecord querytsig; 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int tsigerror; 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenint tsigstart; 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenint tsigState; 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenint sig0start; 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* The message was not signed */ 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic final int TSIG_UNSIGNED = 0; 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* The message was signed and verification succeeded */ 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic final int TSIG_VERIFIED = 1; 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* The message was an unsigned message in multiple-message response */ 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic final int TSIG_INTERMEDIATE = 2; 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* The message was signed and no verification was attempted. */ 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic final int TSIG_SIGNED = 3; 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The message was signed and verification failed, or was not signed 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * when it should have been. 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic final int TSIG_FAILED = 4; 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static Record [] emptyRecordArray = new Record[0]; 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static RRset [] emptyRRsetArray = new RRset[0]; 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenMessage(Header header) { 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sections = new List[4]; 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.header = header; 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Creates a new Message with the specified Message ID */ 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenMessage(int id) { 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this(new Header(id)); 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Creates a new Message with a random Message ID */ 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenMessage() { 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this(new Header()); 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new Message with a random Message ID suitable for sending as a 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * query. 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param r A record containing the question 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Message 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennewQuery(Record r) { 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message m = new Message(); 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen m.header.setOpcode(Opcode.QUERY); 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen m.header.setFlag(Flags.RD); 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen m.addRecord(r, Section.QUESTION); 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return m; 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new Message to contain a dynamic update. A random Message ID 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * and the zone are filled in. 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param zone The zone to be updated 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Message 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennewUpdate(Name zone) { 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return new Update(zone); 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenMessage(DNSInput in) throws IOException { 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this(new Header(in)); 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean isUpdate = (header.getOpcode() == Opcode.UPDATE); 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean truncated = header.getFlag(Flags.TC); 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < 4; i++) { 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int count = header.getCount(i); 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (count > 0) 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sections[i] = new ArrayList(count); 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int j = 0; j < count; j++) { 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int pos = in.current(); 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record rec = Record.fromWire(in, i, isUpdate); 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sections[i].add(rec); 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (i == Section.ADDITIONAL) { 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (rec.getType() == Type.TSIG) 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen tsigstart = pos; 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (rec.getType() == Type.SIG) { 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen SIGRecord sig = (SIGRecord) rec; 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sig.getTypeCovered() == 0) 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sig0start = pos; 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (WireParseException e) { 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (!truncated) 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw e; 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen size = in.current(); 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new Message from its DNS wire format representation 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param b A byte array containing the DNS Message. 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenMessage(byte [] b) throws IOException { 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this(new DNSInput(b)); 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Replaces the Header with a new one. 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Header 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetHeader(Header h) { 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen header = h; 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Retrieves the Header. 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Header 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Header 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetHeader() { 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return header; 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a record to a section of the Message, and adjusts the header. 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Record 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenaddRecord(Record r, int section) { 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sections[section] == null) 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sections[section] = new LinkedList(); 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen header.incCount(section); 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sections[section].add(r); 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes a record from a section of the Message, and adjusts the header. 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Record 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic boolean 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenremoveRecord(Record r, int section) { 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sections[section] != null && sections[section].remove(r)) { 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen header.decCount(section); 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes all records from a section of the Message, and adjusts the header. 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Record 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenremoveAllRecords(int section) { 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sections[section] = null; 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen header.setCount(section, 0); 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Determines if the given record is already present in the given section. 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Record 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic boolean 201d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfindRecord(Record r, int section) { 202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (sections[section] != null && sections[section].contains(r)); 203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Determines if the given record is already present in any section. 207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Record 208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic boolean 211d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfindRecord(Record r) { 212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = Section.ANSWER; i <= Section.ADDITIONAL; i++) 213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sections[i] != null && sections[i].contains(r)) 214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Determines if an RRset with the given name and type is already 220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * present in the given section. 221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see RRset 222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic boolean 225d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfindRRset(Name name, int type, int section) { 226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sections[section] == null) 227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < sections[section].size(); i++) { 229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record r = (Record) sections[section].get(i); 230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (r.getType() == type && name.equals(r.getName())) 231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Determines if an RRset with the given name and type is already 238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * present in any section. 239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see RRset 240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic boolean 243d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfindRRset(Name name, int type) { 244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (findRRset(name, type, Section.ANSWER) || 245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen findRRset(name, type, Section.AUTHORITY) || 246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen findRRset(name, type, Section.ADDITIONAL)); 247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the first record in the QUESTION section. 251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Record 252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Record 255d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetQuestion() { 256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List l = sections[Section.QUESTION]; 257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (l == null || l.size() == 0) 258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (Record) l.get(0); 260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the TSIG record from the ADDITIONAL section, if one is present. 264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see TSIGRecord 265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see TSIG 266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic TSIGRecord 269d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetTSIG() { 270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int count = header.getCount(Section.ADDITIONAL); 271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (count == 0) 272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List l = sections[Section.ADDITIONAL]; 274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record rec = (Record) l.get(count - 1); 275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (rec.type != Type.TSIG) 276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (TSIGRecord) rec; 278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Was this message signed by a TSIG? 282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see TSIG 283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic boolean 285d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenisSigned() { 286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (tsigState == TSIG_SIGNED || 287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen tsigState == TSIG_VERIFIED || 288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen tsigState == TSIG_FAILED); 289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If this message was signed by a TSIG, was the TSIG verified? 293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see TSIG 294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic boolean 296d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenisVerified() { 297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (tsigState == TSIG_VERIFIED); 298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the OPT record from the ADDITIONAL section, if one is present. 302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see OPTRecord 303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic OPTRecord 306d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetOPT() { 307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record [] additional = getSectionArray(Section.ADDITIONAL); 308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < additional.length; i++) 309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (additional[i] instanceof OPTRecord) 310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (OPTRecord) additional[i]; 311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the message's rcode (error code). This incorporates the EDNS 316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * extended rcode. 317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int 319d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetRcode() { 320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int rcode = header.getRcode(); 321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen OPTRecord opt = getOPT(); 322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (opt != null) 323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rcode += (opt.getExtendedRcode() << 4); 324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return rcode; 325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns an array containing all records in the given section, or an 329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * empty array if the section is empty. 330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Record 331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Record [] 334d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetSectionArray(int section) { 335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sections[section] == null) 336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return emptyRecordArray; 337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List l = sections[section]; 338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (Record []) l.toArray(new Record[l.size()]); 339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static boolean 342d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensameSet(Record r1, Record r2) { 343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (r1.getRRsetType() == r2.getRRsetType() && 344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen r1.getDClass() == r2.getDClass() && 345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen r1.getName().equals(r2.getName())); 346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns an array containing all records in the given section grouped into 350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * RRsets. 351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see RRset 352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic RRset [] 355d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetSectionRRsets(int section) { 356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sections[section] == null) 357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return emptyRRsetArray; 358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen List sets = new LinkedList(); 359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record [] recs = getSectionArray(section); 360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Set hash = new HashSet(); 361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < recs.length; i++) { 362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Name name = recs[i].getName(); 363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean newset = true; 364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (hash.contains(name)) { 365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int j = sets.size() - 1; j >= 0; j--) { 366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen RRset set = (RRset) sets.get(j); 367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (set.getType() == recs[i].getRRsetType() && 368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen set.getDClass() == recs[i].getDClass() && 369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen set.getName().equals(name)) 370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen set.addRR(recs[i]); 372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen newset = false; 373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen break; 374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (newset) { 378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen RRset set = new RRset(recs[i]); 379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sets.add(set); 380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen hash.add(name); 381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (RRset []) sets.toArray(new RRset[sets.size()]); 384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenvoid 387d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWire(DNSOutput out) { 388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen header.toWire(out); 389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Compression c = new Compression(); 390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < 4; i++) { 391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sections[i] == null) 392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen continue; 393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int j = 0; j < sections[i].size(); j++) { 394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record rec = (Record)sections[i].get(j); 395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec.toWire(out, i, c); 396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* Returns the number of records not successfully rendered. */ 401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int 402d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensectionToWire(DNSOutput out, int section, Compression c, 403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int maxLength) 404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen{ 405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int n = sections[section].size(); 406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int pos = out.current(); 407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int rendered = 0; 408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record lastrec = null; 409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < n; i++) { 411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record rec = (Record)sections[section].get(i); 412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (lastrec != null && !sameSet(rec, lastrec)) { 413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen pos = out.current(); 414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rendered = i; 415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen lastrec = rec; 417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen rec.toWire(out, section, c); 418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (out.current() > maxLength) { 419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.jump(pos); 420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return n - rendered; 421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return 0; 424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* Returns true if the message could be rendered. */ 427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean 428d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWire(DNSOutput out, int maxLength) { 429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (maxLength < Header.LENGTH) 430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return false; 431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Header newheader = null; 433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int tempMaxLength = maxLength; 435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (tsigkey != null) 436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen tempMaxLength -= tsigkey.recordLength(); 437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int startpos = out.current(); 439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen header.toWire(out); 440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Compression c = new Compression(); 441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < 4; i++) { 442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int skipped; 443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sections[i] == null) 444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen continue; 445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen skipped = sectionToWire(out, i, c, tempMaxLength); 446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (skipped != 0) { 447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (newheader == null) 448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen newheader = (Header) header.clone(); 449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (i != Section.ADDITIONAL) 450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen newheader.setFlag(Flags.TC); 451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int count = newheader.getCount(i); 452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen newheader.setCount(i, count - skipped); 453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int j = i + 1; j < 4; j++) 454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen newheader.setCount(j, 0); 455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.save(); 457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.jump(startpos); 458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen newheader.toWire(out); 459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.restore(); 460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen break; 461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (tsigkey != null) { 465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen TSIGRecord tsigrec = tsigkey.generate(this, out.toByteArray(), 466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen tsigerror, querytsig); 467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (newheader == null) 469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen newheader = (Header) header.clone(); 470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen tsigrec.toWire(out, Section.ADDITIONAL, c); 471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen newheader.incCount(Section.ADDITIONAL); 472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.save(); 474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.jump(startpos); 475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen newheader.toWire(out); 476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen out.restore(); 477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns an array containing the wire format representation of the Message. 484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte [] 486d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWire() { 487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DNSOutput out = new DNSOutput(); 488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen toWire(out); 489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen size = out.current(); 490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return out.toByteArray(); 491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns an array containing the wire format representation of the Message 495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * with the specified maximum length. This will generate a truncated 496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * message (with the TC bit) if the message doesn't fit, and will also 497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * sign the message with the TSIG key set by a call to setTSIG(). This 498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * method may return null if the message could not be rendered at all; this 499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * could happen if maxLength is smaller than a DNS header, for example. 500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param maxLength The maximum length of the message. 501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The wire format of the message, or null if the message could not be 502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * rendered into the specified length. 503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Flags 504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see TSIG 505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte [] 507d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWire(int maxLength) { 508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DNSOutput out = new DNSOutput(); 509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen toWire(out, maxLength); 510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen size = out.current(); 511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return out.toByteArray(); 512d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Sets the TSIG key and other necessary information to sign a message. 516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param key The TSIG key. 517d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param error The value of the TSIG error field. 518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param querytsig If this is a response, the TSIG from the request. 519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void 521d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetTSIG(TSIG key, int error, TSIGRecord querytsig) { 522d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.tsigkey = key; 523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.tsigerror = error; 524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.querytsig = querytsig; 525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 526d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the size of the message. Only valid if the message has been 529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * converted to or from wire format. 530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int 532d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennumBytes() { 533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return size; 534d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the given section of the Message to a String. 538d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Section 539d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic String 541d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensectionToString(int i) { 542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (i > 3) 543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringBuffer sb = new StringBuffer(); 546d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record [] records = getSectionArray(i); 548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int j = 0; j < records.length; j++) { 549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record rec = records[j]; 550d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (i == Section.QUESTION) { 551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(";;\t" + rec.name); 552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(", type = " + Type.string(rec.type)); 553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(", class = " + DClass.string(rec.dclass)); 554d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 555d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(rec); 557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append("\n"); 558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return sb.toString(); 560d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 561d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 562d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 563d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the Message to a String. 564d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 565d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic String 566d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoString() { 567d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringBuffer sb = new StringBuffer(); 568d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen OPTRecord opt = getOPT(); 569d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (opt != null) 570d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(header.toStringWithRcode(getRcode()) + "\n"); 571d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 572d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(header + "\n"); 573d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isSigned()) { 574d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(";; TSIG "); 575d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (isVerified()) 576d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append("ok"); 577d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 578d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append("invalid"); 579d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append('\n'); 580d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 581d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < 4; i++) { 582d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (header.getOpcode() != Opcode.UPDATE) 583d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(";; " + Section.longString(i) + ":\n"); 584d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 585d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(";; " + Section.updString(i) + ":\n"); 586d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(sectionToString(i) + "\n"); 587d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 588d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen sb.append(";; Message size: " + numBytes() + " bytes"); 589d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return sb.toString(); 590d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 591d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 592d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 593d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a copy of this Message. This is done by the Resolver before adding 594d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * TSIG and OPT records, for example. 595d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Resolver 596d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see TSIGRecord 597d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see OPTRecord 598d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 599d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Object 600d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenclone() { 601d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Message m = new Message(); 602d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < sections.length; i++) { 603d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (sections[i] != null) 604d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen m.sections[i] = new LinkedList(sections[i]); 605d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 606d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen m.header = (Header) header.clone(); 607d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen m.size = size; 608d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return m; 609d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 610d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 611d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 612