1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.xbill.DNS;
4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.*;
6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.text.*;
7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.*;
8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.utils.*;
9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A generic DNS resource record.  The specific record types extend this class.
12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A record contains a name, type, class, ttl, and rdata.
13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Brian Wellington
15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic abstract class Record implements Cloneable, Comparable, Serializable {
18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final long serialVersionUID = 2694906050116005466L;
20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected Name name;
22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected int type, dclass;
23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected long ttl;
24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final DecimalFormat byteFormat = new DecimalFormat();
26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic {
28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byteFormat.setMinimumIntegerDigits(3);
29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected
32d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenRecord() {}
33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
34d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenRecord(Name name, int type, int dclass, long ttl) {
35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!name.isAbsolute())
36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new RelativeNameException(name);
37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Type.check(type);
38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	DClass.check(dclass);
39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	TTL.check(ttl);
40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.name = name;
41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.type = type;
42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.dclass = dclass;
43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.ttl = ttl;
44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates an empty record of the correct type; must be overriden
48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenabstract Record
50d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetObject();
51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final Record
53d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetEmptyRecord(Name name, int type, int dclass, long ttl, boolean hasData) {
54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Record proto, rec;
55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (hasData) {
57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		proto = Type.getProto(type);
58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (proto != null)
59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			rec = proto.getObject();
60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		else
61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			rec = new UNKRecord();
62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} else
63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		rec = new EmptyRecord();
64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rec.name = name;
65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rec.type = type;
66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rec.dclass = dclass;
67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rec.ttl = ttl;
68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return rec;
69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the type-specific RR to wire format - must be overriden
73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenabstract void
75d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrrFromWire(DNSInput in) throws IOException;
76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static Record
78d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennewRecord(Name name, int type, int dclass, long ttl, int length, DNSInput in)
79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenthrows IOException
80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen{
81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Record rec;
82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rec = getEmptyRecord(name, type, dclass, ttl, in != null);
83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (in != null) {
84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (in.remaining() < length)
85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw new WireParseException("truncated record");
86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		in.setActive(length);
87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		rec.rrFromWire(in);
89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (in.remaining() > 0)
91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw new WireParseException("invalid record length");
92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		in.clearActive();
93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return rec;
95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new record, with the given parameters.
99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The owner name of the record.
100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The record's type.
101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The record's class.
102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ttl The record's time to live.
103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param length The length of the record's data.
104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param data The rdata of the record, in uncompressed DNS wire format.  Only
105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the first length bytes are used.
106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record
108d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennewRecord(Name name, int type, int dclass, long ttl, int length, byte [] data) {
109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!name.isAbsolute())
110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new RelativeNameException(name);
111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Type.check(type);
112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	DClass.check(dclass);
113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	TTL.check(ttl);
114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	DNSInput in;
116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (data != null)
117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		in = new DNSInput(data);
118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	else
119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		in = null;
120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	try {
121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return newRecord(name, type, dclass, ttl, length, in);
122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	catch (IOException e) {
124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return null;
125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new record, with the given parameters.
130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The owner name of the record.
131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The record's type.
132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The record's class.
133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ttl The record's time to live.
134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param data The complete rdata of the record, in uncompressed DNS wire
135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * format.
136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record
138d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennewRecord(Name name, int type, int dclass, long ttl, byte [] data) {
139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return newRecord(name, type, dclass, ttl, data.length, data);
140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new empty record, with the given parameters.
144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The owner name of the record.
145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The record's type.
146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The record's class.
147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ttl The record's time to live.
148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return An object of a subclass of Record
149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record
151d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennewRecord(Name name, int type, int dclass, long ttl) {
152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!name.isAbsolute())
153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new RelativeNameException(name);
154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Type.check(type);
155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	DClass.check(dclass);
156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	TTL.check(ttl);
157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return getEmptyRecord(name, type, dclass, ttl, false);
159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new empty record, with the given parameters.  This method is
163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * designed to create records that will be added to the QUERY section
164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * of a message.
165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The owner name of the record.
166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The record's type.
167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The record's class.
168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return An object of a subclass of Record
169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record
171d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennewRecord(Name name, int type, int dclass) {
172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return newRecord(name, type, dclass, 0);
173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic Record
176d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfromWire(DNSInput in, int section, boolean isUpdate) throws IOException {
177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int type, dclass;
178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	long ttl;
179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int length;
180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Name name;
181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Record rec;
182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	name = new Name(in);
184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	type = in.readU16();
185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	dclass = in.readU16();
186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (section == Section.QUESTION)
188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return newRecord(name, type, dclass);
189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	ttl = in.readU32();
191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	length = in.readU16();
192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (length == 0 && isUpdate &&
193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	    (section == Section.PREREQ || section == Section.UPDATE))
194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return newRecord(name, type, dclass, ttl);
195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rec = newRecord(name, type, dclass, ttl, length, in);
196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return rec;
197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic Record
200d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfromWire(DNSInput in, int section) throws IOException {
201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return fromWire(in, section, false);
202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Builds a Record from DNS uncompressed wire format.
206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record
208d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfromWire(byte [] b, int section) throws IOException {
209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return fromWire(new DNSInput(b), section, false);
210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenvoid
213d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWire(DNSOutput out, int section, Compression c) {
214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	name.toWire(out, c);
215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	out.writeU16(type);
216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	out.writeU16(dclass);
217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (section == Section.QUESTION)
218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return;
219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	out.writeU32(ttl);
220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int lengthPosition = out.current();
221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	out.writeU16(0); /* until we know better */
222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rrToWire(out, c, false);
223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int rrlength = out.current() - lengthPosition - 2;
224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	out.writeU16At(rrlength, lengthPosition);
225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a Record into DNS uncompressed wire format.
229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte []
231d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWire(int section) {
232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	DNSOutput out = new DNSOutput();
233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	toWire(out, section, null);
234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return out.toByteArray();
235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void
238d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWireCanonical(DNSOutput out, boolean noTTL) {
239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	name.toWireCanonical(out);
240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	out.writeU16(type);
241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	out.writeU16(dclass);
242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (noTTL) {
243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		out.writeU32(0);
244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} else {
245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		out.writeU32(ttl);
246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int lengthPosition = out.current();
248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	out.writeU16(0); /* until we know better */
249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rrToWire(out, null, true);
250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int rrlength = out.current() - lengthPosition - 2;
251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	out.writeU16At(rrlength, lengthPosition);
252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/*
255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a Record into canonical DNS uncompressed wire format (all names are
256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * converted to lowercase), optionally ignoring the TTL.
257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate byte []
259d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWireCanonical(boolean noTTL) {
260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	DNSOutput out = new DNSOutput();
261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	toWireCanonical(out, noTTL);
262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return out.toByteArray();
263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a Record into canonical DNS uncompressed wire format (all names are
267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * converted to lowercase).
268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte []
270d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoWireCanonical() {
271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return toWireCanonical(false);
272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the rdata in a Record into canonical DNS uncompressed wire format
276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (all names are converted to lowercase).
277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic byte []
279d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrdataToWireCanonical() {
280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	DNSOutput out = new DNSOutput();
281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rrToWire(out, null, true);
282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return out.toByteArray();
283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the type-specific RR to text format - must be overriden
287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenabstract String rrToString();
289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the rdata portion of a Record into a String representation
292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic String
294d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrdataToString() {
295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return rrToString();
296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a Record into a String representation
300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic String
302d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoString() {
303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	StringBuffer sb = new StringBuffer();
304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	sb.append(name);
305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (sb.length() < 8)
306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append("\t");
307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (sb.length() < 16)
308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append("\t");
309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	sb.append("\t");
310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (Options.check("BINDTTL"))
311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append(TTL.format(ttl));
312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	else
313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append(ttl);
314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	sb.append("\t");
315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (dclass != DClass.IN || !Options.check("noPrintIN")) {
316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append(DClass.string(dclass));
317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append("\t");
318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	sb.append(Type.string(type));
320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	String rdata = rrToString();
321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!rdata.equals("")) {
322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append("\t");
323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append(rdata);
324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return sb.toString();
326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the text format of an RR to the internal format - must be overriden
330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenabstract void
332d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrdataFromString(Tokenizer st, Name origin) throws IOException;
333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a String into a byte array.
336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected static byte []
338d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenbyteArrayFromString(String s) throws TextParseException {
339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] array = s.getBytes();
340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	boolean escaped = false;
341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	boolean hasEscapes = false;
342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = 0; i < array.length; i++) {
344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (array[i] == '\\') {
345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			hasEscapes = true;
346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			break;
347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!hasEscapes) {
350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (array.length > 255) {
351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw new TextParseException("text string too long");
352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return array;
354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	ByteArrayOutputStream os = new ByteArrayOutputStream();
357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int digits = 0;
359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int intval = 0;
360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = 0; i < array.length; i++) {
361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		byte b = array[i];
362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (escaped) {
363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (b >= '0' && b <= '9' && digits < 3) {
364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				digits++;
365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				intval *= 10;
366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				intval += (b - '0');
367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				if (intval > 255)
368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen					throw new TextParseException
369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen								("bad escape");
370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				if (digits < 3)
371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen					continue;
372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				b = (byte) intval;
373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			}
374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			else if (digits > 0 && digits < 3)
375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				throw new TextParseException("bad escape");
376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			os.write(b);
377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			escaped = false;
378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		else if (array[i] == '\\') {
380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			escaped = true;
381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			digits = 0;
382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			intval = 0;
383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		else
385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			os.write(array[i]);
386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (digits > 0 && digits < 3)
388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new TextParseException("bad escape");
389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	array = os.toByteArray();
390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (array.length > 255) {
391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new TextParseException("text string too long");
392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return os.toByteArray();
395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a byte array into a String.
399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected static String
401d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenbyteArrayToString(byte [] array, boolean quote) {
402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	StringBuffer sb = new StringBuffer();
403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (quote)
404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append('"');
405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = 0; i < array.length; i++) {
406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int b = array[i] & 0xFF;
407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (b < 0x20 || b >= 0x7f) {
408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			sb.append('\\');
409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			sb.append(byteFormat.format(b));
410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else if (b == '"' || b == '\\') {
411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			sb.append('\\');
412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			sb.append((char)b);
413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else
414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			sb.append((char)b);
415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (quote)
417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append('"');
418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return sb.toString();
419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a byte array into the unknown RR format.
423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected static String
425d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenunknownToString(byte [] data) {
426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	StringBuffer sb = new StringBuffer();
427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	sb.append("\\# ");
428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	sb.append(data.length);
429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	sb.append(" ");
430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	sb.append(base16.toString(data));
431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return sb.toString();
432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Builds a new Record from its textual representation
436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The owner name of the record.
437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The record's type.
438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The record's class.
439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ttl The record's time to live.
440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param st A tokenizer containing the textual representation of the rdata.
441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param origin The default origin to be appended to relative domain names.
442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The new record
443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException The text format was invalid.
444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record
446d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfromString(Name name, int type, int dclass, long ttl, Tokenizer st, Name origin)
447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenthrows IOException
448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen{
449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Record rec;
450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!name.isAbsolute())
452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new RelativeNameException(name);
453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Type.check(type);
454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	DClass.check(dclass);
455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	TTL.check(ttl);
456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Tokenizer.Token t = st.get();
458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (t.type == Tokenizer.IDENTIFIER && t.value.equals("\\#")) {
459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int length = st.getUInt16();
460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		byte [] data = st.getHex();
461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (data == null) {
462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			data = new byte[0];
463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (length != data.length)
465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw st.exception("invalid unknown RR encoding: " +
466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen					   "length mismatch");
467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		DNSInput in = new DNSInput(data);
468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return newRecord(name, type, dclass, ttl, length, in);
469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	st.unget();
471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rec = getEmptyRecord(name, type, dclass, ttl, true);
472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rec.rdataFromString(st, origin);
473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	t = st.get();
474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (t.type != Tokenizer.EOL && t.type != Tokenizer.EOF) {
475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw st.exception("unexpected tokens at end of record");
476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return rec;
478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Builds a new Record from its textual representation
482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The owner name of the record.
483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The record's type.
484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param dclass The record's class.
485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param ttl The record's time to live.
486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param s The textual representation of the rdata.
487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param origin The default origin to be appended to relative domain names.
488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The new record
489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws IOException The text format was invalid.
490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static Record
492d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfromString(Name name, int type, int dclass, long ttl, String s, Name origin)
493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenthrows IOException
494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen{
495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return fromString(name, type, dclass, ttl, new Tokenizer(s), origin);
496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the record's name
500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Name
501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Name
503d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetName() {
504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return name;
505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the record's type
509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Type
510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int
512d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetType() {
513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return type;
514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
517d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the type of RRset that this record would belong to.  For all types
518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * except RRSIG, this is equivalent to getType().
519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The type of record, if not RRSIG.  If the type is RRSIG,
520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the type covered is returned.
521d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Type
522d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see RRset
523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see SIGRecord
524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int
526d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetRRsetType() {
527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (type == Type.RRSIG) {
528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		RRSIGRecord sig = (RRSIGRecord) this;
529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return sig.getTypeCovered();
530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return type;
532d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
534d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the record's class
536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int
538d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetDClass() {
539d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return dclass;
540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
541d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the record's TTL
544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic long
546d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetTTL() {
547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return ttl;
548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
550d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts the type-specific RR to wire format - must be overriden
552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenabstract void
554d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrrToWire(DNSOutput out, Compression c, boolean canonical);
555d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Determines if two Records could be part of the same RRset.
558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This compares the name, type, and class of the Records; the ttl and
559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * rdata are not compared.
560d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
561d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic boolean
562d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensameRRset(Record rec) {
563d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return (getRRsetType() == rec.getRRsetType() &&
564d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		dclass == rec.dclass &&
565d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		name.equals(rec.name));
566d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
567d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
568d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
569d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Determines if two Records are identical.  This compares the name, type,
570d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * class, and rdata (with names canonicalized).  The TTLs are not compared.
571d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param arg The record to compare to
572d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return true if the records are equal, false otherwise.
573d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
574d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic boolean
575d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenequals(Object arg) {
576d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (arg == null || !(arg instanceof Record))
577d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return false;
578d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Record r = (Record) arg;
579d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (type != r.type || dclass != r.dclass || !name.equals(r.name))
580d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return false;
581d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] array1 = rdataToWireCanonical();
582d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] array2 = r.rdataToWireCanonical();
583d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return Arrays.equals(array1, array2);
584d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
585d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
586d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
587d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Generates a hash code based on the Record's data.
588d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
589d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int
590d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenhashCode() {
591d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] array = toWireCanonical(true);
592d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int code = 0;
593d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = 0; i < array.length; i++)
594d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		code += ((code << 3) + (array[i] & 0xFF));
595d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return code;
596d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
597d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
598d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenRecord
599d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencloneRecord() {
600d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	try {
601d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return (Record) clone();
602d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
603d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	catch (CloneNotSupportedException e) {
604d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalStateException();
605d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
606d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
607d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
608d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
609d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new record identical to the current record, but with a different
610d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * name.  This is most useful for replacing the name of a wildcard record.
611d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
612d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Record
613d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenwithName(Name name) {
614d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!name.isAbsolute())
615d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new RelativeNameException(name);
616d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Record rec = cloneRecord();
617d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rec.name = name;
618d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return rec;
619d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
620d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
621d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
622d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a new record identical to the current record, but with a different
623d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * class and ttl.  This is most useful for dynamic update.
624d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
625d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenRecord
626d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenwithDClass(int dclass, long ttl) {
627d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Record rec = cloneRecord();
628d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rec.dclass = dclass;
629d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	rec.ttl = ttl;
630d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return rec;
631d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
632d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
633d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* Sets the TTL to the specified value.  This is intentionally not public. */
634d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenvoid
635d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChensetTTL(long ttl) {
636d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.ttl = ttl;
637d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
638d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
639d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
640d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Compares this Record to another Object.
641d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param o The Object to be compared.
642d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The value 0 if the argument is a record equivalent to this record;
643d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * a value less than 0 if the argument is less than this record in the
644d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * canonical ordering, and a value greater than 0 if the argument is greater
645d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * than this record in the canonical ordering.  The canonical ordering
646d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * is defined to compare by name, class, type, and rdata.
647d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws ClassCastException if the argument is not a Record.
648d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
649d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int
650d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencompareTo(Object o) {
651d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Record arg = (Record) o;
652d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
653d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (this == arg)
654d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return (0);
655d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
656d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int n = name.compareTo(arg.name);
657d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (n != 0)
658d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return (n);
659d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	n = dclass - arg.dclass;
660d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (n != 0)
661d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return (n);
662d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	n = type - arg.type;
663d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (n != 0)
664d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return (n);
665d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] rdata1 = rdataToWireCanonical();
666d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] rdata2 = arg.rdataToWireCanonical();
667d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = 0; i < rdata1.length && i < rdata2.length; i++) {
668d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		n = (rdata1[i] & 0xFF) - (rdata2[i] & 0xFF);
669d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (n != 0)
670d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return (n);
671d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
672d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return (rdata1.length - rdata2.length);
673d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
674d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
675d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
676d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the name for which additional data processing should be done
677d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * for this record.  This can be used both for building responses and
678d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * parsing responses.
679d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The name to used for additional data processing, or null if this
680d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * record type does not require additional data processing.
681d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
682d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Name
683d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetAdditionalName() {
684d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return null;
685d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
686d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
687d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* Checks that an int contains an unsigned 8 bit value */
688d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic int
689d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencheckU8(String field, int val) {
690d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (val < 0 || val > 0xFF)
691d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("\"" + field + "\" " + val +
692d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						   " must be an unsigned 8 " +
693d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						   "bit value");
694d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return val;
695d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
696d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
697d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* Checks that an int contains an unsigned 16 bit value */
698d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic int
699d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencheckU16(String field, int val) {
700d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (val < 0 || val > 0xFFFF)
701d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("\"" + field + "\" " + val +
702d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						   " must be an unsigned 16 " +
703d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						   "bit value");
704d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return val;
705d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
706d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
707d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* Checks that a long contains an unsigned 32 bit value */
708d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic long
709d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencheckU32(String field, long val) {
710d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (val < 0 || val > 0xFFFFFFFFL)
711d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("\"" + field + "\" " + val +
712d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						   " must be an unsigned 32 " +
713d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						   "bit value");
714d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return val;
715d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
716d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
717d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* Checks that a name is absolute */
718d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic Name
719d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencheckName(String field, Name name) {
720d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!name.isAbsolute())
721d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new RelativeNameException(name);
722d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return name;
723d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
724d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
725d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenstatic byte []
726d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChencheckByteArrayLength(String field, byte [] array, int maxLength) {
727d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (array.length > 0xFFFF)
728d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("\"" + field + "\" array " +
729d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						   "must have no more than " +
730d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						   maxLength + " elements");
731d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] out = new byte[array.length];
732d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	System.arraycopy(array, 0, out, 0, array.length);
733d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return out;
734d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
735d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
736d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
737