1use 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
49fn resolve_fqdn<C>(fqdn: C, custom_resolv: Option<Arc<ResolveConfig>>) -> CDnsResult<Vec<IpAddr>>
50where C: AsRef<str>
51{
52 let resolvers =
53 custom_resolv.map_or(CACHE.clone_resolve_list()?, |f| f);
54
55 let dns = QDns::make_a_aaaa_request(resolvers, fqdn.as_ref(), QuerySetup::default())?;
57
58 let res = dns.query();
60
61 let mut iplist: Vec<IpAddr> = vec![];
63
64 match res
65 {
66 QDnsQueriesRes::DnsOk{ res } =>
67 {
68 for r in res
69 {
70 if r.is_ok() == false
71 {
72 continue;
74 }
75
76 for dnsr in r.get_responses()
77 {
78 match dnsr.rdata
79 {
80 DnsRdata::A{ ip } => iplist.push(IpAddr::from(ip)),
81 DnsRdata::AAAA{ ip } => iplist.push(IpAddr::from(ip)),
82 _ => continue,
83 }
84 }
85 }
86 },
87 QDnsQueriesRes::DnsNotAvailable =>
88 {
89 internal_error!(CDnsErrorType::DnsNotAvailable, "");
90 }
91 }
92
93 return Ok(iplist);
94}
95
96pub
110fn resolve_mx<C>(fqdn: C, custom_resolv: Option<Arc<ResolveConfig>>) -> CDnsResult<Vec<String>>
111where C: AsRef<str>
112{
113 let resolvers =
114 custom_resolv.map_or(CACHE.clone_resolve_list()?, |f| f);
115
116 let mut dns_req =
117 QDns::make_empty(resolvers, 1, QuerySetup::default());
118
119 dns_req.add_request(QType::MX, fqdn.as_ref());
120
121 let res = dns_req.query();
123
124 let mut mxlist: VecDeque<(u16, String)> = VecDeque::with_capacity(5);
126
127 match res
128 {
129 QDnsQueriesRes::DnsOk{ res } =>
130 {
131 for r in res
132 {
133 if r.is_ok() == false
134 {
135 continue;
137 }
138
139 for dnsr in r.get_responses()
140 {
141 match dnsr.rdata
142 {
143 DnsRdata::MX{ ref preference, ref exchange } =>
144 {
145 let mut index: usize = 0;
147
148 for (pref, _) in mxlist.iter()
149 {
150 if *pref >= *preference
151 {
152 break;
153 }
154
155 index += 1;
156 }
157
158 if index == mxlist.len()
159 {
160 mxlist.push_back((*preference, exchange.clone()));
162 }
163 else
164 {
165 mxlist.insert(index, (*preference, exchange.clone()));
166 }
167 }
168 _ => continue,
169 }
170 }
171 }
172 },
173 QDnsQueriesRes::DnsNotAvailable =>
174 {
175 internal_error!(CDnsErrorType::DnsNotAvailable, "");
176 }
177 }
178
179 return Ok(mxlist.into_iter().map( |(_, ip)| ip).collect());
180}
181
182pub
195fn resolve_soa<C>(fqdn: C, custom_resolv: Option<Arc<ResolveConfig>>) -> CDnsResult<Vec<DnsSoa>>
196where C: AsRef<str>
197{
198 let resolvers =
199 custom_resolv.map_or(CACHE.clone_resolve_list()?, |f| f);
200
201 let mut dns_req =
202 QDns::make_empty(resolvers, 1, QuerySetup::default());
203
204 dns_req.add_request(QType::SOA, fqdn.as_ref());
205
206 let res = dns_req.query();
208
209 let mut soa_list: Vec<DnsSoa> = Vec::new();
210
211 match res
212 {
213 QDnsQueriesRes::DnsOk{ res } =>
214 {
215 for r in res
216 {
217 if r.is_ok() == false
218 {
219 continue;
221 }
222
223 for dnsr in r.move_responses()
224 {
225 match dnsr.rdata
226 {
227 DnsRdata::SOA{ soa } =>
228 {
229 soa_list.push(soa);
230 },
231 _ => {}
232 }
233 }
234 }
235 },
236 QDnsQueriesRes::DnsNotAvailable => {}
237 }
238
239 return Ok(soa_list);
240}
241
242pub
243fn resolve_reverse<C>(fqdn: C, custom_resolv: Option<Arc<ResolveConfig>>) -> CDnsResult<Vec<String>>
244where C: AsRef<str>
245{
246 let resolvers =
247 custom_resolv.map_or(CACHE.clone_resolve_list()?, |f| f);
248
249 let mut dns_req =
250 QDns::make_empty(resolvers, 1, QuerySetup::default());
251
252 dns_req.add_request(QType::PTR, fqdn.as_ref());
253
254 let res = dns_req.query();
256
257 let mut ptr_list: Vec<String> = Vec::new();
258
259 match res
260 {
261 QDnsQueriesRes::DnsOk{ res } =>
262 {
263 for r in res
264 {
265 if r.is_ok() == false
266 {
267 continue;
269 }
270
271 for dnsr in r.move_responses()
272 {
273 match dnsr.rdata
274 {
275 DnsRdata::PTR{ fqdn } =>
276 {
277 ptr_list.push(fqdn);
278 },
279 _ => {}
280 }
281 }
282 }
283 },
284 QDnsQueriesRes::DnsNotAvailable => {}
285 }
286
287 return Ok(ptr_list);
288}
289
290#[test]
291fn test_mx_resolve()
292{
293 let mx_doms = resolve_mx("protonmail.com", None);
294
295 assert_eq!(mx_doms.is_err(), false);
296
297 let mx_doms = mx_doms.unwrap();
298
299 let mut index = 0;
300 for di in mx_doms
301 {
302 match index
303 {
304 0 => assert_eq!(di.as_str(), "mail.protonmail.ch"),
305 1 => assert_eq!(di.as_str(), "mailsec.protonmail.ch"),
306 _ => panic!("test is required to be modified")
307 }
308
309 index += 1;
310
311 println!("{}", di);
312 }
313
314}
315
316
317#[test]
318fn test_a_aaaa_resolve()
319{
320 let a_aaaa = resolve_fqdn("protonmail.com", None);
321
322 assert_eq!(a_aaaa.is_ok(), true);
323
324 let a_aaaa = a_aaaa.unwrap();
325
326 for di in a_aaaa
327 {
328 println!("{}", di);
329 }
330
331}