Code
·
191 lines
·
4751 bytes
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191using MailSharp.DNS.Records;
using System.Buffers.Binary;
using System.Text;
namespace MailSharp.DNS;
public class RecordReader
{
private readonly byte[] data;
private int position;
public RecordReader(byte[] data)
{
this.data = data;
position = 0;
}
public RecordReader(byte[] data, int position)
{
this.data = data;
this.position = position;
}
public int Position
{
get => position;
set => position = value;
}
public byte ReadByte()
{
return data[position++];
}
public byte PeekPosition(int pos)
{
return data[pos];
}
public byte PeekByte()
{
return data[position];
}
public char ReadChar()
{
return (char)ReadByte();
}
public ushort ReadUInt16()
{
ushort value = BinaryPrimitives.ReadUInt16BigEndian(data.AsSpan(position));
position += 2;
return value;
}
public UInt16 ReadUInt16(int offset)
{
position += offset;
return ReadUInt16();
}
public uint ReadUInt32()
{
uint value = BinaryPrimitives.ReadUInt32BigEndian(data.AsSpan(position));
position += 4;
return value;
}
public string ReadDomainName()
{
StringBuilder name = new();
int length;
// get the length of the first label
while ((length = ReadByte()) != 0)
{
// top 2 bits set denotes domain name compression and to reference elsewhere
if ((length & 0xc0) == 0xc0)
{
// work out the existing domain name, copy this pointer
RecordReader newRecordReader = new(data, (length & 0x3f) << 8 | ReadByte());
name.Append(newRecordReader.ReadDomainName());
return name.ToString();
}
// if not using compression, copy a char at a time to the domain name
while (length > 0)
{
name.Append(ReadChar());
length--;
}
name.Append('.');
}
if (name.Length == 0)
return ".";
else
return name.ToString();
}
public string ReadString() =>ReadString(ReadByte());
public string ReadString(int length) => Encoding.ASCII.GetString(ReadBytes(length));
// changed 28 augustus 2008
public byte[] ReadBytes(int count)
{
byte[] result = new byte[count];
Buffer.BlockCopy(data, position, result, 0, count);
position += count;
return result;
}
public DnsRecord ReadRecord(DnsType type)
{
return type switch
{
DnsType.A => new RecordA(this),
DnsType.NS => new RecordNS(this),
DnsType.CNAME => new RecordCNAME(this),
DnsType.SOA => new RecordSOA(this),
DnsType.MB => new RecordMB(this),
DnsType.MG => new RecordMG(this),
DnsType.MR => new RecordMR(this),
DnsType.NULL => new RecordNULL(this),
DnsType.WKS => new RecordWKS(this),
DnsType.PTR => new RecordPTR(this),
DnsType.HINFO => new RecordHINFO(this),
DnsType.MINFO => new RecordMINFO(this),
DnsType.MX => new RecordMX(this),
DnsType.TXT => new RecordTXT(this),
DnsType.RP => new RecordRP(this),
DnsType.AFSDB => new RecordAFSDB(this),
DnsType.X25 => new RecordX25(this),
DnsType.ISDN => new RecordISDN(this),
DnsType.RT => new RecordRT(this),
DnsType.NSAP => new RecordNSAP(this),
DnsType.SIG => new RecordSIG(this),
DnsType.KEY => new RecordKEY(this),
DnsType.PX => new RecordPX(this),
DnsType.AAAA => new RecordAAAA(this),
DnsType.LOC => new RecordLOC(this),
DnsType.SRV => new RecordSRV(this),
DnsType.NAPTR => new RecordNAPTR(this),
DnsType.KX => new RecordKX(this),
DnsType.DNAME => new RecordDNAME(this),
DnsType.DS => new RecordDS(this),
DnsType.TKEY => new RecordTKEY(this),
DnsType.TSIG => new RecordTSIG(this),
DnsType.CAA => new RecordCAA(this),
DnsType.A6 => new RecordA6(this),
DnsType.SPF => new RecordSPF(this),
DnsType.IPSECKEY => new RecordIPSECKEY(this),
DnsType.APL => new RecordAPL(this),
DnsType.RRSIG => new RecordRRSIG(this),
DnsType.DNSKEY => new RecordDNSKEY(this),
DnsType.NSEC => new RecordNSEC(this),
DnsType.NSEC3 => new RecordNSEC3(this),
DnsType.NSEC3PARAM => new RecordNSEC3PARAM(this),
DnsType.CERT => new RecordCERT(this),
DnsType.EID => new RecordEID(this),
DnsType.NIMLOC => new RecordNIMLOC(this),
DnsType.ATMA => new RecordATMA(this),
DnsType.SINK => new RecordSINK(this),
DnsType.SSHFP => new RecordSSHFP(this),
DnsType.DHCID => new RecordDHCID(this),
DnsType.HIP => new RecordHIP(this),
DnsType.UINFO => new RecordUINFO(this),
DnsType.UID => new RecordUID(this),
DnsType.GID => new RecordGID(this),
DnsType.UNSPEC => new RecordUNSPEC(this),
// Incomplete implementation
DnsType.OPT => new RecordOPT(this),
// Obsolete records
DnsType.GPOS => new RecordGPOS(this),
DnsType.NSAPPTR => new RecordNSAPPTR(this),
DnsType.NXT => new RecordNXT(this),
DnsType.MD => new RecordMD(this),
DnsType.MF => new RecordMF(this),
_ => new RecordUnknown(this),
};
}
}