/*
Technitium DNS Server
Copyright (C) 2024 Shreyas Zare (shreyas@technitium.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
using DnsServerCore.Dhcp.Options;
using System;
using System.Globalization;
using System.IO;
using System.Net;
using TechnitiumLibrary.IO;
using TechnitiumLibrary.Net;
namespace DnsServerCore.Dhcp
{
public enum LeaseType : byte
{
None = 0,
Dynamic = 1,
Reserved = 2
}
public class Lease : IComparable
{
#region variables
static readonly char[] _hyphenColonSeparator = new char[] { '-', ':' };
LeaseType _type;
readonly ClientIdentifierOption _clientIdentifier;
string _hostName;
readonly byte[] _hardwareAddress;
readonly IPAddress _address;
string _comments;
readonly DateTime _leaseObtained;
DateTime _leaseExpires;
#endregion
#region constructor
internal Lease(LeaseType type, ClientIdentifierOption clientIdentifier, string hostName, byte[] hardwareAddress, IPAddress address, string comments, uint leaseTime)
{
_type = type;
_clientIdentifier = clientIdentifier;
_hostName = hostName;
_hardwareAddress = hardwareAddress;
_address = address;
_comments = comments;
_leaseObtained = DateTime.UtcNow;
ExtendLease(leaseTime);
}
internal Lease(LeaseType type, string hostName, DhcpMessageHardwareAddressType hardwareAddressType, byte[] hardwareAddress, IPAddress address, string comments)
: this(type, new ClientIdentifierOption((byte)hardwareAddressType, hardwareAddress), hostName, hardwareAddress, address, comments, 0)
{ }
internal Lease(LeaseType type, string hostName, DhcpMessageHardwareAddressType hardwareAddressType, string hardwareAddress, IPAddress address, string comments)
: this(type, hostName, hardwareAddressType, ParseHardwareAddress(hardwareAddress), address, comments)
{ }
internal Lease(BinaryReader bR)
{
byte version = bR.ReadByte();
switch (version)
{
case 1:
case 2:
_type = (LeaseType)bR.ReadByte();
_clientIdentifier = DhcpOption.Parse(bR.BaseStream) as ClientIdentifierOption;
_clientIdentifier.ParseOptionValue();
_hostName = bR.ReadShortString();
if (string.IsNullOrWhiteSpace(_hostName))
_hostName = null;
_hardwareAddress = bR.ReadBuffer();
_address = IPAddressExtensions.ReadFrom(bR);
if (version >= 2)
{
_comments = bR.ReadShortString();
if (string.IsNullOrWhiteSpace(_comments))
_comments = null;
}
_leaseObtained = bR.ReadDateTime();
_leaseExpires = bR.ReadDateTime();
break;
default:
throw new InvalidDataException("Lease data format version not supported.");
}
}
#endregion
#region internal
internal static byte[] ParseHardwareAddress(string hardwareAddress)
{
string[] parts = hardwareAddress.Split(_hyphenColonSeparator);
byte[] address = new byte[parts.Length];
for (int i = 0; i < parts.Length; i++)
address[i] = byte.Parse(parts[i], NumberStyles.HexNumber, CultureInfo.InvariantCulture);
return address;
}
internal void ConvertToReserved()
{
_type = LeaseType.Reserved;
}
internal void ConvertToDynamic()
{
_type = LeaseType.Dynamic;
}
internal void SetHostName(string hostName)
{
_hostName = hostName;
}
#endregion
#region public
public void ExtendLease(uint leaseTime)
{
_leaseExpires = DateTime.UtcNow.AddSeconds(leaseTime);
}
public void WriteTo(BinaryWriter bW)
{
bW.Write((byte)2); //version
bW.Write((byte)_type);
_clientIdentifier.WriteTo(bW.BaseStream);
if (string.IsNullOrWhiteSpace(_hostName))
bW.Write((byte)0);
else
bW.WriteShortString(_hostName);
bW.WriteBuffer(_hardwareAddress);
_address.WriteTo(bW);
if (string.IsNullOrWhiteSpace(_comments))
bW.Write((byte)0);
else
bW.WriteShortString(_comments);
bW.Write(_leaseObtained);
bW.Write(_leaseExpires);
}
public string GetClientInfo()
{
string hardwareAddress = BitConverter.ToString(_hardwareAddress);
if (string.IsNullOrWhiteSpace(_hostName))
return "[" + hardwareAddress + "]";
return _hostName + " [" + hardwareAddress + "]";
}
public int CompareTo(Lease other)
{
return _address.ConvertIpToNumber().CompareTo(other._address.ConvertIpToNumber());
}
#endregion
#region properties
public LeaseType Type
{ get { return _type; } }
internal ClientIdentifierOption ClientIdentifier
{ get { return _clientIdentifier; } }
public string HostName
{ get { return _hostName; } }
public byte[] HardwareAddress
{ get { return _hardwareAddress; } }
public IPAddress Address
{ get { return _address; } }
public string Comments
{
get { return _comments; }
set { _comments = value; }
}
public DateTime LeaseObtained
{ get { return _leaseObtained; } }
public DateTime LeaseExpires
{ get { return _leaseExpires; } }
#endregion
}
}