-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d181fbc
commit 594b11d
Showing
2 changed files
with
133 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
//! The lookup command of _dnsi._ | ||
|
||
use crate::error::Error; | ||
use domain::base::name::UncertainName; | ||
use domain::resolv::stub::StubResolver; | ||
use std::net::IpAddr; | ||
use std::str::FromStr; | ||
|
||
//------------ Lookup -------------------------------------------------------- | ||
|
||
#[derive(Clone, Debug, clap::Args)] | ||
pub struct Lookup { | ||
/// The host or address to look up. | ||
#[arg(value_name = "HOST_OR_ADDR")] | ||
names: Vec<ServerName>, | ||
} | ||
|
||
/// # Executing the command | ||
/// | ||
impl Lookup { | ||
pub fn execute(self) -> Result<(), Error> { | ||
tokio::runtime::Builder::new_multi_thread() | ||
.enable_all() | ||
.build() | ||
.unwrap() | ||
.block_on(self.async_execute()) | ||
} | ||
|
||
pub async fn async_execute(self) -> Result<(), Error> { | ||
let resolver = StubResolver::new(); | ||
|
||
let mut res = Ok(()); | ||
let mut names = self.names.iter(); | ||
|
||
if let Some(name) = names.next() { | ||
res = res.and(self.execute_one_name(&resolver, name).await); | ||
} | ||
|
||
for name in names { | ||
println!(); | ||
res = res.and(self.execute_one_name(&resolver, name).await); | ||
} | ||
|
||
res.map_err(|_| "not all lookups have succeeded".into()) | ||
} | ||
|
||
async fn execute_one_name(&self, resolver: &StubResolver, name: &ServerName) -> Result<(), ()> { | ||
let res = match name { | ||
ServerName::Name(host) => forward(&resolver, host).await, | ||
Check failure on line 49 in src/commands/lookup.rs GitHub Actions / test (ubuntu-latest, stable)
|
||
ServerName::Addr(addr) => reverse(&resolver, *addr).await, | ||
Check failure on line 50 in src/commands/lookup.rs GitHub Actions / test (ubuntu-latest, stable)
|
||
}; | ||
|
||
if let Err(err) = res { | ||
eprintln!("{err}"); | ||
return Err(()); | ||
} | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
async fn forward(resolver: &StubResolver, name: &UncertainName<Vec<u8>>) -> Result<(), Error> { | ||
let answer = match name { | ||
UncertainName::Absolute(ref name) => resolver.lookup_host(name).await?, | ||
UncertainName::Relative(ref name) => resolver.search_host(name).await?, | ||
}; | ||
|
||
print!("{name}"); | ||
|
||
let canon = answer.canonical_name(); | ||
if canon != answer.qname() { | ||
print!(" (alias for {canon})"); | ||
} | ||
|
||
println!(); | ||
|
||
if answer.is_empty() { | ||
println!(" <no addresses found>"); | ||
return Ok(()); | ||
} | ||
|
||
for addr in answer.iter() { | ||
println!(" {addr}"); | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
async fn reverse(resolver: &StubResolver, addr: IpAddr) -> Result<(), Error> { | ||
let answer = resolver.lookup_addr(addr).await?; | ||
println!("{addr}"); | ||
|
||
// Little workaround for not having an is_empty method on FoundAddrs | ||
let mut answer = answer.iter().peekable(); | ||
let is_empty = answer.peek().is_none(); | ||
if is_empty { | ||
println!(" <no hosts found>"); | ||
return Ok(()); | ||
} | ||
|
||
for name in answer { | ||
println!(" {name}"); | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
//------------ ServerName --------------------------------------------------- | ||
|
||
#[derive(Clone, Debug)] | ||
enum ServerName { | ||
Name(UncertainName<Vec<u8>>), | ||
Addr(IpAddr), | ||
} | ||
|
||
impl FromStr for ServerName { | ||
type Err = &'static str; | ||
|
||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
if let Ok(addr) = IpAddr::from_str(s) { | ||
Ok(ServerName::Addr(addr)) | ||
} else { | ||
UncertainName::from_str(s) | ||
.map(Self::Name) | ||
.map_err(|_| "illegal host name or address") | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters