Code
·
71 lines
·
2275 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
71using MailSharp.DNS.Records;
using System.Net;
namespace MailSharp.DNS;
public partial class Resolver
{
public async Task<Response> QueryAsync(IPEndPoint server, string name, DnsQType type, DnsQClass @class, CancellationToken ct = default)
{
if (!name.EndsWith('.'))
name += '.';
if (recordCache.IsEmpty)
await BootstrapRootAsync(ct);
var question = new QuestionRecord(name, type, @class);
if (SearchInRecordCache(question) is Response cached)
return cached;
var request = new Request();
request.AddQuestion(question);
return await GetResponseAsync(server, request);
}
private async Task BootstrapRootAsync(CancellationToken ct)
{
if (!File.Exists("root\\named_root.txt"))
return;
List<RR> authorities = [];
await foreach (var authority in RootHintsParser.ParseAsync("root\\named_root.txt", ct))
authorities.Add(authority);
AddToCache(new Response
{
Questions = [new QuestionRecord(".", DnsQType.NS, DnsQClass.IN)],
Authorities = authorities
});
}
public async Task<IPHostEntry> GetHostEntryAsync(IPEndPoint server, string hostNameOrAddress, CancellationToken ct = default)
=> IPAddress.TryParse(hostNameOrAddress, out var ip)
? await GetHostEntryAsync(server, ip, ct)
: await ResolveForwardAsync(server, hostNameOrAddress, ct);
public async Task<IPHostEntry> GetHostEntryAsync(IPEndPoint server, IPAddress ip, CancellationToken ct = default)
{
var response = await QueryAsync(server, GetArpaFromIp(ip), DnsQType.PTR, DnsQClass.IN, ct);
return response.RecordsPTR.Length > 0
? await ResolveForwardAsync(server, response.RecordsPTR[0].PtrName, ct)
: new IPHostEntry();
}
private async Task<IPHostEntry> ResolveForwardAsync(IPEndPoint server, string hostName, CancellationToken ct)
{
var response = await QueryAsync(server, hostName, DnsQType.A, DnsQClass.IN, ct);
var entry = new IPHostEntry { HostName = hostName };
var addresses = new List<IPAddress>();
var aliases = new List<string>();
foreach (var rr in response.Answers)
{
if (rr.Type == DnsType.A && rr.Record is RecordA a)
addresses.Add(a.Address);
else if (rr.Type == DnsType.CNAME)
aliases.Add(rr.Name);
}
entry.AddressList = [.. addresses];
entry.Aliases = [.. aliases];
return entry;
}
}