Change byte[] to ReadOnlyMemory<byte>. Implement DNS system.

This commit is contained in:
femsci 2023-08-30 17:32:36 +02:00
parent 8ab872589c
commit efdf871b4e
Signed by: femsci
GPG key ID: 08F7911F0E650C67
25 changed files with 623 additions and 30 deletions

View file

@ -1,6 +1,7 @@
{
"sonarlint.connectedMode.project": {
"connectionId": "",
"projectKey": ""
}
"sonarlint.connectedMode.project": {
"connectionId": "",
"projectKey": ""
},
"dotnet.defaultSolution": "IPMeow.sln"
}

View file

@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IPMeow.Test", "test\IPMeow.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IPMeow.Dhcp", "src\IPMeow.Dhcp\IPMeow.Dhcp.csproj", "{E43DAE0D-7B29-443A-875B-3F5B5D8D2985}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IPMeow.Dns", "src\IPMeow.Dns\IPMeow.Dns.csproj", "{8FC668A7-613D-453A-B8C5-9560AC0CD3C7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -52,6 +54,10 @@ Global
{E43DAE0D-7B29-443A-875B-3F5B5D8D2985}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E43DAE0D-7B29-443A-875B-3F5B5D8D2985}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E43DAE0D-7B29-443A-875B-3F5B5D8D2985}.Release|Any CPU.Build.0 = Release|Any CPU
{8FC668A7-613D-453A-B8C5-9560AC0CD3C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8FC668A7-613D-453A-B8C5-9560AC0CD3C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FC668A7-613D-453A-B8C5-9560AC0CD3C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FC668A7-613D-453A-B8C5-9560AC0CD3C7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{7B05EB40-4EDE-4ECA-A877-76B5A121ED52} = {8C8C298E-21E9-4519-AAC0-205AF974F4E2}
@ -60,5 +66,6 @@ Global
{81E9956C-89B1-4724-A006-1D1E398DBE81} = {8C8C298E-21E9-4519-AAC0-205AF974F4E2}
{7B861E40-93E1-4A53-A0F2-A744E94BD517} = {74533C64-0AB7-493E-8824-94B0CFC563B2}
{E43DAE0D-7B29-443A-875B-3F5B5D8D2985} = {8C8C298E-21E9-4519-AAC0-205AF974F4E2}
{8FC668A7-613D-453A-B8C5-9560AC0CD3C7} = {8C8C298E-21E9-4519-AAC0-205AF974F4E2}
EndGlobalSection
EndGlobal

View file

@ -32,7 +32,7 @@ public class BootpHeader
public override string ToString()
{
return $"{Hops}\nXid: {Xid}, Seconds: {Seconds}, Flags: {Flags:x}\nci: {ClientAddress}\nyi: {YourAddress}, ns: {NextServerAddress}, ra: {RelayAgentAddress}\nhw: {MacAddress.Parse(GetMacAddress())}";
return $"{Hops}\nXid: {Xid}, Seconds: {Seconds}, Flags: {Flags:x}\nci: {ClientAddress}\nyi: {YourAddress}, ns: {NextServerAddress}, ra: {RelayAgentAddress}\nhw: {GetMacAddress()}";
}
public byte[] GetClientHwAddress()
@ -49,7 +49,7 @@ public class BootpHeader
return buf;
}
public byte[] GetMacAddress() => ClientHWAddress[0..6];
public MacAddress GetMacAddress() => MacAddress.Parse(ClientHWAddress[0..6]);
public static BootpHeader? Deserialize(byte[] data)
{

View file

@ -14,8 +14,13 @@ public class Dhcp4Server : IDhcpServer, IDisposable
{
_addrProvider = addressProvider;
_udp = new UdpClient(serverPort, AddressFamily.InterNetwork);
_token = new();
_serverThread = new Thread(async () => await Run(_token.Token));
}
private readonly CancellationTokenSource _token;
private readonly Thread _serverThread;
private readonly IAddressProvider<AddressRequestContext> _addrProvider;
public event EventHandler<DhcpRequestEventArgs> DhcpRequestedEvent = delegate { };
@ -46,10 +51,18 @@ public class Dhcp4Server : IDhcpServer, IDisposable
packet.IsValidated = true;
AddressRequestContext ctx = new()
{
IsV6 = false,
MacAddress = packet.Header.GetMacAddress()
};
_addrProvider.GetAddress(ctx);
DhcpRequestedEvent.Invoke(this, new()
{
IsV6 = false,
MacAddress = MacAddress.Parse(packet.Header.GetMacAddress()),
MacAddress = packet.Header.GetMacAddress(),
RequestOrigin = packet.Header.ClientAddress
});
//TODO
@ -97,15 +110,20 @@ public class Dhcp4Server : IDhcpServer, IDisposable
}
}
public async Task StartAsync(CancellationToken cancellationToken)
public Task StartAsync(CancellationToken cancellationToken)
{
new Thread(async () => await Run(cancellationToken)).Start();
_serverThread.Start();
Console.WriteLine("V4 started.");
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
public async Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
await Task.Run(() =>
{
_token.Cancel();
_serverThread.Join();
}, cancellationToken);
}
private readonly UdpClient _udp;

