diff --git a/src/pdns-dhcp/Kea/KeaDhcp4Lease.cs b/src/pdns-dhcp/Kea/KeaDhcp4Lease.cs index 1ed3223..fa748b3 100644 --- a/src/pdns-dhcp/Kea/KeaDhcp4Lease.cs +++ b/src/pdns-dhcp/Kea/KeaDhcp4Lease.cs @@ -3,8 +3,12 @@ using System.Net.NetworkInformation; using nietras.SeparatedValues; +using Cell = System.ReadOnlySpan; + 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 public record struct KeaDhcp4Lease( IPAddress Address, @@ -20,9 +24,9 @@ public record struct KeaDhcp4Lease( string? UserContext, 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++) { if (Parse(ref result, i, row[i].Span) == false) @@ -34,7 +38,7 @@ public record struct KeaDhcp4Lease( return result; } - private static bool? Parse(ref KeaDhcp4Lease lease, int column, in ReadOnlySpan span) + private static bool? Parse(ref Lease lease, int column, in Cell span) { return column switch { @@ -50,84 +54,85 @@ public record struct KeaDhcp4Lease( 9 => ToState(ref lease, span), 10 => ToUserContext(ref lease, span), 11 => ToPoolId(ref lease, span), + _ => null }; - static bool? ToIPAddress(ref KeaDhcp4Lease lease, in ReadOnlySpan span) + static bool ToIPAddress(ref Lease lease, in Cell span) { bool result = IPAddress.TryParse(span, out var address); lease.Address = address!; return result; } - static bool? ToHWAddr(ref KeaDhcp4Lease lease, in ReadOnlySpan span) + static bool ToHWAddr(ref Lease lease, in Cell span) { bool result = PhysicalAddress.TryParse(span, out var hwaddr); lease.HWAddr = hwaddr!; return result; } - static bool? ToClientId(ref KeaDhcp4Lease lease, in ReadOnlySpan span) + static bool ToClientId(ref Lease lease, in Cell span) { lease.ClientId = span.ToString(); return true; } - static bool? ToValidLifetime(ref KeaDhcp4Lease lease, in ReadOnlySpan span) + 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 KeaDhcp4Lease lease, in ReadOnlySpan span) + 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 KeaDhcp4Lease lease, in ReadOnlySpan span) + static bool ToSubnetId(ref Lease lease, in Cell span) { bool result = uint.TryParse(span, out var subnetId); lease.SubnetId = subnetId; return result; } - static bool? ToFqdnFwd(ref KeaDhcp4Lease lease, in ReadOnlySpan span) + 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 KeaDhcp4Lease lease, in ReadOnlySpan span) + 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 KeaDhcp4Lease lease, in ReadOnlySpan span) + static bool ToHostname(ref Lease lease, in Cell span) { lease.Hostname = KeaDhcpLease.Unescape(span); return true; } - static bool? ToState(ref KeaDhcp4Lease lease, in ReadOnlySpan span) + 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 KeaDhcp4Lease lease, in ReadOnlySpan span) + static bool ToUserContext(ref Lease lease, in Cell span) { lease.UserContext = KeaDhcpLease.Unescape(span); return true; } - static bool? ToPoolId(ref KeaDhcp4Lease lease, in ReadOnlySpan span) + static bool ToPoolId(ref Lease lease, in Cell span) { bool result = uint.TryParse(span, out var poolId); lease.PoolId = poolId; diff --git a/src/pdns-dhcp/Kea/KeaDhcp6Lease.cs b/src/pdns-dhcp/Kea/KeaDhcp6Lease.cs index fd374a7..3e4299a 100644 --- a/src/pdns-dhcp/Kea/KeaDhcp6Lease.cs +++ b/src/pdns-dhcp/Kea/KeaDhcp6Lease.cs @@ -3,8 +3,12 @@ using System.Net.NetworkInformation; using nietras.SeparatedValues; +using Cell = System.ReadOnlySpan; + 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 public record struct KeaDhcp6Lease( IPAddress Address, @@ -26,88 +30,167 @@ public record struct KeaDhcp6Lease( uint? HWAddrSource, 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++) { - var span = row[i].Span; - switch (i) + if (Parse(ref result, i, row[i].Span) == false) { - case 0: - 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 null; } } 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; + } + } } diff --git a/src/pdns-dhcp/Kea/KeaDhcp6LeaseHandler.cs b/src/pdns-dhcp/Kea/KeaDhcp6LeaseHandler.cs index 39113a8..3bfd098 100644 --- a/src/pdns-dhcp/Kea/KeaDhcp6LeaseHandler.cs +++ b/src/pdns-dhcp/Kea/KeaDhcp6LeaseHandler.cs @@ -8,8 +8,11 @@ public class KeaDhcp6LeaseHandler : IKeaDhcpLeaseHandler { 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); } }