Dhcp6 parsing

This commit is contained in:
Jöran Malek 2023-12-31 02:05:38 +01:00
parent a33c39e841
commit 81aec473ae
3 changed files with 183 additions and 92 deletions

View file

@ -3,8 +3,12 @@ using System.Net.NetworkInformation;
using nietras.SeparatedValues; using nietras.SeparatedValues;
using Cell = System.ReadOnlySpan<char>;
namespace pdns_dhcp.Kea; namespace pdns_dhcp.Kea;
using Lease = KeaDhcp4Lease;
// ref: https://github.com/isc-projects/kea/blob/Kea-2.5.3/src/lib/dhcpsrv/csv_lease_file4.h // ref: https://github.com/isc-projects/kea/blob/Kea-2.5.3/src/lib/dhcpsrv/csv_lease_file4.h
public record struct KeaDhcp4Lease( public record struct KeaDhcp4Lease(
IPAddress Address, IPAddress Address,
@ -20,9 +24,9 @@ public record struct KeaDhcp4Lease(
string? UserContext, string? UserContext,
uint PoolId) uint PoolId)
{ {
public static KeaDhcp4Lease? Parse(in SepReader.Row row) public static Lease? Parse(in SepReader.Row row)
{ {
KeaDhcp4Lease result = new(); Lease result = new();
for (int i = 0; i < row.ColCount; i++) for (int i = 0; i < row.ColCount; i++)
{ {
if (Parse(ref result, i, row[i].Span) == false) if (Parse(ref result, i, row[i].Span) == false)
@ -34,7 +38,7 @@ public record struct KeaDhcp4Lease(
return result; return result;
} }
private static bool? Parse(ref KeaDhcp4Lease lease, int column, in ReadOnlySpan<char> span) private static bool? Parse(ref Lease lease, int column, in Cell span)
{ {
return column switch return column switch
{ {
@ -50,84 +54,85 @@ public record struct KeaDhcp4Lease(
9 => ToState(ref lease, span), 9 => ToState(ref lease, span),
10 => ToUserContext(ref lease, span), 10 => ToUserContext(ref lease, span),
11 => ToPoolId(ref lease, span), 11 => ToPoolId(ref lease, span),
_ => null _ => null
}; };
static bool? ToIPAddress(ref KeaDhcp4Lease lease, in ReadOnlySpan<char> span) static bool ToIPAddress(ref Lease lease, in Cell span)
{ {
bool result = IPAddress.TryParse(span, out var address); bool result = IPAddress.TryParse(span, out var address);
lease.Address = address!; lease.Address = address!;
return result; return result;
} }
static bool? ToHWAddr(ref KeaDhcp4Lease lease, in ReadOnlySpan<char> span) static bool ToHWAddr(ref Lease lease, in Cell span)
{ {
bool result = PhysicalAddress.TryParse(span, out var hwaddr); bool result = PhysicalAddress.TryParse(span, out var hwaddr);
lease.HWAddr = hwaddr!; lease.HWAddr = hwaddr!;
return result; return result;
} }
static bool? ToClientId(ref KeaDhcp4Lease lease, in ReadOnlySpan<char> span) static bool ToClientId(ref Lease lease, in Cell span)
{ {
lease.ClientId = span.ToString(); lease.ClientId = span.ToString();
return true; return true;
} }
static bool? ToValidLifetime(ref KeaDhcp4Lease lease, in ReadOnlySpan<char> span) static bool ToValidLifetime(ref Lease lease, in Cell span)
{ {
bool result = uint.TryParse(span, out var validLifetime); bool result = uint.TryParse(span, out var validLifetime);
lease.ValidLifetime = validLifetime; lease.ValidLifetime = validLifetime;
return result; return result;
} }
static bool? ToExpire(ref KeaDhcp4Lease lease, in ReadOnlySpan<char> span) static bool ToExpire(ref Lease lease, in Cell span)
{ {
bool result = ulong.TryParse(span, out var expire); bool result = ulong.TryParse(span, out var expire);
lease.Expire = DateTimeOffset.FromUnixTimeSeconds(unchecked((long)expire)); lease.Expire = DateTimeOffset.FromUnixTimeSeconds(unchecked((long)expire));
return result; return result;
} }
static bool? ToSubnetId(ref KeaDhcp4Lease lease, in ReadOnlySpan<char> span) static bool ToSubnetId(ref Lease lease, in Cell span)
{ {
bool result = uint.TryParse(span, out var subnetId); bool result = uint.TryParse(span, out var subnetId);
lease.SubnetId = subnetId; lease.SubnetId = subnetId;
return result; return result;
} }
static bool? ToFqdnFwd(ref KeaDhcp4Lease lease, in ReadOnlySpan<char> span) static bool ToFqdnFwd(ref Lease lease, in Cell span)
{ {
bool result = byte.TryParse(span, out var fqdnFwd); bool result = byte.TryParse(span, out var fqdnFwd);
lease.FqdnFwd = fqdnFwd != 0; lease.FqdnFwd = fqdnFwd != 0;
return result; return result;
} }
static bool? ToFqdnRev(ref KeaDhcp4Lease lease, in ReadOnlySpan<char> span) static bool ToFqdnRev(ref Lease lease, in Cell span)
{ {
bool result = byte.TryParse(span, out var fqdnRev); bool result = byte.TryParse(span, out var fqdnRev);
lease.FqdnRev = fqdnRev != 0; lease.FqdnRev = fqdnRev != 0;
return result; return result;
} }
static bool? ToHostname(ref KeaDhcp4Lease lease, in ReadOnlySpan<char> span) static bool ToHostname(ref Lease lease, in Cell span)
{ {
lease.Hostname = KeaDhcpLease.Unescape(span); lease.Hostname = KeaDhcpLease.Unescape(span);
return true; return true;
} }
static bool? ToState(ref KeaDhcp4Lease lease, in ReadOnlySpan<char> span) static bool ToState(ref Lease lease, in Cell span)
{ {
bool result = uint.TryParse(span, out var state); bool result = uint.TryParse(span, out var state);
lease.State = state; lease.State = state;
return result; return result;
} }
static bool? ToUserContext(ref KeaDhcp4Lease lease, in ReadOnlySpan<char> span) static bool ToUserContext(ref Lease lease, in Cell span)
{ {
lease.UserContext = KeaDhcpLease.Unescape(span); lease.UserContext = KeaDhcpLease.Unescape(span);
return true; return true;
} }
static bool? ToPoolId(ref KeaDhcp4Lease lease, in ReadOnlySpan<char> span) static bool ToPoolId(ref Lease lease, in Cell span)
{ {
bool result = uint.TryParse(span, out var poolId); bool result = uint.TryParse(span, out var poolId);
lease.PoolId = poolId; lease.PoolId = poolId;

View file

@ -3,8 +3,12 @@ using System.Net.NetworkInformation;
using nietras.SeparatedValues; using nietras.SeparatedValues;
using Cell = System.ReadOnlySpan<char>;
namespace pdns_dhcp.Kea; namespace pdns_dhcp.Kea;
using Lease = KeaDhcp6Lease;
// ref: https://github.com/isc-projects/kea/blob/Kea-2.5.3/src/lib/dhcpsrv/csv_lease_file6.h // ref: https://github.com/isc-projects/kea/blob/Kea-2.5.3/src/lib/dhcpsrv/csv_lease_file6.h
public record struct KeaDhcp6Lease( public record struct KeaDhcp6Lease(
IPAddress Address, IPAddress Address,
@ -26,88 +30,167 @@ public record struct KeaDhcp6Lease(
uint? HWAddrSource, uint? HWAddrSource,
uint PoolId) uint PoolId)
{ {
public static KeaDhcp6Lease Parse(in SepReader.Row row) public static Lease? Parse(in SepReader.Row row)
{ {
KeaDhcp6Lease result = new(); Lease result = new();
for (int i = 0; i < row.ColCount; i++) for (int i = 0; i < row.ColCount; i++)
{ {
var span = row[i].Span; if (Parse(ref result, i, row[i].Span) == false)
switch (i)
{ {
case 0: return null;
result.Address = IPAddress.Parse(span);
break;
case 1:
result.DUId = span.ToString();
break;
case 2:
result.ValidLifetime = uint.Parse(span);
break;
case 3:
result.Expire = DateTimeOffset.FromUnixTimeSeconds(unchecked((long)ulong.Parse(span)));
break;
case 4:
result.SubnetId = uint.Parse(span);
break;
case 5:
result.PrefLifetime = uint.Parse(span);
break;
case 6:
result.LeaseType = (LeaseType)byte.Parse(span);
break;
case 7:
result.IAId = uint.Parse(span);
break;
case 8:
result.PrefixLen = byte.Parse(span);
break;
case 9:
result.FqdnFwd = byte.Parse(span) != 0;
break;
case 10:
result.FqdnRev = byte.Parse(span) != 0;
break;
case 11:
result.Hostname = KeaDhcpLease.Unescape(span);
break;
case 12 when !span.IsWhiteSpace():
result.HWAddr = PhysicalAddress.Parse(span);
break;
case 13:
result.State = uint.Parse(span);
break;
case 14 when !span.IsWhiteSpace():
result.UserContext = KeaDhcpLease.Unescape(span);
break;
case 15:
result.HWType = ushort.Parse(span);
break;
case 16:
result.HWAddrSource = uint.Parse(span);
break;
case 17:
result.PoolId = uint.Parse(span);
break;
} }
} }
return result; return result;
} }
private static bool? Parse(ref Lease lease, int column, in Cell span)
{
return column switch
{
0 => ToAddress(ref lease, span),
1 => ToDUId(ref lease, span),
2 => ToValidLifetime(ref lease, span),
3 => ToExpire(ref lease, span),
4 => ToSubnetId(ref lease, span),
5 => ToPrefLifetime(ref lease, span),
6 => ToLeaseType(ref lease, span),
7 => ToIAId(ref lease, span),
8 => ToPrefixLen(ref lease, span),
9 => ToFqdnFwd(ref lease, span),
10 => ToFqdnRev(ref lease, span),
11 => ToHostname(ref lease, span),
12 when !span.IsWhiteSpace() => ToHWAddr(ref lease, span),
13 => ToState(ref lease, span),
14 when !span.IsWhiteSpace() => ToUserContext(ref lease, span),
15 => ToHWType(ref lease, span),
16 => ToHWAddrSource(ref lease, span),
17 => ToPoolId(ref lease, span),
_ => null
};
static bool ToAddress(ref Lease lease, in Cell span)
{
bool result = IPAddress.TryParse(span, out var address);
lease.Address = address!;
return result;
}
static bool ToDUId(ref Lease lease, in Cell span)
{
lease.DUId = span.ToString();
return true;
}
static bool ToValidLifetime(ref Lease lease, in Cell span)
{
bool result = uint.TryParse(span, out var validLifetime);
lease.ValidLifetime = validLifetime;
return result;
}
static bool ToExpire(ref Lease lease, in Cell span)
{
bool result = ulong.TryParse(span, out var expire);
lease.Expire = DateTimeOffset.FromUnixTimeSeconds(unchecked((long)expire));
return result;
}
static bool ToSubnetId(ref Lease lease, in Cell span)
{
bool result = uint.TryParse(span, out var subnetId);
lease.SubnetId = subnetId;
return result;
}
static bool ToPrefLifetime(ref Lease lease, in Cell span)
{
bool result = uint.TryParse(span, out var prefLifetime);
lease.PrefLifetime = prefLifetime;
return result;
}
static bool ToLeaseType(ref Lease lease, in Cell span)
{
bool result = byte.TryParse(span, out var leaseType);
lease.LeaseType = (LeaseType)leaseType;
return result;
}
static bool ToIAId(ref Lease lease, in Cell span)
{
bool result = uint.TryParse(span, out var iaId);
lease.IAId = iaId;
return result;
}
static bool ToPrefixLen(ref Lease lease, in Cell span)
{
bool result = byte.TryParse(span, out var prefixLen);
lease.PrefixLen = prefixLen;
return result;
}
static bool ToFqdnFwd(ref Lease lease, in Cell span)
{
bool result = byte.TryParse(span, out var fqdnFwd);
lease.FqdnFwd = fqdnFwd != 0;
return result;
}
static bool ToFqdnRev(ref Lease lease, in Cell span)
{
bool result = byte.TryParse(span, out var fqdnRev);
lease.FqdnRev = fqdnRev != 0;
return result;
}
static bool ToHostname(ref Lease lease, in Cell span)
{
lease.Hostname = KeaDhcpLease.Unescape(span);
return true;
}
static bool ToHWAddr(ref Lease lease, in Cell span)
{
bool result = PhysicalAddress.TryParse(span, out var hwAddr);
lease.HWAddr = hwAddr!;
return result;
}
static bool ToState(ref Lease lease, in Cell span)
{
bool result = uint.TryParse(span, out var state);
lease.State = state;
return result;
}
static bool ToUserContext(ref Lease lease, in Cell span)
{
lease.UserContext = KeaDhcpLease.Unescape(span);
return true;
}
static bool ToHWType(ref Lease lease, in Cell span)
{
bool result = ushort.TryParse(span, out var hwType);
lease.HWType = hwType;
return result;
}
static bool ToHWAddrSource(ref Lease lease, in Cell span)
{
bool result = uint.TryParse(span, out var hwAddrSource);
lease.HWAddrSource = hwAddrSource;
return result;
}
static bool ToPoolId(ref Lease lease, in Cell span)
{
bool result = uint.TryParse(span, out var poolId);
lease.PoolId = poolId;
return result;
}
}
} }

View file

@ -8,8 +8,11 @@ public class KeaDhcp6LeaseHandler : IKeaDhcpLeaseHandler
{ {
public DhcpLeaseChange? Handle(in SepReader.Row row) public DhcpLeaseChange? Handle(in SepReader.Row row)
{ {
KeaDhcp6Lease lease = KeaDhcp6Lease.Parse(row); if (KeaDhcp6Lease.Parse(row) is not { } lease)
{
return null;
}
return default; return new(lease.Address, lease.Hostname, null, default);
} }
} }