use domain::base::name::UncertainDname;
use domain::resolv::StubResolver;
use std::env;
use std::net::IpAddr;
use std::str::FromStr;
async fn forward(resolver: &StubResolver, name: UncertainDname<Vec<u8>>) {
let answer = match name {
UncertainDname::Absolute(ref name) => {
resolver.lookup_host(name).await
}
UncertainDname::Relative(ref name) => {
resolver.search_host(name).await
}
};
match answer {
Ok(answer) => {
if let UncertainDname::Relative(_) = name {
println!("Found answer for {}", answer.qname());
}
let canon = answer.canonical_name();
if canon != answer.qname() {
println!("{} is an alias for {}", answer.qname(), canon);
}
for addr in answer.iter() {
println!("{} has address {}", canon, addr);
}
}
Err(err) => {
println!("Query failed: {}", err);
}
}
}
async fn reverse(resolver: &StubResolver, addr: IpAddr) {
match resolver.lookup_addr(addr).await {
Ok(answer) => {
for name in answer.iter() {
println!("Host {} has domain name pointer {}", addr, name);
}
}
Err(err) => println!("Query failed: {}", err),
}
}
#[tokio::main]
async fn main() {
let names: Vec<_> = env::args().skip(1).collect();
if names.is_empty() {
println!("Usage: lookup <hostname_or_addr> [...]");
return;
}
let resolver = StubResolver::new();
for name in names {
if let Ok(addr) = IpAddr::from_str(&name) {
reverse(&resolver, addr).await;
} else if let Ok(name) = UncertainDname::from_str(&name) {
forward(&resolver, name).await;
} else {
println!("Not a domain name: {}", name);
}
}
}