using System; using System.Net; using System.Net.Sockets; using System.Threading; namespace DhcpServer { internal class DhcpProgram { private static bool _isRunning; private static void Main(string[] args) { Console.WriteLine("Starting..."); if (AppConfigs.CreateDefaultClientEntryIfNoExist()) Console.WriteLine("Default client entry config created."); var tWorker = new Thread(Working); _isRunning = true; tWorker.Start(); Console.WriteLine("Press ENTER to Stop."); Console.ReadLine(); Console.Write("Shutting down..."); _isRunning = false; tWorker.Join(); Console.Write("Stopped."); Console.WriteLine(); Console.Write("Press ENTER to Exit."); Console.ReadLine(); } private static void Working(object obj) { var listenEndPoint = new IPEndPoint(IPAddress.Parse(Properties.Settings.Default.ListenOn), 67); var socket = new Socket(listenEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp) { EnableBroadcast = true, SendBufferSize = 65536, ReceiveBufferSize = 65536 }; socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); socket.Bind(listenEndPoint); var upTime = DateTime.Now; Console.WriteLine($"DHCP Server started, listing on: {listenEndPoint}"); var buffer = new byte[65536]; EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 68); var polling = DateTime.Now; while (_isRunning) { Console.CursorLeft = 0; if (false == socket.Poll(500 * 1000, SelectMode.SelectRead)) { var timeSpan = DateTime.Now - polling; var up = DateTime.Now - upTime; Console.Write($"Polling..." + $" {timeSpan.Days:00}D {timeSpan.Hours:00}H {timeSpan.Minutes:00}M {timeSpan.Seconds:00}S {timeSpan.Milliseconds:000}" + $" / UP {up.Days:00}D {up.Hours:00}H {up.Minutes:00}M {up.Seconds:00}S {up.Milliseconds:000}"); } else { polling = DateTime.Now; Console.WriteLine(); var bytes = socket.ReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref remoteEndPoint); Console.Write($"Receive {bytes} byte From {remoteEndPoint}"); try { var packet = new DhcpPacket(buffer); var mac = packet.ClientMacAddressHex; Console.Write($" {packet.MessageType} by {mac}"); var entry = AppConfigs.GetClientEntry(mac); if (entry.Enable == false) { Console.WriteLine(" ** No enabled, please edit config file."); } else { packet.OpCode = DhcpOpCode.BootReply; DhcpMessageType reply; switch (packet.MessageType) { default: reply = DhcpMessageType.Unknown; break; case DhcpMessageType.Discover: reply = DhcpMessageType.Offer; break; case DhcpMessageType.Request: reply = DhcpMessageType.Ack; break; } if (reply != DhcpMessageType.Unknown) { packet.Options.Clear(); packet.DhcpServerIdentifier = listenEndPoint.Address; packet.MessageType = reply; packet.LoadClientEntry(AppConfigs.GetDefaultClientEntry()); packet.LoadClientEntry(entry); bytes = packet.WriteToBuffer(buffer); var to = new IPEndPoint(IPAddress.Broadcast, 68); Console.WriteLine(); Console.WriteLine($"Send {bytes} bytes to {to} {packet.MessageType} by {mac}"); socket.SendTo(buffer, 0, bytes, SocketFlags.None, to); } } } catch (Exception e) { Console.WriteLine(e); } } } socket.Close(); } } }