Initial Commit

master
Harald Christian Joachim Wolff 2019-04-23 09:22:14 +02:00
commit bd73b1c8b2
25 changed files with 12197 additions and 0 deletions

147
BootPPacket.cs 100644
View File

@ -0,0 +1,147 @@
using System;
using System.Net;
using ln.types.net;
using ln.types;
using System.Collections.Generic;
using System.IO;
namespace ln.dhcp
{
public enum OP:byte { BOOTREQUEST = 1,BOOTREPLY = 2 }
[Flags]
public enum BootPFlags:short
{
BROADCAST = 0x0001
}
public class BootPPacket
{
public IPEndPoint RemoteEndpoint { get; set; }
public OP OP { get; set; }
public byte HType { get; set; }
public byte HLen { get; set; }
public byte Hops { get; set; }
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 MAC CHAddr { get; set; }
public byte[] SName { get; set; }
public byte[] File { get; set; }
public byte[] Vend { get; set; }
List<Option> options = new List<Option>();
public Option[] Options => options.ToArray();
static byte[] magicVend = new byte[] { 0x63, 0x82, 0x53, 0x63 };
public BootPPacket()
{
}
public BootPPacket(byte[] bytes,IPEndPoint remoteEndpoint)
{
if (bytes.Length < 290)
throw new ArgumentOutOfRangeException(nameof(bytes), "BootP Packet too small");
RemoteEndpoint = remoteEndpoint;
OP = (OP)bytes[0];
HType = bytes[1];
HLen = bytes[2];
Hops = bytes[3];
XID = bytes.GetUInt(4,true);
Secs = bytes.GetUShort(8, true);
Flags = (BootPFlags)bytes.GetShort(10, true);
CIAddr = new IPv4(bytes, 12);
YIAddr = new IPv4(bytes, 16);
SIAddr = new IPv4(bytes, 20);
GIAddr = new IPv4(bytes, 24);
if (HLen != 6)
throw new ArgumentOutOfRangeException(nameof(bytes),"Only 6 byte HW Addresses are supported by this implementation");
CHAddr = new MAC(bytes.Slice(28, 6));
SName = bytes.Slice(44, 64);
File = bytes.Slice(108, 128);
Vend = bytes.Slice(236);
if ((Vend.Length >= 4) && Vend.Slice(0, 4).AreEqual(magicVend))
{
options.AddRange(Option.ParseOptions(Vend, 4));
}
Option overload = GetFirstOption(0x34);
if (overload != null)
{
if ((overload.Bytes[0] & 0x01) != 0)
options.AddRange(Option.ParseOptions(File, 4));
if ((overload.Bytes[0] & 0x02) != 0)
options.AddRange(Option.ParseOptions(SName, 4));
}
}
public byte[] ToBytes()
{
MemoryStream memoryStream = new MemoryStream();
memoryStream.WriteByte((byte)OP);
memoryStream.WriteByte(HType);
memoryStream.WriteByte(HLen);
memoryStream.WriteByte(Hops);
memoryStream.WriteUInteger(XID);
memoryStream.WriteUShort(Secs);
memoryStream.WriteShort((short)Flags);
memoryStream.WriteBytes(CIAddr.IPBytes);
memoryStream.WriteBytes(YIAddr.IPBytes);
memoryStream.WriteBytes(SIAddr.IPBytes);
memoryStream.WriteBytes(GIAddr.IPBytes);
memoryStream.WriteBytes(new byte[192]);
memoryStream.WriteBytes(magicVend);
byte[] options = Option.ToBytes(Options);
memoryStream.WriteBytes(options);
return memoryStream.ToArray();
}
public OT GetFirstOption<OT>() where OT : Option
{
foreach (Option option in options)
{
if (option is OT)
return (OT)option;
}
return null;
}
public Option GetFirstOption(byte tag)
{
foreach (Option option in options)
{
if (option.Tag == tag)
return option;
}
return null;
}
public void RemoveOption(Option option) => options.Remove(option);
public void AddOption(Option option) => options.Add(option);
public void SetOption(Option option)
{
foreach (Option op in options)
if (op.Tag == option.Tag)
RemoveOption(op);
AddOption(option);
}
public override string ToString()
{
return String.Format("[OP={0} Options: {1}]",OP,String.Join(", ", (object[])Options));
}
}
}

