From efdf871b4eacb862cdfa691ce30d31027eca5ff4 Mon Sep 17 00:00:00 2001 From: femsci Date: Wed, 30 Aug 2023 17:32:36 +0200 Subject: [PATCH] Change byte[] to ReadOnlyMemory. Implement DNS system. --- .vscode/settings.json | 9 +- IPMeow.sln | 7 ++ src/IPMeow.Dhcp/Server/Dhcp4/Bootp.cs | 4 +- src/IPMeow.Dhcp/Server/Dhcp4/DhcpServer.cs | 28 ++++- src/IPMeow.Dhcp/Server/Dhcp6/DhcpServer.cs | 33 ++++- src/IPMeow.Dns/DnsMessage.cs | 119 ++++++++++++++++++ src/IPMeow.Dns/IPMeow.Dns.csproj | 13 ++ src/IPMeow.Dns/ResourceRecord.cs | 109 ++++++++++++++++ src/IPMeow.Lib/Address/MacAddress.cs | 3 +- src/IPMeow.Lib/BitEnumerator.cs | 20 +-- src/IPMeow.Lib/BitUtils.cs | 24 ++++ src/IPMeow.Lib/IBinarySerializable.cs | 13 ++ src/IPMeow.Lib/Identity/DhcpClientId.cs | 11 ++ src/IPMeow.Lib/Identity/Duid.cs | 19 +++ src/IPMeow.Lib/Identity/IIdentity.cs | 11 ++ src/IPMeow.Lib/Identity/Identity.cs | 11 ++ src/IPMeow.Lib/Server/DnsServer.cs | 14 +++ src/IPMeow.Lib/Server/IRoutedServer.cs | 13 ++ src/IPMeow.Lib/Server/Protocol.cs | 12 ++ src/IPMeow.Lib/Server/Protocols.cs | 51 ++++++++ src/IPMeow.Lib/Site/Network.cs | 13 ++ .../Controllers/AddressController.cs | 23 +++- .../Controllers/InfoController.cs | 36 ++++++ test/IPMeow.Test/DnsTest.cs | 56 +++++++++ test/IPMeow.Test/IPMeow.Test.csproj | 1 + 25 files changed, 623 insertions(+), 30 deletions(-) create mode 100644 src/IPMeow.Dns/DnsMessage.cs create mode 100644 src/IPMeow.Dns/IPMeow.Dns.csproj create mode 100644 src/IPMeow.Dns/ResourceRecord.cs create mode 100644 src/IPMeow.Lib/BitUtils.cs create mode 100644 src/IPMeow.Lib/IBinarySerializable.cs create mode 100644 src/IPMeow.Lib/Identity/DhcpClientId.cs create mode 100644 src/IPMeow.Lib/Identity/Duid.cs create mode 100644 src/IPMeow.Lib/Identity/IIdentity.cs create mode 100644 src/IPMeow.Lib/Identity/Identity.cs create mode 100644 src/IPMeow.Lib/Server/DnsServer.cs create mode 100644 src/IPMeow.Lib/Server/IRoutedServer.cs create mode 100644 src/IPMeow.Lib/Server/Protocol.cs create mode 100644 src/IPMeow.Lib/Server/Protocols.cs create mode 100644 src/IPMeow.Lib/Site/Network.cs create mode 100644 src/IPMeow.Server/Controllers/InfoController.cs create mode 100644 test/IPMeow.Test/DnsTest.cs diff --git a/.vscode/settings.json b/.vscode/settings.json index 8541e7e..0b6ce81 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { - "sonarlint.connectedMode.project": { - "connectionId": "", - "projectKey": "" - } + "sonarlint.connectedMode.project": { + "connectionId": "", + "projectKey": "" + }, + "dotnet.defaultSolution": "IPMeow.sln" } diff --git a/IPMeow.sln b/IPMeow.sln index aafe85b..d655d09 100644 --- a/IPMeow.sln +++ b/IPMeow.sln @@ -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 diff --git a/src/IPMeow.Dhcp/Server/Dhcp4/Bootp.cs b/src/IPMeow.Dhcp/Server/Dhcp4/Bootp.cs index 1f4ff59..4da447a 100644 --- a/src/IPMeow.Dhcp/Server/Dhcp4/Bootp.cs +++ b/src/IPMeow.Dhcp/Server/Dhcp4/Bootp.cs @@ -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) { diff --git a/src/IPMeow.Dhcp/Server/Dhcp4/DhcpServer.cs b/src/IPMeow.Dhcp/Server/Dhcp4/DhcpServer.cs index 893e504..06e8432 100644 --- a/src/IPMeow.Dhcp/Server/Dhcp4/DhcpServer.cs +++ b/src/IPMeow.Dhcp/Server/Dhcp4/DhcpServer.cs @@ -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 _addrProvider; public event EventHandler 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; diff --git a/src/IPMeow.Dhcp/Server/Dhcp6/DhcpServer.cs b/src/IPMeow.Dhcp/Server/Dhcp6/DhcpServer.cs index 83eefb6..b6f4463 100644 --- a/src/IPMeow.Dhcp/Server/Dhcp6/DhcpServer.cs +++ b/src/IPMeow.Dhcp/Server/Dhcp6/DhcpServer.cs @@ -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 _addrProvider; private readonly UdpClient _listener, _sender; + private readonly Thread _thread; + private readonly CancellationTokenSource _token; + public event EventHandler 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); + } } diff --git a/src/IPMeow.Dns/DnsMessage.cs b/src/IPMeow.Dns/DnsMessage.cs new file mode 100644 index 0000000..f4cfa8f --- /dev/null +++ b/src/IPMeow.Dns/DnsMessage.cs @@ -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 +{ + 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 Questions { get; set; } + + public static DnsMessage Deserialize(ReadOnlyMemory 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 Serialize() + { + ArrayBufferWriter 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 +} diff --git a/src/IPMeow.Dns/IPMeow.Dns.csproj b/src/IPMeow.Dns/IPMeow.Dns.csproj new file mode 100644 index 0000000..553ef24 --- /dev/null +++ b/src/IPMeow.Dns/IPMeow.Dns.csproj @@ -0,0 +1,13 @@ + + + + + + + + net7.0 + enable + enable + + + diff --git a/src/IPMeow.Dns/ResourceRecord.cs b/src/IPMeow.Dns/ResourceRecord.cs new file mode 100644 index 0000000..afbe698 --- /dev/null +++ b/src/IPMeow.Dns/ResourceRecord.cs @@ -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 +{ + 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 data) + { + throw new NotImplementedException(); + } + + public ReadOnlySpan SerializeName() + { + string name = Name.Normalize().Trim('.'); + + if (name.Length > 255) + { + throw new ArgumentOutOfRangeException("Name must be less than 255"); + } + + ArrayBufferWriter 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 Serialize() + { + var buffer = new ArrayBufferWriter(); + + 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; + } +} diff --git a/src/IPMeow.Lib/Address/MacAddress.cs b/src/IPMeow.Lib/Address/MacAddress.cs index befe296..728473d 100644 --- a/src/IPMeow.Lib/Address/MacAddress.cs +++ b/src/IPMeow.Lib/Address/MacAddress.cs @@ -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) { diff --git a/src/IPMeow.Lib/BitEnumerator.cs b/src/IPMeow.Lib/BitEnumerator.cs index 81e2dd0..7839a67 100644 --- a/src/IPMeow.Lib/BitEnumerator.cs +++ b/src/IPMeow.Lib/BitEnumerator.cs @@ -4,17 +4,17 @@ namespace IPMeow.Lib; public class BitEnumerator { - public BitEnumerator(byte[] data) + public BitEnumerator(ReadOnlyMemory data) { _data = data; } - private readonly byte[] _data; + private readonly ReadOnlyMemory _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; diff --git a/src/IPMeow.Lib/BitUtils.cs b/src/IPMeow.Lib/BitUtils.cs new file mode 100644 index 0000000..cd25900 --- /dev/null +++ b/src/IPMeow.Lib/BitUtils.cs @@ -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 +{ + /// + /// Gets the nth most significant bit + /// + /// + /// + /// + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool GetBit(short data, int bit) + { + return (data & (0x1 << (15 - bit))) == (0x1 << (15 - bit)); + } +} diff --git a/src/IPMeow.Lib/IBinarySerializable.cs b/src/IPMeow.Lib/IBinarySerializable.cs new file mode 100644 index 0000000..67c756f --- /dev/null +++ b/src/IPMeow.Lib/IBinarySerializable.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace IPMeow.Lib; + +public interface IBinarySerializable +{ + public ReadOnlyMemory Serialize(); + + public static abstract T Deserialize(ReadOnlyMemory data); +} diff --git a/src/IPMeow.Lib/Identity/DhcpClientId.cs b/src/IPMeow.Lib/Identity/DhcpClientId.cs new file mode 100644 index 0000000..d31e0d4 --- /dev/null +++ b/src/IPMeow.Lib/Identity/DhcpClientId.cs @@ -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 +{ + +} diff --git a/src/IPMeow.Lib/Identity/Duid.cs b/src/IPMeow.Lib/Identity/Duid.cs new file mode 100644 index 0000000..ce4a9b1 --- /dev/null +++ b/src/IPMeow.Lib/Identity/Duid.cs @@ -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 +} diff --git a/src/IPMeow.Lib/Identity/IIdentity.cs b/src/IPMeow.Lib/Identity/IIdentity.cs new file mode 100644 index 0000000..4c5781b --- /dev/null +++ b/src/IPMeow.Lib/Identity/IIdentity.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace IPMeow.Lib.Identity; + +public interface IIdentity +{ + +} diff --git a/src/IPMeow.Lib/Identity/Identity.cs b/src/IPMeow.Lib/Identity/Identity.cs new file mode 100644 index 0000000..b7e2cc8 --- /dev/null +++ b/src/IPMeow.Lib/Identity/Identity.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace IPMeow.Lib.Identity; + +public class Identity where T : IIdentity +{ + +} diff --git a/src/IPMeow.Lib/Server/DnsServer.cs b/src/IPMeow.Lib/Server/DnsServer.cs new file mode 100644 index 0000000..ec05e4e --- /dev/null +++ b/src/IPMeow.Lib/Server/DnsServer.cs @@ -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 Protocols { get; set; } + public bool SupportsTls { get; set; } +} diff --git a/src/IPMeow.Lib/Server/IRoutedServer.cs b/src/IPMeow.Lib/Server/IRoutedServer.cs new file mode 100644 index 0000000..c0852bd --- /dev/null +++ b/src/IPMeow.Lib/Server/IRoutedServer.cs @@ -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 Protocols { get; set; } +} diff --git a/src/IPMeow.Lib/Server/Protocol.cs b/src/IPMeow.Lib/Server/Protocol.cs new file mode 100644 index 0000000..acd03b8 --- /dev/null +++ b/src/IPMeow.Lib/Server/Protocol.cs @@ -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; } +} diff --git a/src/IPMeow.Lib/Server/Protocols.cs b/src/IPMeow.Lib/Server/Protocols.cs new file mode 100644 index 0000000..134e320 --- /dev/null +++ b/src/IPMeow.Lib/Server/Protocols.cs @@ -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 _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)); + } +} + diff --git a/src/IPMeow.Lib/Site/Network.cs b/src/IPMeow.Lib/Site/Network.cs new file mode 100644 index 0000000..6484c3f --- /dev/null +++ b/src/IPMeow.Lib/Site/Network.cs @@ -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 DnsServers { get; set; } + public virtual ICollection Networks { get; set; } +} diff --git a/src/IPMeow.Server/Controllers/AddressController.cs b/src/IPMeow.Server/Controllers/AddressController.cs index 85cd294..4e90bad 100644 --- a/src/IPMeow.Server/Controllers/AddressController.cs +++ b/src/IPMeow.Server/Controllers/AddressController.cs @@ -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 RequestAddress(AddressRequestContext ctx) { + + throw new NotImplementedException(); + } + + [HttpGet] + public async Task ConfirmRequest() + { + throw new NotImplementedException(); + } +} + +[ApiController] +[Route("api/address/v4")] +public class V4AddressController : ControllerBase +{ + [HttpPost("request")] + public async Task RequestAddress(AddressRequestContext ctx) + { + throw new NotImplementedException(); } diff --git a/src/IPMeow.Server/Controllers/InfoController.cs b/src/IPMeow.Server/Controllers/InfoController.cs new file mode 100644 index 0000000..9b09f7b --- /dev/null +++ b/src/IPMeow.Server/Controllers/InfoController.cs @@ -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 GetAllData() + { + throw new NotImplementedException(); + } + + [HttpGet("dns")] + public async Task GetDnsServers() + { + throw new NotImplementedException(); + } + + [HttpGet("ntp")] + public async Task GetNtpServers() + { + throw new NotImplementedException(); + } + + [HttpGet("snmp")] + public async Task GetSnmpServers() + { + throw new NotImplementedException(); + } +} diff --git a/test/IPMeow.Test/DnsTest.cs b/test/IPMeow.Test/DnsTest.cs new file mode 100644 index 0000000..ff494f8 --- /dev/null +++ b/test/IPMeow.Test/DnsTest.cs @@ -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() + { + 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); + } +} diff --git a/test/IPMeow.Test/IPMeow.Test.csproj b/test/IPMeow.Test/IPMeow.Test.csproj index 26245fc..5b0f9ae 100644 --- a/test/IPMeow.Test/IPMeow.Test.csproj +++ b/test/IPMeow.Test/IPMeow.Test.csproj @@ -27,6 +27,7 @@ +