Implement lookup of ANY, IPv4 and IPv6 records

This commit is contained in:
Jöran Malek 2024-01-04 01:34:51 +01:00
parent 1f6312f8fc
commit 4db719d210
4 changed files with 65 additions and 14 deletions

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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<Reply> HandleLookup(LookupParameters parameters)
{
switch (parameters.Qtype.ToUpperInvariant())
AddressFamily? qtype = parameters.Qtype.ToUpperInvariant() switch
{
case "ANY":
return ValueTask.FromResult<Reply>(new LookupReply([]));
"ANY" => AddressFamily.Unknown,
"A" => AddressFamily.InterNetwork,
"AAAA" => AddressFamily.InterNetworkV6,
_ => default(AddressFamily?)
};
case "A":
return ValueTask.FromResult<Reply>(BoolReply.False);
case "AAAA":
_logger.LogInformation("AAAA request: {Options}", parameters);
return ValueTask.FromResult<Reply>(BoolReply.False);
default:
if (qtype is null)
{
_logger.LogWarning("Unhandled QType {QType}", parameters.Qtype);
return ValueTask.FromResult<Reply>(BoolReply.False);
}
return FindByName(((AddressFamily)qtype, parameters.Qname.AsMemory()), _repository, _logger);
static async ValueTask<Reply> FindByName((AddressFamily Family, ReadOnlyMemory<char> 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);
}
}
}

View file

@ -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;