async_traceroute/traceroute/utils/
dns.rs

1use std::net::IpAddr;
2
3use domain::base::Name;
4use domain::resolv::lookup::lookup_host;
5use domain::resolv::stub::StubResolver;
6
7pub async fn dns_lookup(hostname: &str) -> Option<Vec<IpAddr>> {
8    let hostname = match Name::bytes_from_str(hostname) {
9        Ok(hostname) => hostname,
10        Err(_) => return None,
11    };
12
13    let stub_resolver = StubResolver::new();
14
15
16    match lookup_host(&&stub_resolver, hostname).await {
17        Ok(answers) => {
18            let ip_addrs: Vec<_> = answers
19                .iter()
20                .collect();
21            
22            if ip_addrs.is_empty() { None } else { Some(ip_addrs) }
23        }
24        Err(_) => None,
25    }
26}
27
28pub async fn dns_lookup_first_ipv4_addr(hostname: &str) -> Option<IpAddr> {
29    if let Some(ip_addrs) = dns_lookup(hostname).await {
30        for ip_addr in ip_addrs.iter() {
31            if ip_addr.is_ipv4() {
32                return Some(*ip_addr)
33            }
34        }
35    }
36    
37    None
38}
39
40pub async fn reverse_dns_lookup(ip_address: &IpAddr) -> Option<Vec<String>> {
41    let resolver = StubResolver::new();
42    match resolver.lookup_addr(*ip_address).await {
43        Ok(addrs) => {
44            let hostnames: Vec<_> = addrs.into_iter()
45                .map(|addr| addr.to_string())
46                .collect();
47            
48            if hostnames.is_empty() { None } else { Some(hostnames) }
49        },
50        Err(_) => None
51    }
52}
53
54pub async fn reverse_dns_lookup_first_hostname(ip_address: &IpAddr) -> Option<String> {
55    reverse_dns_lookup(ip_address)
56        .await
57        .map(|hostnames|
58                hostnames.first()
59                    .expect("hostnames should contain at least one hostname")
60                    .to_string())
61}