diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a438b1c8..c9545655e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Fixed +- Reverse DNS lookup not working in reports ([#509](https://github.com/fujiapple852/trippy/issues/509)) + ## [0.8.0] - 2023-05-15 ### Added diff --git a/src/dns.rs b/src/dns.rs index 8d4ca30d1..c528ff4c0 100644 --- a/src/dns.rs +++ b/src/dns.rs @@ -114,12 +114,27 @@ impl DnsResolver { }) } - /// Resolve a DNS hostname to IP addresses. + /// Perform a blocking DNS hostname lookup and return a vector of IP addresses. pub fn lookup(&self, hostname: &str) -> anyhow::Result> { self.inner.lookup(hostname) } - /// Perform a non-blocking reverse DNS lookup of `IpAddr` and return a `DnsEntry`. + /// Perform a blocking reverse DNS lookup of `IpAddr` and return a `DnsEntry`. + /// + /// As this method is blocking it will never return a `DnsEntry::Pending`. + pub fn reverse_lookup(&self, addr: IpAddr) -> DnsEntry { + self.inner.reverse_lookup(addr, false, false) + } + + /// Perform a blocking reverse DNS lookup of `IpAddr` and return a `DnsEntry` with `AS` information. + /// + /// See [`DnsResolver::reverse_lookup`] + #[allow(dead_code)] + pub fn reverse_lookup_with_asinfo(&self, addr: IpAddr) -> DnsEntry { + self.inner.reverse_lookup(addr, true, false) + } + + /// Perform a lazy reverse DNS lookup of `IpAddr` and return a `DnsEntry`. /// /// If the `IpAddr` has already been resolved then `DnsEntry::Resolved` is returned immediately. /// @@ -129,15 +144,15 @@ impl DnsResolver { /// If the entry exists but is `DnsEntry::Timeout` then it is changed to be `DnsEntry::Pending` and enqueued. /// /// If enqueuing times out then the entry is changed to be `DnsEntry::Timeout` and returned. - pub fn reverse_lookup(&self, addr: IpAddr) -> DnsEntry { - self.inner.reverse_lookup(addr, false) + pub fn lazy_reverse_lookup(&self, addr: IpAddr) -> DnsEntry { + self.inner.reverse_lookup(addr, false, true) } - /// Perform a non-blocking reverse DNS lookup of `IpAddr` and return a `DnsEntry` with `AS` information. + /// Perform a lazy reverse DNS lookup of `IpAddr` and return a `DnsEntry` with `AS` information. /// - /// See [`DnsResolver::reverse_lookup`] - pub fn reverse_lookup_with_asinfo(&self, addr: IpAddr) -> DnsEntry { - self.inner.reverse_lookup(addr, true) + /// See [`DnsResolver::lazy_reverse_lookup`] + pub fn lazy_reverse_lookup_with_asinfo(&self, addr: IpAddr) -> DnsEntry { + self.inner.reverse_lookup(addr, true, true) } /// Get the `DnsResolverConfig`. @@ -252,7 +267,15 @@ mod inner { } } - pub fn reverse_lookup(&self, addr: IpAddr, with_asinfo: bool) -> DnsEntry { + pub fn reverse_lookup(&self, addr: IpAddr, with_asinfo: bool, lazy: bool) -> DnsEntry { + if lazy { + self.lazy_reverse_lookup(addr, with_asinfo) + } else { + reverse_lookup(&self.provider, addr, with_asinfo) + } + } + + fn lazy_reverse_lookup(&self, addr: IpAddr, with_asinfo: bool) -> DnsEntry { let mut enqueue = false; // Check if we have already attempted to resolve this `IpAddr` and return the current `DnsEntry` if so, @@ -319,47 +342,52 @@ mod inner { cache: &Cache, ) { for DnsResolveRequest { addr, with_asinfo } in rx { - let entry = match &provider { - DnsProvider::DnsLookup => { - // we can't distinguish between a failed lookup or a genuine error and so we just assume all - // failures are `DnsEntry::NotFound`. - match dns_lookup::lookup_addr(&addr) { - Ok(dns) => DnsEntry::Resolved(Resolved::Normal(addr, vec![dns])), - Err(_) => DnsEntry::NotFound(Unresolved::Normal(addr)), + cache + .write() + .insert(addr, reverse_lookup(provider, addr, with_asinfo)); + } + } + + fn reverse_lookup(provider: &DnsProvider, addr: IpAddr, with_asinfo: bool) -> DnsEntry { + match &provider { + DnsProvider::DnsLookup => { + // we can't distinguish between a failed lookup or a genuine error and so we just assume all + // failures are `DnsEntry::NotFound`. + match dns_lookup::lookup_addr(&addr) { + Ok(dns) => DnsEntry::Resolved(Resolved::Normal(addr, vec![dns])), + Err(_) => DnsEntry::NotFound(Unresolved::Normal(addr)), + } + } + DnsProvider::TrustDns(resolver) => match resolver.reverse_lookup(addr) { + Ok(name) => { + let hostnames = name + .into_iter() + .map(|mut s| { + s.set_fqdn(false); + s + }) + .map(|s| s.to_string()) + .collect(); + if with_asinfo { + let as_info = lookup_asinfo(resolver, addr).unwrap_or_default(); + DnsEntry::Resolved(Resolved::WithAsInfo(addr, hostnames, as_info)) + } else { + DnsEntry::Resolved(Resolved::Normal(addr, hostnames)) } } - DnsProvider::TrustDns(resolver) => match resolver.reverse_lookup(addr) { - Ok(name) => { - let hostnames = name - .into_iter() - .map(|mut s| { - s.set_fqdn(false); - s - }) - .map(|s| s.to_string()) - .collect(); + Err(err) => match err.kind() { + ResolveErrorKind::NoRecordsFound { .. } => { if with_asinfo { let as_info = lookup_asinfo(resolver, addr).unwrap_or_default(); - DnsEntry::Resolved(Resolved::WithAsInfo(addr, hostnames, as_info)) + DnsEntry::NotFound(Unresolved::WithAsInfo(addr, as_info)) } else { - DnsEntry::Resolved(Resolved::Normal(addr, hostnames)) + DnsEntry::NotFound(Unresolved::Normal(addr)) } } - Err(err) => match err.kind() { - ResolveErrorKind::NoRecordsFound { .. } => { - if with_asinfo { - let as_info = lookup_asinfo(resolver, addr).unwrap_or_default(); - DnsEntry::NotFound(Unresolved::WithAsInfo(addr, as_info)) - } else { - DnsEntry::NotFound(Unresolved::Normal(addr)) - } - } - ResolveErrorKind::Timeout => DnsEntry::Timeout(addr), - _ => DnsEntry::Failed(addr), - }, + ResolveErrorKind::Timeout => DnsEntry::Timeout(addr), + _ => DnsEntry::Failed(addr), }, - }; - cache.write().insert(addr, entry); + }, } } diff --git a/src/frontend/render/header.rs b/src/frontend/render/header.rs index 454dabdd4..303fcd8f8 100644 --- a/src/frontend/render/header.rs +++ b/src/frontend/render/header.rs @@ -101,7 +101,9 @@ pub fn render(f: &mut Frame<'_, B>, app: &mut TuiApp, rect: Rect) { /// Render the source address of the trace. fn render_source(app: &mut TuiApp) -> String { - let src_hostname = app.resolver.reverse_lookup(app.tracer_config().source_addr); + let src_hostname = app + .resolver + .lazy_reverse_lookup(app.tracer_config().source_addr); let src_addr = app.tracer_config().source_addr; match app.tracer_config().port_direction { PortDirection::None => { diff --git a/src/frontend/render/table.rs b/src/frontend/render/table.rs index 5a0cc3d92..2c6683ca1 100644 --- a/src/frontend/render/table.rs +++ b/src/frontend/render/table.rs @@ -234,19 +234,19 @@ fn format_address( AddressMode::IP => addr.to_string(), AddressMode::Host => { if config.lookup_as_info { - let entry = dns.reverse_lookup_with_asinfo(*addr); + let entry = dns.lazy_reverse_lookup_with_asinfo(*addr); format_dns_entry(entry, true, config.as_mode) } else { - let entry = dns.reverse_lookup(*addr); + let entry = dns.lazy_reverse_lookup(*addr); format_dns_entry(entry, false, config.as_mode) } } AddressMode::Both => { let hostname = if config.lookup_as_info { - let entry = dns.reverse_lookup_with_asinfo(*addr); + let entry = dns.lazy_reverse_lookup_with_asinfo(*addr); format_dns_entry(entry, true, config.as_mode) } else { - let entry = dns.reverse_lookup(*addr); + let entry = dns.lazy_reverse_lookup(*addr); format_dns_entry(entry, false, config.as_mode) }; format!("{hostname} ({addr})") @@ -360,7 +360,7 @@ fn format_details( let geoip = geoip_lookup.lookup(*addr).unwrap_or_default(); if config.lookup_as_info { - let dns_entry = dns.reverse_lookup_with_asinfo(*addr); + let dns_entry = dns.lazy_reverse_lookup_with_asinfo(*addr); match dns_entry { DnsEntry::Pending(addr) => { let details = fmt_details_with_asn(addr, index, count, None, None, geoip); @@ -388,7 +388,7 @@ fn format_details( | DnsEntry::NotFound(Unresolved::Normal(_)) => unreachable!(), } } else { - let dns_entry = dns.reverse_lookup(*addr); + let dns_entry = dns.lazy_reverse_lookup(*addr); match dns_entry { DnsEntry::Pending(addr) => { let details = fmt_details_no_asn(addr, index, count, None, geoip);