View file

@ -1,6 +1,7 @@
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using IPMeow.Lib.Address;
using IPMeow.Lib.Request;
namespace IPMeow.Dhcp.Server.Dhcp6;
@ -15,11 +16,17 @@ public class Dhcp6Server : IDhcpServer, IDisposable
_listener = new(serverPort, AddressFamily.InterNetworkV6);
_listener.JoinMulticastGroup(IPAddress.Parse("ff02::1:2"));
_sender = new(clientPort, AddressFamily.InterNetworkV6);
_token = new();
_thread = new(async () => await Run(_token.Token));
}
private readonly IAddressProvider<AddressRequestContext> _addrProvider;
private readonly UdpClient _listener, _sender;
private readonly Thread _thread;
private readonly CancellationTokenSource _token;
public event EventHandler<DhcpRequestEventArgs> DhcpRequestedEvent = delegate { };
public void Dispose()
@ -49,6 +56,15 @@ public class Dhcp6Server : IDhcpServer, IDisposable
return;
}
AddressRequestContext ctx = new()
{
IsV6 = true,
MacAddress = null
};
_addrProvider.GetAddress(ctx);
//TODO
}
@ -64,14 +80,19 @@ public class Dhcp6Server : IDhcpServer, IDisposable
}
}
public async Task StartAsync(CancellationToken cancellationToken)
public Task StartAsync(CancellationToken cancellationToken)
{
new Thread(async () => await Run(cancellationToken)).Start();
_thread.Start();
Console.WriteLine("V6 started.");
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public async Task StopAsync(CancellationToken cancellationToken)
{
await Task.Run(() =>
{
_token.Cancel();
_thread.Join();
}, cancellationToken);
}
}

View file

