1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Copyright (c) 2004 Brian Wellington (bwelling@xbill.org)
2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.xbill.DNS;
4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.*;
6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.net.*;
7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.*;
8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.utils.*;
9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * APL - Address Prefix List.  See RFC 3123.
12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Brian Wellington
14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/*
17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Note: this currently uses the same constants as the Address class;
18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * this could change if more constants are defined for APL records.
19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class APLRecord extends Record {
22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static class Element {
24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	public final int family;
25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	public final boolean negative;
26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	public final int prefixLength;
27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	public final Object address;
28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	private
30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Element(int family, boolean negative, Object address, int prefixLength)
31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	{
32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.family = family;
33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.negative = negative;
34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.address = address;
35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.prefixLength = prefixLength;
36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (!validatePrefixLength(family, prefixLength)) {
37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw new IllegalArgumentException("invalid prefix " +
38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen							   "length");
39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	/**
43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	 * Creates an APL element corresponding to an IPv4 or IPv6 prefix.
44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	 * @param negative Indicates if this prefix is a negation.
45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	 * @param address The IPv4 or IPv6 address.
46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	 * @param prefixLength The length of this prefix, in bits.
47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	 * @throws IllegalArgumentException The prefix length is invalid.
48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	 */
49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	public
50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Element(boolean negative, InetAddress address, int prefixLength) {
51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this(Address.familyOf(address), negative, address,
52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		     prefixLength);
53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	public String
56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	toString() {
57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		StringBuffer sb = new StringBuffer();
58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (negative)
59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			sb.append("!");
60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append(family);
61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append(":");
62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (family == Address.IPv4 || family == Address.IPv6)
63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			sb.append(((InetAddress) address).getHostAddress());
64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		else
65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			sb.append(base16.toString((byte []) address));
66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append("/");
67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append(prefixLength);
68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return sb.toString();
69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	public boolean
72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	equals(Object arg) {
73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (arg == null || !(arg instanceof Element))
74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return false;
75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Element elt = (Element) arg;
76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return (family == elt.family &&
77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			negative == elt.negative &&
78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			prefixLength == elt.prefixLength &&
79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			address.equals(elt.address));
80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	public int
83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	hashCode() {
84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return address.hashCode() + prefixLength + (negative ? 1 : 0);
85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final long serialVersionUID = -1348173791712935864L;
89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate List elements;
91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
92d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenAPLRecord() {}
93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
94d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenRecord
95d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetObject() {
96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return new APLRecord();
97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static boolean
100d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenvalidatePrefixLength(int family, int prefixLength) {
101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (prefixLength < 0 || prefixLength >= 256)
102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return false;
103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if ((family == Address.IPv4 && prefixLength > 32) ||
104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	    (family == Address.IPv6 && prefixLength > 128))
105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return false;
106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return true;
107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates an APL Record from the given data.
111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param elements The list of APL elements.
112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic
114d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenAPLRecord(Name name, int dclass, long ttl, List elements) {
115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	super(name, Type.APL, dclass, ttl);
116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	this.elements = new ArrayList(elements.size());
117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (Iterator it = elements.iterator(); it.hasNext(); ) {
118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Object o = it.next();
119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (!(o instanceof Element)) {
120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw new IllegalArgumentException("illegal element");
121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Element element = (Element) o;
123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (element.family != Address.IPv4 &&
124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		    element.family != Address.IPv6)
125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		{
126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw new IllegalArgumentException("unknown family");
127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		this.elements.add(element);
129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static byte []
134d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenparseAddress(byte [] in, int length) throws WireParseException {
135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (in.length > length)
136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new WireParseException("invalid address length");
137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (in.length == length)
138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return in;
139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] out = new byte[length];
140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	System.arraycopy(in, 0, out, 0, in.length);
141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return out;
142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenvoid
145d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrrFromWire(DNSInput in) throws IOException {
146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	elements = new ArrayList(1);
147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	while (in.remaining() != 0) {
148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int family = in.readU16();
149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int prefix = in.readU8();
150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int length = in.readU8();
151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		boolean negative = (length & 0x80) != 0;
152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		length &= ~0x80;
153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		byte [] data = in.readByteArray(length);
155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Element element;
156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (!validatePrefixLength(family, prefix)) {
157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw new WireParseException("invalid prefix length");
158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (family == Address.IPv4 || family == Address.IPv6) {
161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			data = parseAddress(data,
162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen					    Address.addressLength(family));
163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			InetAddress addr = InetAddress.getByAddress(data);
164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			element = new Element(negative, addr, prefix);
165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else {
166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			element = new Element(family, negative, data, prefix);
167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		elements.add(element);
169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenvoid
174d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrdataFromString(Tokenizer st, Name origin) throws IOException {
175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	elements = new ArrayList(1);
176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	while (true) {
177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Tokenizer.Token t = st.get();
178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (!t.isString())
179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			break;
180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		boolean negative = false;
182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int family = 0;
183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int prefix = 0;
184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		String s = t.value;
186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int start = 0;
187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (s.startsWith("!")) {
188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			negative = true;
189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			start = 1;
190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int colon = s.indexOf(':', start);
192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (colon < 0)
193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw st.exception("invalid address prefix element");
194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int slash = s.indexOf('/', colon);
195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (slash < 0)
196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw st.exception("invalid address prefix element");
197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		String familyString = s.substring(start, colon);
199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		String addressString = s.substring(colon + 1, slash);
200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		String prefixString = s.substring(slash + 1);
201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		try {
203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			family = Integer.parseInt(familyString);
204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		catch (NumberFormatException e) {
206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw st.exception("invalid family");
207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (family != Address.IPv4 && family != Address.IPv6)
209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw st.exception("unknown family");
210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		try {
212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			prefix = Integer.parseInt(prefixString);
213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		catch (NumberFormatException e) {
215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw st.exception("invalid prefix length");
216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (!validatePrefixLength(family, prefix)) {
219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw st.exception("invalid prefix length");
220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		byte [] bytes = Address.toByteArray(addressString, family);
223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (bytes == null)
224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw st.exception("invalid IP address " +
225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen					   addressString);
226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		InetAddress address = InetAddress.getByAddress(bytes);
228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		elements.add(new Element(negative, address, prefix));
229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	st.unget();
231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
233d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenString
234d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrrToString() {
235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	StringBuffer sb = new StringBuffer();
236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (Iterator it = elements.iterator(); it.hasNext(); ) {
237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Element element = (Element) it.next();
238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		sb.append(element);
239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (it.hasNext())
240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			sb.append(" ");
241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return sb.toString();
243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Returns the list of APL elements. */
246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic List
247d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetElements() {
248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return elements;
249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static int
252d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenaddressLength(byte [] addr) {
253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = addr.length - 1; i >= 0; i--) {
254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (addr[i] != 0)
255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return i + 1;
256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return 0;
258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenvoid
261d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenrrToWire(DNSOutput out, Compression c, boolean canonical) {
262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (Iterator it = elements.iterator(); it.hasNext(); ) {
263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Element element = (Element) it.next();
264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int length = 0;
265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		byte [] data;
266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (element.family == Address.IPv4 ||
267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		    element.family == Address.IPv6)
268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		{
269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			InetAddress addr = (InetAddress) element.address;
270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			data = addr.getAddress();
271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			length = addressLength(data);
272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else {
273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			data = (byte []) element.address;
274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			length = data.length;
275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int wlength = length;
277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (element.negative) {
278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			wlength |= 0x80;
279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		out.writeU16(element.family);
281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		out.writeU8(element.prefixLength);
282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		out.writeU8(wlength);
283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		out.writeByteArray(data, 0, length);
284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
288