Refactor DHCP to implement DHCP and DHCPv6. Implement most DHCPv6 options.
This commit is contained in:
parent
22cd2dbf3a
commit
5ae056ad64
15 changed files with 642 additions and 41 deletions
|
@ -1,10 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IPMeow.Lib\IPMeow.Lib.csproj" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IPMeow.Lib\IPMeow.Lib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
|
16
src/IPMeow.Dhcp/Program.cs
Normal file
16
src/IPMeow.Dhcp/Program.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using IPMeow.Dhcp.Server;
|
||||
using IPMeow.Dhcp.Server.Dhcp4;
|
||||
|
||||
namespace IPMeow.Dhcp
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Listening on DHCP...");
|
||||
var dhcp = new DhcpServer();
|
||||
|
||||
await dhcp.Run();
|
||||
}
|
||||
}
|
||||
}
|
15
src/IPMeow.Dhcp/Server/AddressAssociation.cs
Normal file
15
src/IPMeow.Dhcp/Server/AddressAssociation.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IPMeow.Dhcp.Server;
|
||||
|
||||
public readonly struct AddressAssociation
|
||||
{
|
||||
public IPAddress Address { get; }
|
||||
public int PreferredLifetime { get; }
|
||||
public int ValidLifetime { get; }
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
namespace IPMeow.Dhcp.Server;
|
||||
namespace IPMeow.Dhcp.Server.Dhcp4;
|
||||
|
||||
public enum DhcpMessageType
|
||||
{
|
135
src/IPMeow.Dhcp/Server/Dhcp4/DhcpPacket.cs
Normal file
135
src/IPMeow.Dhcp/Server/Dhcp4/DhcpPacket.cs
Normal file
|
@ -0,0 +1,135 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using IPMeow.Lib;
|
||||
|
||||
namespace IPMeow.Dhcp.Server.Dhcp4;
|
||||
|
||||
public class DhcpPacket
|
||||
{
|
||||
public required DhcpOpType OpType { get; init; }
|
||||
public required byte HType { get; init; }
|
||||
public required byte HLen { get; init; }
|
||||
public required byte Hops { get; init; }
|
||||
public required uint Xid { get; init; }
|
||||
public required short Seconds { get; init; }
|
||||
public required short Flags { get; init; }
|
||||
public required IPAddress ClientAddress { get; init; }
|
||||
public required IPAddress YourAddress { get; init; }
|
||||
public required IPAddress NextServerAddress { get; init; }
|
||||
public required IPAddress RelayAgentAddress { get; init; }
|
||||
public required byte[] ClientHWAddress { get; init; }
|
||||
public required string ServerHostName { get; init; }
|
||||
public required string BootFileName { get; init; }
|
||||
public bool? IsValidated { get; set; }
|
||||
|
||||
public byte[] GetClientHwAddress()
|
||||
{
|
||||
int padLen = 16 - ClientHWAddress.Length;
|
||||
|
||||
if (padLen == 16)
|
||||
{
|
||||
return ClientHWAddress;
|
||||
}
|
||||
|
||||
var buf = new byte[16];
|
||||
ClientHWAddress.CopyTo(buf, 0);
|
||||
return buf;
|
||||
}
|
||||
|
||||
public byte[] GetSnameBytes()
|
||||
{
|
||||
var buf = new byte[64];
|
||||
if (!string.IsNullOrWhiteSpace(ServerHostName))
|
||||
{
|
||||
Encoding.UTF8.GetBytes(ServerHostName).CopyTo(buf, 0);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
public byte[] GetBootFileBytes()
|
||||
{
|
||||
var buf = new byte[128];
|
||||
if (!string.IsNullOrWhiteSpace(BootFileName))
|
||||
{
|
||||
Encoding.UTF8.GetBytes(BootFileName).CopyTo(buf, 0);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
public static DhcpPacket Deserialize(byte[] data)
|
||||
{
|
||||
BitEnumerator enu = new(data);
|
||||
|
||||
if (data.Length < 236 || data.Length > 576)
|
||||
{
|
||||
throw new ArgumentException("Invalid datagram.");
|
||||
}
|
||||
|
||||
var OpType = (DhcpOpType)enu.TakeByte();
|
||||
|
||||
var HType = enu.TakeByte();
|
||||
var HLen = enu.TakeByte();
|
||||
var Hops = enu.TakeByte();
|
||||
var Xid = enu.TakeUInt32();
|
||||
var Seconds = enu.TakeInt16();
|
||||
var Flags = enu.TakeInt16();
|
||||
var ClientAddress = new IPAddress(enu.TakeBytes(4));
|
||||
var YourAddress = new IPAddress(enu.TakeBytes(4));
|
||||
var NextServerAddress = new IPAddress(enu.TakeBytes(4));
|
||||
var RelayAgentAddress = new IPAddress(enu.TakeBytes(4));
|
||||
byte[] chaddr = enu.TakeBytes(16);
|
||||
byte[] sname = enu.TakeBytes(64);
|
||||
byte[] file = enu.TakeBytes(128);
|
||||
|
||||
var BootFileName = Encoding.UTF8.GetString(file.TakeWhile(x => x != 0).ToArray());
|
||||
var ServerHostName = Encoding.UTF8.GetString(sname.TakeWhile(x => x != 0).ToArray());
|
||||
|
||||
return new()
|
||||
{
|
||||
OpType = OpType,
|
||||
HType = HType,
|
||||
HLen = HLen,
|
||||
Hops = Hops,
|
||||
Xid = Xid,
|
||||
Seconds = Seconds,
|
||||
Flags = Flags,
|
||||
ClientAddress = ClientAddress,
|
||||
YourAddress = YourAddress,
|
||||
NextServerAddress = NextServerAddress,
|
||||
RelayAgentAddress = RelayAgentAddress,
|
||||
ClientHWAddress = chaddr,
|
||||
ServerHostName = ServerHostName,
|
||||
BootFileName = BootFileName
|
||||
};
|
||||
}
|
||||
|
||||
public byte[] Serialize()
|
||||
{
|
||||
using MemoryStream buffer = new();
|
||||
BinaryWriter writer = new(buffer);
|
||||
|
||||
writer.Write((byte)OpType);
|
||||
writer.Write(HType);
|
||||
writer.Write(HLen);
|
||||
writer.Write(Hops);
|
||||
writer.Write(Xid);
|
||||
writer.Write(Seconds);
|
||||
writer.Write(Flags);
|
||||
writer.Write(ClientAddress.GetAddressBytes());
|
||||
writer.Write(YourAddress.GetAddressBytes());
|
||||
writer.Write(NextServerAddress.GetAddressBytes());
|
||||
writer.Write(RelayAgentAddress.GetAddressBytes());
|
||||
writer.Write(GetClientHwAddress());
|
||||
writer.Write(GetSnameBytes());
|
||||
writer.Write(GetBootFileBytes());
|
||||
|
||||
return buffer.GetBuffer();
|
||||
}
|
||||
}
|
75
src/IPMeow.Dhcp/Server/Dhcp4/DhcpServer.cs
Normal file
75
src/IPMeow.Dhcp/Server/Dhcp4/DhcpServer.cs
Normal file
|
@ -0,0 +1,75 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IPMeow.Dhcp.Server.Dhcp4;
|
||||
|
||||
public class DhcpServer
|
||||
{
|
||||
public const int clientPort = 68, serverPort = 67;
|
||||
|
||||
public DhcpServer()
|
||||
{
|
||||
_udp = new UdpClient(serverPort, AddressFamily.InterNetwork);
|
||||
}
|
||||
|
||||
public async Task Run()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
await Receive();
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task Receive()
|
||||
{
|
||||
var datagram = await _udp.ReceiveAsync();
|
||||
|
||||
if (datagram.Buffer.Length < 236 || datagram.Buffer.Length > 576)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var packet = DhcpPacket.Deserialize(datagram.Buffer);
|
||||
packet.IsValidated = ValidateIncoming(packet);
|
||||
|
||||
if (!packet.IsValidated.Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Console.WriteLine("Solicitation: ");
|
||||
Console.WriteLine(packet.ToString());
|
||||
}
|
||||
|
||||
public bool ValidateIncoming(DhcpPacket packet)
|
||||
{
|
||||
if (packet.OpType != DhcpOpType.BOOTREQUEST)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//Discard unsupported
|
||||
bool supported = packet.HLen == 6 && packet.HType == 1;
|
||||
|
||||
if (!supported)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (packet.NextServerAddress != IPAddress.Any)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private readonly UdpClient _udp;
|
||||
}
|
24
src/IPMeow.Dhcp/Server/Dhcp6/DhcpFields.cs
Normal file
24
src/IPMeow.Dhcp/Server/Dhcp6/DhcpFields.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IPMeow.Dhcp.Server.Dhcp6;
|
||||
|
||||
public enum DhcpMessageType : byte
|
||||
{
|
||||
Invalid = 0,
|
||||
Solicit = 1,
|
||||
Advertise = 2,
|
||||
Request = 3,
|
||||
Confirm = 4,
|
||||
Renew = 5,
|
||||
Rebind = 6,
|
||||
Reply = 7,
|
||||
Release = 8,
|
||||
Decline = 9,
|
||||
Reconfigure = 10,
|
||||
InfoRequest = 11,
|
||||
RelayForw = 12,
|
||||
RelayRepl = 13
|
||||
}
|
161
src/IPMeow.Dhcp/Server/Dhcp6/DhcpOption.cs
Normal file
161
src/IPMeow.Dhcp/Server/Dhcp6/DhcpOption.cs
Normal file
|
@ -0,0 +1,161 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IPMeow.Dhcp.Server.Dhcp6;
|
||||
|
||||
public enum DhcpOptionCode : short
|
||||
{
|
||||
ClientId = 1,
|
||||
ServerId = 2,
|
||||
IANonTempAssoc = 3,
|
||||
IATempAssoc = 4,
|
||||
IAAddr = 5,
|
||||
OptionRequest = 6,
|
||||
Preference = 7,
|
||||
ElapsedTime = 8,
|
||||
ServerUnicast = 12,
|
||||
StatusCode = 13,
|
||||
|
||||
|
||||
}
|
||||
|
||||
public interface IDhcpOption
|
||||
{
|
||||
public DhcpOptionCode Code { get; }
|
||||
public byte[] Data { get; set; }
|
||||
public Type DataType { get; }
|
||||
public abstract object GetData();
|
||||
}
|
||||
|
||||
public class ClientIdentifierOption : IDhcpOption
|
||||
{
|
||||
public DhcpOptionCode Code => DhcpOptionCode.ClientId;
|
||||
|
||||
public required byte[] Data { get; set; }
|
||||
|
||||
public Type DataType => typeof(Duid);
|
||||
|
||||
public object GetData()
|
||||
{
|
||||
return new Duid(Data);
|
||||
}
|
||||
}
|
||||
|
||||
public class ServerIdentifierOption : IDhcpOption
|
||||
{
|
||||
public DhcpOptionCode Code => DhcpOptionCode.ServerId;
|
||||
|
||||
public required byte[] Data { get; set; }
|
||||
|
||||
public Type DataType => typeof(Duid);
|
||||
|
||||
public object GetData()
|
||||
{
|
||||
return new Duid(Data);
|
||||
}
|
||||
}
|
||||
|
||||
public class NonTempIdentityAssociationOption : IDhcpOption
|
||||
{
|
||||
public DhcpOptionCode Code => DhcpOptionCode.IANonTempAssoc;
|
||||
|
||||
public required byte[] Data { get; set; }
|
||||
|
||||
public Type DataType => typeof(IdentityAssociation);
|
||||
|
||||
public object GetData()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class TempIdentityAssociationOption : IDhcpOption
|
||||
{
|
||||
public DhcpOptionCode Code => DhcpOptionCode.IATempAssoc;
|
||||
|
||||
public required byte[] Data { get; set; }
|
||||
|
||||
public Type DataType => typeof(IdentityAssociation);
|
||||
|
||||
public object GetData()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class IAAddressOption : IDhcpOption
|
||||
{
|
||||
public DhcpOptionCode Code => DhcpOptionCode.IAAddr;
|
||||
|
||||
public required byte[] Data { get; set; }
|
||||
|
||||
public Type DataType => typeof(AddressAssociation);
|
||||
|
||||
public object GetData()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class OptionRequestOption : IDhcpOption
|
||||
{
|
||||
public DhcpOptionCode Code => DhcpOptionCode.OptionRequest;
|
||||
|
||||
public required byte[] Data { get; set; }
|
||||
|
||||
public Type DataType => typeof(ICollection<DhcpOptionCode>);
|
||||
|
||||
public object GetData()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class ElapsedTimeOption : IDhcpOption
|
||||
{
|
||||
public DhcpOptionCode Code => DhcpOptionCode.ElapsedTime;
|
||||
|
||||
public required byte[] Data { get; set; }
|
||||
|
||||
public Type DataType => typeof(TimeSpan);
|
||||
|
||||
public object GetData()
|
||||
{
|
||||
return TimeSpan.FromSeconds(BitConverter.ToInt16(Data, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public class ServerUnicastOption : IDhcpOption
|
||||
{
|
||||
public DhcpOptionCode Code => DhcpOptionCode.ServerUnicast;
|
||||
public required byte[] Data { get; set; }
|
||||
|
||||
public Type DataType => typeof(IPAddress);
|
||||
|
||||
public object GetData()
|
||||
{
|
||||
return new IPAddress(Data);
|
||||
}
|
||||
}
|
||||
|
||||
public class StatusCodeOption : IDhcpOption
|
||||
{
|
||||
public DhcpOptionCode Code => DhcpOptionCode.StatusCode;
|
||||
|
||||
public required byte[] Data { get; set; }
|
||||
|
||||
public Type DataType => typeof(DhcpStatus);
|
||||
|
||||
public object GetData()
|
||||
{
|
||||
ushort code = BitConverter.ToUInt16(Data.AsSpan()[..2]);
|
||||
|
||||
string? message = Data.Length > 2 ? Encoding.UTF8.GetString(Data.AsSpan()[2..]) : null;
|
||||
|
||||
return new DhcpStatus(code, message);
|
||||
}
|
||||
}
|
66
src/IPMeow.Dhcp/Server/Dhcp6/DhcpPacket.cs
Normal file
66
src/IPMeow.Dhcp/Server/Dhcp6/DhcpPacket.cs
Normal file
|
@ -0,0 +1,66 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using IPMeow.Lib;
|
||||
|
||||
namespace IPMeow.Dhcp.Server.Dhcp6;
|
||||
|
||||
public class DhcpPacket
|
||||
{
|
||||
public required DhcpMessageType MessageType { get; init; }
|
||||
public required uint Xid { get; init; }
|
||||
public ICollection<IDhcpOption> Options { get; init; } = new List<IDhcpOption>();
|
||||
|
||||
public static IDhcpOption GetOption(DhcpOptionCode type, byte[] data)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
DhcpOptionCode.ClientId => new ClientIdentifierOption()
|
||||
{
|
||||
Data = data
|
||||
},
|
||||
DhcpOptionCode.ServerId => throw new NotImplementedException(),
|
||||
DhcpOptionCode.IANonTempAssoc => throw new NotImplementedException(),
|
||||
DhcpOptionCode.IATempAssoc => throw new NotImplementedException(),
|
||||
DhcpOptionCode.IAAddr => throw new NotImplementedException(),
|
||||
DhcpOptionCode.OptionRequest => throw new NotImplementedException(),
|
||||
DhcpOptionCode.Preference => throw new NotImplementedException(),
|
||||
DhcpOptionCode.ElapsedTime => throw new NotImplementedException(),
|
||||
DhcpOptionCode.StatusCode => throw new NotImplementedException(),
|
||||
_ => throw new InvalidOperationException($"Invalid option type {type}")
|
||||
};
|
||||
}
|
||||
|
||||
public static DhcpPacket Deserialize(byte[] data)
|
||||
{
|
||||
BitEnumerator enu = new(data);
|
||||
|
||||
byte[] header = enu.TakeBytes(4);
|
||||
|
||||
DhcpMessageType MessageType = (DhcpMessageType)header[0];
|
||||
|
||||
uint Xid = BitConverter.ToUInt32(header, 1);
|
||||
|
||||
while (enu.Position < data.Length)
|
||||
{
|
||||
short optionCode = enu.TakeInt16();
|
||||
short optionLen = enu.TakeInt16();
|
||||
|
||||
if (enu.Position + optionLen > data.Length)
|
||||
{
|
||||
throw new DataMisalignedException("Invalid option length.");
|
||||
}
|
||||
|
||||
byte[] optionData = enu.TakeBytes(optionLen);
|
||||
|
||||
|
||||
}
|
||||
|
||||
return new()
|
||||
{
|
||||
MessageType = MessageType,
|
||||
Xid = Xid
|
||||
};
|
||||
}
|
||||
}
|
49
src/IPMeow.Dhcp/Server/Dhcp6/DhcpServer.cs
Normal file
49
src/IPMeow.Dhcp/Server/Dhcp6/DhcpServer.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using IPMeow.Dhcp.Server.Dhcp4;
|
||||
|
||||
namespace IPMeow.Dhcp.Server.Dhcp6;
|
||||
|
||||
public class DhcpServer : IDhcpServer, IDisposable
|
||||
{
|
||||
public const int clientPort = 546, serverPort = 547;
|
||||
|
||||
public DhcpServer()
|
||||
{
|
||||
_listener = new(new IPEndPoint(IPAddress.Parse("ff02::1:2"), serverPort));
|
||||
_sender = new(clientPort, AddressFamily.InterNetworkV6);
|
||||
}
|
||||
private UdpClient _listener, _sender;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
_listener.Dispose();
|
||||
_sender.Dispose();
|
||||
}
|
||||
|
||||
public async Task Run()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
await Receive();
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task Receive()
|
||||
{
|
||||
var datagram = await _listener.ReceiveAsync();
|
||||
|
||||
var packet = DhcpPacket.Deserialize(datagram.Buffer);
|
||||
|
||||
if (packet.MessageType is DhcpMessageType.Invalid or DhcpMessageType.Solicit or DhcpMessageType.Confirm or DhcpMessageType.Rebind)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
47
src/IPMeow.Dhcp/Server/Dhcp6/DhcpStatus.cs
Normal file
47
src/IPMeow.Dhcp/Server/Dhcp6/DhcpStatus.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IPMeow.Dhcp.Server.Dhcp6;
|
||||
|
||||
public struct DhcpStatus
|
||||
{
|
||||
public DhcpStatus(ushort code, string? message)
|
||||
{
|
||||
Code = code;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
public static DhcpStatus? TryParse(byte[] data)
|
||||
{
|
||||
if (data.Length < 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ushort code = BitConverter.ToUInt16(data.AsSpan()[..2]);
|
||||
string? message = data.Length > 2 ? Encoding.UTF8.GetString(data.AsSpan()[2..]) : null;
|
||||
|
||||
return new(code, message);
|
||||
}
|
||||
|
||||
public ushort Code { get; set; }
|
||||
public string? Message { get; set; }
|
||||
|
||||
public byte[] Serialize()
|
||||
{
|
||||
byte[] buf = new byte[2 + Message?.Length ?? 0];
|
||||
|
||||
buf[0] = (byte)((Code & 0xff00) >> 8);
|
||||
buf[1] = (byte)(Code & 0x00ff);
|
||||
|
||||
if (Message is not null)
|
||||
{
|
||||
Encoding.UTF8.GetBytes(Message).CopyTo(buf, 2);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
26
src/IPMeow.Dhcp/Server/Dhcp6/Duid.cs
Normal file
26
src/IPMeow.Dhcp/Server/Dhcp6/Duid.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IPMeow.Dhcp.Server.Dhcp6;
|
||||
|
||||
public enum DuidType : short
|
||||
{
|
||||
LLAddrWithTime = 1,
|
||||
VendorUID = 2,
|
||||
LLAddr = 3,
|
||||
Uuid = 4
|
||||
}
|
||||
|
||||
public readonly struct Duid
|
||||
{
|
||||
public Duid(byte[] data)
|
||||
{
|
||||
Type = (DuidType)BitConverter.ToInt16(data.AsSpan()[0..2]);
|
||||
Data = data[2..];
|
||||
}
|
||||
|
||||
public DuidType Type { get; }
|
||||
public byte[] Data { get; }
|
||||
}
|
13
src/IPMeow.Dhcp/Server/Dhcp6/IdentityAssociation.cs
Normal file
13
src/IPMeow.Dhcp/Server/Dhcp6/IdentityAssociation.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IPMeow.Dhcp.Server.Dhcp6;
|
||||
|
||||
public struct IdentityAssociation
|
||||
{
|
||||
public int IAId { get; }
|
||||
public int TimeToRefresh { get; }
|
||||
public int TimeToNextAdvertise { get; } //T2 in RFC8415, 21.4
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using IPMeow.Lib;
|
||||
|
||||
namespace IPMeow.Dhcp.Server;
|
||||
|
||||
public class DhcpPacket
|
||||
{
|
||||
public DhcpPacket(byte[] data)
|
||||
{
|
||||
BitEnumerator enu = new(data);
|
||||
|
||||
DhcpOpType opType = (DhcpOpType)enu.TakeByte();
|
||||
|
||||
byte hType = enu.TakeByte();
|
||||
byte hLen = enu.TakeByte();
|
||||
byte hOps = enu.TakeByte();
|
||||
|
||||
uint xid = enu.TakeUInt32();
|
||||
|
||||
short secs = enu.TakeInt16();
|
||||
|
||||
short flags = enu.TakeInt16();
|
||||
|
||||
IPAddress ciaddr = new(enu.TakeBytes(4));
|
||||
IPAddress yiaddr = new(enu.TakeBytes(4));
|
||||
IPAddress siaddr = new(enu.TakeBytes(4));
|
||||
IPAddress giaddr = new(enu.TakeBytes(4));
|
||||
|
||||
byte[] chaddr = enu.TakeBytes(16);
|
||||
|
||||
byte[] sname = enu.TakeBytes(64);
|
||||
byte[] file = enu.TakeBytes(128);
|
||||
}
|
||||
}
|
11
src/IPMeow.Dhcp/Server/IDhcpServer.cs
Normal file
11
src/IPMeow.Dhcp/Server/IDhcpServer.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IPMeow.Dhcp.Server;
|
||||
|
||||
public interface IDhcpServer
|
||||
{
|
||||
public Task Run();
|
||||
}
|
Loading…
Reference in a new issue