-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExtensions.cs
More file actions
159 lines (126 loc) · 5.05 KB
/
Copy pathExtensions.cs
File metadata and controls
159 lines (126 loc) · 5.05 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
using System.Text;
namespace DnsMessageParser;
public static class Extensions
{
public static int QuestionSectionSkippedPosition(this byte[] udpPacket, int initialPositionOffset = 12)
{
if (initialPositionOffset >= udpPacket.Length)
{
return initialPositionOffset;
}
// Skip the domain name (variable length)
while (udpPacket[initialPositionOffset] != 0)
{
// Check if the domain name is compressed
if ((udpPacket[initialPositionOffset] & 0xC0) == 0xC0)
{
// Skip the pointer (2 bytes total) and break
initialPositionOffset += 2;
break;
}
initialPositionOffset += udpPacket[initialPositionOffset] + 1;
if (initialPositionOffset >= udpPacket.Length)
{
throw new IndexOutOfRangeException("Domain name parsing went out of bounds.");
}
}
// Skip the null terminator of the domain name (0x00)
initialPositionOffset++;
if (initialPositionOffset + 4 > udpPacket.Length)
{
throw new IndexOutOfRangeException("Not enough data for type and class in the DNS question.");
}
// Skip DNS Type (2 bytes) and DNS Class (2 bytes)
return initialPositionOffset + 4;
}
public static string ReadDomainName(this byte[] udpPacket, ref int position)
{
var domainName = new StringBuilder();
while (udpPacket[position] != 0)
{
int labelLength = udpPacket[position];
position++;
if ((labelLength & 0xC0) == 0xC0)
{
var offset = ((labelLength & 0x3F) << 8) | udpPacket[position];
position++;
return ReadDomainName(udpPacket, ref offset);
}
domainName.Append(Encoding.UTF8.GetString(udpPacket, position, labelLength));
position += labelLength;
if (udpPacket[position] != 0)
{
domainName.Append('.');
}
}
position++;
return domainName.ToString();
}
public static byte[] GetDnsQuestionBytes(this List<DnsQuestionItem> dnsQuestions)
{
using var stream = new MemoryStream();
foreach (var dnsQuestionItem in dnsQuestions)
{
var domainNameBytes = dnsQuestionItem.DomainName.GetDomainNameBytes();
var dnsTypeBytes = BitConverter.GetBytes((ushort)dnsQuestionItem.DnsType);
var dnsClassBytes = BitConverter.GetBytes((ushort)dnsQuestionItem.DnsClass);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(dnsTypeBytes);
Array.Reverse(dnsClassBytes);
}
stream.Write(domainNameBytes, 0, domainNameBytes.Length);
stream.Write(dnsTypeBytes, 0, dnsTypeBytes.Length);
stream.Write(dnsClassBytes, 0, dnsClassBytes.Length);
}
return stream.ToArray();
}
public static byte[] GetDnsAnswerBytes(this List<DnsAnswerItem> dnsAnswers)
{
using var stream = new MemoryStream();
foreach (var dnsAnswerItem in dnsAnswers)
{
var domainNameBytes = dnsAnswerItem.DomainName.GetDomainNameBytes();
var dnsTypeBytes = BitConverter.GetBytes((ushort)dnsAnswerItem.DnsType);
var dnsClassBytes = BitConverter.GetBytes((ushort)dnsAnswerItem.DnsClass);
var ttlBytes = BitConverter.GetBytes(dnsAnswerItem.TimeToLive);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(dnsTypeBytes);
Array.Reverse(dnsClassBytes);
Array.Reverse(ttlBytes);
}
stream.Write(domainNameBytes, 0, domainNameBytes.Length);
stream.Write(dnsTypeBytes, 0, dnsTypeBytes.Length);
stream.Write(dnsClassBytes, 0, dnsClassBytes.Length);
stream.Write(ttlBytes, 0, ttlBytes.Length);
var ipAddressParts = dnsAnswerItem.Data.Split('.');
var rdataBytes = new byte[4];
for (var i = 0; i < 4; i++)
{
rdataBytes[i] = byte.Parse(ipAddressParts[i]);
}
var rdLengthBytes = BitConverter.GetBytes((ushort)rdataBytes.Length);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(rdLengthBytes);
}
stream.Write(rdLengthBytes, 0, rdLengthBytes.Length);
stream.Write(rdataBytes, 0, rdataBytes.Length);
}
return stream.ToArray();
}
private static byte[] GetDomainNameBytes(this string domainName)
{
var parts = domainName.Split('.');
using var stream = new MemoryStream();
foreach (var part in parts)
{
stream.WriteByte((byte)part.Length);
var partBytes = Encoding.ASCII.GetBytes(part);
stream.Write(partBytes, 0, partBytes.Length);
}
stream.WriteByte(0);
return stream.ToArray();
}
}