@ -0,0 +1,119 @@
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using IPMeow.Lib;
namespace IPMeow.Dns;
public struct DnsMessage : IBinarySerializable<DnsMessage>
{
public UInt128 Header { get; set; }
public ushort MessageId { get; set; }
public bool IsAuthoritative { get; set; }
public bool IsTruncated { get; set; }
public bool IsRecursionDesired { get; set; }
public bool IsRecursionAvailable { get; set; }
public DnsMessageType MessageType { get; set; }
public DnsMessageOpcode Opcode { get; set; }
public DnsResponseCode ResponseCode { get; set; }
public ICollection<ResourceRecord> Questions { get; set; }
public static DnsMessage Deserialize(ReadOnlyMemory<byte> data)
{
BitEnumerator b = new(data);
ushort messageId = b.TakeUInt16();
short flags = b.TakeInt16();
DnsMessageType type = BitUtils.GetBit(flags, 0) ? DnsMessageType.Reply : DnsMessageType.Query;
DnsMessageOpcode opcode = (DnsMessageOpcode)(flags & (0xf << 11) >> 11);
bool isAuth = BitUtils.GetBit(flags, 5);
bool isTruncated = BitUtils.GetBit(flags, 6);
bool isRecursionDesired = BitUtils.GetBit(flags, 7);
bool isRecursionAvailable = BitUtils.GetBit(flags, 8);
DnsResponseCode code = (DnsResponseCode)(flags & 0xf);
short question = b.TakeInt16(), answer = b.TakeInt16(), authority = b.TakeInt16(), additional = b.TakeInt16();
return new DnsMessage()
{
MessageId = messageId,
MessageType = type,
Opcode = opcode,
IsAuthoritative = isAuth,
IsTruncated = isTruncated,
IsRecursionDesired = isRecursionDesired,
IsRecursionAvailable = isRecursionAvailable,
ResponseCode = code,
};
}
public readonly ReadOnlyMemory<byte> Serialize()
{
ArrayBufferWriter<byte> buffer = new(12); //(this.AnswerCount + this.AuthorityCount + this.QuestionCount + this.AdditionalDataCount));
int flags = (ushort)ResponseCode | ((ushort)Opcode << 11);
if (MessageType == DnsMessageType.Reply)
{
flags |= 0x8000;
}
flags |= IsAuthoritative ? 0b10000000000 : 0;
flags |= IsTruncated ? 0b1000000000 : 0;
flags |= IsRecursionDesired ? 0b100000000 : 0;
flags |= IsRecursionAvailable ? 0b10000000 : 0;
BinaryPrimitives.WriteUInt16BigEndian(buffer.GetSpan(), MessageId);
buffer.Advance(2);
BinaryPrimitives.WriteUInt16BigEndian(buffer.GetSpan(), (ushort)flags);
buffer.Advance(2);
BinaryPrimitives.WriteInt16BigEndian(buffer.GetSpan(), (short)Questions.Count);
buffer.Advance(2);
BinaryPrimitives.WriteInt16BigEndian(buffer.GetSpan(), 0);
buffer.Advance(2);
BinaryPrimitives.WriteInt16BigEndian(buffer.GetSpan(), 0);
buffer.Advance(2);
BinaryPrimitives.WriteInt16BigEndian(buffer.GetSpan(), 0);
buffer.Advance(2);
if (Questions.Any())
{
foreach (var question in Questions)
{
buffer.Write(question.Serialize().Span);
}
}
return buffer.WrittenMemory;
}
}
public enum DnsMessageType : byte
{
Query = 0,
Reply = 1
}
public enum DnsMessageOpcode : byte
{
Query = 0,
InverseQuery = 1,
Status = 2
}
public enum DnsResponseCode : byte
{
Ok = 0,
FormatError = 1,
ServerFail = 2,
NxDomain = 3
}

