Dhcp4 parser
This commit is contained in:
parent
5e69ae245e
commit
4c7671b396
5 changed files with 124 additions and 11 deletions
|
|
@ -1,17 +1,71 @@
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
|
||||||
|
using nietras.SeparatedValues;
|
||||||
|
|
||||||
namespace pdns_dhcp.Kea;
|
namespace pdns_dhcp.Kea;
|
||||||
|
|
||||||
// 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(
|
||||||
string Address,
|
IPAddress Address,
|
||||||
string HWAddr,
|
PhysicalAddress HWAddr,
|
||||||
string? ClientId,
|
string? ClientId,
|
||||||
uint ValidLifetime,
|
uint ValidLifetime,
|
||||||
ulong Expire,
|
DateTimeOffset Expire,
|
||||||
string SubnetId,
|
uint SubnetId,
|
||||||
byte FqdnFwd,
|
bool FqdnFwd,
|
||||||
byte FqdnRev,
|
bool FqdnRev,
|
||||||
string Hostname,
|
string Hostname,
|
||||||
uint State,
|
uint State,
|
||||||
string UserContext,
|
string? UserContext,
|
||||||
uint PoolId
|
uint PoolId)
|
||||||
);
|
{
|
||||||
|
public static KeaDhcp4Lease Parse(in SepReader.Row row)
|
||||||
|
{
|
||||||
|
var address = IPAddress.Parse(row[0].Span);
|
||||||
|
PhysicalAddress hwaddr = PhysicalAddress.None;
|
||||||
|
if (row[1].Span is { IsEmpty: false } physical)
|
||||||
|
{
|
||||||
|
hwaddr = PhysicalAddress.Parse(physical);
|
||||||
|
}
|
||||||
|
string? clientId = row[2].ToString();
|
||||||
|
uint validLifetime = uint.Parse(row[3].Span);
|
||||||
|
DateTimeOffset expire = DateTimeOffset.FromUnixTimeSeconds(unchecked((long)ulong.Parse(row[4].Span)));
|
||||||
|
uint subnetId = uint.Parse(row[5].Span);
|
||||||
|
bool fqdnFwd = sbyte.Parse(row[6].Span) != 0;
|
||||||
|
bool fqdnRev = sbyte.Parse(row[7].Span) != 0;
|
||||||
|
string hostname = KeaDhcpLease.Unescape(row[8].Span);
|
||||||
|
|
||||||
|
uint state = 0;
|
||||||
|
if (row.ColCount > 9)
|
||||||
|
{
|
||||||
|
state = uint.Parse(row[9].Span);
|
||||||
|
}
|
||||||
|
|
||||||
|
string? userContext = default;
|
||||||
|
if (row.ColCount > 10)
|
||||||
|
{
|
||||||
|
userContext = KeaDhcpLease.Unescape(row[10].Span);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint poolId = 0;
|
||||||
|
if (row.ColCount > 11)
|
||||||
|
{
|
||||||
|
poolId = uint.Parse(row[11].Span);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new(
|
||||||
|
address,
|
||||||
|
hwaddr,
|
||||||
|
clientId,
|
||||||
|
validLifetime,
|
||||||
|
expire,
|
||||||
|
subnetId,
|
||||||
|
fqdnFwd,
|
||||||
|
fqdnRev,
|
||||||
|
hostname,
|
||||||
|
state,
|
||||||
|
userContext,
|
||||||
|
poolId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,8 @@ namespace pdns_dhcp.Kea;
|
||||||
|
|
||||||
public class KeaDhcp4LeaseHandler : IKeaDhcpLeaseHandler
|
public class KeaDhcp4LeaseHandler : IKeaDhcpLeaseHandler
|
||||||
{
|
{
|
||||||
public void Handle(in SepReader.Row row) { }
|
public void Handle(in SepReader.Row row)
|
||||||
|
{
|
||||||
|
KeaDhcp4Lease lease = KeaDhcp4Lease.Parse(row);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
49
src/pdns-dhcp/Kea/KeaDhcpLease.cs
Normal file
49
src/pdns-dhcp/Kea/KeaDhcpLease.cs
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
using DotNext.Buffers;
|
||||||
|
|
||||||
|
namespace pdns_dhcp.Kea;
|
||||||
|
|
||||||
|
public static class KeaDhcpLease
|
||||||
|
{
|
||||||
|
private static ReadOnlySpan<char> EscapeTag => ['&', '#', 'x'];
|
||||||
|
|
||||||
|
public static string Unescape(in ReadOnlySpan<char> text)
|
||||||
|
{
|
||||||
|
int esc_pos = text.IndexOf(EscapeTag);
|
||||||
|
return esc_pos == -1 ? text.ToString() : SlowPath(esc_pos, text);
|
||||||
|
|
||||||
|
static string SlowPath(int esc_pos, in ReadOnlySpan<char> text)
|
||||||
|
{
|
||||||
|
SpanReader<char> reader = new(text);
|
||||||
|
ArrayBufferWriter<char> writer = new(text.Length);
|
||||||
|
while (reader.RemainingCount > 0)
|
||||||
|
{
|
||||||
|
writer.Write(reader.Read(esc_pos));
|
||||||
|
reader.Advance(EscapeTag.Length);
|
||||||
|
if (EscapeTag.Length <= reader.RemainingCount - 2)
|
||||||
|
{
|
||||||
|
var digits = reader.Read(2);
|
||||||
|
if (byte.TryParse(digits, NumberStyles.AllowHexSpecifier, null, out var escaped_char))
|
||||||
|
{
|
||||||
|
writer.Write((char)escaped_char);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.Write(EscapeTag);
|
||||||
|
writer.Write(digits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esc_pos = reader.RemainingSpan.IndexOf(EscapeTag);
|
||||||
|
if (esc_pos == -1)
|
||||||
|
{
|
||||||
|
writer.Write(reader.ReadToEnd());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return writer.WrittenSpan.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -163,7 +163,11 @@ public sealed class KeaDhcpLeaseWatcher<T> : IHostedService
|
||||||
{
|
{
|
||||||
if (reader is null)
|
if (reader is null)
|
||||||
{
|
{
|
||||||
reader = Sep.Reader().From(_pipe.Reader.AsStream());
|
reader = Sep.New(',').Reader(o => o with
|
||||||
|
{
|
||||||
|
DisableColCountCheck = true,
|
||||||
|
Unescape = false
|
||||||
|
}).From(_pipe.Reader.AsStream());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,6 +176,8 @@ public sealed class KeaDhcpLeaseWatcher<T> : IHostedService
|
||||||
// TODO Error state.
|
// TODO Error state.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_handler.Handle(reader.Current);
|
||||||
}
|
}
|
||||||
|
|
||||||
var memory = writer.GetMemory();
|
var memory = writer.GetMemory();
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="DotNext" Version="4.15.2" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||||
<PackageReference Include="Sep" Version="0.3.0" />
|
<PackageReference Include="Sep" Version="0.3.0" />
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue