cdns_rs/a_sync/
request.rs1use std::collections::VecDeque;
25use std::net::IpAddr;
26use std::sync::Arc;
27
28use crate::error::*;
29use crate::internal_error;
30
31use super::caches::CACHE;
32use super::query::QDns;
33use super::{QuerySetup, QDnsQueriesRes, ResolveConfig};
34use super::common::{QType, DnsRdata, DnsSoa};
35
36pub async
51fn resolve_fqdn<C>(fqdn: C, custom_resolv: Option<Arc<ResolveConfig>>) -> CDnsResult<Vec<IpAddr>>
52where C: AsRef<str>
53{
54 let resolvers =
55 custom_resolv.map_or(CACHE.clone_resolve_list().await?, |f| f);
56
57 let dns =
59 QDns::make_a_aaaa_request(resolvers, fqdn.as_ref(), QuerySetup::default());
60
61 let res = dns.query().await;
63
64 let mut iplist: Vec<IpAddr> = vec![];
66
67 match res
68 {
69 QDnsQueriesRes::DnsOk{ res } =>
70 {
71 for r in res
72 {
73 if r.is_ok() == false
74 {
75 continue;
77 }
78
79 for dnsr in r.get_responses()
80 {
81 match dnsr.rdata
82 {
83 DnsRdata::A{ ip } => iplist.push(IpAddr::from(ip)),
84 DnsRdata::AAAA{ ip } => iplist.push(IpAddr::from(ip)),
85 _ => continue,
86 }
87 }
88 }
89 },
90 QDnsQueriesRes::DnsNotAvailable =>
91 {
92 internal_error!(CDnsErrorType::DnsNotAvailable, "");
93 }
94 }
95
96 return Ok(iplist);
97}
98
99pub async
115fn resolve_mx<C>(fqdn: C, custom_resolv: Option<Arc<ResolveConfig>>) -> CDnsResult<Vec<String>>
116where C: AsRef<str>
117{
118 let resolvers =
119 custom_resolv.map_or(CACHE.clone_resolve_list().await?, |f| f);
120
121 let mut dns_req =
122 QDns::make_empty(resolvers, 1, QuerySetup::default());
123
124 dns_req.add_request(QType::MX, fqdn.as_ref());
125
126 let res = dns_req.query().await;
128
129 let mut mxlist: VecDeque<(u16, String)> = VecDeque::with_capacity(5);
131
132 match res
133 {
134 QDnsQueriesRes::DnsOk{ res } =>
135 {
136 for r in res
137 {
138 if r.is_ok() == false
139 {
140 continue;
142 }
143
144 for dnsr in r.get_responses()
145 {
146 match dnsr.rdata
147 {
148 DnsRdata::MX{ ref preference, ref exchange } =>
149 {
150 let mut index: usize = 0;
152
153 for (pref, _) in mxlist.iter()
154 {
155 if *pref >= *preference
156 {
157 break;
158 }
159
160 index += 1;
161 }
162
163 if index == mxlist.len()
164 {
165 mxlist.push_back((*preference, exchange.clone()));
167 }
168 else
169 {
170 mxlist.insert(index, (*preference, exchange.clone()));
171 }
172 }
173 _ => continue,
174 }
175 }
176 }
177 },
178 QDnsQueriesRes::DnsNotAvailable =>
179 {
180 internal_error!(CDnsErrorType::DnsNotAvailable, "");
181 }
182 }
183
184 return Ok(mxlist.into_iter().map( |(_, ip)| ip).collect());
185}
186
187pub async
202fn resolve_soa<C>(fqdn: C, custom_resolv: Option<Arc<ResolveConfig>>) -> CDnsResult<Vec<DnsSoa>>
203where C: AsRef<str>
204{
205 let resolvers =
206 custom_resolv.map_or(CACHE.clone_resolve_list().await?, |f| f);
207
208 let mut dns_req =
209 QDns::make_empty(resolvers, 1, QuerySetup::default());
210
211 dns_req.add_request(QType::SOA, fqdn.as_ref());
212
213 let res = dns_req.query().await;
215
216 let mut soa_list: Vec<DnsSoa> = Vec::new();
217
218 match res
219 {
220 QDnsQueriesRes::DnsOk{ res } =>
221 {
222 for r in res
223 {
224 if r.is_ok() == false
225 {
226 continue;
228 }
229
230 for dnsr in r.move_responses()
231 {
232 match dnsr.rdata
233 {
234 DnsRdata::SOA{ soa } =>
235 {
236 soa_list.push(soa);
237 },
238 _ => {}
239 }
240 }
241 }
242 },
243 QDnsQueriesRes::DnsNotAvailable => {}
244 }
245
246 return Ok(soa_list);
247}
248
249pub async
264fn resolve_reverse<C>(ipaddr: C, custom_resolv: Option<Arc<ResolveConfig>>) -> CDnsResult<Vec<String>>
265where C: AsRef<str>
266{
267 let resolvers =
268 custom_resolv.map_or(CACHE.clone_resolve_list().await?, |f| f);
269
270 let mut dns_req =
271 QDns::make_empty(resolvers, 1, QuerySetup::default());
272
273 dns_req.add_request(QType::PTR, ipaddr.as_ref());
274
275 let res = dns_req.query().await;
277
278 let mut ptr_list: Vec<String> = Vec::new();
279
280 match res
281 {
282 QDnsQueriesRes::DnsOk{ res } =>
283 {
284 for r in res
285 {
286 if r.is_ok() == false
287 {
288 continue;
290 }
291
292 for dnsr in r.move_responses()
293 {
294 match dnsr.rdata
295 {
296 DnsRdata::PTR{ fqdn } =>
297 {
298 ptr_list.push(fqdn);
299 },
300 _ => {}
301 }
302 }
303 }
304 },
305 QDnsQueriesRes::DnsNotAvailable => {}
306 }
307
308 return Ok(ptr_list);
309}
310
311#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
312async fn test_mx_resolve()
313{
314 let mx_doms = resolve_mx("protonmail.com", None).await;
315
316 assert_eq!(mx_doms.is_err(), false);
317
318 let mx_doms = mx_doms.unwrap();
319
320 let mut index = 0;
321 for di in mx_doms
322 {
323 match index
324 {
325 0 => assert_eq!(di.as_str(), "mail.protonmail.ch"),
326 1 => assert_eq!(di.as_str(), "mailsec.protonmail.ch"),
327 _ => panic!("test is required to be modified")
328 }
329
330 index += 1;
331
332 println!("{}", di);
333 }
334
335}
336
337
338#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
339async fn test_a_aaaa_resolve()
340{
341 let a_aaaa = resolve_fqdn("protonmail.com", None).await;
342
343 assert_eq!(a_aaaa.is_ok(), true);
344
345 let a_aaaa = a_aaaa.unwrap();
346
347 for di in a_aaaa
348 {
349 println!("{}", di);
350 }
351
352}
353
354#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
355async fn test_ptr_resolve_fail()
356{
357 let ptr = resolve_reverse("protonmail.com", None).await;
358
359 assert_eq!(ptr.is_ok(), true);
360
361 let ptr = ptr.unwrap();
362
363 assert_eq!(ptr.len(), 0);
364
365}