1
// Copyright (c) 2004 Brian Wellington (bwelling@xbill.org)
8
import org.xbill.DNS.utils.*;
11
* APL - Address Prefix List. See RFC 3123.
13
* @author Brian Wellington
17
* Note: this currently uses the same constants as the Address class;
18
* this could change if more constants are defined for APL records.
21
public class APLRecord extends Record {
23
public static class Element {
24
public final int family;
25
public final boolean negative;
26
public final int prefixLength;
27
public final Object address;
30
Element(int family, boolean negative, Object address, int prefixLength)
33
this.negative = negative;
34
this.address = address;
35
this.prefixLength = prefixLength;
36
if (!validatePrefixLength(family, prefixLength)) {
37
throw new IllegalArgumentException("invalid prefix " +
43
* Creates an APL element corresponding to an IPv4 or IPv6 prefix.
44
* @param negative Indicates if this prefix is a negation.
45
* @param address The IPv4 or IPv6 address.
46
* @param prefixLength The length of this prefix, in bits.
47
* @throws IllegalArgumentException The prefix length is invalid.
50
Element(boolean negative, InetAddress address, int prefixLength) {
51
this(Address.familyOf(address), negative, address,
57
StringBuffer sb = new StringBuffer();
62
if (family == Address.IPv4 || family == Address.IPv6)
63
sb.append(((InetAddress) address).getHostAddress());
65
sb.append(base16.toString((byte []) address));
67
sb.append(prefixLength);
73
if (arg == null || !(arg instanceof Element))
75
Element elt = (Element) arg;
76
return (family == elt.family &&
77
negative == elt.negative &&
78
prefixLength == elt.prefixLength &&
79
address.equals(elt.address));
83
private List elements;
89
return new APLRecord();
92
private static boolean
93
validatePrefixLength(int family, int prefixLength) {
94
if (prefixLength < 0 || prefixLength >= 256)
96
if ((family == Address.IPv4 && prefixLength > 32) ||
97
(family == Address.IPv6 && prefixLength > 128))
103
* Creates an APL Record from the given data.
104
* @param elements The list of APL elements.
107
APLRecord(Name name, int dclass, long ttl, List elements) {
108
super(name, Type.APL, dclass, ttl);
109
this.elements = new ArrayList(elements.size());
110
for (Iterator it = elements.iterator(); it.hasNext(); ) {
111
Object o = it.next();
112
if (!(o instanceof Element)) {
113
throw new IllegalArgumentException("illegal element");
115
Element element = (Element) o;
116
if (element.family != Address.IPv4 &&
117
element.family != Address.IPv6)
119
throw new IllegalArgumentException("unknown family");
121
this.elements.add(element);
126
private static byte []
127
parseAddress(byte [] in, int length) throws WireParseException {
128
if (in.length > length)
129
throw new WireParseException("invalid address length");
130
if (in.length == length)
132
byte [] out = new byte[length];
133
System.arraycopy(in, 0, out, 0, in.length);
138
rrFromWire(DNSInput in) throws IOException {
139
elements = new ArrayList(1);
140
while (in.remaining() != 0) {
141
int family = in.readU16();
142
int prefix = in.readU8();
143
int length = in.readU8();
144
boolean negative = (length & 0x80) != 0;
147
byte [] data = in.readByteArray(length);
149
if (!validatePrefixLength(family, prefix)) {
150
throw new WireParseException("invalid prefix length");
153
if (family == Address.IPv4 || family == Address.IPv6) {
154
data = parseAddress(data,
155
Address.addressLength(family));
156
InetAddress addr = InetAddress.getByAddress(data);
157
element = new Element(negative, addr, prefix);
159
element = new Element(family, negative, data, prefix);
161
elements.add(element);
167
rdataFromString(Tokenizer st, Name origin) throws IOException {
168
elements = new ArrayList(1);
170
Tokenizer.Token t = st.get();
174
boolean negative = false;
180
if (s.startsWith("!")) {
184
int colon = s.indexOf(':', start);
186
throw st.exception("invalid address prefix element");
187
int slash = s.indexOf('/', colon);
189
throw st.exception("invalid address prefix element");
191
String familyString = s.substring(start, colon);
192
String addressString = s.substring(colon + 1, slash);
193
String prefixString = s.substring(slash + 1);
196
family = Integer.parseInt(familyString);
198
catch (NumberFormatException e) {
199
throw st.exception("invalid family");
201
if (family != Address.IPv4 && family != Address.IPv6)
202
throw st.exception("unknown family");
205
prefix = Integer.parseInt(prefixString);
207
catch (NumberFormatException e) {
208
throw st.exception("invalid prefix length");
211
if (!validatePrefixLength(family, prefix)) {
212
throw st.exception("invalid prefix length");
215
byte [] bytes = Address.toByteArray(addressString, family);
217
throw st.exception("invalid IP address " +
220
InetAddress address = InetAddress.getByAddress(bytes);
221
elements.add(new Element(negative, address, prefix));
228
StringBuffer sb = new StringBuffer();
229
for (Iterator it = elements.iterator(); it.hasNext(); ) {
230
Element element = (Element) it.next();
235
return sb.toString();
238
/** Returns the list of APL elements. */
245
addressLength(byte [] addr) {
246
for (int i = addr.length - 1; i >= 0; i--) {
254
rrToWire(DNSOutput out, Compression c, boolean canonical) {
255
for (Iterator it = elements.iterator(); it.hasNext(); ) {
256
Element element = (Element) it.next();
259
if (element.family == Address.IPv4 ||
260
element.family == Address.IPv6)
262
InetAddress addr = (InetAddress) element.address;
263
data = addr.getAddress();
264
length = addressLength(data);
266
data = (byte []) element.address;
267
length = data.length;
269
int wlength = length;
270
if (element.negative) {
273
out.writeU16(element.family);
274
out.writeU8(element.prefixLength);
275
out.writeU8(wlength);
276
out.writeByteArray(data, 0, length);