-
Notifications
You must be signed in to change notification settings - Fork 264
Expand file tree
/
Copy pathOPTRecord.java
More file actions
240 lines (217 loc) · 7.17 KB
/
Copy pathOPTRecord.java
File metadata and controls
240 lines (217 loc) · 7.17 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
// 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.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Options - describes Extended DNS (EDNS) properties of a Message. No specific options are defined
* other than those specified in the header. An OPT should be generated by Resolver.
*
* <p>EDNS is a method to extend the DNS protocol while providing backwards compatibility and not
* significantly changing the protocol. This implementation of EDNS is mostly complete at level 0.
*
* @see Message
* @see Resolver
* @see <a href="https://datatracker.ietf.org/doc/html/rfc6891">RFC 6891: Extension Mechanisms for
* DNS</a>
* @author Brian Wellington
*/
public class OPTRecord extends Record {
private List<EDNSOption> options;
OPTRecord() {}
/**
* Creates an OPT Record. This is normally called by SimpleResolver, but can also be called by a
* server.
*
* @param payloadSize The size of a packet that can be reassembled on the sending host.
* @param xrcode The value of the extended rcode field. This is the upper 16 bits of the full
* rcode.
* @param flags Additional message flags.
* @param version The EDNS version that this DNS implementation supports. This should be 0 for
* dnsjava.
* @param options The options that comprise the data field.
* @see ExtendedFlags
*/
public OPTRecord(int payloadSize, int xrcode, int version, int flags, EDNSOption... options) {
this(payloadSize, xrcode, version, flags);
if (options != null) {
this.options = new ArrayList<>(Arrays.asList(options));
}
}
/**
* Creates an OPT Record. This is normally called by SimpleResolver, but can also be called by a
* server.
*
* @param payloadSize The size of a packet that can be reassembled on the sending host.
* @param xrcode The value of the extended rcode field. This is the upper 16 bits of the full
* rcode.
* @param flags Additional message flags.
* @param version The EDNS version that this DNS implementation supports. This should be 0 for
* dnsjava.
* @param options The list of options that comprise the data field.
* @see ExtendedFlags
*/
public OPTRecord(int payloadSize, int xrcode, int version, int flags, List<EDNSOption> options) {
this(payloadSize, xrcode, version, flags);
if (options != null) {
this.options = new ArrayList<>(options);
}
}
/**
* Creates an OPT Record with no data. This is normally called by SimpleResolver, but can also be
* called by a server.
*
* @param payloadSize The size of a packet that can be reassembled on the sending host.
* @param xrcode The value of the extended rcode field. This is the upper 16 bits of the full
* rcode.
* @param flags Additional message flags.
* @param version The EDNS version that this DNS implementation supports. This should be 0 for
* dnsjava.
* @see ExtendedFlags
*/
public OPTRecord(int payloadSize, int xrcode, int version, int flags) {
super(Name.root, Type.OPT, payloadSize, 0);
checkU16("payloadSize", payloadSize);
checkU8("xrcode", xrcode);
checkU8("version", version);
checkU16("flags", flags);
ttl = ((long) xrcode << 24) + ((long) version << 16) + flags;
}
/**
* Creates an OPT Record with no data. This is normally called by SimpleResolver, but can also be
* called by a server.
*/
public OPTRecord(int payloadSize, int xrcode, int version) {
this(payloadSize, xrcode, version, 0);
}
@Override
protected void rrFromWire(DNSInput in) throws IOException {
if (in.remaining() > 0) {
options = new ArrayList<>();
}
while (in.remaining() > 0) {
EDNSOption option = EDNSOption.fromWire(in);
options.add(option);
}
}
@Override
protected void rdataFromString(Tokenizer st, Name origin) throws IOException {
throw st.exception("no text format defined for OPT");
}
/** Converts rdata to a String */
@Override
protected String rrToString() {
StringBuilder sb = new StringBuilder();
if (options != null) {
sb.append(options);
sb.append(" ");
}
sb.append(" ; payload ");
sb.append(getPayloadSize());
sb.append(", xrcode ");
sb.append(getExtendedRcode());
sb.append(", version ");
sb.append(getVersion());
sb.append(", flags ");
sb.append(getFlags());
return sb.toString();
}
/** Converts this record to a String representation */
@Override
public String toString() {
return Name.root + "\t\t\t\t" + Type.string(type) + "\t" + rrToString();
}
void printPseudoSection(StringBuilder sb) {
sb.append(";; OPT PSEUDOSECTION: \n; EDNS: version: ");
sb.append(getVersion());
sb.append("; flags: ");
for (int i = 0; i < 16; i++) {
if ((getFlags() & (1 << (15 - i))) != 0) {
sb.append(ExtendedFlags.stringFromBit(i));
sb.append(" ");
}
}
sb.append("; udp: ").append(getPayloadSize());
if (options != null) {
for (EDNSOption o : options) {
sb.append("\n; ")
.append(EDNSOption.Code.string(o.getCode()))
.append(": ")
.append(o.optionToString());
}
}
}
/** Returns the maximum allowed payload size. */
public int getPayloadSize() {
return dclass;
}
/**
* Returns the extended Rcode
*
* @see Rcode
*/
public int getExtendedRcode() {
return (int) (ttl >>> 24);
}
/** Returns the highest supported EDNS version */
public int getVersion() {
return (int) ((ttl >>> 16) & 0xFF);
}
/** Returns the EDNS flags */
public int getFlags() {
return (int) (ttl & 0xFFFF);
}
@Override
protected void rrToWire(DNSOutput out, Compression c, boolean canonical) {
if (options == null) {
return;
}
for (EDNSOption option : options) {
option.toWire(out);
}
}
/** Gets all options in the OPTRecord. This returns a list of EDNSOptions. */
public List<EDNSOption> getOptions() {
if (options == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(options);
}
/** Gets all options in the OPTRecord with a specific code. This returns a list of EDNSOptions. */
public List<EDNSOption> getOptions(int code) {
if (options == null) {
return Collections.emptyList();
}
List<EDNSOption> list = new ArrayList<>();
for (EDNSOption opt : options) {
if (opt.getCode() == code) {
list.add(opt);
}
}
return list;
}
/**
* Determines if two OPTRecords are identical. This compares the name, type, class, and rdata
* (with names canonicalized). Additionally, because TTLs are relevant for OPT records, the TTLs
* are compared.
*
* @param arg The record to compare to
* @return true if the records are equal, false otherwise.
*/
@Override
public boolean equals(final Object arg) {
return super.equals(arg) && ttl == ((OPTRecord) arg).ttl;
}
@Override
public int hashCode() {
byte[] array = toWireCanonical();
int code = 0;
for (byte b : array) {
code += (code << 3) + (b & 0xFF);
}
return code;
}
}