WIP
parent
bd73b1c8b2
commit
7304747952
|
@ -4,6 +4,7 @@ using ln.types.net;
|
|||
using ln.types;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime;
|
||||
namespace ln.dhcp
|
||||
{
|
||||
public enum OP:byte { BOOTREQUEST = 1,BOOTREPLY = 2 }
|
||||
|
@ -24,12 +25,12 @@ namespace ln.dhcp
|
|||
public uint XID { get; set; }
|
||||
public ushort Secs { get; set; }
|
||||
public BootPFlags Flags { get; set; }
|
||||
public IPv4 CIAddr { get; set; }
|
||||
public IPv4 YIAddr { get; set; }
|
||||
public IPv4 SIAddr { get; set; }
|
||||
public IPv4 GIAddr { get; set; }
|
||||
public IPv4 CIAddr { get; set; } = IPv4.ANY;
|
||||
public IPv4 YIAddr { get; set; } = IPv4.ANY;
|
||||
public IPv4 SIAddr { get; set; } = IPv4.ANY;
|
||||
public IPv4 GIAddr { get; set; } = IPv4.ANY;
|
||||
|
||||
public MAC CHAddr { get; set; }
|
||||
public MAC CHAddr { get; set; } = new MAC(new byte[6]);
|
||||
|
||||
public byte[] SName { get; set; }
|
||||
public byte[] File { get; set; }
|
||||
|
@ -99,6 +100,8 @@ namespace ln.dhcp
|
|||
memoryStream.WriteBytes(YIAddr.IPBytes);
|
||||
memoryStream.WriteBytes(SIAddr.IPBytes);
|
||||
memoryStream.WriteBytes(GIAddr.IPBytes);
|
||||
memoryStream.WriteBytes(CHAddr.Bytes);
|
||||
memoryStream.WriteBytes(new byte[10]);
|
||||
memoryStream.WriteBytes(new byte[192]);
|
||||
memoryStream.WriteBytes(magicVend);
|
||||
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
using System;
|
||||
using System.Net.Sockets;
|
||||
using ln.types.net;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Threading;
|
||||
using ln.logging;
|
||||
using System.Text;
|
||||
namespace ln.dhcp
|
||||
{
|
||||
public class DHCPListener
|
||||
{
|
||||
public DHCPServer DHCPServer { get; private set; }
|
||||
public DHCPServerInterface ServerInterface { get; private set; }
|
||||
public IPv4 InterfaceAddress => ServerInterface.InterfaceAddress;
|
||||
|
||||
public InterfaceConfiguration ListeningInterfaceConfiguration { get; private set; }
|
||||
public IPv4 ListeningAddress { get; private set; }
|
||||
|
||||
UdpClient udpClient;
|
||||
Thread listenerThread;
|
||||
|
||||
public DHCPListener(DHCPServer dhcpServer,DHCPServerInterface serverInterface)
|
||||
{
|
||||
DHCPServer = dhcpServer;
|
||||
ServerInterface = serverInterface;
|
||||
ListeningInterfaceConfiguration = FindNetworkInterface(InterfaceAddress);
|
||||
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
||||
SetupWindows();
|
||||
else
|
||||
SetupLinux();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (((listenerThread == null) || !listenerThread.IsAlive) && (ListeningInterfaceConfiguration != null))
|
||||
{
|
||||
listenerThread = new Thread(() => InterfaceListener());
|
||||
listenerThread.Start();
|
||||
}
|
||||
}
|
||||
public void Close()
|
||||
{
|
||||
udpClient.Close();
|
||||
}
|
||||
|
||||
public InterfaceConfiguration FindNetworkInterface(IPv4 interfaceAddr)
|
||||
{
|
||||
NetworkInterface[] networkInterfaces = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
|
||||
foreach (NetworkInterface networkInterface in networkInterfaces)
|
||||
{
|
||||
foreach (UnicastIPAddressInformation addressInformation in networkInterface.GetIPProperties().UnicastAddresses)
|
||||
{
|
||||
if (interfaceAddr.Equals(addressInformation.Address))
|
||||
{
|
||||
return new InterfaceConfiguration(networkInterface.Name, addressInformation.Address, addressInformation.IPv4Mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void SetupWindows()
|
||||
{
|
||||
if (ListeningInterfaceConfiguration == null)
|
||||
return;
|
||||
|
||||
ListeningAddress = ListeningInterfaceConfiguration.BroadcastAddress;
|
||||
}
|
||||
private void SetupLinux()
|
||||
{
|
||||
if (ListeningInterfaceConfiguration == null)
|
||||
return;
|
||||
|
||||
ListeningAddress = IPAddress.Any;
|
||||
}
|
||||
|
||||
private void FixupSocket()
|
||||
{
|
||||
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
|
||||
{
|
||||
IntPtr socket = udpClient.Client.Handle;
|
||||
byte[] ifName = Encoding.ASCII.GetBytes(ListeningInterfaceConfiguration.Name);
|
||||
|
||||
int result = Mono.Unix.Native.Syscall.setsockopt(
|
||||
(int)socket,
|
||||
Mono.Unix.Native.UnixSocketProtocol.SOL_SOCKET,
|
||||
Mono.Unix.Native.UnixSocketOptionName.SO_BINDTODEVICE,
|
||||
ifName,
|
||||
ifName.Length
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void InterfaceListener()
|
||||
{
|
||||
udpClient = new UdpClient(new IPEndPoint(ListeningAddress, 67));
|
||||
udpClient.EnableBroadcast = true;
|
||||
|
||||
FixupSocket();
|
||||
|
||||
try
|
||||
{
|
||||
Logging.Log(LogLevel.INFO, "InterfaceListener started: {0}", ServerInterface.InterfaceAddress);
|
||||
|
||||
while (true)
|
||||
{
|
||||
IPEndPoint remoteEndpoint = new IPEndPoint(IPAddress.Any, 0);
|
||||
byte[] rxBytes = udpClient.Receive(ref remoteEndpoint);
|
||||
Logging.Log(LogLevel.INFO, "RX: {0} {1}", ServerInterface.InterfaceAddress,BitConverter.ToString(rxBytes));
|
||||
BootPPacket bootPPacket = new BootPPacket(rxBytes, remoteEndpoint);
|
||||
Logging.Log(LogLevel.INFO, "RX: {0} {1}", ServerInterface.InterfaceAddress, bootPPacket);
|
||||
DHCPServer.Pool.Enqueue(() => DHCPServer.Received(ServerInterface, bootPPacket));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Log(LogLevel.WARNING, "DHCPServer.InterfaceListener(): Caught exception: {0}", e);
|
||||
}
|
||||
|
||||
Logging.Log(LogLevel.INFO, "InterfaceListener stopped: {0}", ServerInterface.InterfaceAddress);
|
||||
|
||||
lock (this)
|
||||
{
|
||||
udpClient.Dispose();
|
||||
listenerThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Send(byte[] packet,IPEndPoint remoteEndpoint)
|
||||
{
|
||||
Logging.Log(LogLevel.INFO, "DHCPListener: Send(): {0} {1}", remoteEndpoint, BitConverter.ToString(packet));
|
||||
udpClient.Send(packet, packet.Length, remoteEndpoint);
|
||||
}
|
||||
|
||||
public class InterfaceConfiguration
|
||||
{
|
||||
public String Name;
|
||||
public IPv4 Address;
|
||||
public IPv4 Netmask;
|
||||
public Network4 Network => new Network4(Address, Netmask);
|
||||
|
||||
public IPv4 BroadcastAddress => Network.Last;
|
||||
|
||||
public InterfaceConfiguration(String name,IPv4 address,IPv4 netmask)
|
||||
{
|
||||
Name = name;
|
||||
Address = address;
|
||||
Netmask = netmask;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ namespace ln.dhcp
|
|||
public string StoragePath { get; private set; }
|
||||
public bool IsStarted { get; private set; }
|
||||
|
||||
Pool pool = new Pool(8);
|
||||
public Pool Pool { get; private set; } = new Pool(8);
|
||||
|
||||
ODBCollection<DHCPServerInterface> interfaces;
|
||||
public DHCPServerInterface[] Interfaces => interfaces.ToArray();
|
||||
|
@ -31,8 +31,9 @@ namespace ln.dhcp
|
|||
ODBCollection<DHCPLease> leases;
|
||||
public DHCPLease[] Leases => leases.ToArray();
|
||||
|
||||
Dictionary<DHCPServerInterface, DHCPListener> listeners = new Dictionary<DHCPServerInterface, DHCPListener>();
|
||||
|
||||
ODB odb;
|
||||
Dictionary<IPv4, UdpClient> udpClients = new Dictionary<IPv4, UdpClient>();
|
||||
|
||||
FileLogger logLease;
|
||||
|
||||
|
@ -83,29 +84,45 @@ namespace ln.dhcp
|
|||
}
|
||||
}
|
||||
|
||||
public void EnsureInterface(IPv4 interfaceAddr)
|
||||
{
|
||||
foreach (DHCPServerInterface serverInterface in interfaces)
|
||||
if (serverInterface.InterfaceAddress.Equals(interfaceAddr))
|
||||
return;
|
||||
|
||||
AddInterface(interfaceAddr);
|
||||
}
|
||||
public void EnsurePool(String name, IPv4 first, IPv4 last)
|
||||
{
|
||||
foreach (IPPool pool in IPPools)
|
||||
if (pool.Name.Equals(name))
|
||||
return;
|
||||
AddPool(new IPPool(name, first, last));
|
||||
}
|
||||
|
||||
|
||||
private void StartInterface(DHCPServerInterface serverInterface)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
Logging.Log(LogLevel.INFO, "Starting ServerInterface {0}",serverInterface.InterfaceAddress);
|
||||
|
||||
if (!udpClients.ContainsKey(serverInterface.InterfaceAddress))
|
||||
{
|
||||
Thread iThread = new Thread(() => InterfaceListener(serverInterface,null));
|
||||
iThread.Start();
|
||||
}
|
||||
if (!listeners.ContainsKey(serverInterface))
|
||||
listeners.Add(serverInterface, new DHCPListener(this, serverInterface));
|
||||
|
||||
listeners[serverInterface].Start();
|
||||
}
|
||||
}
|
||||
private void StopInterface(DHCPServerInterface serverInterface)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (udpClients.ContainsKey(serverInterface.InterfaceAddress))
|
||||
udpClients[serverInterface.InterfaceAddress].Close();
|
||||
if (listeners.ContainsKey(serverInterface))
|
||||
listeners[serverInterface].Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void Received(DHCPServerInterface serverInterface,BootPPacket packet)
|
||||
public void Received(DHCPServerInterface serverInterface,BootPPacket packet)
|
||||
{
|
||||
Logging.Log(LogLevel.INFO, "Received: {0}",packet);
|
||||
|
||||
|
@ -129,39 +146,6 @@ namespace ln.dhcp
|
|||
}
|
||||
}
|
||||
}
|
||||
private void InterfaceListener(DHCPServerInterface serverInterface, UdpClient udp)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logging.Log(LogLevel.INFO, "InterfaceListener started: {0}",serverInterface.InterfaceAddress);
|
||||
|
||||
//udp = new UdpClient(new IPEndPoint(serverInterface.InterfaceAddress, 67));
|
||||
udp = new UdpClient(new IPEndPoint(IPAddress.Any, 67));
|
||||
udp.EnableBroadcast = true;
|
||||
|
||||
while (IsStarted)
|
||||
{
|
||||
IPEndPoint remoteEndpoint = new IPEndPoint(IPAddress.Any, 0);
|
||||
byte[] rxBytes = udp.Receive(ref remoteEndpoint);
|
||||
Logging.Log(LogLevel.INFO, "RX: {0}", BitConverter.ToString(rxBytes));
|
||||
BootPPacket bootPPacket = new BootPPacket(rxBytes, remoteEndpoint);
|
||||
Logging.Log(LogLevel.INFO, "RX: {0}", bootPPacket);
|
||||
pool.Enqueue(() => Received(serverInterface,bootPPacket));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Log(LogLevel.WARNING, "DHCPServer.InterfaceListener(): Caught exception: {0}", e);
|
||||
}
|
||||
|
||||
Logging.Log(LogLevel.INFO, "InterfaceListener stopped: {0}", serverInterface.InterfaceAddress);
|
||||
|
||||
lock (this)
|
||||
{
|
||||
udpClients.Remove(serverInterface.InterfaceAddress);
|
||||
udp.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddInterface(IPv4 ip)
|
||||
{
|
||||
|
@ -205,9 +189,10 @@ namespace ln.dhcp
|
|||
reply.RemoteEndpoint = new IPEndPoint(request.CIAddr, 68);
|
||||
else if (request.Flags.HasFlag(BootPFlags.BROADCAST))
|
||||
reply.RemoteEndpoint = new IPEndPoint(IPAddress.Broadcast, 68);
|
||||
else
|
||||
else if (!request.YIAddr.Equals(IPv4.ANY))
|
||||
reply.RemoteEndpoint = new IPEndPoint(request.YIAddr, 68);
|
||||
|
||||
else
|
||||
reply.RemoteEndpoint = new IPEndPoint(IPAddress.Broadcast, 68);
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
@ -249,6 +234,14 @@ namespace ln.dhcp
|
|||
}
|
||||
}
|
||||
|
||||
private void Send(DHCPServerInterface serverInterface,byte[] packet,IPEndPoint remoteEndpoint)
|
||||
{
|
||||
if (listeners.ContainsKey(serverInterface))
|
||||
{
|
||||
listeners[serverInterface].Send(packet, remoteEndpoint);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendOffer(DHCPServerInterface serverInterface, DHCPLease lease, BootPPacket request)
|
||||
{
|
||||
BootPPacket reply = ConstructReply(serverInterface, request, DHCPMessageType.OFFER);
|
||||
|
@ -258,8 +251,7 @@ namespace ln.dhcp
|
|||
reply.AddOption(new DHCPLeaseTimeOption(lease.ValidThrough));
|
||||
|
||||
byte[] replyBytes = reply.ToBytes();
|
||||
UdpClient udpClient = udpClients[serverInterface.InterfaceAddress];
|
||||
udpClient.Send(replyBytes, replyBytes.Length, reply.RemoteEndpoint);
|
||||
Send(serverInterface, replyBytes, reply.RemoteEndpoint);
|
||||
}
|
||||
private void SendACK(DHCPServerInterface serverInterface, DHCPLease lease, BootPPacket request)
|
||||
{
|
||||
|
@ -270,16 +262,14 @@ namespace ln.dhcp
|
|||
reply.AddOption(new DHCPLeaseTimeOption(lease.ValidThrough));
|
||||
|
||||
byte[] replyBytes = reply.ToBytes();
|
||||
UdpClient udpClient = udpClients[serverInterface.InterfaceAddress];
|
||||
udpClient.Send(replyBytes, replyBytes.Length, reply.RemoteEndpoint);
|
||||
Send(serverInterface, replyBytes, reply.RemoteEndpoint);
|
||||
}
|
||||
private void SendNAK(DHCPServerInterface serverInterface, BootPPacket request)
|
||||
{
|
||||
BootPPacket reply = ConstructReply(serverInterface, request, DHCPMessageType.NAK);
|
||||
|
||||
byte[] replyBytes = reply.ToBytes();
|
||||
UdpClient udpClient = udpClients[serverInterface.InterfaceAddress];
|
||||
udpClient.Send(replyBytes, replyBytes.Length, reply.RemoteEndpoint);
|
||||
Send(serverInterface, replyBytes, reply.RemoteEndpoint);
|
||||
}
|
||||
|
||||
private void DHCPRequest(DHCPServerInterface serverInterface, BootPPacket packet)
|
||||
|
|
14
Option.cs
14
Option.cs
|
@ -17,7 +17,6 @@ namespace ln.dhcp
|
|||
public Option(byte tag)
|
||||
{
|
||||
Tag = tag;
|
||||
Bytes = new byte[0];
|
||||
}
|
||||
public Option(byte tag, byte[] bytes)
|
||||
{
|
||||
|
@ -72,7 +71,7 @@ namespace ln.dhcp
|
|||
{
|
||||
byte[] b = option.Bytes;
|
||||
memoryStream.WriteByte(option.Tag);
|
||||
memoryStream.WriteByte((byte)(b.Length + 2));
|
||||
memoryStream.WriteByte((byte)(b.Length));
|
||||
memoryStream.Write(b, 0, b.Length);
|
||||
}
|
||||
memoryStream.WriteByte(0xff);
|
||||
|
@ -90,7 +89,7 @@ namespace ln.dhcp
|
|||
AddFactory(0x33, (tag, bytes) => new DHCPLeaseTimeOption(bytes));// Lease Time
|
||||
|
||||
AddFactory(0x35, (tag, bytes) => new DHCPMessageTypeOption(bytes[0])); // DHCP Message Type
|
||||
AddFactory(0x36, (tag, bytes) => new IPv4Option(tag, bytes)); // Server ID
|
||||
AddFactory(0x36, (tag, bytes) => new DHCPServerIdentifierOption(bytes)); // Server ID
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -197,10 +196,15 @@ namespace ln.dhcp
|
|||
public class DHCPServerIdentifierOption : IPv4Option
|
||||
{
|
||||
public DHCPServerIdentifierOption()
|
||||
: base(53)
|
||||
: base(0x36)
|
||||
{ }
|
||||
public DHCPServerIdentifierOption(byte[] bytes)
|
||||
: base(0x36)
|
||||
{
|
||||
IP = new IPv4(bytes);
|
||||
}
|
||||
public DHCPServerIdentifierOption(IPv4 ip)
|
||||
: base(53, ip)
|
||||
: base(0x36, ip)
|
||||
{ }
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -28,6 +28,7 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="Mono.Posix" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="DHCPServer.cs" />
|
||||
|
@ -38,6 +39,7 @@
|
|||
<Compile Include="DHCPLease.cs" />
|
||||
<Compile Include="IPPool.cs" />
|
||||
<Compile Include="DHCPMessageType.cs" />
|
||||
<Compile Include="DHCPListener.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ln.types\ln.types.csproj">
|
||||
|
|
|
@ -1 +1 @@
|
|||
351cd8cebd3a846083459b35e2cffc1b4dd124b9
|
||||
62f8061fbf7e671ceaa150fc217748d6af510370
|
||||
|
|
|
@ -12,3 +12,17 @@
|
|||
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/bin/Debug/sharp.logging.pdb
|
||||
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/obj/Debug/ln.dhcp.csprojAssemblyReference.cache
|
||||
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/obj/Debug/ln.dhcp.csproj.CopyComplete
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/obj/Debug/ln.dhcp.csprojAssemblyReference.cache
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/obj/Debug/ln.dhcp.csproj.CoreCompileInputs.cache
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/obj/Debug/ln.dhcp.dll
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/obj/Debug/ln.dhcp.pdb
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Debug/ln.dhcp.dll
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Debug/ln.dhcp.pdb
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Debug/ln.types.dll
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Debug/sharp.logging.dll
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Debug/Newtonsoft.Json.dll
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Debug/ln.types.pdb
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Debug/sharp.logging.pdb
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Debug/Newtonsoft.Json.xml
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/obj/Debug/ln.dhcp.csproj.CopyComplete
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Debug/Newtonsoft.Json.pdb
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
17d7086814bead1da5d13b67562de4d6832acd41
|
|
@ -0,0 +1,11 @@
|
|||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Release/ln.dhcp.dll
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Release/ln.types.dll
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Release/sharp.logging.dll
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Release/Newtonsoft.Json.dll
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Release/Newtonsoft.Json.pdb
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Release/Newtonsoft.Json.xml
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/obj/Release/ln.dhcp.csproj.CoreCompileInputs.cache
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/obj/Release/ln.dhcp.csproj.CopyComplete
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/obj/Release/ln.dhcp.dll
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/bin/Release/Mono.Posix.dll
|
||||
/home/haraldwolff/src/ln.skyspot/ln.dhcp/obj/Release/ln.dhcp.csprojAssemblyReference.cache
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue