123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Net;
- using System.Text;
- using Utils;
- 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 BroadcastAddress
- {
- get => Options.MapValue(DhcpOption.BroadcastAddress, value => new IPAddress(value));
- set => Options[DhcpOption.BroadcastAddress] = value.GetAddressBytes();
- }
- public IPAddress ServerIdentifier
- {
- get => Options.MapValue(DhcpOption.ServerIdentifier, value => new IPAddress(value));
- set => Options[DhcpOption.ServerIdentifier] = value.GetAddressBytes();
- }
- public IPAddress DhcpServerIdentifier
- {
- get => Options.MapValue(DhcpOption.DhcpServerIdentifier, value => new IPAddress(value));
- set => Options[DhcpOption.DhcpServerIdentifier] = value.GetAddressBytes();
- }
- public string UserClass
- {
- get => Options.MapValue(DhcpOption.UserClass, value => Encoding.ASCII.GetString(value))?.Trim().Trim('\0');
- set => Options[DhcpOption.UserClass] = Encoding.ASCII.GetBytes(value);
- }
- public string HostName => Options.MapValue(DhcpOption.HostName, v => Encoding.ASCII.GetString(v))?.Trim().Trim('\0');
- public string Vendor => Options.MapValue(DhcpOption.Vendor, v => Encoding.ASCII.GetString(v))?.Trim().Trim('\0');
- public TimeSpan LeaseTime
- {
- get => Options.MapValue(DhcpOption.LeaseTime, p => TimeSpan.FromSeconds(ToBeUint(p)));
- set => Options[DhcpOption.LeaseTime] = ToBytes((uint)value.TotalSeconds);
- }
- public TimeSpan RenewalTime
- {
- get => Options.MapValue(DhcpOption.RenewalTime, p => TimeSpan.FromSeconds(ToBeUint(p)));
- set => Options[DhcpOption.RenewalTime] = ToBytes((uint)value.TotalSeconds);
- }
- public TimeSpan RebindingTime
- {
- get => Options.MapValue(DhcpOption.RebindingTime, p => TimeSpan.FromSeconds(ToBeUint(p)));
- set => Options[DhcpOption.RebindingTime] = ToBytes((uint)value.TotalSeconds);
- }
- public byte[] ClientIdentifier
- {
- get => Options.MapValue(DhcpOption.ClientIdentifier, p => p);
- set => Options[DhcpOption.ClientIdentifier] = value;
- }
- 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()
- {
- }
- private static uint ToBeUint(byte[] buf)
- {
- return (uint)buf[0] << 24 |
- (uint)buf[1] << 16 |
- (uint)buf[2] << 8 |
- (uint)buf[3];
- }
- private static byte[] ToBytes(uint value)
- {
- var buf = new byte[4];
- buf[0] = (byte)(value >> 24);
- buf[1] = (byte)(value >> 16);
- buf[2] = (byte)(value >> 8);
- buf[3] = (byte)(value);
- return buf;
- }
- }
- }
|