Implement lookup of ANY, IPv4 and IPv6 records
This commit is contained in:
parent
1f6312f8fc
commit
4db719d210
4 changed files with 65 additions and 14 deletions
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue