use tracing::debug;
#[cfg(feature = "__dnssec")]
use crate::{authority::Nsec3QueryInfo, dnssec::NxProofKind, proto::dnssec::Proof};
use crate::{
authority::{
Authority, LookupControlFlow, LookupOptions, MessageRequest, UpdateResult, ZoneType,
},
proto::rr::{LowerName, Record, RecordType},
server::RequestInfo,
};
#[async_trait::async_trait]
pub trait AuthorityObject: Send + Sync {
fn zone_type(&self) -> ZoneType;
fn is_axfr_allowed(&self) -> bool;
fn can_validate_dnssec(&self) -> bool;
async fn update(&self, update: &MessageRequest) -> UpdateResult<bool>;
fn origin(&self) -> &LowerName;
async fn lookup(
&self,
name: &LowerName,
rtype: RecordType,
lookup_options: LookupOptions,
) -> LookupControlFlow<Box<dyn LookupObject>>;
async fn consult(
&self,
name: &LowerName,
rtype: RecordType,
lookup_options: LookupOptions,
last_result: LookupControlFlow<Box<dyn LookupObject>>,
) -> LookupControlFlow<Box<dyn LookupObject>>;
async fn search(
&self,
request_info: RequestInfo<'_>,
lookup_options: LookupOptions,
) -> LookupControlFlow<Box<dyn LookupObject>>;
async fn ns(&self, lookup_options: LookupOptions) -> LookupControlFlow<Box<dyn LookupObject>> {
self.lookup(self.origin(), RecordType::NS, lookup_options)
.await
}
async fn get_nsec_records(
&self,
name: &LowerName,
lookup_options: LookupOptions,
) -> LookupControlFlow<Box<dyn LookupObject>>;
#[cfg(feature = "__dnssec")]
async fn get_nsec3_records(
&self,
info: Nsec3QueryInfo<'_>,
lookup_options: LookupOptions,
) -> LookupControlFlow<Box<dyn LookupObject>>;
async fn soa(&self) -> LookupControlFlow<Box<dyn LookupObject>> {
self.lookup(self.origin(), RecordType::SOA, LookupOptions::default())
.await
}
async fn soa_secure(
&self,
lookup_options: LookupOptions,
) -> LookupControlFlow<Box<dyn LookupObject>> {
self.lookup(self.origin(), RecordType::SOA, lookup_options)
.await
}
#[cfg(feature = "__dnssec")]
fn nx_proof_kind(&self) -> Option<&NxProofKind>;
}
#[async_trait::async_trait]
impl<A, L> AuthorityObject for A
where
A: Authority<Lookup = L> + Send + Sync + 'static,
L: LookupObject + Send + Sync + 'static,
{
fn zone_type(&self) -> ZoneType {
Authority::zone_type(self)
}
fn is_axfr_allowed(&self) -> bool {
Authority::is_axfr_allowed(self)
}
fn can_validate_dnssec(&self) -> bool {
Authority::can_validate_dnssec(self)
}
async fn update(&self, update: &MessageRequest) -> UpdateResult<bool> {
Authority::update(self, update).await
}
fn origin(&self) -> &LowerName {
Authority::origin(self)
}
async fn lookup(
&self,
name: &LowerName,
rtype: RecordType,
lookup_options: LookupOptions,
) -> LookupControlFlow<Box<dyn LookupObject>> {
Authority::lookup(self, name, rtype, lookup_options)
.await
.map_dyn()
}
async fn consult(
&self,
name: &LowerName,
rtype: RecordType,
lookup_options: LookupOptions,
last_result: LookupControlFlow<Box<dyn LookupObject>>,
) -> LookupControlFlow<Box<dyn LookupObject>> {
Authority::consult(self, name, rtype, lookup_options, last_result).await
}
async fn search(
&self,
request_info: RequestInfo<'_>,
lookup_options: LookupOptions,
) -> LookupControlFlow<Box<dyn LookupObject>> {
debug!("performing {} on {}", request_info.query, self.origin());
Authority::search(self, request_info, lookup_options)
.await
.map_dyn()
}
async fn get_nsec_records(
&self,
name: &LowerName,
lookup_options: LookupOptions,
) -> LookupControlFlow<Box<dyn LookupObject>> {
Authority::get_nsec_records(self, name, lookup_options)
.await
.map_dyn()
}
#[cfg(feature = "__dnssec")]
async fn get_nsec3_records(
&self,
info: Nsec3QueryInfo<'_>,
lookup_options: LookupOptions,
) -> LookupControlFlow<Box<dyn LookupObject>> {
Authority::get_nsec3_records(self, info, lookup_options)
.await
.map_dyn()
}
#[cfg(feature = "__dnssec")]
fn nx_proof_kind(&self) -> Option<&NxProofKind> {
Authority::nx_proof_kind(self)
}
}
#[derive(Clone, Copy, Debug)]
pub enum DnssecSummary {
Secure,
Bogus,
Insecure,
}
pub trait LookupObject: Send {
fn is_empty(&self) -> bool;
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Record> + Send + 'a>;
fn take_additionals(&mut self) -> Option<Box<dyn LookupObject>>;
#[cfg(feature = "__dnssec")]
fn dnssec_summary(&self) -> DnssecSummary {
let mut all_secure = None;
for record in self.iter() {
match record.proof() {
Proof::Secure => {
all_secure.get_or_insert(true);
}
Proof::Bogus => return DnssecSummary::Bogus,
_ => all_secure = Some(false),
}
}
if all_secure.unwrap_or(false) {
DnssecSummary::Secure
} else {
DnssecSummary::Insecure
}
}
#[cfg(not(feature = "__dnssec"))]
fn dnssec_summary(&self) -> DnssecSummary {
DnssecSummary::Insecure
}
}
#[derive(Clone, Copy, Debug)]
pub struct EmptyLookup;
impl LookupObject for EmptyLookup {
fn is_empty(&self) -> bool {
true
}
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Record> + Send + 'a> {
Box::new([].iter())
}
fn take_additionals(&mut self) -> Option<Box<dyn LookupObject>> {
None
}
}