View file

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\IPMeow.Lib\IPMeow.Lib.csproj" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,109 @@
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
using IPMeow.Lib;
namespace IPMeow.Dns;
public enum ResourceRecordType : short
{
Invalid = 0,
A = 1,
NS = 2,
CNAME = 5,
SOA = 6,
PTR = 12,
MX = 15,
TXT = 16,
RP = 17,
AAAA = 28,
LOC = 29,
SRV = 33,
NAPTR = 35,
CERT = 37,
DNAME = 39,
OPT = 41,
DS = 43,
SSHFP = 44,
RRSIG = 46,
NSEC = 47,
DNSKEY = 48,
DHCID = 49,
NSEC3 = 50,
NSEC3PARAM = 51,
TLSA = 52,
HIP = 55,
OPENPGPKEY = 61,
CSYNC = 62,
CAA = 257,
}
public enum ResourceRecordClass : short
{
Invalid = 0,
IN = 1,
CH = 3,
HS = 4,
}
public struct ResourceRecord : IBinarySerializable<ResourceRecord>
{
public string Name { get; set; }
public ResourceRecordType Type { get; set; }
public ResourceRecordClass Class { get; set; }
public TimeSpan Ttl { get; set; }
public static ResourceRecord Deserialize(ReadOnlyMemory<byte> data)
{
throw new NotImplementedException();
}
public ReadOnlySpan<byte> SerializeName()
{
string name = Name.Normalize().Trim('.');
if (name.Length > 255)
{
throw new ArgumentOutOfRangeException("Name must be less than 255");
}
ArrayBufferWriter<byte> buffer = new(name.Length + 1 + 4);
foreach (string s in name.Split('.'))
{
byte[] b = Encoding.UTF8.GetBytes(s);
var lenBuf = buffer.GetSpan(1);
lenBuf[0] = (byte)b.Length;
buffer.Advance(1);
buffer.Write(b);
}
var zero = buffer.GetSpan(1);
zero[0] = 0;
buffer.Advance(1);
return buffer.WrittenSpan;
}
public ReadOnlyMemory<byte> Serialize()
{
var buffer = new ArrayBufferWriter<byte>();
buffer.Write(SerializeName());
BinaryPrimitives.WriteInt16BigEndian(buffer.GetSpan(), (short)Type);
buffer.Advance(2);
BinaryPrimitives.WriteInt16BigEndian(buffer.GetSpan(), (short)Class);
buffer.Advance(2);
BinaryPrimitives.WriteInt32BigEndian(buffer.GetSpan(), (int)Ttl.TotalSeconds);
buffer.Advance(4);
//TODO: Implement RDATA
BinaryPrimitives.WriteInt16BigEndian(buffer.GetSpan(), 0);
buffer.Advance(2);
return buffer.WrittenMemory;
}
}

View file

