|
|
|
@ -24,9 +24,33 @@ pub enum CheckDomainError { |
|
|
|
|
pub enum DNSRecord { |
|
|
|
|
A(net::Ipv4Addr), |
|
|
|
|
AAAA(net::Ipv6Addr), |
|
|
|
|
CNAME(domain::Name), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl DNSRecord { |
|
|
|
|
async fn check_a( |
|
|
|
|
client: &mut AsyncClient, |
|
|
|
|
domain: &trust_dns_client::rr::Name, |
|
|
|
|
addr: &net::Ipv4Addr, |
|
|
|
|
) -> Result<bool, unexpected::Error> { |
|
|
|
|
let response = client |
|
|
|
|
.query(domain.clone(), DNSClass::IN, RecordType::A) |
|
|
|
|
.await |
|
|
|
|
.or_unexpected_while("querying A record")?; |
|
|
|
|
|
|
|
|
|
let records = response.answers(); |
|
|
|
|
|
|
|
|
|
for record in records { |
|
|
|
|
if let Some(RData::A(record_addr)) = record.data() { |
|
|
|
|
if record_addr == addr { |
|
|
|
|
return Ok(true); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return Ok(false); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn check_aaaa( |
|
|
|
|
client: &mut AsyncClient, |
|
|
|
|
domain: &trust_dns_client::rr::Name, |
|
|
|
@ -35,42 +59,42 @@ impl DNSRecord { |
|
|
|
|
let response = client |
|
|
|
|
.query(domain.clone(), DNSClass::IN, RecordType::AAAA) |
|
|
|
|
.await |
|
|
|
|
.or_unexpected_while("querying A record")?; |
|
|
|
|
.or_unexpected_while("querying AAAA record")?; |
|
|
|
|
|
|
|
|
|
let records = response.answers(); |
|
|
|
|
|
|
|
|
|
if records.len() != 1 { |
|
|
|
|
return Ok(false); |
|
|
|
|
for record in records { |
|
|
|
|
if let Some(RData::AAAA(record_addr)) = record.data() { |
|
|
|
|
if record_addr == addr { |
|
|
|
|
return Ok(true); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// if the single record isn't a AAAA, or it's not the target AAAA, then return false
|
|
|
|
|
match records[0].data() { |
|
|
|
|
Some(RData::AAAA(remote_addr)) if remote_addr == addr => Ok(true), |
|
|
|
|
_ => return Ok(false), |
|
|
|
|
} |
|
|
|
|
return Ok(false); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn check_a( |
|
|
|
|
async fn check_cname( |
|
|
|
|
client: &mut AsyncClient, |
|
|
|
|
domain: &trust_dns_client::rr::Name, |
|
|
|
|
addr: &net::Ipv4Addr, |
|
|
|
|
cname: &trust_dns_client::rr::Name, |
|
|
|
|
) -> Result<bool, unexpected::Error> { |
|
|
|
|
let response = client |
|
|
|
|
.query(domain.clone(), DNSClass::IN, RecordType::A) |
|
|
|
|
.query(domain.clone(), DNSClass::IN, RecordType::CNAME) |
|
|
|
|
.await |
|
|
|
|
.or_unexpected_while("querying A record")?; |
|
|
|
|
.or_unexpected_while("querying CNAME record")?; |
|
|
|
|
|
|
|
|
|
let records = response.answers(); |
|
|
|
|
|
|
|
|
|
if records.len() != 1 { |
|
|
|
|
return Ok(false); |
|
|
|
|
for record in records { |
|
|
|
|
if let Some(RData::CNAME(record_cname)) = record.data() { |
|
|
|
|
if record_cname == cname { |
|
|
|
|
return Ok(true); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// if the single record isn't a A, or it's not the target A, then return false
|
|
|
|
|
match records[0].data() { |
|
|
|
|
Some(RData::A(remote_addr)) if remote_addr == addr => Ok(true), |
|
|
|
|
_ => return Ok(false), |
|
|
|
|
} |
|
|
|
|
return Ok(false); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn check( |
|
|
|
@ -81,6 +105,7 @@ impl DNSRecord { |
|
|
|
|
match self { |
|
|
|
|
Self::A(addr) => Self::check_a(client, domain, &addr).await, |
|
|
|
|
Self::AAAA(addr) => Self::check_aaaa(client, domain, &addr).await, |
|
|
|
|
Self::CNAME(name) => Self::check_cname(client, domain, name.as_rr()).await, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|