-
Notifications
You must be signed in to change notification settings - Fork 264
Expand file tree
/
Copy pathEDNSOption.java
More file actions
363 lines (320 loc) · 9.35 KB
/
Copy pathEDNSOption.java
File metadata and controls
363 lines (320 loc) · 9.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
package org.xbill.DNS;
import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
/**
* DNS extension options, as described in RFC 6891. The rdata of an OPT record is defined as a list
* of options; this represents a single option.
*
* @author Brian Wellington
* @author Ming Zhou <mizhou@bnivideo.com>, Beaumaris Networks
*/
public abstract class EDNSOption implements Serializable {
/**
* @see <a
* href="https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-11">IANA
* DNS EDNS0 Option Codes (OPT)</a>
*/
public static class Code {
private Code() {}
/**
* Apple's DNS Long-Lived Queries protocol.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc8764/">RFC 8764</a>
*/
public static final int LLQ = 1;
/**
* Dynamic DNS Update Leases.
*
* @see <a
* href="https://datatracker.ietf.org/doc/html/draft-sekar-dns-ul-03">draft-sekar-dns-ul-03</a>
*/
public static final int UL = 2;
/**
* Name Server Identifier.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc5001/">RFC 5001</a>
*/
public static final int NSID = 3;
/**
* DNSSEC Algorithm Understood (DAU).
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc6975/">RFC 6975</a>
*/
public static final int DAU = 5;
/**
* DNSSEC DS Hash Understood (DHU).
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc8764/">RFC 8764</a>
*/
public static final int DHU = 6;
/**
* DNSSEC NSEC3 Hash Understood (N3U).
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc6975/">RFC 6975</a>
*/
public static final int N3U = 7;
/**
* Client Subnet.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc7871/">RFC 7871</a>
*/
public static final int CLIENT_SUBNET = 8;
/**
* (EDNS) EXPIRE Option.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc7314/">RFC 7314</a>
*/
public static final int EDNS_EXPIRE = 9;
/**
* Cookie.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc7873/">RFC 7873</a>
*/
public static final int COOKIE = 10;
/**
* TCP Keepalive.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc7828/">RFC 7828</a>
*/
public static final int TCP_KEEPALIVE = 11;
/**
* EDNS(0) Padding Option.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc7830/">RFC 7830</a>
*/
public static final int PADDING = 12;
/**
* CHAIN Query Requests in DNS.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc7901/">RFC 7901</a>
*/
public static final int CHAIN = 13;
/**
* Signaling Trust Anchor Knowledge in DNS Security Extensions (DNSSEC).
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc8145/">RFC 8145</a>
*/
public static final int EDNS_KEY_TAG = 14;
/**
* Extended DNS Errors.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc8914/">RFC 8914</a>
*/
public static final int EDNS_EXTENDED_ERROR = 15;
/**
* DNS EDNS Tags.
*
* @see <a
* href="https://datatracker.ietf.org/doc/html/draft-bellis-dnsop-edns-tags-01">draft-bellis-dnsop-edns-tags-01</a>
*/
public static final int EDNS_CLIENT_TAG = 16;
/**
* DNS EDNS Tags.
*
* @see <a
* href="https://datatracker.ietf.org/doc/html/draft-bellis-dnsop-edns-tags-01">draft-bellis-dnsop-edns-tags-01</a>
*/
public static final int EDNS_SERVER_TAG = 17;
/**
* Report Channel.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc9567/">RFC 9567</a>
* @since 3.6
*/
public static final int REPORT_CHANNEL = 18;
/**
* Report Channel.
*
* @since 3.6.5
* @see <a href="https://datatracker.ietf.org/doc/html/rfc9660/">RFC 9660</a>
*/
public static final int ZONEVERSION = 19;
private static final Mnemonic codes =
new Mnemonic("EDNS Option Codes", Mnemonic.CASE_SENSITIVE);
static {
codes.setMaximum(0xFFFF);
codes.setPrefix("CODE");
codes.setNumericAllowed(true);
codes.add(LLQ, "LLQ");
codes.add(UL, "UL");
codes.add(NSID, "NSID");
codes.add(DAU, "DAU");
codes.add(DHU, "DHU");
codes.add(N3U, "N3U");
codes.add(CLIENT_SUBNET, "edns-client-subnet");
codes.add(EDNS_EXPIRE, "EDNS_EXPIRE");
codes.add(COOKIE, "COOKIE");
codes.add(TCP_KEEPALIVE, "edns-tcp-keepalive");
codes.add(PADDING, "Padding");
codes.add(CHAIN, "CHAIN");
codes.add(EDNS_KEY_TAG, "edns-key-tag");
codes.add(EDNS_EXTENDED_ERROR, "Extended_DNS_Error");
codes.add(EDNS_CLIENT_TAG, "EDNS-Client-Tag");
codes.add(EDNS_SERVER_TAG, "EDNS-Server-Tag");
codes.add(REPORT_CHANNEL, "Report-Channel");
codes.add(ZONEVERSION, "ZONEVERSION");
}
/** Converts an EDNS Option Code into its textual representation */
public static String string(int code) {
return codes.getText(code);
}
/**
* Converts a textual representation of an EDNS Option Code into its numeric value.
*
* @param s The textual representation of the option code
* @return The option code, or -1 on error.
*/
public static int value(String s) {
return codes.getValue(s);
}
}
private final int code;
/** Creates an option with the given option code and data. */
public EDNSOption(int code) {
this.code = Record.checkU16("code", code);
}
@Override
public String toString() {
return "{" + Code.string(code) + ": " + optionToString() + "}";
}
/**
* Returns the EDNS Option's code.
*
* @return the option code
*/
public int getCode() {
return code;
}
/**
* Returns the EDNS Option's data, as a byte array.
*
* @return the option data
*/
byte[] getData() {
DNSOutput out = new DNSOutput();
optionToWire(out);
return out.toByteArray();
}
/**
* Converts the wire format of an EDNS Option (the option data only) into the type-specific
* format.
*
* @param in The input Stream.
*/
abstract void optionFromWire(DNSInput in) throws IOException;
/**
* Converts the wire format of an EDNS Option (including code and length) into the type-specific
* format.
*
* @param in The input stream.
*/
static EDNSOption fromWire(DNSInput in) throws IOException {
int code;
int length;
code = in.readU16();
length = in.readU16();
if (in.remaining() < length) {
throw new WireParseException("truncated option");
}
int save = in.saveActive();
in.setActive(length);
EDNSOption option;
switch (code) {
case Code.NSID:
option = new NSIDOption();
break;
case Code.CLIENT_SUBNET:
option = new ClientSubnetOption();
break;
case Code.DAU:
case Code.DHU:
case Code.N3U:
option = new DnssecAlgorithmOption(code);
break;
case Code.COOKIE:
option = new CookieOption();
break;
case Code.TCP_KEEPALIVE:
option = new TcpKeepaliveOption();
break;
case Code.EDNS_EXTENDED_ERROR:
option = new ExtendedErrorCodeOption();
break;
default:
option = new GenericEDNSOption(code);
break;
}
option.optionFromWire(in);
in.restoreActive(save);
return option;
}
/**
* Converts the wire format of an EDNS Option (including code and length) into the type-specific
* format.
*
* @return The option, in wire format.
*/
public static EDNSOption fromWire(byte[] b) throws IOException {
return fromWire(new DNSInput(b));
}
/**
* Converts an EDNS Option (the type-specific option data only) into wire format.
*
* @param out The output stream.
*/
abstract void optionToWire(DNSOutput out);
/**
* Converts an EDNS Option (including code and length) into wire format.
*
* @param out The output stream.
*/
void toWire(DNSOutput out) {
out.writeU16(code);
int lengthPosition = out.current();
out.writeU16(0); /* until we know better */
optionToWire(out);
int length = out.current() - lengthPosition - 2;
out.writeU16At(length, lengthPosition);
}
/**
* Converts an EDNS Option (including code and length) into wire format.
*
* @return The option, in wire format.
*/
public byte[] toWire() {
DNSOutput out = new DNSOutput();
toWire(out);
return out.toByteArray();
}
/**
* Determines if two EDNS Options are identical.
*
* @param arg The option to compare to
* @return true if the options are equal, false otherwise.
*/
@Override
public boolean equals(Object arg) {
if (!(arg instanceof EDNSOption)) {
return false;
}
EDNSOption opt = (EDNSOption) arg;
if (code != opt.code) {
return false;
}
return Arrays.equals(getData(), opt.getData());
}
/** Generates a hash code based on the EDNS Option's data. */
@Override
public int hashCode() {
byte[] array = getData();
int hashval = 0;
for (byte b : array) {
hashval += (hashval << 3) + (b & 0xFF);
}
return hashval;
}
abstract String optionToString();
}