44
DHCPLease.cs 100644
View File

@ -0,0 +1,44 @@
using System;
using ln.types.net;
using ln.types.odb.attributes;
namespace ln.dhcp
{
public class DHCPLease
{
[DocumentID]
public readonly Guid ID = Guid.NewGuid();
public MAC ClientMAC { get; set; }
public IPv4 ClientIP { get; set; }
public String ClientName { get; set; }
public IPv4 ServerInterface { get; set; }
public DateTimeOffset Created { get; set; }
public DateTimeOffset LastUpdate { get; set; }
public DateTimeOffset ValidThrough { get; set; }
public DateTimeOffset Released { get; set; }
private DHCPLease()
{}
public DHCPLease(IPv4 serverInterface,MAC clientMac, IPv4 clientIP)
:this(serverInterface,clientMac)
{
ClientIP = clientIP;
}
public DHCPLease(IPv4 serverInterface,MAC clientMac)
{
Created = DateTimeOffset.Now;
LastUpdate = Created;
ValidThrough = Created + TimeSpan.FromSeconds(60);
Released = DateTimeOffset.MinValue;
ServerInterface = serverInterface;
ClientMAC = clientMac;
ClientName = "";
ClientIP = IPv4.ANY;
}
}
}

14
DHCPMessageType.cs 100644
View File

@ -0,0 +1,14 @@
using System;
namespace ln.dhcp
{
public enum DHCPMessageType : byte
{
DISCOVER = 1,
OFFER = 2,
REQUEST = 3,
DECLINE = 4,
ACK = 5,
NAK = 6,
RELEASE = 7
}
}

399
DHCPServer.cs 100644
View File

