forked from MichaCo/DnsClient.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDnsMessageHandler.cs
119 lines (101 loc) · 5.46 KB
/
DnsMessageHandler.cs
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
using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using DnsClient.Protocol.Options;
namespace DnsClient
{
internal abstract class DnsMessageHandler
{
public abstract DnsResponseMessage Query(IPEndPoint endpoint, DnsRequestMessage request, TimeSpan timeout);
public abstract Task<DnsResponseMessage> QueryAsync(IPEndPoint endpoint, DnsRequestMessage request, CancellationToken cancellationToken,
Action<Action> cancelationCallback);
public abstract bool IsTransientException<T>(T exception) where T : Exception;
public virtual void GetRequestData(DnsRequestMessage request, DnsDatagramWriter writer)
{
var question = request.Question;
/*
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* */
// 4 more bytes for the type and class
writer.WriteInt16NetworkOrder((short)request.Header.Id);
writer.WriteUInt16NetworkOrder(request.Header.RawFlags);
writer.WriteInt16NetworkOrder(1); // we support single question only... (as most DNS servers anyways).
writer.WriteInt16NetworkOrder(0);
writer.WriteInt16NetworkOrder(0);
writer.WriteInt16NetworkOrder(1); // one additional for the Opt record.
writer.WriteHostName(question.QueryName);
writer.WriteUInt16NetworkOrder((ushort)question.QuestionType);
writer.WriteUInt16NetworkOrder((ushort)question.QuestionClass);
/*
+------------+--------------+------------------------------+
| Field Name | Field Type | Description |
+------------+--------------+------------------------------+
| NAME | domain name | MUST be 0 (root domain) |
| TYPE | u_int16_t | OPT (41) |
| CLASS | u_int16_t | requestor's UDP payload size |
| TTL | u_int32_t | extended RCODE and flags |
| RDLEN | u_int16_t | length of all RDATA |
| RDATA | octet stream | {attribute,value} pairs |
+------------+--------------+------------------------------+
* */
var opt = new OptRecord();
writer.WriteHostName("");
writer.WriteUInt16NetworkOrder((ushort)opt.RecordType);
writer.WriteUInt16NetworkOrder((ushort)opt.RecordClass);
writer.WriteUInt32NetworkOrder((ushort)opt.InitialTimeToLive);
writer.WriteUInt16NetworkOrder(0);
}
public virtual DnsResponseMessage GetResponseMessage(ArraySegment<byte> responseData)
{
var reader = new DnsDatagramReader(responseData);
var factory = new DnsRecordFactory(reader);
var id = reader.ReadUInt16NetworkOrder();
var flags = reader.ReadUInt16NetworkOrder();
var questionCount = reader.ReadUInt16NetworkOrder();
var answerCount = reader.ReadUInt16NetworkOrder();
var nameServerCount = reader.ReadUInt16NetworkOrder();
var additionalCount = reader.ReadUInt16NetworkOrder();
var header = new DnsResponseHeader(id, flags, questionCount, answerCount, additionalCount, nameServerCount);
var response = new DnsResponseMessage(header, responseData.Count);
for (int questionIndex = 0; questionIndex < questionCount; questionIndex++)
{
var question = new DnsQuestion(reader.ReadQuestionQueryString(), (QueryType)reader.ReadUInt16NetworkOrder(), (QueryClass)reader.ReadUInt16NetworkOrder());
response.AddQuestion(question);
}
for (int answerIndex = 0; answerIndex < answerCount; answerIndex++)
{
var info = factory.ReadRecordInfo();
var record = factory.GetRecord(info);
response.AddAnswer(record);
}
for (int serverIndex = 0; serverIndex < nameServerCount; serverIndex++)
{
var info = factory.ReadRecordInfo();
var record = factory.GetRecord(info);
response.AddAuthority(record);
}
for (int additionalIndex = 0; additionalIndex < additionalCount; additionalIndex++)
{
var info = factory.ReadRecordInfo();
var record = factory.GetRecord(info);
response.AddAdditional(record);
}
return response;
}
}
}