Skip to content

Commit eab6c74

Browse files
authored
Merge pull request #42 from BornToBeRoot/DNS-Lookup
DNS Lookup added
2 parents 5dc1891 + 3a92fa3 commit eab6c74

104 files changed

Lines changed: 6631 additions & 382 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
using System;
2+
using System.IO;
3+
using System.Collections.Generic;
4+
using System.Net;
5+
using System.Text;
6+
7+
namespace Heijden.DNS
8+
{
9+
#region RFC specification
10+
/*
11+
4.1.1. Header section format
12+
13+
The header contains the following fields:
14+
15+
1 1 1 1 1 1
16+
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
17+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
18+
| ID |
19+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
20+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
21+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
22+
| QDCOUNT |
23+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
24+
| ANCOUNT |
25+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
26+
| NSCOUNT |
27+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
28+
| ARCOUNT |
29+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
30+
31+
where:
32+
33+
ID A 16 bit identifier assigned by the program that
34+
generates any kind of query. This identifier is copied
35+
the corresponding reply and can be used by the requester
36+
to match up replies to outstanding queries.
37+
38+
QR A one bit field that specifies whether this message is a
39+
query (0), or a response (1).
40+
41+
OPCODE A four bit field that specifies kind of query in this
42+
message. This value is set by the originator of a query
43+
and copied into the response. The values are:
44+
45+
0 a standard query (QUERY)
46+
47+
1 an inverse query (IQUERY)
48+
49+
2 a server status request (STATUS)
50+
51+
3-15 reserved for future use
52+
53+
AA Authoritative Answer - this bit is valid in responses,
54+
and specifies that the responding name server is an
55+
authority for the domain name in question section.
56+
57+
Note that the contents of the answer section may have
58+
multiple owner names because of aliases. The AA bit
59+
corresponds to the name which matches the query name, or
60+
the first owner name in the answer section.
61+
62+
TC TrunCation - specifies that this message was truncated
63+
due to length greater than that permitted on the
64+
transmission channel.
65+
66+
RD Recursion Desired - this bit may be set in a query and
67+
is copied into the response. If RD is set, it directs
68+
the name server to pursue the query recursively.
69+
Recursive query support is optional.
70+
71+
RA Recursion Available - this be is set or cleared in a
72+
response, and denotes whether recursive query support is
73+
available in the name server.
74+
75+
Z Reserved for future use. Must be zero in all queries
76+
and responses.
77+
78+
RCODE Response code - this 4 bit field is set as part of
79+
responses. The values have the following
80+
interpretation:
81+
82+
0 No error condition
83+
84+
1 Format error - The name server was
85+
unable to interpret the query.
86+
87+
2 Server failure - The name server was
88+
unable to process this query due to a
89+
problem with the name server.
90+
91+
3 Name Error - Meaningful only for
92+
responses from an authoritative name
93+
server, this code signifies that the
94+
domain name referenced in the query does
95+
not exist.
96+
97+
4 Not Implemented - The name server does
98+
not support the requested kind of query.
99+
100+
5 Refused - The name server refuses to
101+
perform the specified operation for
102+
policy reasons. For example, a name
103+
server may not wish to provide the
104+
information to the particular requester,
105+
or a name server may not wish to perform
106+
a particular operation (e.g., zone
107+
transfer) for particular data.
108+
109+
6-15 Reserved for future use.
110+
111+
QDCOUNT an unsigned 16 bit integer specifying the number of
112+
entries in the question section.
113+
114+
ANCOUNT an unsigned 16 bit integer specifying the number of
115+
resource records in the answer section.
116+
117+
NSCOUNT an unsigned 16 bit integer specifying the number of name
118+
server resource records in the authority records
119+
section.
120+
121+
ARCOUNT an unsigned 16 bit integer specifying the number of
122+
resource records in the additional records section.
123+
124+
*/
125+
#endregion
126+
127+
public class Header
128+
{
129+
/// <summary>
130+
/// An identifier assigned by the program
131+
/// </summary>
132+
public ushort ID;
133+
134+
// internal flag
135+
private ushort Flags;
136+
137+
/// <summary>
138+
/// the number of entries in the question section
139+
/// </summary>
140+
public ushort QDCOUNT;
141+
142+
/// <summary>
143+
/// the number of resource records in the answer section
144+
/// </summary>
145+
public ushort ANCOUNT;
146+
147+
/// <summary>
148+
/// the number of name server resource records in the authority records section
149+
/// </summary>
150+
public ushort NSCOUNT;
151+
152+
/// <summary>
153+
/// the number of resource records in the additional records section
154+
/// </summary>
155+
public ushort ARCOUNT;
156+
157+
public Header()
158+
{
159+
}
160+
161+
public Header(RecordReader rr)
162+
{
163+
ID = rr.ReadUInt16();
164+
Flags = rr.ReadUInt16();
165+
QDCOUNT = rr.ReadUInt16();
166+
ANCOUNT = rr.ReadUInt16();
167+
NSCOUNT = rr.ReadUInt16();
168+
ARCOUNT = rr.ReadUInt16();
169+
}
170+
171+
172+
private ushort SetBits(ushort oldValue, int position, int length, bool blnValue)
173+
{
174+
return SetBits(oldValue, position, length, blnValue ? (ushort)1 : (ushort)0);
175+
}
176+
177+
private ushort SetBits(ushort oldValue, int position, int length, ushort newValue)
178+
{
179+
// sanity check
180+
if (length <= 0 || position >= 16)
181+
return oldValue;
182+
183+
// get some mask to put on
184+
int mask = (2 << (length - 1)) - 1;
185+
186+
// clear out value
187+
oldValue &= (ushort)~(mask << position);
188+
189+
// set new value
190+
oldValue |= (ushort)((newValue & mask) << position);
191+
return oldValue;
192+
}
193+
194+
private ushort GetBits(ushort oldValue, int position, int length)
195+
{
196+
// sanity check
197+
if (length <= 0 || position >= 16)
198+
return 0;
199+
200+
// get some mask to put on
201+
int mask = (2 << (length - 1)) - 1;
202+
203+
// shift down to get some value and mask it
204+
return (ushort)((oldValue >> position) & mask);
205+
}
206+
207+
/// <summary>
208+
/// Represents the header as a byte array
209+
/// </summary>
210+
public byte[] Data
211+
{
212+
get
213+
{
214+
List<byte> data = new List<byte>();
215+
data.AddRange(WriteShort(ID));
216+
data.AddRange(WriteShort(Flags));
217+
data.AddRange(WriteShort(QDCOUNT));
218+
data.AddRange(WriteShort(ANCOUNT));
219+
data.AddRange(WriteShort(NSCOUNT));
220+
data.AddRange(WriteShort(ARCOUNT));
221+
return data.ToArray();
222+
}
223+
}
224+
225+
private byte[] WriteShort(ushort sValue)
226+
{
227+
return BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)sValue));
228+
}
229+
230+
231+
/// <summary>
232+
/// query (false), or a response (true)
233+
/// </summary>
234+
public bool QR
235+
{
236+
get
237+
{
238+
return GetBits(Flags, 15, 1) == 1;
239+
}
240+
set
241+
{
242+
Flags = SetBits(Flags, 15, 1, value);
243+
}
244+
}
245+
246+
/// <summary>
247+
/// Specifies kind of query
248+
/// </summary>
249+
public OPCode OPCODE
250+
{
251+
get
252+
{
253+
return (OPCode)GetBits(Flags, 11, 4);
254+
}
255+
set
256+
{
257+
Flags = SetBits(Flags, 11, 4, (ushort)value);
258+
}
259+
}
260+
261+
/// <summary>
262+
/// Authoritative Answer
263+
/// </summary>
264+
public bool AA
265+
{
266+
get
267+
{
268+
return GetBits(Flags, 10, 1) == 1;
269+
}
270+
set
271+
{
272+
Flags = SetBits(Flags, 10, 1, value);
273+
}
274+
}
275+
276+
/// <summary>
277+
/// TrunCation
278+
/// </summary>
279+
public bool TC
280+
{
281+
get
282+
{
283+
return GetBits(Flags, 9, 1) == 1;
284+
}
285+
set
286+
{
287+
Flags = SetBits(Flags, 9, 1, value);
288+
}
289+
}
290+
291+
/// <summary>
292+
/// Recursion Desired
293+
/// </summary>
294+
public bool RD
295+
{
296+
get
297+
{
298+
return GetBits(Flags, 8, 1) == 1;
299+
}
300+
set
301+
{
302+
Flags = SetBits(Flags, 8, 1, value);
303+
}
304+
}
305+
306+
/// <summary>
307+
/// Recursion Available
308+
/// </summary>
309+
public bool RA
310+
{
311+
get
312+
{
313+
return GetBits(Flags, 7, 1) == 1;
314+
}
315+
set
316+
{
317+
Flags = SetBits(Flags, 7, 1, value);
318+
}
319+
}
320+
321+
/// <summary>
322+
/// Reserved for future use
323+
/// </summary>
324+
public ushort Z
325+
{
326+
get
327+
{
328+
return GetBits(Flags, 4, 3);
329+
}
330+
set
331+
{
332+
Flags = SetBits(Flags, 4, 3, value);
333+
}
334+
}
335+
336+
/// <summary>
337+
/// Response code
338+
/// </summary>
339+
public RCode RCODE
340+
{
341+
get
342+
{
343+
return (RCode)GetBits(Flags, 0, 4);
344+
}
345+
set
346+
{
347+
Flags = SetBits(Flags, 0, 4, (ushort)value);
348+
}
349+
}
350+
}
351+
}

0 commit comments

Comments
 (0)