• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
2 package org.xbill.DNS;
3 
4 import java.io.*;
5 import java.util.Arrays;
6 
7 /**
8  * DNS extension options, as described in RFC 2671.  The rdata of an OPT record
9  * is defined as a list of options; this represents a single option.
10  *
11  * @author Brian Wellington
12  * @author Ming Zhou <mizhou@bnivideo.com>, Beaumaris Networks
13  */
14 public abstract class EDNSOption {
15 
16 public static class Code {
Code()17 	private Code() {}
18 
19 	/** Name Server Identifier, RFC 5001 */
20 	public final static int NSID = 3;
21 
22 	/** Client Subnet, defined in draft-vandergaast-edns-client-subnet-00 */
23 	public final static int CLIENT_SUBNET = 20730;
24 
25 	private static Mnemonic codes = new Mnemonic("EDNS Option Codes",
26 						     Mnemonic.CASE_UPPER);
27 
28 	static {
29 		codes.setMaximum(0xFFFF);
30 		codes.setPrefix("CODE");
31 		codes.setNumericAllowed(true);
32 
codes.add(NSID, "NSID")33 		codes.add(NSID, "NSID");
codes.add(CLIENT_SUBNET, "CLIENT_SUBNET")34 		codes.add(CLIENT_SUBNET, "CLIENT_SUBNET");
35 	}
36 
37 	/**
38 	 * Converts an EDNS Option Code into its textual representation
39 	 */
40 	public static String
string(int code)41 	string(int code) {
42 		return codes.getText(code);
43 	}
44 
45 	/**
46 	 * Converts a textual representation of an EDNS Option Code into its
47 	 * numeric value.
48 	 * @param s The textual representation of the option code
49 	 * @return The option code, or -1 on error.
50 	 */
51 	public static int
value(String s)52 	value(String s) {
53 		return codes.getValue(s);
54 	}
55 }
56 
57 private final int code;
58 
59 /**
60  *
61  * Creates an option with the given option code and data.
62  */
63 public
EDNSOption(int code)64 EDNSOption(int code) {
65 	this.code = Record.checkU16("code", code);
66 }
67 
68 public String
toString()69 toString() {
70 	StringBuffer sb = new StringBuffer();
71 
72 	sb.append("{");
73 	sb.append(EDNSOption.Code.string(code));
74 	sb.append(": ");
75 	sb.append(optionToString());
76 	sb.append("}");
77 
78 	return sb.toString();
79 }
80 
81 /**
82  * Returns the EDNS Option's code.
83  *
84  * @return the option code
85  */
86 public int
getCode()87 getCode() {
88 	return code;
89 }
90 
91 /**
92  * Returns the EDNS Option's data, as a byte array.
93  *
94  * @return the option data
95  */
96 byte []
getData()97 getData() {
98 	DNSOutput out = new DNSOutput();
99 	optionToWire(out);
100 	return out.toByteArray();
101 }
102 
103 /**
104  * Converts the wire format of an EDNS Option (the option data only) into the
105  * type-specific format.
106  * @param in The input Stream.
107  */
108 abstract void
optionFromWire(DNSInput in)109 optionFromWire(DNSInput in) throws IOException;
110 
111 /**
112  * Converts the wire format of an EDNS Option (including code and length) into
113  * the type-specific format.
114  * @param out The input stream.
115  */
116 static EDNSOption
fromWire(DNSInput in)117 fromWire(DNSInput in) throws IOException {
118 	int code, length;
119 
120 	code = in.readU16();
121 	length = in.readU16();
122 	if (in.remaining() < length)
123 		throw new WireParseException("truncated option");
124 	int save = in.saveActive();
125 	in.setActive(length);
126 	EDNSOption option;
127 	switch (code) {
128 	case Code.NSID:
129 		option = new NSIDOption();
130 		break;
131 	case Code.CLIENT_SUBNET:
132 		option = new ClientSubnetOption();
133 		break;
134 	default:
135 		option = new GenericEDNSOption(code);
136 		break;
137 	}
138 	option.optionFromWire(in);
139 	in.restoreActive(save);
140 
141 	return option;
142 }
143 
144 /**
145  * Converts the wire format of an EDNS Option (including code and length) into
146  * the type-specific format.
147  * @return The option, in wire format.
148  */
149 public static EDNSOption
fromWire(byte [] b)150 fromWire(byte [] b) throws IOException {
151 	return fromWire(new DNSInput(b));
152 }
153 
154 /**
155  * Converts an EDNS Option (the type-specific option data only) into wire format.
156  * @param out The output stream.
157  */
158 abstract void
optionToWire(DNSOutput out)159 optionToWire(DNSOutput out);
160 
161 /**
162  * Converts an EDNS Option (including code and length) into wire format.
163  * @param out The output stream.
164  */
165 void
toWire(DNSOutput out)166 toWire(DNSOutput out) {
167 	out.writeU16(code);
168 	int lengthPosition = out.current();
169 	out.writeU16(0); /* until we know better */
170 	optionToWire(out);
171 	int length = out.current() - lengthPosition - 2;
172 	out.writeU16At(length, lengthPosition);
173 }
174 
175 /**
176  * Converts an EDNS Option (including code and length) into wire format.
177  * @return The option, in wire format.
178  */
179 public byte []
toWire()180 toWire() throws IOException {
181 	DNSOutput out = new DNSOutput();
182 	toWire(out);
183 	return out.toByteArray();
184 }
185 
186 /**
187  * Determines if two EDNS Options are identical.
188  * @param arg The option to compare to
189  * @return true if the options are equal, false otherwise.
190  */
191 public boolean
equals(Object arg)192 equals(Object arg) {
193 	if (arg == null || !(arg instanceof EDNSOption))
194 		return false;
195 	EDNSOption opt = (EDNSOption) arg;
196 	if (code != opt.code)
197 		return false;
198 	return Arrays.equals(getData(), opt.getData());
199 }
200 
201 /**
202  * Generates a hash code based on the EDNS Option's data.
203  */
204 public int
hashCode()205 hashCode() {
206 	byte [] array = getData();
207 	int hashval = 0;
208 	for (int i = 0; i < array.length; i++)
209 		hashval += ((hashval << 3) + (array[i] & 0xFF));
210 	return hashval;
211 }
212 
optionToString()213 abstract String optionToString();
214 
215 }
216