2 // Mono.Net.Dns.DnsHeader
5 // Gonzalo Paniagua Javier (gonzalo.mono@gmail.com)
7 // Copyright 2011 Gonzalo Paniagua Javier
9 // Licensed under the Apache License, Version 2.0 (the "License");
10 // you may not use this file except in compliance with the License.
11 // You may obtain a copy of the License at
13 // http://www.apache.org/licenses/LICENSE-2.0
15 // Unless required by applicable law or agreed to in writing, software
16 // distributed under the License is distributed on an "AS IS" BASIS,
17 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 // See the License for the specific language governing permissions and
19 // limitations under the License.
22 using System.Collections.Generic;
25 namespace Mono.Net.Dns {
27 public const int DnsHeaderLength = 12;
28 ArraySegment<byte> bytes;
30 public DnsHeader (byte [] bytes)
35 public DnsHeader (byte [] bytes, int offset)
36 : this (new ArraySegment<byte> (bytes, offset, DnsHeaderLength))
40 public DnsHeader (ArraySegment<byte> segment)
42 if (segment.Count != DnsHeaderLength)
43 throw new ArgumentException ("Count must be 12", "segment");
50 for (int i = 0; i < DnsHeaderLength; i++)
51 bytes.Array [i + bytes.Offset] = 0;
56 return (ushort)(bytes.Array [bytes.Offset] * 256 + bytes.Array [bytes.Offset + 1]);
59 bytes.Array [bytes.Offset] = (byte) ((value & 0x0ff00) >> 8);
60 bytes.Array [bytes.Offset + 1] = (byte) (value & 0x0ff);
65 get { return ((bytes.Array [2 + bytes.Offset] & 0x80) != 0); }
68 bytes.Array [2 + bytes.Offset] |= 0x80;
70 bytes.Array [2 + bytes.Offset] &= 0x7f;
75 public DnsOpCode OpCode {
76 get { return (DnsOpCode) ((bytes.Array [2 + bytes.Offset] & 0x78) >> 3); }
78 if (!Enum.IsDefined (typeof (DnsOpCode), value))
79 throw new ArgumentOutOfRangeException ("value", "Invalid DnsOpCode value");
83 int prev = (bytes.Array [2 + bytes.Offset] & 0x87);
85 bytes.Array [2 + bytes.Offset] = (byte) v;
89 public bool AuthoritativeAnswer {
90 get { return (bytes.Array [2 + bytes.Offset] & 4) != 0; }
93 bytes.Array [2 + bytes.Offset] |= 4;
95 bytes.Array [2 + bytes.Offset] &= 0xFB;
100 public bool Truncation {
101 get { return (bytes.Array [2 + bytes.Offset] & 2) != 0; }
104 bytes.Array [2 + bytes.Offset] |= 2;
106 bytes.Array [2 + bytes.Offset] &= 0xFD;
111 public bool RecursionDesired {
112 get { return (bytes.Array [2 + bytes.Offset] & 1) != 0; }
115 bytes.Array [2 + bytes.Offset] |= 1;
117 bytes.Array [2 + bytes.Offset] &= 0xFE;
122 public bool RecursionAvailable {
123 get { return (bytes.Array [3 + bytes.Offset] & 0x80) != 0; }
126 bytes.Array [3 + bytes.Offset] |= 0x80;
128 bytes.Array [3 + bytes.Offset] &= 0x7F;
133 // TODO: Add AuthenticData and Checking Disabled (bit 10 and 11 of Z)
134 public int ZReserved {
135 get { return (bytes.Array [3 + bytes.Offset] & 0x70) >> 4; }
137 if(value < 0 || value > 7) {
138 throw new ArgumentOutOfRangeException("value", "Must be between 0 and 7");
140 bytes.Array [3 + bytes.Offset] &= 0x8F;
141 bytes.Array [3 + bytes.Offset] |= (byte) ((value << 4) & 0x70);
145 public DnsRCode RCode {
146 get { return (DnsRCode) (bytes.Array [3 + bytes.Offset] & 0x0f); }
149 //Info: Values > 15 are encoded in other records (OPT, TSIG, TKEY)
151 throw new ArgumentOutOfRangeException("value", "Must be between 0 and 15");
153 bytes.Array [3 + bytes.Offset] &= 0x0f;
154 bytes.Array [3 + bytes.Offset] |= (byte) v;
158 static ushort GetUInt16 (byte [] bytes, int offset)
160 return (ushort)(bytes [offset] * 256 + bytes [offset + 1]);
163 static void SetUInt16 (byte [] bytes, int offset, ushort val)
165 bytes [offset] = (byte) ((val & 0x0ff00) >> 8);
166 bytes [offset + 1] = (byte) (val & 0x0ff);
169 public ushort QuestionCount {
170 get { return GetUInt16 (bytes.Array, 4); }
171 set { SetUInt16 (bytes.Array, 4, value); }
174 public ushort AnswerCount {
175 get { return GetUInt16 (bytes.Array, 6); }
176 set { SetUInt16 (bytes.Array, 6, value); }
179 public ushort AuthorityCount {
180 get { return GetUInt16 (bytes.Array, 8); }
181 set { SetUInt16 (bytes.Array, 8, value); }
184 public ushort AdditionalCount {
185 get { return GetUInt16 (bytes.Array, 10); }
186 set { SetUInt16 (bytes.Array, 10, value); }
189 public override string ToString ()
191 StringBuilder sb = new StringBuilder();
192 sb.AppendFormat ("ID: {0} QR: {1} Opcode: {2} AA: {3} TC: {4} RD: {5} RA: {6} \r\nRCode: {7} ",
193 ID, IsQuery, OpCode, AuthoritativeAnswer, Truncation, RecursionDesired,
194 RecursionAvailable, RCode);
195 sb.AppendFormat ("Q: {0} A: {1} NS: {2} AR: {3}\r\n", QuestionCount, AnswerCount, AuthorityCount, AdditionalCount);
196 return sb.ToString();