use std::env; use std::net::IpAddr; use std::str::FromStr; use domain::base::name::UncertainDname; use domain_resolv::StubResolver; async fn forward( resolver: &StubResolver, name: UncertainDname>, ) { 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 [...]"); 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); } } }