|
@@ -0,0 +1,153 @@
|
|
|
+using DhcpServer.Utils;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.IO;
|
|
|
+using System.Net;
|
|
|
+using System.Text;
|
|
|
+
|
|
|
+namespace DhcpServer
|
|
|
+{
|
|
|
+ public partial class DhcpPacket
|
|
|
+ {
|
|
|
+ public DhcpOpCode OpCode { get; set; }
|
|
|
+ public DhcpHardwareType HardwareType { get; set; }
|
|
|
+ public byte Hops { get; set; }
|
|
|
+ public int TransactionId { get; set; }
|
|
|
+
|
|
|
+ public short SecondsElapsed { get; set; }
|
|
|
+
|
|
|
+ public DhcpBootpFlag BootpFlags { get; set; }
|
|
|
+ public IPAddress ClientIpAddress { get; set; }
|
|
|
+
|
|
|
+ public IPAddress YourIpAddress { get; set; }
|
|
|
+
|
|
|
+ public IPAddress NextServerIpAddress { get; set; }
|
|
|
+
|
|
|
+ public IPAddress RelayAgentIpAddress { get; set; }
|
|
|
+
|
|
|
+ public byte[] ClientMacAddress { get; set; }
|
|
|
+
|
|
|
+ public string ServerHostName { get; set; }
|
|
|
+ public string BootFileName { get; set; }
|
|
|
+
|
|
|
+ public int MagicCookie { get; set; } = 0x63825363;
|
|
|
+
|
|
|
+ public Dictionary<DhcpOption, byte[]> Options { get; set; } = new Dictionary<DhcpOption, byte[]>();
|
|
|
+
|
|
|
+ public DhcpMessageType MessageType
|
|
|
+ {
|
|
|
+ get => Options.MapValue(DhcpOption.DhcpMessageType, value => (DhcpMessageType)value[0]);
|
|
|
+
|
|
|
+ set => Options[DhcpOption.DhcpMessageType] = new[] { (byte)value };
|
|
|
+ }
|
|
|
+
|
|
|
+ public IPAddress SubNetMask
|
|
|
+ {
|
|
|
+ get => Options.MapValue(DhcpOption.SubNetMask, value => new IPAddress(value));
|
|
|
+ set => Options[DhcpOption.SubNetMask] = value.GetAddressBytes();
|
|
|
+ }
|
|
|
+
|
|
|
+ public IPAddress Router
|
|
|
+ {
|
|
|
+ get => Options.MapValue(DhcpOption.Router, value => new IPAddress(value));
|
|
|
+ set => Options[DhcpOption.Router] = value.GetAddressBytes();
|
|
|
+ }
|
|
|
+
|
|
|
+ public IPAddress DnsServer
|
|
|
+ {
|
|
|
+ get => Options.MapValue(DhcpOption.DnsServer, value => new IPAddress(value));
|
|
|
+ set => Options[DhcpOption.DnsServer] = value.GetAddressBytes();
|
|
|
+ }
|
|
|
+
|
|
|
+ public string TftpServer
|
|
|
+ {
|
|
|
+ get => Options.MapValue(DhcpOption.TftpServer, value => Encoding.ASCII.GetString(value));
|
|
|
+ set => Options[DhcpOption.TftpServer] = Encoding.ASCII.GetBytes(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ public IPAddress DhcpServerIdentifier
|
|
|
+ {
|
|
|
+ get => Options.MapValue(DhcpOption.DhcpServerIdentifier, value => new IPAddress(value));
|
|
|
+ set => Options[DhcpOption.DhcpServerIdentifier] = value.GetAddressBytes();
|
|
|
+ }
|
|
|
+
|
|
|
+ public DhcpPacket(byte[] buffer)
|
|
|
+ {
|
|
|
+ using var stream = new MemoryStream(buffer);
|
|
|
+ using var reader = new BinaryReader(stream);
|
|
|
+ OpCode = (DhcpOpCode)reader.ReadByte();
|
|
|
+ HardwareType = (DhcpHardwareType)reader.ReadByte();
|
|
|
+ var hardwareAddressLength = reader.ReadByte();
|
|
|
+ Hops = reader.ReadByte();
|
|
|
+ TransactionId = reader.ReadInt32();
|
|
|
+ SecondsElapsed = IPAddress.NetworkToHostOrder(reader.ReadInt16());
|
|
|
+ BootpFlags = (DhcpBootpFlag)IPAddress.NetworkToHostOrder(reader.ReadInt16());
|
|
|
+ ClientIpAddress = new IPAddress(reader.ReadBytes(4));
|
|
|
+ YourIpAddress = new IPAddress(reader.ReadBytes(4));
|
|
|
+ NextServerIpAddress = new IPAddress(reader.ReadBytes(4));
|
|
|
+ RelayAgentIpAddress = new IPAddress(reader.ReadBytes(4));
|
|
|
+ ClientMacAddress = reader.ReadBytes(hardwareAddressLength);
|
|
|
+ stream.Position += 16 - hardwareAddressLength; // Skip padding bytes
|
|
|
+ ServerHostName = Encoding.ASCII.GetString(reader.ReadBytes(64)).Trim('\0');
|
|
|
+ BootFileName = Encoding.ASCII.GetString(reader.ReadBytes(128)).Trim('\0');
|
|
|
+ MagicCookie = reader.ReadInt32();
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ var option = reader.ReadByte();
|
|
|
+ if (option == 0xFF) break;
|
|
|
+
|
|
|
+ Options[(DhcpOption)option] = reader.ReadBytes(reader.ReadByte());
|
|
|
+ } while (true);
|
|
|
+ }
|
|
|
+
|
|
|
+ public int WriteToBuffer(byte[] buffer)
|
|
|
+ {
|
|
|
+ using var stream = new MemoryStream(buffer);
|
|
|
+ using var writer = new BinaryWriter(stream);
|
|
|
+ writer.Write((byte)OpCode);
|
|
|
+ writer.Write((byte)HardwareType);
|
|
|
+ writer.Write((byte)ClientMacAddress.Length);
|
|
|
+ writer.Write(Hops);
|
|
|
+ writer.Write(TransactionId);
|
|
|
+ writer.Write(IPAddress.HostToNetworkOrder(SecondsElapsed));
|
|
|
+ writer.Write(IPAddress.HostToNetworkOrder((short)BootpFlags));
|
|
|
+ writer.Write(ClientIpAddress.GetAddressBytes());
|
|
|
+ writer.Write(YourIpAddress.GetAddressBytes());
|
|
|
+ writer.Write(NextServerIpAddress.GetAddressBytes());
|
|
|
+ writer.Write(RelayAgentIpAddress.GetAddressBytes());
|
|
|
+
|
|
|
+ writer.Write(ClientMacAddress);
|
|
|
+ stream.Position += 16 - ClientMacAddress.Length;
|
|
|
+
|
|
|
+ var buf = Encoding.ASCII.GetBytes(ServerHostName);
|
|
|
+ writer.Write(buf);
|
|
|
+ stream.Position += 64 - buf.Length;
|
|
|
+
|
|
|
+ buf = Encoding.ASCII.GetBytes(BootFileName);
|
|
|
+ writer.Write(buf);
|
|
|
+ stream.Position += 128 - buf.Length;
|
|
|
+
|
|
|
+ writer.Write(MagicCookie);
|
|
|
+
|
|
|
+ foreach (var option in Options)
|
|
|
+ {
|
|
|
+ writer.Write((byte)option.Key);
|
|
|
+ writer.Write((byte)option.Value.Length);
|
|
|
+ writer.Write(option.Value);
|
|
|
+ }
|
|
|
+ writer.Write((byte)0xFF);
|
|
|
+
|
|
|
+ return (int)(stream.Position);
|
|
|
+ }
|
|
|
+
|
|
|
+ public DhcpPacket()
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public int GetByteCount()
|
|
|
+ {
|
|
|
+ throw new NotImplementedException();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|