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