make dig
queries more configurable
switch from enum arguments like `Recurse` and `Dnssec` to a build-pattern-based `Settings` struct
This commit is contained in:
parent
df344e57b1
commit
b87ae21d2a
@ -1,6 +1,6 @@
|
|||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
use dns_test::client::{Client, Dnssec, Recurse};
|
use dns_test::client::{Client, DigSettings};
|
||||||
use dns_test::name_server::NameServer;
|
use dns_test::name_server::NameServer;
|
||||||
use dns_test::record::{Record, RecordType};
|
use dns_test::record::{Record, RecordType};
|
||||||
use dns_test::zone_file::Root;
|
use dns_test::zone_file::Root;
|
||||||
@ -44,13 +44,9 @@ fn can_resolve() -> Result<()> {
|
|||||||
let resolver_ip_addr = resolver.ipv4_addr();
|
let resolver_ip_addr = resolver.ipv4_addr();
|
||||||
|
|
||||||
let client = Client::new(&network)?;
|
let client = Client::new(&network)?;
|
||||||
let output = client.dig(
|
|
||||||
Recurse::Yes,
|
let settings = *DigSettings::default().recurse();
|
||||||
Dnssec::No,
|
let output = client.dig(settings, resolver_ip_addr, RecordType::A, &needle_fqdn)?;
|
||||||
resolver_ip_addr,
|
|
||||||
RecordType::A,
|
|
||||||
&needle_fqdn,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
assert!(output.status.is_noerror());
|
assert!(output.status.is_noerror());
|
||||||
|
|
||||||
@ -94,13 +90,8 @@ fn nxdomain() -> Result<()> {
|
|||||||
let resolver_ip_addr = resolver.ipv4_addr();
|
let resolver_ip_addr = resolver.ipv4_addr();
|
||||||
|
|
||||||
let client = Client::new(&network)?;
|
let client = Client::new(&network)?;
|
||||||
let output = client.dig(
|
let settings = *DigSettings::default().recurse();
|
||||||
Recurse::Yes,
|
let output = client.dig(settings, resolver_ip_addr, RecordType::A, &needle_fqdn)?;
|
||||||
Dnssec::No,
|
|
||||||
resolver_ip_addr,
|
|
||||||
RecordType::A,
|
|
||||||
&needle_fqdn,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
assert!(dbg!(output).status.is_nxdomain());
|
assert!(dbg!(output).status.is_nxdomain());
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use dns_test::client::{Client, Dnssec, Recurse};
|
use dns_test::client::{Client, DigSettings};
|
||||||
use dns_test::name_server::NameServer;
|
use dns_test::name_server::NameServer;
|
||||||
use dns_test::record::RecordType;
|
use dns_test::record::RecordType;
|
||||||
use dns_test::tshark::{Capture, Direction};
|
use dns_test::tshark::{Capture, Direction};
|
||||||
@ -20,13 +20,8 @@ fn edns_support() -> Result<()> {
|
|||||||
let mut tshark = resolver.eavesdrop()?;
|
let mut tshark = resolver.eavesdrop()?;
|
||||||
|
|
||||||
let client = Client::new(network)?;
|
let client = Client::new(network)?;
|
||||||
let ans = client.dig(
|
let settings = *DigSettings::default().authentic_data().recurse();
|
||||||
Recurse::Yes,
|
let ans = client.dig(settings, resolver.ipv4_addr(), RecordType::SOA, &FQDN::ROOT)?;
|
||||||
Dnssec::Yes,
|
|
||||||
resolver.ipv4_addr(),
|
|
||||||
RecordType::SOA,
|
|
||||||
&FQDN::ROOT,
|
|
||||||
)?;
|
|
||||||
assert!(ans.status.is_servfail());
|
assert!(ans.status.is_servfail());
|
||||||
|
|
||||||
tshark.wait_for_capture()?;
|
tshark.wait_for_capture()?;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
use dns_test::client::{Client, Dnssec, Recurse};
|
use dns_test::client::{Client, DigSettings};
|
||||||
use dns_test::name_server::NameServer;
|
use dns_test::name_server::NameServer;
|
||||||
use dns_test::record::{Record, RecordType};
|
use dns_test::record::{Record, RecordType};
|
||||||
use dns_test::zone_file::Root;
|
use dns_test::zone_file::Root;
|
||||||
@ -31,13 +31,8 @@ fn can_validate_without_delegation() -> Result<()> {
|
|||||||
let resolver_addr = resolver.ipv4_addr();
|
let resolver_addr = resolver.ipv4_addr();
|
||||||
|
|
||||||
let client = Client::new(&network)?;
|
let client = Client::new(&network)?;
|
||||||
let output = client.dig(
|
let settings = *DigSettings::default().recurse().authentic_data();
|
||||||
Recurse::Yes,
|
let output = client.dig(settings, resolver_addr, RecordType::SOA, &FQDN::ROOT)?;
|
||||||
Dnssec::Yes,
|
|
||||||
resolver_addr,
|
|
||||||
RecordType::SOA,
|
|
||||||
&FQDN::ROOT,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
assert!(output.status.is_noerror());
|
assert!(output.status.is_noerror());
|
||||||
assert!(output.flags.authenticated_data);
|
assert!(output.flags.authenticated_data);
|
||||||
@ -103,19 +98,14 @@ fn can_validate_with_delegation() -> Result<()> {
|
|||||||
let resolver_addr = resolver.ipv4_addr();
|
let resolver_addr = resolver.ipv4_addr();
|
||||||
|
|
||||||
let client = Client::new(&network)?;
|
let client = Client::new(&network)?;
|
||||||
let output = client.dig(
|
let settings = *DigSettings::default().recurse().authentic_data();
|
||||||
Recurse::Yes,
|
let output = client.dig(settings, resolver_addr, RecordType::A, &needle_fqdn)?;
|
||||||
Dnssec::Yes,
|
|
||||||
resolver_addr,
|
|
||||||
RecordType::A,
|
|
||||||
&needle_fqdn,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
assert!(output.status.is_noerror());
|
assert!(output.status.is_noerror());
|
||||||
|
|
||||||
assert!(output.flags.authenticated_data);
|
assert!(output.flags.authenticated_data);
|
||||||
|
|
||||||
let [a, _rrsig] = output.answer.try_into().unwrap();
|
let [a] = output.answer.try_into().unwrap();
|
||||||
let a = a.try_into_a().unwrap();
|
let a = a.try_into_a().unwrap();
|
||||||
|
|
||||||
assert_eq!(needle_fqdn, a.fqdn);
|
assert_eq!(needle_fqdn, a.fqdn);
|
||||||
|
@ -53,16 +53,17 @@ impl Client {
|
|||||||
|
|
||||||
pub fn dig(
|
pub fn dig(
|
||||||
&self,
|
&self,
|
||||||
recurse: Recurse,
|
settings: DigSettings,
|
||||||
dnssec: Dnssec,
|
|
||||||
server: Ipv4Addr,
|
server: Ipv4Addr,
|
||||||
record_type: RecordType,
|
record_type: RecordType,
|
||||||
fqdn: &FQDN,
|
fqdn: &FQDN,
|
||||||
) -> Result<DigOutput> {
|
) -> Result<DigOutput> {
|
||||||
let output = self.inner.stdout(&[
|
let output = self.inner.stdout(&[
|
||||||
"dig",
|
"dig",
|
||||||
recurse.as_str(),
|
settings.rdflag(),
|
||||||
dnssec.as_str(),
|
settings.do_bit(),
|
||||||
|
settings.adflag(),
|
||||||
|
settings.cdflag(),
|
||||||
&format!("@{server}"),
|
&format!("@{server}"),
|
||||||
record_type.as_str(),
|
record_type.as_str(),
|
||||||
fqdn.as_str(),
|
fqdn.as_str(),
|
||||||
@ -72,32 +73,68 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Default)]
|
||||||
pub enum Dnssec {
|
pub struct DigSettings {
|
||||||
Yes,
|
adflag: bool,
|
||||||
No,
|
cdflag: bool,
|
||||||
|
dnssec: bool,
|
||||||
|
recurse: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dnssec {
|
impl DigSettings {
|
||||||
fn as_str(&self) -> &'static str {
|
/// Sets the AD bit in the query
|
||||||
match self {
|
pub fn authentic_data(&mut self) -> &mut Self {
|
||||||
Self::Yes => "+dnssec",
|
self.adflag = true;
|
||||||
Self::No => "+nodnssec",
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn adflag(&self) -> &'static str {
|
||||||
|
if self.adflag {
|
||||||
|
"+adflag"
|
||||||
|
} else {
|
||||||
|
"+noadflag"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
/// Sets the CD bit in the query
|
||||||
pub enum Recurse {
|
pub fn checking_disabled(&mut self) -> &mut Self {
|
||||||
Yes,
|
self.cdflag = true;
|
||||||
No,
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Recurse {
|
fn cdflag(&self) -> &'static str {
|
||||||
fn as_str(&self) -> &'static str {
|
if self.cdflag {
|
||||||
match self {
|
"+cdflag"
|
||||||
Self::Yes => "+recurse",
|
} else {
|
||||||
Self::No => "+norecurse",
|
"+nocdflag"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the DO bit in the query
|
||||||
|
pub fn dnssec(&mut self) -> &mut Self {
|
||||||
|
self.dnssec = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_bit(&self) -> &'static str {
|
||||||
|
if self.dnssec {
|
||||||
|
"+dnssec"
|
||||||
|
} else {
|
||||||
|
"+nodnssec"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the RD bit in the query
|
||||||
|
pub fn recurse(&mut self) -> &mut Self {
|
||||||
|
self.recurse = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rdflag(&self) -> &'static str {
|
||||||
|
if self.recurse {
|
||||||
|
"+recurse"
|
||||||
|
} else {
|
||||||
|
"+norecurse"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,11 +221,12 @@ impl FromStr for DigOutput {
|
|||||||
|
|
||||||
#[derive(Debug, Default, PartialEq)]
|
#[derive(Debug, Default, PartialEq)]
|
||||||
pub struct DigFlags {
|
pub struct DigFlags {
|
||||||
pub qr: bool,
|
|
||||||
pub recursion_desired: bool,
|
|
||||||
pub recursion_available: bool,
|
|
||||||
pub authoritative_answer: bool,
|
|
||||||
pub authenticated_data: bool,
|
pub authenticated_data: bool,
|
||||||
|
pub authoritative_answer: bool,
|
||||||
|
pub checking_disabled: bool,
|
||||||
|
pub qr: bool,
|
||||||
|
pub recursion_available: bool,
|
||||||
|
pub recursion_desired: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for DigFlags {
|
impl FromStr for DigFlags {
|
||||||
@ -200,6 +238,7 @@ impl FromStr for DigFlags {
|
|||||||
let mut recursion_available = false;
|
let mut recursion_available = false;
|
||||||
let mut authoritative_answer = false;
|
let mut authoritative_answer = false;
|
||||||
let mut authenticated_data = false;
|
let mut authenticated_data = false;
|
||||||
|
let mut checking_disabled = false;
|
||||||
|
|
||||||
for flag in input.split_whitespace() {
|
for flag in input.split_whitespace() {
|
||||||
match flag {
|
match flag {
|
||||||
@ -208,16 +247,18 @@ impl FromStr for DigFlags {
|
|||||||
"ra" => recursion_available = true,
|
"ra" => recursion_available = true,
|
||||||
"aa" => authoritative_answer = true,
|
"aa" => authoritative_answer = true,
|
||||||
"ad" => authenticated_data = true,
|
"ad" => authenticated_data = true,
|
||||||
|
"cd" => checking_disabled = true,
|
||||||
_ => return Err(format!("unknown flag: {flag}").into()),
|
_ => return Err(format!("unknown flag: {flag}").into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
qr,
|
|
||||||
recursion_desired,
|
|
||||||
recursion_available,
|
|
||||||
authoritative_answer,
|
|
||||||
authenticated_data,
|
authenticated_data,
|
||||||
|
authoritative_answer,
|
||||||
|
checking_disabled,
|
||||||
|
qr,
|
||||||
|
recursion_available,
|
||||||
|
recursion_desired,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,7 @@ fn nsd_conf(fqdn: &FQDN) -> String {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::client::{Client, Dnssec, Recurse};
|
use crate::client::{Client, DigSettings};
|
||||||
use crate::record::RecordType;
|
use crate::record::RecordType;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -307,13 +307,7 @@ mod tests {
|
|||||||
let ip_addr = tld_ns.ipv4_addr();
|
let ip_addr = tld_ns.ipv4_addr();
|
||||||
|
|
||||||
let client = Client::new(&network)?;
|
let client = Client::new(&network)?;
|
||||||
let output = client.dig(
|
let output = client.dig(DigSettings::default(), ip_addr, RecordType::SOA, &FQDN::COM)?;
|
||||||
Recurse::No,
|
|
||||||
Dnssec::No,
|
|
||||||
ip_addr,
|
|
||||||
RecordType::SOA,
|
|
||||||
&FQDN::COM,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
assert!(output.status.is_noerror());
|
assert!(output.status.is_noerror());
|
||||||
|
|
||||||
@ -338,8 +332,7 @@ mod tests {
|
|||||||
|
|
||||||
let client = Client::new(&network)?;
|
let client = Client::new(&network)?;
|
||||||
let output = client.dig(
|
let output = client.dig(
|
||||||
Recurse::No,
|
DigSettings::default(),
|
||||||
Dnssec::No,
|
|
||||||
ipv4_addr,
|
ipv4_addr,
|
||||||
RecordType::NS,
|
RecordType::NS,
|
||||||
&FQDN::COM,
|
&FQDN::COM,
|
||||||
@ -364,13 +357,8 @@ mod tests {
|
|||||||
let ns_addr = tld_ns.ipv4_addr();
|
let ns_addr = tld_ns.ipv4_addr();
|
||||||
|
|
||||||
let client = Client::new(&network)?;
|
let client = Client::new(&network)?;
|
||||||
let output = client.dig(
|
let settings = *DigSettings::default().dnssec();
|
||||||
Recurse::No,
|
let output = client.dig(settings, ns_addr, RecordType::SOA, &FQDN::ROOT)?;
|
||||||
Dnssec::Yes,
|
|
||||||
ns_addr,
|
|
||||||
RecordType::SOA,
|
|
||||||
&FQDN::ROOT,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
assert!(output.status.is_noerror());
|
assert!(output.status.is_noerror());
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ struct Ip {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::client::{Client, Dnssec, Recurse};
|
use crate::client::{Client, DigSettings};
|
||||||
use crate::name_server::NameServer;
|
use crate::name_server::NameServer;
|
||||||
use crate::record::{Record, RecordType};
|
use crate::record::{Record, RecordType};
|
||||||
use crate::zone_file::Root;
|
use crate::zone_file::Root;
|
||||||
@ -260,8 +260,7 @@ mod tests {
|
|||||||
|
|
||||||
let client = Client::new(network)?;
|
let client = Client::new(network)?;
|
||||||
let resp = client.dig(
|
let resp = client.dig(
|
||||||
Recurse::No,
|
DigSettings::default(),
|
||||||
Dnssec::No,
|
|
||||||
ns.ipv4_addr(),
|
ns.ipv4_addr(),
|
||||||
RecordType::SOA,
|
RecordType::SOA,
|
||||||
&FQDN::ROOT,
|
&FQDN::ROOT,
|
||||||
@ -322,13 +321,8 @@ mod tests {
|
|||||||
let resolver_addr = resolver.ipv4_addr();
|
let resolver_addr = resolver.ipv4_addr();
|
||||||
|
|
||||||
let client = Client::new(network)?;
|
let client = Client::new(network)?;
|
||||||
let output = client.dig(
|
let settings = *DigSettings::default().recurse();
|
||||||
Recurse::Yes,
|
let output = client.dig(settings, dbg!(resolver_addr), RecordType::A, root_ns.fqdn())?;
|
||||||
Dnssec::No,
|
|
||||||
dbg!(resolver_addr),
|
|
||||||
RecordType::A,
|
|
||||||
root_ns.fqdn(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
assert!(output.status.is_noerror());
|
assert!(output.status.is_noerror());
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user