• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
2 
3 package org.xbill.DNS;
4 
5 import java.io.*;
6 import java.util.*;
7 
8 /**
9  * A DNS message header
10  * @see Message
11  *
12  * @author Brian Wellington
13  */
14 
15 public class Header implements Cloneable {
16 
17 private int id;
18 private int flags;
19 private int [] counts;
20 
21 private static Random random = new Random();
22 
23 /** The length of a DNS Header in wire format. */
24 public static final int LENGTH = 12;
25 
26 private void
init()27 init() {
28 	counts = new int[4];
29 	flags = 0;
30 	id = -1;
31 }
32 
33 /**
34  * Create a new empty header.
35  * @param id The message id
36  */
37 public
Header(int id)38 Header(int id) {
39 	init();
40 	setID(id);
41 }
42 
43 /**
44  * Create a new empty header with a random message id
45  */
46 public
Header()47 Header() {
48 	init();
49 }
50 
51 /**
52  * Parses a Header from a stream containing DNS wire format.
53  */
Header(DNSInput in)54 Header(DNSInput in) throws IOException {
55 	this(in.readU16());
56 	flags = in.readU16();
57 	for (int i = 0; i < counts.length; i++)
58 		counts[i] = in.readU16();
59 }
60 
61 /**
62  * Creates a new Header from its DNS wire format representation
63  * @param b A byte array containing the DNS Header.
64  */
65 public
Header(byte [] b)66 Header(byte [] b) throws IOException {
67 	this(new DNSInput(b));
68 }
69 
70 void
toWire(DNSOutput out)71 toWire(DNSOutput out) {
72 	out.writeU16(getID());
73 	out.writeU16(flags);
74 	for (int i = 0; i < counts.length; i++)
75 		out.writeU16(counts[i]);
76 }
77 
78 public byte []
toWire()79 toWire() {
80 	DNSOutput out = new DNSOutput();
81 	toWire(out);
82 	return out.toByteArray();
83 }
84 
85 static private boolean
validFlag(int bit)86 validFlag(int bit) {
87 	return (bit >= 0 && bit <= 0xF && Flags.isFlag(bit));
88 }
89 
90 static private void
checkFlag(int bit)91 checkFlag(int bit) {
92 	if (!validFlag(bit))
93 		throw new IllegalArgumentException("invalid flag bit " + bit);
94 }
95 
96 /**
97  * Sets a flag to the supplied value
98  * @see Flags
99  */
100 public void
setFlag(int bit)101 setFlag(int bit) {
102 	checkFlag(bit);
103 	// bits are indexed from left to right
104 	flags |= (1 << (15 - bit));
105 }
106 
107 /**
108  * Sets a flag to the supplied value
109  * @see Flags
110  */
111 public void
unsetFlag(int bit)112 unsetFlag(int bit) {
113 	checkFlag(bit);
114 	// bits are indexed from left to right
115 	flags &= ~(1 << (15 - bit));
116 }
117 
118 /**
119  * Retrieves a flag
120  * @see Flags
121  */
122 public boolean
getFlag(int bit)123 getFlag(int bit) {
124 	checkFlag(bit);
125 	// bits are indexed from left to right
126 	return (flags & (1 << (15 - bit))) != 0;
127 }
128 
129 boolean []
getFlags()130 getFlags() {
131 	boolean [] array = new boolean[16];
132 	for (int i = 0; i < array.length; i++)
133 		if (validFlag(i))
134 			array[i] = getFlag(i);
135 	return array;
136 }
137 
138 /**
139  * Retrieves the message ID
140  */
141 public int
getID()142 getID() {
143 	if (id >= 0)
144 		return id;
145 	synchronized (this) {
146 		if (id < 0)
147 			id = random.nextInt(0xffff);
148 		return id;
149 	}
150 }
151 
152 /**
153  * Sets the message ID
154  */
155 public void
setID(int id)156 setID(int id) {
157 	if (id < 0 || id > 0xffff)
158 		throw new IllegalArgumentException("DNS message ID " + id +
159 						   " is out of range");
160 	this.id = id;
161 }
162 
163 /**
164  * Sets the message's rcode
165  * @see Rcode
166  */
167 public void
setRcode(int value)168 setRcode(int value) {
169 	if (value < 0 || value > 0xF)
170 		throw new IllegalArgumentException("DNS Rcode " + value +
171 						   " is out of range");
172 	flags &= ~0xF;
173 	flags |= value;
174 }
175 
176 /**
177  * Retrieves the mesasge's rcode
178  * @see Rcode
179  */
180 public int
getRcode()181 getRcode() {
182 	return flags & 0xF;
183 }
184 
185 /**
186  * Sets the message's opcode
187  * @see Opcode
188  */
189 public void
setOpcode(int value)190 setOpcode(int value) {
191 	if (value < 0 || value > 0xF)
192 		throw new IllegalArgumentException("DNS Opcode " + value +
193 						   "is out of range");
194 	flags &= 0x87FF;
195 	flags |= (value << 11);
196 }
197 
198 /**
199  * Retrieves the mesasge's opcode
200  * @see Opcode
201  */
202 public int
getOpcode()203 getOpcode() {
204 	return (flags >> 11) & 0xF;
205 }
206 
207 void
setCount(int field, int value)208 setCount(int field, int value) {
209 	if (value < 0 || value > 0xFFFF)
210 		throw new IllegalArgumentException("DNS section count " +
211 						   value + " is out of range");
212 	counts[field] = value;
213 }
214 
215 void
incCount(int field)216 incCount(int field) {
217 	if (counts[field] == 0xFFFF)
218 		throw new IllegalStateException("DNS section count cannot " +
219 						"be incremented");
220 	counts[field]++;
221 }
222 
223 void
decCount(int field)224 decCount(int field) {
225 	if (counts[field] == 0)
226 		throw new IllegalStateException("DNS section count cannot " +
227 						"be decremented");
228 	counts[field]--;
229 }
230 
231 /**
232  * Retrieves the record count for the given section
233  * @see Section
234  */
235 public int
getCount(int field)236 getCount(int field) {
237 	return counts[field];
238 }
239 
240 /** Converts the header's flags into a String */
241 public String
printFlags()242 printFlags() {
243 	StringBuffer sb = new StringBuffer();
244 
245 	for (int i = 0; i < 16; i++)
246 		if (validFlag(i) && getFlag(i)) {
247 			sb.append(Flags.string(i));
248 			sb.append(" ");
249 		}
250 	return sb.toString();
251 }
252 
253 String
toStringWithRcode(int newrcode)254 toStringWithRcode(int newrcode) {
255 	StringBuffer sb = new StringBuffer();
256 
257 	sb.append(";; ->>HEADER<<- ");
258 	sb.append("opcode: " + Opcode.string(getOpcode()));
259 	sb.append(", status: " + Rcode.string(newrcode));
260 	sb.append(", id: " + getID());
261 	sb.append("\n");
262 
263 	sb.append(";; flags: " + printFlags());
264 	sb.append("; ");
265 	for (int i = 0; i < 4; i++)
266 		sb.append(Section.string(i) + ": " + getCount(i) + " ");
267 	return sb.toString();
268 }
269 
270 /** Converts the header into a String */
271 public String
toString()272 toString() {
273 	return toStringWithRcode(getRcode());
274 }
275 
276 /* Creates a new Header identical to the current one */
277 public Object
clone()278 clone() {
279 	Header h = new Header();
280 	h.id = id;
281 	h.flags = flags;
282 	System.arraycopy(counts, 0, h.counts, 0, counts.length);
283 	return h;
284 }
285 
286 }
287