@ -0,0 +1,399 @@
using System;
using System.Collections.Generic;
using ln.types.threads;
using ln.types.net;
using System.Net.Sockets;
using System.Net;
using ln.logging;
using ln.types.odb;
using System.IO;
using ln.types.odb.mapped;
using System.Linq;
using System.Threading;
namespace ln.dhcp
{
public class DHCPServer
{
public string StoragePath { get; private set; }
public bool IsStarted { get; private set; }
Pool pool = new Pool(8);
ODBCollection<DHCPServerInterface> interfaces;
public DHCPServerInterface[] Interfaces => interfaces.ToArray();
ODBCollection<IPPool> ippools;
public IPPool[] IPPools => ippools.ToArray();
ODBCollection<Option> defaultOptions;
public Option[] DefaultOptions => defaultOptions.ToArray();
ODBCollection<DHCPLease> leases;
public DHCPLease[] Leases => leases.ToArray();
ODB odb;
Dictionary<IPv4, UdpClient> udpClients = new Dictionary<IPv4, UdpClient>();
FileLogger logLease;
LeasesAPI leasesAPI;
public DHCPServer()
:this("default")
{
}
public DHCPServer(String uniqueName)
{
StoragePath = Path.Combine("/var/cache/ln.dhcp", uniqueName);
if (!Directory.Exists(StoragePath))
Directory.CreateDirectory(StoragePath);
logLease = new FileLogger(Path.Combine(StoragePath, "lease.log"));
odb = new ODB(StoragePath);
defaultOptions = odb.GetCollection<Option>();
ippools = odb.GetCollection<IPPool>();
interfaces = odb.GetCollection<DHCPServerInterface>();
leases = odb.GetCollection<DHCPLease>();
leasesAPI = new LeasesAPI(this);
}
public void Start()
{
lock (this)
{
if (!IsStarted && interfaces.Count > 0)
{
foreach (DHCPServerInterface serverInterface in interfaces)
StartInterface(serverInterface);
IsStarted = true;
}
}
}
public void Stop()
{
lock (this)
{
foreach (DHCPServerInterface serverInterface in interfaces)
StartInterface(serverInterface);
IsStarted = false;
}
}
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();
}
}
}
private void StopInterface(DHCPServerInterface serverInterface)
{
lock (this)
{
if (udpClients.ContainsKey(serverInterface.InterfaceAddress))
udpClients[serverInterface.InterfaceAddress].Close();
}
}
private void Received(DHCPServerInterface serverInterface,BootPPacket packet)
{
Logging.Log(LogLevel.INFO, "Received: {0}",packet);
DHCPMessageTypeOption messageType = packet.GetFirstOption<DHCPMessageTypeOption>();
if (messageType != null)
{
switch (messageType.DHCPMessageType)
{
case DHCPMessageType.DISCOVER:
DHCPDiscover(serverInterface, packet);
break;
case DHCPMessageType.RELEASE:
DHCPRelease(serverInterface, packet);
break;
case DHCPMessageType.REQUEST:
DHCPRequest(serverInterface, packet);
break;
case DHCPMessageType.DECLINE:
DHCPDecline(serverInterface, packet);
break;
}
}
}
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)
{
DHCPServerInterface serverInterface = new DHCPServerInterface(ip);
lock (this)
{
if (!interfaces.Insert(serverInterface))
throw new ArgumentException(nameof(ip),String.Format("DHCPServer already has interface for IP {0}",ip));
if (IsStarted)
StartInterface(serverInterface);
}
}
public void AddPool(IPPool pool)
{
lock (this)
{
if (!ippools.Insert(pool))
throw new ArgumentException(nameof(pool), String.Format("DHCPServer could not insert new pool {0}", pool));
}
}
private BootPPacket ConstructReply(DHCPServerInterface serverInterface,BootPPacket request,DHCPMessageType replyType)
{
BootPPacket reply = new BootPPacket();
reply.OP = OP.BOOTREPLY;
reply.HType = request.HType;
reply.HLen = request.HLen;
reply.XID = request.XID;
reply.Flags = request.Flags;
reply.GIAddr = request.GIAddr;
reply.CHAddr = request.CHAddr;
reply.AddOption(new DHCPMessageTypeOption(replyType));
reply.AddOption(new DHCPServerIdentifierOption(serverInterface.InterfaceAddress));
if (!request.GIAddr.Equals(IPv4.ANY))
reply.RemoteEndpoint = new IPEndPoint(request.GIAddr, 67);
else if (replyType == DHCPMessageType.NAK)
reply.RemoteEndpoint = new IPEndPoint(IPAddress.Broadcast, 68);
else if (!request.CIAddr.Equals(IPv4.ANY))
reply.RemoteEndpoint = new IPEndPoint(request.CIAddr, 68);
else if (request.Flags.HasFlag(BootPFlags.BROADCAST))
reply.RemoteEndpoint = new IPEndPoint(IPAddress.Broadcast, 68);
else
reply.RemoteEndpoint = new IPEndPoint(request.YIAddr, 68);
return reply;
}
private void CollectDefaultOptions(DHCPServerInterface serverInterface,BootPPacket packet)
{
foreach (Option defaultOption in defaultOptions)
packet.SetOption(defaultOption);
foreach (Option defaultOption in serverInterface.DefaultOptions)
packet.SetOption(defaultOption);
}
private void DHCPDiscover(DHCPServerInterface serverInterface, BootPPacket packet)
{
lock (leasesAPI)
{
DHCPLease lease = leasesAPI.FindLease(serverInterface.InterfaceAddress, packet.CHAddr);
if (lease == null)
{
IPv4 offeredIP = AcquireIP(serverInterface.Pool);
if (offeredIP != null)
{
lease = new DHCPLease(serverInterface.InterfaceAddress, packet.CHAddr);
lease.ClientIP = offeredIP;
}
}
if (lease != null)
{
DateTimeOffset reservationTimeout = DateTimeOffset.Now + TimeSpan.FromSeconds(60);
if (lease.ValidThrough < reservationTimeout)
{
lease.ValidThrough = reservationTimeout;
Commit(lease);
logLease.Log(LogLevel.INFO, "[OFFERED] {0} {1} {2}", lease.ClientMAC, lease.ClientIP, lease.ClientName);
}
SendOffer(serverInterface, lease, packet);
}
}
}
private void SendOffer(DHCPServerInterface serverInterface, DHCPLease lease, BootPPacket request)
{
BootPPacket reply = ConstructReply(serverInterface, request, DHCPMessageType.OFFER);
CollectDefaultOptions(serverInterface, reply);
reply.YIAddr = lease.ClientIP;
reply.AddOption(new DHCPLeaseTimeOption(lease.ValidThrough));
byte[] replyBytes = reply.ToBytes();
UdpClient udpClient = udpClients[serverInterface.InterfaceAddress];
udpClient.Send(replyBytes, replyBytes.Length, reply.RemoteEndpoint);
}
private void SendACK(DHCPServerInterface serverInterface, DHCPLease lease, BootPPacket request)
{
BootPPacket reply = ConstructReply(serverInterface, request, DHCPMessageType.ACK);
CollectDefaultOptions(serverInterface, reply);
reply.YIAddr = lease.ClientIP;
reply.AddOption(new DHCPLeaseTimeOption(lease.ValidThrough));
byte[] replyBytes = reply.ToBytes();
UdpClient udpClient = udpClients[serverInterface.InterfaceAddress];
udpClient.Send(replyBytes, replyBytes.Length, 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);
}
private void DHCPRequest(DHCPServerInterface serverInterface, BootPPacket packet)
{
lock (leasesAPI)
{
DHCPLease lease = leasesAPI.FindLease(serverInterface.InterfaceAddress, packet.CHAddr);
DHCPRequestedIPOption requestedIP = packet.GetFirstOption<DHCPRequestedIPOption>();
if ((requestedIP != null) && (lease != null) && (lease.ClientIP.Equals(requestedIP.IP)))
{
DateTimeOffset validThrough = DateTimeOffset.Now + serverInterface.Pool.DefaultLeaseTime;
if (lease.ValidThrough < validThrough)
{
lease.ValidThrough = validThrough;
Commit(lease);
}
logLease.Log(LogLevel.INFO, "[ACK ] {0} {1} {2}", lease.ClientMAC, lease.ClientIP, lease.ClientName);
SendACK(serverInterface, lease, packet);
}
else
{
SendNAK(serverInterface, packet);
}
}
}
private void DHCPDecline(DHCPServerInterface serverInterface, BootPPacket packet)
{
}
private void DHCPRelease(DHCPServerInterface serverInterface, BootPPacket packet)
{
}
private IPv4 AcquireIP(IPPool ippool)
{
lock (this)
{
IPv4 start = ippool.NextIP;
IPv4 test = start;
while (leasesAPI.FindLease(test) != null)
{
test = ippool.NextIP;
if (test.Equals(start))
return null;
}
return test;
}
}
public bool Commit(IPPool ippool) => ippools.Upsert(ippool);
public bool Commit(DHCPServerInterface serverInterface) => interfaces.Upsert(serverInterface);
public bool Commit(DHCPLease lease) => leases.Upsert(lease);
public class LeasesAPI
{
DHCPServer dhcp;
public LeasesAPI(DHCPServer dhcpServer)
{
dhcp = dhcpServer;
}
public void CleanupLeases() => CleanupLeases(TimeSpan.Zero);
public void CleanupLeases(TimeSpan acceptedOverdue)
{
DateTimeOffset now = DateTimeOffset.Now;
lock (this)
{
foreach (DHCPLease lease in dhcp.Leases)
{
if ((lease.ValidThrough + acceptedOverdue) < now)
dhcp.leases.Delete(lease);
}
}
}
public DHCPLease FindLease(IPv4 serverInterface,MAC mac)
{
lock (this)
{
Query queryLease = Query.AND(
Query.Equals<DHCPLease>("ClientMAC", mac),
Query.Equals<DHCPLease>("ServerInterface", serverInterface)
);
DHCPLease lease = dhcp.leases.Query(queryLease).FirstOrDefault();
return lease;
}
}
public DHCPLease FindLease(IPv4 ip)
{
lock (this)
{
DHCPLease lease = dhcp.leases.Query(Query.Equals<DHCPLease>("ClientIP", ip)).FirstOrDefault();
return lease;
}
}
public void ReleaseLease(DHCPLease lease)
{
lock (this)
{
lease.Released = DateTimeOffset.Now;
dhcp.logLease.Log(LogLevel.INFO, "[RELEASE] {0} {1} {2}", lease.ClientMAC, lease.ClientIP, lease.ClientName);
}
}
public void RemoveLease(DHCPLease lease)
{
lock (this)
{
dhcp.leases.Delete(lease);
dhcp.logLease.Log(LogLevel.INFO, "[REMOVE] {0} {1} {2}", lease.ClientMAC, lease.ClientIP, lease.ClientName);
}
}
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using ln.types.net;
using ln.types.odb.attributes;
using System.Collections.Generic;
namespace ln.dhcp
{
public class DHCPServerInterface
{
[DocumentID]
public String Name { get; set; }
public IPv4 InterfaceAddress { get; set; }
[ByReference]
IPPool pool;
public IPPool Pool
{
get => pool;
set => pool = value;
}
List<Option> defaultOptions = new List<Option>();
public Option[] DefaultOptions => defaultOptions.ToArray();
private DHCPServerInterface()
{
}
public DHCPServerInterface(IPv4 interfaceAddress)
{
InterfaceAddress = interfaceAddress;
Name = InterfaceAddress.ToString();
}
}
}

45
IPPool.cs 100644
View File

@ -0,0 +1,45 @@
using System;
using ln.types.net;
using System.Collections.Generic;
using ln.types.odb.attributes;
namespace ln.dhcp
{
public class IPPool
{
[DocumentID]
public String Name { get; set; }
public IPv4 FirstIP { get; set; }
public IPv4 LastIP { get; set; }
IPv4 nextIP;
public IPv4 NextIP
{
get
{
IPv4 next = nextIP++;
if (nextIP > LastIP)
nextIP = FirstIP;
return next;
}
set => nextIP = value;
}
public TimeSpan DefaultLeaseTime { get; set; }
private IPPool()
{
DefaultLeaseTime = TimeSpan.FromHours(1);
}
public IPPool(String name, IPv4 first, IPv4 last)
: this()
{
Name = name;
FirstIP = first;
LastIP = last;
NextIP = FirstIP;
}
}
}

292
Option.cs 100644
View File

@ -0,0 +1,292 @@
using System;
using ln.types;
using System.Collections.Generic;
using ln.types.net;
using System.Linq;
using System.Text;
using System.IO;
namespace ln.dhcp
{
public delegate Option OptionFactory(byte tag, byte[] bytes);
public class Option
{
public byte Tag { get; }
public virtual byte[] Bytes { get; set; }
public Option(byte tag)
{
Tag = tag;
Bytes = new byte[0];
}
public Option(byte tag, byte[] bytes)
{
Tag = tag;
Bytes = bytes;
}
public override string ToString()
{
return String.Format("[Option TAG={0} Bytes={1}]", Tag, BitConverter.ToString(Bytes));
}
static Dictionary<byte, OptionFactory> factories = new Dictionary<byte, OptionFactory>();
static void AddFactory(byte tag, OptionFactory factory) => factories.Add(tag, factory);
public static Option[] ParseOptions(byte[] bytes, int offset)
{
List<Option> options = new List<Option>();
while ((offset < bytes.Length) && (bytes[offset] != 0xff))
if (bytes[offset] != 0x00)
options.Add(Option.Parse(bytes, ref offset));
else
offset++;
return options.ToArray();
}
public static Option Parse(byte[] bytes, ref int offset)
{
Console.WriteLine("OFFSET: {0}", offset);
switch (bytes[offset])
{
case 0:
case 255:
return new Option(bytes[offset++]);
default:
byte tag = bytes[offset++];
byte len = bytes[offset++];
byte[] slice = bytes.Slice(offset, len);
offset += len;
if (factories.ContainsKey(bytes[offset]))
return factories[tag](tag, slice);
else
return new Option(tag, slice);
}
}
public static byte[] ToBytes(IEnumerable<Option> options)
{
MemoryStream memoryStream = new MemoryStream();
foreach(Option option in options)
{
byte[] b = option.Bytes;
memoryStream.WriteByte(option.Tag);
memoryStream.WriteByte((byte)(b.Length + 2));
memoryStream.Write(b, 0, b.Length);
}
memoryStream.WriteByte(0xff);
return memoryStream.ToArray();
}
static Option()
{
AddFactory(0x01, (tag, bytes) => new NetmaskOption(bytes)); // Netmask
AddFactory(0x03, (tag, bytes) => new GatewaysOption(bytes)); // Gateways
AddFactory(0x0C, (tag, bytes) => new TextOption(tag, bytes)); // Host Name
AddFactory(0x0F, (tag, bytes) => new TextOption(tag, bytes)); // Domain Name
AddFactory(0x32, (tag, bytes) => new IPv4Option(tag, bytes)); // Requested IP
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
}
}
public class IPv4ListOption : Option
{
public IPv4[] IPs { get; set; }
public override byte[] Bytes
{
get => IPs.SelectMany(ip => ip.IPBytes).ToArray();
set
{
IPs = new IPv4[value.Length / 4];
for (int n = 0; n < value.Length / 4; n++)
IPs[n] = new IPv4(value.Slice(n * 4, 4));
}
}
public IPv4ListOption(byte tag)
:base(tag)
{
IPs = new IPv4[0];
}
public IPv4ListOption(byte tag, IPv4[] ips)
: base(tag)
{
IPs = ips.Slice(0);
}
public IPv4ListOption(byte tag, byte[] bytes)
: base(tag)
{
IPs = new IPv4[] { new IPv4(bytes) };
}
}
public class GatewaysOption : IPv4ListOption
{
public GatewaysOption()
: base(0x03,new byte[0])
{
}
public GatewaysOption(byte[] bytes)
: base(0x03,bytes)
{
}
public GatewaysOption(IEnumerable<IPv4> gateways)
: base(0x03)
{
IPs = gateways.ToArray();
}
}
public class IPv4Option : Option
{
public IPv4 IP { get; set; }
public override byte[] Bytes
{
get => IP.IPBytes;
set => IP = new IPv4(value);
}
public IPv4Option(byte tag)
: base(tag)
{ }
public IPv4Option(byte tag, IPv4 ip)
: base(tag)
{
IP = ip;
}
public IPv4Option(byte tag, byte[] bytes)
: base(tag)
{
Bytes = bytes;
}
}
public class NetmaskOption : IPv4Option
{
public NetmaskOption()
: base(0x01)
{ }
public NetmaskOption(byte[] bytes)
: base(0x01)
{
Bytes = bytes;
}
public NetmaskOption(IPv4 ip)
: base(0x01, ip)
{ }
}
public class DHCPRequestedIPOption : IPv4Option
{
public DHCPRequestedIPOption()
: base(0x32)
{ }
public DHCPRequestedIPOption(byte[] bytes)
: base(0x32)
{
Bytes = bytes;
}
public DHCPRequestedIPOption(IPv4 ip)
: base(0x32, ip)
{ }
}
public class DHCPServerIdentifierOption : IPv4Option
{
public DHCPServerIdentifierOption()
: base(53)
{ }
public DHCPServerIdentifierOption(IPv4 ip)
: base(53, ip)
{ }
}
public class TextOption : Option
{
public String Text { get; set; }
public override byte[] Bytes
{
get => Encoding.UTF8.GetBytes(Text);
set => Text = Encoding.UTF8.GetString(value);
}
public TextOption(byte tag)
: base(tag)
{ }
public TextOption(byte tag, byte[] bytes)
: base(tag)
{
Bytes = bytes;
}
public TextOption(byte tag, string text)
: this(tag)
{
Text = text;
}
}
public class IntegerOption : Option
{
public int Integer { get; set; }
public override byte[] Bytes
{
get => Integer.GetBytes(true);
set => Integer = value.GetInt(true);
}
public IntegerOption(byte tag)
: base(tag)
{ }
public IntegerOption(byte tag, byte[] bytes)
: base(tag)
{
Bytes = bytes;
}
public IntegerOption(byte tag, int i)
: this(tag)
{
Integer = i;
}
}
public class DHCPLeaseTimeOption : IntegerOption
{
public DHCPLeaseTimeOption(byte[] val)
: base(0x33, val)
{}
public DHCPLeaseTimeOption(int leaseTime)
: base(0x33)
{
Integer = leaseTime;
}
public DHCPLeaseTimeOption(DateTimeOffset validThrough)
:base(0x33)
{
Integer = (int)(validThrough - DateTimeOffset.Now).TotalSeconds;
}
}
public class DHCPMessageTypeOption : Option
{
public DHCPMessageType DHCPMessageType { get; set; }
public override byte[] Bytes
{
get => new byte[] { (byte)DHCPMessageType };
set => DHCPMessageType = value.Length > 0 ? (DHCPMessageType)value[0] : DHCPMessageType.DISCOVER;
}
public DHCPMessageTypeOption()
: base(0x35)
{
}
public DHCPMessageTypeOption(DHCPMessageType messageType)
: base(0x35)
{
DHCPMessageType = messageType;
}
public DHCPMessageTypeOption(byte value)
: this()
{
DHCPMessageType = (DHCPMessageType)value;
}
}
}

View File

@ -0,0 +1,26 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("ln.dhcp")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("${AuthorCopyright}")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

53
ln.dhcp.csproj 100644
View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{13869452-1A9D-4652-9B51-F9D1A9F7919F}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>ln.dhcp</RootNamespace>
<AssemblyName>ln.dhcp</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="DHCPServer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="BootPPacket.cs" />
<Compile Include="Option.cs" />
<Compile Include="DHCPServerInterface.cs" />
<Compile Include="DHCPLease.cs" />
<Compile Include="IPPool.cs" />
<Compile Include="DHCPMessageType.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ln.types\ln.types.csproj">
<Project>{8D9AB9A5-E513-4BA7-A450-534F6456BF28}</Project>
<Name>ln.types</Name>
</ProjectReference>
<ProjectReference Include="..\ln.logging\ln.logging.csproj">
<Project>{D471A566-9FB6-41B2-A777-3C32874ECD0E}</Project>
<Name>ln.logging</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(RunConfiguration)' == 'Default' ">
<StartAction>Project</StartAction>
<ConsolePause>true</ConsolePause>
</PropertyGroup>
</Project>

View File

@ -0,0 +1 @@
351cd8cebd3a846083459b35e2cffc1b4dd124b9

View File

@ -0,0 +1,14 @@
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/bin/Debug/ln.dhcp.dll
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/bin/Debug/ln.dhcp.pdb
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/obj/Debug/ln.dhcp.csproj.CoreCompileInputs.cache
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/obj/Debug/ln.dhcp.dll
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/obj/Debug/ln.dhcp.pdb
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/bin/Debug/ln.types.dll
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/bin/Debug/Newtonsoft.Json.dll
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/bin/Debug/sharp.logging.dll
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/bin/Debug/ln.types.pdb
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/bin/Debug/Newtonsoft.Json.pdb
/Volumes/HOMES/haraldwolff/src/skyspot/ln.dhcp/bin/Debug/Newtonsoft.Json.xml
/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

Binary file not shown.

Binary file not shown.