@ -1,9 +1,10 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using IPMeow.Lib.Identity;
namespace IPMeow.Lib.Address;
public readonly struct MacAddress
public readonly struct MacAddress : IIdentity
{
public MacAddress(byte[] addr)
{

View file

@ -4,17 +4,17 @@ namespace IPMeow.Lib;
public class BitEnumerator
{
public BitEnumerator(byte[] data)
public BitEnumerator(ReadOnlyMemory<byte> data)
{
_data = data;
}
private readonly byte[] _data;
private readonly ReadOnlyMemory<byte> _data;
private int _position = 0;
public byte TakeByte()
{
return _data[_position++];
return _data.Span[_position++];
}
public byte[] TakeBytes(int len)
@ -23,12 +23,12 @@ public class BitEnumerator
_position += len;
return data;
return data.ToArray();
}
public short TakeInt16()
{
short num = BinaryPrimitives.ReadInt16BigEndian(_data.AsSpan()[_position..(_position + 2)]);
short num = BinaryPrimitives.ReadInt16BigEndian(_data.Span[_position..(_position + 2)]);
_position += 2;
@ -37,7 +37,7 @@ public class BitEnumerator
public int TakeInt32()
{
int num = BinaryPrimitives.ReadInt32BigEndian(_data.AsSpan()[_position..(_position + 4)]);
int num = BinaryPrimitives.ReadInt32BigEndian(_data.Span[_position..(_position + 4)]);
_position += 4;
@ -46,7 +46,7 @@ public class BitEnumerator
public long TakeInt64()
{
long num = BinaryPrimitives.ReadInt64BigEndian(_data.AsSpan()[_position..(_position + 8)]);
long num = BinaryPrimitives.ReadInt64BigEndian(_data.Span[_position..(_position + 8)]);
_position += 8;
@ -55,7 +55,7 @@ public class BitEnumerator
public ushort TakeUInt16()
{
ushort num = BinaryPrimitives.ReadUInt16BigEndian(_data.AsSpan()[_position..(_position + 2)]);
ushort num = BinaryPrimitives.ReadUInt16BigEndian(_data.Span[_position..(_position + 2)]);
_position += 2;
@ -64,7 +64,7 @@ public class BitEnumerator
public uint TakeUInt32()
{
uint num = BinaryPrimitives.ReadUInt32BigEndian(_data.AsSpan()[_position..(_position + 4)]);
uint num = BinaryPrimitives.ReadUInt32BigEndian(_data.Span[_position..(_position + 4)]);
_position += 4;
@ -73,7 +73,7 @@ public class BitEnumerator
public ulong TakeUInt64()
{
ulong num = BinaryPrimitives.ReadUInt64BigEndian(_data.AsSpan()[_position..(_position + 8)]);
ulong num = BinaryPrimitives.ReadUInt64BigEndian(_data.Span[_position..(_position + 8)]);
_position += 8;

View file

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace IPMeow.Lib;
public static class BitUtils
{
/// <summary>
/// Gets the nth most significant bit
/// </summary>
/// <param name="data"></param>
/// <param name="bit"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool GetBit(short data, int bit)
{
return (data & (0x1 << (15 - bit))) == (0x1 << (15 - bit));
}
}

View file

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IPMeow.Lib;
public interface IBinarySerializable<T>
{
public ReadOnlyMemory<byte> Serialize();
public static abstract T Deserialize(ReadOnlyMemory<byte> data);
}

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IPMeow.Lib.Identity;
public class DhcpClientId : IIdentity
{
}

View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IPMeow.Lib.Identity;
public class Duid : IIdentity
{
}
public enum DuidType : short
{
LinkLayerTime = 1,
EnterpriseNumber = 2,
LinkLayerAddress = 3,
Uuid = 4
}

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IPMeow.Lib.Identity;
public interface IIdentity
{
}

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IPMeow.Lib.Identity;
public class Identity<T> where T : IIdentity
{
}

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
namespace IPMeow.Lib.Server;
public class DnsServer : IRoutedServer
{
public required IPAddress Address { get; set; }
public required ICollection<Protocol> Protocols { get; set; }
public bool SupportsTls { get; set; }
}

View file

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
namespace IPMeow.Lib.Server;
public interface IRoutedServer
{
public IPAddress Address { get; set; }
public ICollection<Protocol> Protocols { get; set; }
}

View file

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IPMeow.Lib.Server;
public struct Protocol
{
public short Port { get; set; }
public string Name { get; set; }
}

View file

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IPMeow.Lib.Server;
public static class Protocols
{
private static readonly HashSet<Protocol> _protos = new()
{
Http,
Dns,
DnsOverTls,
DnsOverHttps,
Ntp,
Ssh,
Snmp,
Ldap,
Kerberos,
Radius,
Smtp,
Pop3,
Imap
};
public static readonly Protocol Http = new() { Name = "HTTP", Port = 80 };
public static readonly Protocol Dns = new() { Name = "DNS", Port = 53 };
public static readonly Protocol DnsOverTls = new() { Name = "DNS-over-TLS", Port = 853 };
public static readonly Protocol DnsOverHttps = new() { Name = "DNS-over-HTTPS", Port = 443 };
public static readonly Protocol Ntp = new() { Name = "NTP", Port = 123 };
public static readonly Protocol Ssh = new() { Name = "SSH", Port = 22 };
public static readonly Protocol Snmp = new() { Name = "SNMP", Port = 161 };
public static readonly Protocol Ldap = new() { Name = "LDAP", Port = 389 };
public static readonly Protocol Kerberos = new() { Name = "Kerberos", Port = 88 };
public static readonly Protocol Radius = new() { Name = "RADIUS", Port = 1812 };
public static readonly Protocol Smtp = new() { Name = "SMTP", Port = 25 };
public static readonly Protocol Pop3 = new() { Name = "POP3", Port = 110 };
public static readonly Protocol Imap = new() { Name = "IMAP", Port = 143 };
public static Protocol? GetByPort(short port)
{
return _protos.SingleOrDefault(s => s.Port == port);
}
public static Protocol? GetByName(string name)
{
return _protos.SingleOrDefault(s => s.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
}
}

View file

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
using IPMeow.Lib.Address;
using IPMeow.Lib.Server;
namespace IPMeow.Lib.Site;
public class Network
{
[Key]
public required string Name { get; set; }
public virtual ICollection<DnsServer> DnsServers { get; set; }
public virtual ICollection<Address.Network> Networks { get; set; }
}

View file

@ -4,12 +4,31 @@ using Microsoft.AspNetCore.Mvc;
namespace IPMeow.Server.Controllers;
[ApiController]
[Route("api/[controller]")]
public class AddressController : ControllerBase
[Route("api/address/v6")]
public class V6AddressController : ControllerBase
{
[HttpPost("request")]
public async Task<IActionResult> RequestAddress(AddressRequestContext ctx)
{
throw new NotImplementedException();
}
[HttpGet]
public async Task<IActionResult> ConfirmRequest()
{
throw new NotImplementedException();
}
}
[ApiController]
[Route("api/address/v4")]
public class V4AddressController : ControllerBase
{
[HttpPost("request")]
public async Task<IActionResult> RequestAddress(AddressRequestContext ctx)
{
throw new NotImplementedException();
}

View file

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace IPMeow.Server.Controllers;
[ApiController]
[Route("/api/info")]
public class InfoController
{
[HttpGet("all")]
public async Task<IActionResult> GetAllData()
{
throw new NotImplementedException();
}
[HttpGet("dns")]
public async Task<IActionResult> GetDnsServers()
{
throw new NotImplementedException();
}
[HttpGet("ntp")]
public async Task<IActionResult> GetNtpServers()
{
throw new NotImplementedException();
}
[HttpGet("snmp")]
public async Task<IActionResult> GetSnmpServers()
{
throw new NotImplementedException();
}
}

View file

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using IPMeow.Dns;
namespace IPMeow.Test;
public class DnsTest
{
[Fact]
public async Task TestDns()
{
DnsMessage msg = new()
{
IsRecursionDesired = true,
IsRecursionAvailable = true,
MessageId = 0xbabe,
MessageType = DnsMessageType.Query,
Opcode = DnsMessageOpcode.Query,
Questions = new List<ResourceRecord>()
{
new ResourceRecord()
{
Class = ResourceRecordClass.IN,
Ttl = TimeSpan.Zero,
Name = "meow.lgbt",
Type = ResourceRecordType.A
},
},
ResponseCode = 0,
};
await Send(msg);
Console.WriteLine("sendt");
msg.IsRecursionDesired = false;
msg.IsAuthoritative = true;
msg.MessageType = DnsMessageType.Reply;
msg.Opcode = DnsMessageOpcode.Status;
msg.ResponseCode = DnsResponseCode.NxDomain;
await Send(msg);
}
private async Task Send(DnsMessage msg)
{
var data = msg.Serialize();
using UdpClient udp = new UdpClient(AddressFamily.InterNetwork);
udp.Connect(IPAddress.Parse("1.1.1.1"), 53);
await udp.SendAsync(data);
}
}

View file

@ -27,6 +27,7 @@
<ProjectReference Include="..\..\src\IPMeow.Cli\IPMeow.Cli.csproj" />
<ProjectReference Include="..\..\src\IPMeow.Server\IPMeow.Server.csproj" />
<ProjectReference Include="..\..\src\IPMeow.Viewer\IPMeow.Viewer.csproj" />
<ProjectReference Include="..\..\src\IPMeow.Dns\IPMeow.Dns.csproj" />
</ItemGroup>
</Project>