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 Options { get; set; } = new Dictionary(); 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(); } } }