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.NetworkInformation;
using System.Net.Sockets; using System.Net.Sockets;
using DotNext.Threading;
using Timeout = System.Threading.Timeout; using Timeout = System.Threading.Timeout;
namespace pdns_dhcp.Dns; namespace pdns_dhcp.Dns;

View file

@ -10,7 +10,12 @@ public class KeaDhcp4LeaseHandler : IKeaDhcpLeaseHandler
{ {
if (KeaDhcp4Lease.Parse(row) is not { } lease) if (KeaDhcp4Lease.Parse(row) is not { } lease)
{ {
return null; goto exitNull;
}
if (lease.State != 0)
{
goto exitNull;
} }
DhcpLeaseIdentifier identifier = lease.ClientId switch DhcpLeaseIdentifier identifier = lease.ClientId switch
@ -20,5 +25,8 @@ public class KeaDhcp4LeaseHandler : IKeaDhcpLeaseHandler
}; };
return new(lease.Address, lease.Hostname, identifier, lease.ValidLifetime); return new(lease.Address, lease.Hostname, identifier, lease.ValidLifetime);
exitNull:
return null;
} }
} }

View file

@ -1,4 +1,5 @@
using System.Buffers; using System.Buffers;
using System.Net.Sockets;
using System.Text.Json; using System.Text.Json;
using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Connections;
@ -123,21 +124,64 @@ public class PowerDnsHandler : ConnectionHandler
private ValueTask<Reply> HandleLookup(LookupParameters parameters) private ValueTask<Reply> HandleLookup(LookupParameters parameters)
{ {
switch (parameters.Qtype.ToUpperInvariant()) AddressFamily? qtype = parameters.Qtype.ToUpperInvariant() switch
{ {
case "ANY": "ANY" => AddressFamily.Unknown,
return ValueTask.FromResult<Reply>(new LookupReply([])); "A" => AddressFamily.InterNetwork,
"AAAA" => AddressFamily.InterNetworkV6,
_ => default(AddressFamily?)
};
case "A": if (qtype is null)
return ValueTask.FromResult<Reply>(BoolReply.False); {
_logger.LogWarning("Unhandled QType {QType}", parameters.Qtype);
return ValueTask.FromResult<Reply>(BoolReply.False);
}
case "AAAA": return FindByName(((AddressFamily)qtype, parameters.Qname.AsMemory()), _repository, _logger);
_logger.LogInformation("AAAA request: {Options}", parameters);
return ValueTask.FromResult<Reply>(BoolReply.False);
default: static async ValueTask<Reply> FindByName((AddressFamily Family, ReadOnlyMemory<char> Qname) query, DnsRepository repository, ILogger logger)
_logger.LogWarning("Unhandled QType {QType}", parameters.Qtype); {
return ValueTask.FromResult<Reply>(BoolReply.False); 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( [JsonSerializable(typeof(Reply)), JsonSourceGenerationOptions(
GenerationMode = JsonSourceGenerationMode.Metadata, GenerationMode = JsonSourceGenerationMode.Metadata,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = false WriteIndented = false
)] )]
internal partial class ReplyContext : JsonSerializerContext; internal partial class ReplyContext : JsonSerializerContext;