aboutsummaryrefslogtreecommitdiff
path: root/src/org/xbill/DNS/APLRecord.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/xbill/DNS/APLRecord.java')
-rw-r--r--src/org/xbill/DNS/APLRecord.java287
1 files changed, 287 insertions, 0 deletions
diff --git a/src/org/xbill/DNS/APLRecord.java b/src/org/xbill/DNS/APLRecord.java
new file mode 100644
index 0000000..5940da2
--- /dev/null
+++ b/src/org/xbill/DNS/APLRecord.java
@@ -0,0 +1,287 @@
+// Copyright (c) 2004 Brian Wellington (bwelling@xbill.org)
+
+package org.xbill.DNS;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import org.xbill.DNS.utils.*;
+
+/**
+ * APL - Address Prefix List. See RFC 3123.
+ *
+ * @author Brian Wellington
+ */
+
+/*
+ * Note: this currently uses the same constants as the Address class;
+ * this could change if more constants are defined for APL records.
+ */
+
+public class APLRecord extends Record {
+
+public static class Element {
+ public final int family;
+ public final boolean negative;
+ public final int prefixLength;
+ public final Object address;
+
+ private
+ Element(int family, boolean negative, Object address, int prefixLength)
+ {
+ this.family = family;
+ this.negative = negative;
+ this.address = address;
+ this.prefixLength = prefixLength;
+ if (!validatePrefixLength(family, prefixLength)) {
+ throw new IllegalArgumentException("invalid prefix " +
+ "length");
+ }
+ }
+
+ /**
+ * Creates an APL element corresponding to an IPv4 or IPv6 prefix.
+ * @param negative Indicates if this prefix is a negation.
+ * @param address The IPv4 or IPv6 address.
+ * @param prefixLength The length of this prefix, in bits.
+ * @throws IllegalArgumentException The prefix length is invalid.
+ */
+ public
+ Element(boolean negative, InetAddress address, int prefixLength) {
+ this(Address.familyOf(address), negative, address,
+ prefixLength);
+ }
+
+ public String
+ toString() {
+ StringBuffer sb = new StringBuffer();
+ if (negative)
+ sb.append("!");
+ sb.append(family);
+ sb.append(":");
+ if (family == Address.IPv4 || family == Address.IPv6)
+ sb.append(((InetAddress) address).getHostAddress());
+ else
+ sb.append(base16.toString((byte []) address));
+ sb.append("/");
+ sb.append(prefixLength);
+ return sb.toString();
+ }
+
+ public boolean
+ equals(Object arg) {
+ if (arg == null || !(arg instanceof Element))
+ return false;
+ Element elt = (Element) arg;
+ return (family == elt.family &&
+ negative == elt.negative &&
+ prefixLength == elt.prefixLength &&
+ address.equals(elt.address));
+ }
+
+ public int
+ hashCode() {
+ return address.hashCode() + prefixLength + (negative ? 1 : 0);
+ }
+}
+
+private static final long serialVersionUID = -1348173791712935864L;
+
+private List elements;
+
+APLRecord() {}
+
+Record
+getObject() {
+ return new APLRecord();
+}
+
+private static boolean
+validatePrefixLength(int family, int prefixLength) {
+ if (prefixLength < 0 || prefixLength >= 256)
+ return false;
+ if ((family == Address.IPv4 && prefixLength > 32) ||
+ (family == Address.IPv6 && prefixLength > 128))
+ return false;
+ return true;
+}
+
+/**
+ * Creates an APL Record from the given data.
+ * @param elements The list of APL elements.
+ */
+public
+APLRecord(Name name, int dclass, long ttl, List elements) {
+ super(name, Type.APL, dclass, ttl);
+ this.elements = new ArrayList(elements.size());
+ for (Iterator it = elements.iterator(); it.hasNext(); ) {
+ Object o = it.next();
+ if (!(o instanceof Element)) {
+ throw new IllegalArgumentException("illegal element");
+ }
+ Element element = (Element) o;
+ if (element.family != Address.IPv4 &&
+ element.family != Address.IPv6)
+ {
+ throw new IllegalArgumentException("unknown family");
+ }
+ this.elements.add(element);
+
+ }
+}
+
+private static byte []
+parseAddress(byte [] in, int length) throws WireParseException {
+ if (in.length > length)
+ throw new WireParseException("invalid address length");
+ if (in.length == length)
+ return in;
+ byte [] out = new byte[length];
+ System.arraycopy(in, 0, out, 0, in.length);
+ return out;
+}
+
+void
+rrFromWire(DNSInput in) throws IOException {
+ elements = new ArrayList(1);
+ while (in.remaining() != 0) {
+ int family = in.readU16();
+ int prefix = in.readU8();
+ int length = in.readU8();
+ boolean negative = (length & 0x80) != 0;
+ length &= ~0x80;
+
+ byte [] data = in.readByteArray(length);
+ Element element;
+ if (!validatePrefixLength(family, prefix)) {
+ throw new WireParseException("invalid prefix length");
+ }
+
+ if (family == Address.IPv4 || family == Address.IPv6) {
+ data = parseAddress(data,
+ Address.addressLength(family));
+ InetAddress addr = InetAddress.getByAddress(data);
+ element = new Element(negative, addr, prefix);
+ } else {
+ element = new Element(family, negative, data, prefix);
+ }
+ elements.add(element);
+
+ }
+}
+
+void
+rdataFromString(Tokenizer st, Name origin) throws IOException {
+ elements = new ArrayList(1);
+ while (true) {
+ Tokenizer.Token t = st.get();
+ if (!t.isString())
+ break;
+
+ boolean negative = false;
+ int family = 0;
+ int prefix = 0;
+
+ String s = t.value;
+ int start = 0;
+ if (s.startsWith("!")) {
+ negative = true;
+ start = 1;
+ }
+ int colon = s.indexOf(':', start);
+ if (colon < 0)
+ throw st.exception("invalid address prefix element");
+ int slash = s.indexOf('/', colon);
+ if (slash < 0)
+ throw st.exception("invalid address prefix element");
+
+ String familyString = s.substring(start, colon);
+ String addressString = s.substring(colon + 1, slash);
+ String prefixString = s.substring(slash + 1);
+
+ try {
+ family = Integer.parseInt(familyString);
+ }
+ catch (NumberFormatException e) {
+ throw st.exception("invalid family");
+ }
+ if (family != Address.IPv4 && family != Address.IPv6)
+ throw st.exception("unknown family");
+
+ try {
+ prefix = Integer.parseInt(prefixString);
+ }
+ catch (NumberFormatException e) {
+ throw st.exception("invalid prefix length");
+ }
+
+ if (!validatePrefixLength(family, prefix)) {
+ throw st.exception("invalid prefix length");
+ }
+
+ byte [] bytes = Address.toByteArray(addressString, family);
+ if (bytes == null)
+ throw st.exception("invalid IP address " +
+ addressString);
+
+ InetAddress address = InetAddress.getByAddress(bytes);
+ elements.add(new Element(negative, address, prefix));
+ }
+ st.unget();
+}
+
+String
+rrToString() {
+ StringBuffer sb = new StringBuffer();
+ for (Iterator it = elements.iterator(); it.hasNext(); ) {
+ Element element = (Element) it.next();
+ sb.append(element);
+ if (it.hasNext())
+ sb.append(" ");
+ }
+ return sb.toString();
+}
+
+/** Returns the list of APL elements. */
+public List
+getElements() {
+ return elements;
+}
+
+private static int
+addressLength(byte [] addr) {
+ for (int i = addr.length - 1; i >= 0; i--) {
+ if (addr[i] != 0)
+ return i + 1;
+ }
+ return 0;
+}
+
+void
+rrToWire(DNSOutput out, Compression c, boolean canonical) {
+ for (Iterator it = elements.iterator(); it.hasNext(); ) {
+ Element element = (Element) it.next();
+ int length = 0;
+ byte [] data;
+ if (element.family == Address.IPv4 ||
+ element.family == Address.IPv6)
+ {
+ InetAddress addr = (InetAddress) element.address;
+ data = addr.getAddress();
+ length = addressLength(data);
+ } else {
+ data = (byte []) element.address;
+ length = data.length;
+ }
+ int wlength = length;
+ if (element.negative) {
+ wlength |= 0x80;
+ }
+ out.writeU16(element.family);
+ out.writeU8(element.prefixLength);
+ out.writeU8(wlength);
+ out.writeByteArray(data, 0, length);
+ }
+}
+
+}