master
Harald Wolff 2019-04-23 12:59:29 +02:00
parent bd73b1c8b2
commit 7304747952
28 changed files with 11363 additions and 62 deletions

View File

@ -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);

155
DHCPListener.cs 100644
View File

@ -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;
}
}
}
}

View File

@ -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)

View File

@ -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.

View File

@ -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">

View File

@ -1 +1 @@
351cd8cebd3a846083459b35e2cffc1b4dd124b9
62f8061fbf7e671ceaa150fc217748d6af510370

View File

@ -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.

View File

@ -0,0 +1 @@
17d7086814bead1da5d13b67562de4d6832acd41

View File

@ -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.