|
@@ -30,6 +30,10 @@ namespace DhcpServer
|
|
|
private static string _pxeFileName;
|
|
|
private static string _ipxeScriptUri;
|
|
|
|
|
|
+ private static string _u64FileName;
|
|
|
+ private static string _u86FileName;
|
|
|
+ private static string _uHttpFileName;
|
|
|
+
|
|
|
private static IReadOnlyCollection<PoolSlot> _pool;
|
|
|
private static IPAddress _ipxeRouter;
|
|
|
private static IPAddress _pxeRouter;
|
|
@@ -131,6 +135,7 @@ namespace DhcpServer
|
|
|
|
|
|
var clientMac = packet.ClientMacAddressHex;
|
|
|
Console.WriteLine($" {packet.MessageType} by {clientMac}");
|
|
|
+ Console.WriteLine($" {packet.Vendor ?? "Unknown Vendor"} / {packet.UserClass ?? "Unknown Class"}");
|
|
|
|
|
|
DhcpMessageType reply;
|
|
|
switch (packet.MessageType)
|
|
@@ -158,7 +163,13 @@ namespace DhcpServer
|
|
|
var requestParameters = packet.Options[DhcpOption.ParameterRequestList];
|
|
|
var hostName = packet.HostName;
|
|
|
var userClass = packet.UserClass;
|
|
|
- var ven = packet.Vendor;
|
|
|
+ var vendor = packet.Vendor;
|
|
|
+
|
|
|
+ //byte arch = 0;
|
|
|
+ //if (packet.Options.TryGetValue(DhcpOption.ClientIdentifier, out var bufArch))
|
|
|
+ //{
|
|
|
+ // arch = bufArch?.FirstOrDefault() ?? 0;
|
|
|
+ //}
|
|
|
|
|
|
// Allocate ip address
|
|
|
|
|
@@ -222,19 +233,38 @@ namespace DhcpServer
|
|
|
|
|
|
packet.DhcpServerIdentifier = _listenOn.Address;
|
|
|
|
|
|
- // Extend Process
|
|
|
+ // vendor spec
|
|
|
+
|
|
|
+ packet.Router = _pxeRouter;
|
|
|
+ packet.TftpServer = _pxeTftp.ToString();
|
|
|
+ packet.NextServerIpAddress = _pxeTftp;
|
|
|
|
|
|
if (userClass == "iPXE")
|
|
|
{
|
|
|
packet.BootFileName = _ipxeScriptUri;
|
|
|
packet.Router = _ipxeRouter;
|
|
|
}
|
|
|
- else if (requestParameters != null && requestParameters.Contains((byte)67))
|
|
|
+ else
|
|
|
{
|
|
|
- packet.Router = _pxeRouter;
|
|
|
- packet.BootFileName = _pxeFileName;
|
|
|
- packet.TftpServer = _pxeTftp.ToString();
|
|
|
- packet.NextServerIpAddress = _pxeTftp;
|
|
|
+ if (true == vendor?.StartsWith("PXEClient:Arch:00000"))
|
|
|
+ {
|
|
|
+ //Legacy
|
|
|
+ packet.BootFileName = _pxeFileName;
|
|
|
+ }
|
|
|
+ else if (true == vendor?.StartsWith("PXEClient:Arch:00002")
|
|
|
+ || true == vendor?.StartsWith("PXEClient:Arch:00006"))
|
|
|
+ {
|
|
|
+ //UEFI x86
|
|
|
+ packet.BootFileName = _u86FileName;
|
|
|
+ }
|
|
|
+ else if (true == vendor?.StartsWith("PXEClient:Arch:00007")
|
|
|
+ || true == vendor?.StartsWith("PXEClient:Arch:00008")
|
|
|
+ || true == vendor?.StartsWith("PXEClient:Arch:00009")
|
|
|
+ )
|
|
|
+ {
|
|
|
+ //UEFI x64
|
|
|
+ packet.BootFileName = _u64FileName;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -280,32 +310,6 @@ namespace DhcpServer
|
|
|
slots[0] = new PoolSlot(_poolStart);
|
|
|
for (var i = 1; i < _poolSize; i++) slots[i] = new PoolSlot(slots[i - 1].Address.NextAddress());
|
|
|
|
|
|
- //Task.Factory.StartNew(() =>
|
|
|
- //{
|
|
|
- // foreach (var item in slots)
|
|
|
- // {
|
|
|
- // item.MacStatus = "Requesting...";
|
|
|
- // var mac = GetMac(item.Address, out var err);
|
|
|
- // if (null != mac)
|
|
|
- // {
|
|
|
- // item.Mac = mac;
|
|
|
- // item.LastConfirm = DateTime.Now;
|
|
|
- // item.MacStatus = "OK";
|
|
|
- // }
|
|
|
- // else
|
|
|
- // {
|
|
|
- // item.MacStatus = err ?? "Fail";
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // foreach (var slot in slots)
|
|
|
- // {
|
|
|
- // slot.HostNameStatus = "Requesting...";
|
|
|
- // slot.HostName = GetHostName(slot.Address, out var err);
|
|
|
- // slot.HostNameStatus = err ?? "OK";
|
|
|
- // }
|
|
|
- //});
|
|
|
-
|
|
|
_pool = slots;
|
|
|
}
|
|
|
|
|
@@ -319,8 +323,10 @@ namespace DhcpServer
|
|
|
_dns = IPAddress.Parse(Settings.Default.Dns);
|
|
|
_pxeRouter = IPAddress.Parse(Settings.Default.PxeRouter);
|
|
|
_pxeTftp = IPAddress.Parse(Settings.Default.PxeTftp);
|
|
|
- _pxeFileName = Settings.Default.PxeFileName;
|
|
|
- _ipxeScriptUri = Settings.Default.IpxeScriptUri;
|
|
|
+ _pxeFileName = Settings.Default.FileName;
|
|
|
+ _u64FileName = Settings.Default.FileName_UEFI_x64;
|
|
|
+ _u86FileName = Settings.Default.FileName_UEFI_I386;
|
|
|
+ _ipxeScriptUri = Settings.Default.FileName_iPXE_HTTP;
|
|
|
_ipxeRouter = IPAddress.Parse(Settings.Default.IpxeRouter);
|
|
|
_broadcastAddress = IPAddress.Parse(Settings.Default.BroadcastAddress);
|
|
|
}
|
|
@@ -393,116 +399,5 @@ namespace DhcpServer
|
|
|
|
|
|
return msg;
|
|
|
}
|
|
|
-
|
|
|
- //-----------------------------
|
|
|
-
|
|
|
- private static void Working()
|
|
|
- {
|
|
|
- if (DhcpEntryManager.CreateDefaultEntryIfNoExist()) Console.WriteLine("Default client entry config created.");
|
|
|
-
|
|
|
- var listenEndPoint = new IPEndPoint(IPAddress.Parse(Settings.Default.ListenOn), 67);
|
|
|
-
|
|
|
- var socket = new Socket(listenEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp)
|
|
|
- {
|
|
|
- EnableBroadcast = true,
|
|
|
- SendBufferSize = 65536,
|
|
|
- ReceiveBufferSize = 65536
|
|
|
- };
|
|
|
- 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;
|
|
|
-
|
|
|
- var pooled = false;
|
|
|
- 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 sockets..." +
|
|
|
- $" {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}");
|
|
|
- pooled = true;
|
|
|
- }
|
|
|
- else // polled
|
|
|
- {
|
|
|
- if (pooled)
|
|
|
- {
|
|
|
- pooled = false;
|
|
|
- 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 = DhcpEntryManager.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)
|
|
|
- {
|
|
|
- var userClass = packet.UserClass;
|
|
|
- packet.Options.Clear();
|
|
|
- packet.DhcpServerIdentifier = listenEndPoint.Address;
|
|
|
- packet.MessageType = reply;
|
|
|
-
|
|
|
- packet.LoadClientEntry(DhcpEntryManager.GetDefaultEntry());
|
|
|
- packet.LoadClientEntry(DhcpEntryManager.GetDefaultEntry(userClass));
|
|
|
-
|
|
|
- packet.LoadClientEntry(entry);
|
|
|
- packet.LoadClientEntry(DhcpEntryManager.GetClientEntry(mac, userClass));
|
|
|
-
|
|
|
- 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);
|
|
|
- }
|
|
|
- polling = DateTime.Now;
|
|
|
- }// end if poll
|
|
|
- }
|
|
|
-
|
|
|
- socket.Close();
|
|
|
- }
|
|
|
}
|
|
|
}
|