~ubuntu-branches/ubuntu/wily/dnsjava/wily-proposed

« back to all changes in this revision

Viewing changes to org/xbill/DNS/APLRecord.java

  • Committer: Bazaar Package Importer
  • Author(s): Thierry Carrez
  • Date: 2009-07-21 15:17:03 UTC
  • Revision ID: james.westby@ubuntu.com-20090721151703-6v0107p1s3h7gv1c
Tags: upstream-2.0.6
ImportĀ upstreamĀ versionĀ 2.0.6

Show diffs side-by-side

added added

removed removed

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