domain/resolv/lookup/
addr.rs1use crate::base::iana::Rtype;
4use crate::base::message::RecordIter;
5use crate::base::name::{Name, ParsedName};
6use crate::rdata::Ptr;
7use crate::resolv::resolver::Resolver;
8use octseq::octets::Octets;
9use std::io;
10use std::net::IpAddr;
11
12type Octets128 = octseq::array::Array<128>;
15
16pub async fn lookup_addr<R: Resolver>(
27 resolv: &R,
28 addr: IpAddr,
29) -> Result<FoundAddrs<R>, io::Error> {
30 let name = Name::<Octets128>::reverse_from_addr(addr)
31 .expect("address domain name too long");
32 resolv.query((name, Rtype::PTR)).await.map(FoundAddrs)
33}
34
35pub struct FoundAddrs<R: Resolver>(R::Answer);
42
43impl<R: Resolver> FoundAddrs<R> {
44 pub fn iter(&self) -> FoundAddrsIter<'_, R::Octets>
46 where
47 R::Octets: Octets,
48 {
49 FoundAddrsIter {
50 name: self.0.as_ref().canonical_name(),
51 answer: {
52 self.0
53 .as_ref()
54 .answer()
55 .ok()
56 .map(|sec| sec.limit_to::<Ptr<_>>())
57 },
58 }
59 }
60}
61
62impl<'a, R: Resolver> IntoIterator for &'a FoundAddrs<R>
63where
64 R::Octets: Octets,
65{
66 type Item = ParsedName<<<R as Resolver>::Octets as Octets>::Range<'a>>;
67 type IntoIter = FoundAddrsIter<'a, R::Octets>;
68
69 fn into_iter(self) -> Self::IntoIter {
70 self.iter()
71 }
72}
73
74pub struct FoundAddrsIter<'a, Octs: Octets> {
78 name: Option<ParsedName<Octs::Range<'a>>>,
79 answer: Option<RecordIter<'a, Octs, Ptr<ParsedName<Octs::Range<'a>>>>>,
80}
81
82impl<'a, Octs: Octets> Iterator for FoundAddrsIter<'a, Octs> {
83 type Item = ParsedName<Octs::Range<'a>>;
84
85 fn next(&mut self) -> Option<Self::Item> {
86 let name = self.name.as_ref()?;
87 let answer = self.answer.as_mut()?;
88 while let Some(Ok(record)) = answer.next() {
89 if record.owner() == name {
90 return Some(record.into_data().into_ptrdname());
91 }
92 }
93 None
94 }
95}