From 4db719d2102ad44847f179756194d4bc06ce67e4 Mon Sep 17 00:00:00 2001 From: AliveDevil Date: Thu, 4 Jan 2024 01:34:51 +0100 Subject: [PATCH] Implement lookup of ANY, IPv4 and IPv6 records --- src/pdns-dhcp/Dns/DnsRepository.cs | 2 - src/pdns-dhcp/Kea/KeaDhcp4LeaseHandler.cs | 10 +++- src/pdns-dhcp/PowerDns/PowerDnsHandler.cs | 66 +++++++++++++++++++---- src/pdns-dhcp/PowerDns/Replies.cs | 1 + 4 files changed, 65 insertions(+), 14 deletions(-) diff --git a/src/pdns-dhcp/Dns/DnsRepository.cs b/src/pdns-dhcp/Dns/DnsRepository.cs index f229af6..6044460 100644 --- a/src/pdns-dhcp/Dns/DnsRepository.cs +++ b/src/pdns-dhcp/Dns/DnsRepository.cs @@ -2,8 +2,6 @@ using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; -using DotNext.Threading; - using Timeout = System.Threading.Timeout; namespace pdns_dhcp.Dns; diff --git a/src/pdns-dhcp/Kea/KeaDhcp4LeaseHandler.cs b/src/pdns-dhcp/Kea/KeaDhcp4LeaseHandler.cs index d9e8365..855cfa1 100644 --- a/src/pdns-dhcp/Kea/KeaDhcp4LeaseHandler.cs +++ b/src/pdns-dhcp/Kea/KeaDhcp4LeaseHandler.cs @@ -10,7 +10,12 @@ public class KeaDhcp4LeaseHandler : IKeaDhcpLeaseHandler { if (KeaDhcp4Lease.Parse(row) is not { } lease) { - return null; + goto exitNull; + } + + if (lease.State != 0) + { + goto exitNull; } DhcpLeaseIdentifier identifier = lease.ClientId switch @@ -20,5 +25,8 @@ public class KeaDhcp4LeaseHandler : IKeaDhcpLeaseHandler }; return new(lease.Address, lease.Hostname, identifier, lease.ValidLifetime); + + exitNull: + return null; } } diff --git a/src/pdns-dhcp/PowerDns/PowerDnsHandler.cs b/src/pdns-dhcp/PowerDns/PowerDnsHandler.cs index 477a414..518e8ed 100644 --- a/src/pdns-dhcp/PowerDns/PowerDnsHandler.cs +++ b/src/pdns-dhcp/PowerDns/PowerDnsHandler.cs @@ -1,4 +1,5 @@ using System.Buffers; +using System.Net.Sockets; using System.Text.Json; using Microsoft.AspNetCore.Connections; @@ -123,21 +124,64 @@ public class PowerDnsHandler : ConnectionHandler private ValueTask HandleLookup(LookupParameters parameters) { - switch (parameters.Qtype.ToUpperInvariant()) + AddressFamily? qtype = parameters.Qtype.ToUpperInvariant() switch { - case "ANY": - return ValueTask.FromResult(new LookupReply([])); + "ANY" => AddressFamily.Unknown, + "A" => AddressFamily.InterNetwork, + "AAAA" => AddressFamily.InterNetworkV6, + _ => default(AddressFamily?) + }; - case "A": - return ValueTask.FromResult(BoolReply.False); + if (qtype is null) + { + _logger.LogWarning("Unhandled QType {QType}", parameters.Qtype); + return ValueTask.FromResult(BoolReply.False); + } - case "AAAA": - _logger.LogInformation("AAAA request: {Options}", parameters); - return ValueTask.FromResult(BoolReply.False); + return FindByName(((AddressFamily)qtype, parameters.Qname.AsMemory()), _repository, _logger); - default: - _logger.LogWarning("Unhandled QType {QType}", parameters.Qtype); - return ValueTask.FromResult(BoolReply.False); + static async ValueTask FindByName((AddressFamily Family, ReadOnlyMemory Qname) query, DnsRepository repository, ILogger logger) + { + QueryResult[]? records = null; + + var qname = query.Qname.Trim().TrimEnd("."); + if (qname.Span.IsWhiteSpace()) + { + goto exitEmpty; + } + + var results = await repository.FindAsync(record => + { + if ((record.RecordType & query.Family) != record.RecordType) + { + return false; + } + + return qname.Span.Equals(record.FQDN, StringComparison.OrdinalIgnoreCase); + }).ConfigureAwait(false); + + if (results.Count == 0) + { + goto exitEmpty; + } + + records = new QueryResult[results.Count]; + for (int i = 0; i < results.Count; i++) + { + DnsRecord record = results[i]; +#pragma warning disable CS8509 // RecordType is by convention InterNetwork or InterNetworkV6 + records[i] = new(record.RecordType switch +#pragma warning restore + { + AddressFamily.InterNetwork => "A", + AddressFamily.InterNetworkV6 => "AAAA" + }, record.FQDN, record.Address.ToString(), (int)record.Lifetime.TotalSeconds); + } + + exitEmpty: + records ??= []; + + return new LookupReply(records); } } } diff --git a/src/pdns-dhcp/PowerDns/Replies.cs b/src/pdns-dhcp/PowerDns/Replies.cs index 0312e44..f5f9c2f 100644 --- a/src/pdns-dhcp/PowerDns/Replies.cs +++ b/src/pdns-dhcp/PowerDns/Replies.cs @@ -8,6 +8,7 @@ public abstract class Reply; [JsonSerializable(typeof(Reply)), JsonSourceGenerationOptions( GenerationMode = JsonSourceGenerationMode.Metadata, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, WriteIndented = false )] internal partial class ReplyContext : JsonSerializerContext;