1use std::collections::HashMap;
25use std::convert::{TryFrom, TryInto};
26use std::net::SocketAddr;
27use std::fmt;
28use std::ops::Index;
29use std::time::Duration;
30use std::time::Instant;
31
32
33use crate::error::*;
34use crate::internal_error;
35use crate::query_private::QDnsReq;
36
37use super::common::*;
38
39
40#[derive(Debug, Clone)]
42pub struct QuerySetup
43{
44 pub(crate) measure_time: bool,
46
47 pub(crate) ign_hosts: bool,
49
50 pub(crate) timeout: Option<u32>,
52}
53
54impl Default for QuerySetup
55{
56 fn default() -> Self
57 {
58 return Self { measure_time: false, ign_hosts: false, timeout: None };
59 }
60}
61
62impl QuerySetup
63{
64 pub
67 fn set_measure_time(&mut self, flag: bool) -> &mut Self
68 {
69 self.measure_time = flag;
70
71 return self;
72 }
73
74 pub
77 fn set_ign_hosts(&mut self, flag: bool) -> &mut Self
78 {
79 self.ign_hosts = flag;
80
81 return self;
82 }
83
84 pub
86 fn set_override_timeout(&mut self, timeout: u32) -> &mut Self
87 {
88 if timeout == 0
89 {
90 return self;
91 }
92
93 self.timeout = Some(timeout);
94
95 return self;
96 }
97
98 pub
100 fn reset_override_timeout(&mut self) -> &mut Self
101 {
102 self.timeout = None;
103
104 return self;
105 }
106
107}
108
109#[derive(Clone, Copy, Debug, PartialEq, Eq)]
111pub enum QDnsQueryRec
112{
113 Ok,
115 ServFail,
117 NxDomain,
119 Refused,
121 NotImpl,
123 Truncated,
125 FormError,
127}
128
129impl QDnsQueryRec
130{
131 pub(crate)
135 fn try_next_nameserver(&self, aa: bool) -> bool
136 {
137 match *self
138 {
139 Self::NxDomain =>
140 {
141 if aa == true
142 {
143 return false;
145 }
146
147 return true;
148 },
149 Self::Truncated =>
150 {
151 return true;
152 },
153 Self::Ok | Self::Refused | Self::ServFail | Self::NotImpl | Self::FormError =>
154 {
155 return true;
156 }
157 }
158 }
159
160 pub(crate)
161 fn should_try_tcp(&self) -> bool
162 {
163 return *self == Self::Truncated || *self == Self::ServFail || *self == Self::NxDomain;
164 }
165}
166
167impl TryFrom<StatusBits> for QDnsQueryRec
168{
169 type Error = CDnsError;
170
171 fn try_from(value: StatusBits) -> Result<Self, Self::Error>
172 {
173 if value.contains(StatusBits::TRUN_CATION) == true
174 {
175 return Ok(QDnsQueryRec::Truncated);
176 }
177 else if value.contains(StatusBits::RESP_NOERROR) == true
178 {
179 return Ok(QDnsQueryRec::Ok);
183 }
184 else if value.contains(StatusBits::RESP_FORMERR) == true
185 {
186 return Ok(QDnsQueryRec::FormError);
187 }
188 else if value.contains(StatusBits::RESP_NOT_IMPL) == true
189 {
190 return Ok(QDnsQueryRec::NotImpl);
191 }
192 else if value.contains(StatusBits::RESP_NXDOMAIN) == true
193 {
194 return Ok(QDnsQueryRec::NxDomain);
195 }
196 else if value.contains(StatusBits::RESP_REFUSED) == true
197 {
198 return Ok(QDnsQueryRec::Refused);
199 }
200 else if value.contains(StatusBits::RESP_SERVFAIL) == true
201 {
202 return Ok(QDnsQueryRec::ServFail);
203 }
204 else
205 {
206 internal_error!(CDnsErrorType::DnsResponse, "response status bits unknwon result: '{}'", value.bits());
207 };
208 }
209}
210
211
212impl fmt::Display for QDnsQueryRec
213{
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
215 {
216 match *self
217 {
218 Self::Ok =>
219 writeln!(f, "OK"),
220 Self::ServFail =>
221 writeln!(f, "SERVFAIL"),
222 Self::NxDomain =>
223 writeln!(f, "NXDOMAIN"),
224 Self::Refused =>
225 writeln!(f, "REFUSED"),
226 Self::NotImpl =>
227 writeln!(f, "NOT IMPLEMENTED"),
228 Self::Truncated =>
229 writeln!(f, "TRUNCATED"),
230 Self::FormError =>
231 writeln!(f, "FORMAT ERROR"),
232 }
233 }
234}
235
236#[derive(Debug, Default)]
238pub struct QDnsQueryResult
239{
240 queries: HashMap<QDnsReq, CDnsResult<QDnsQuery>>,
241}
242
243impl IntoIterator for QDnsQueryResult
244{
245 type Item = (QDnsReq, CDnsResult<QDnsQuery>);
246 type IntoIter = std::collections::hash_map::IntoIter<QDnsReq, CDnsResult<QDnsQuery>>;
247
248 #[inline]
249 fn into_iter(self) -> Self::IntoIter
250 {
251 return self.queries.into_iter();
252 }
253}
254
255
256impl Index<QDnsReq> for QDnsQueryResult
257{
258 type Output = CDnsResult<QDnsQuery>;
259
260 fn index(&self, index: QDnsReq) -> &Self::Output
261 {
262 return &self.queries.get(&index).unwrap();
263 }
264}
265
266impl QDnsQueryResult
267{
268 pub(crate)
269 fn with_capacity(cap: usize) -> Self
270 {
271 return Self{ queries: HashMap::with_capacity(cap) };
272 }
273
274 pub(crate)
275 fn push(&mut self, req: QDnsReq, resp: CDnsResult<QDnsQuery>)
276 {
277 self.queries.insert(req, resp);
278 }
279
280 pub
281 fn is_empty(&self) -> bool
282 {
283 return self.queries.is_empty();
284 }
285
286 pub
287 fn contains_dnsreq(&self, req: &QDnsReq) -> bool
288 {
289 return self.queries.contains_key(req);
290 }
291
292 pub
293 fn extend(&mut self, other: Self)
294 {
295 self.queries.extend(other.queries);
296 }
297
298 pub
299 fn list_results(&self) -> std::collections::hash_map::Iter<'_, QDnsReq, Result<QDnsQuery, CDnsError>>
300 {
301 return self.queries.iter();
302 }
303
304 pub
305 fn get_result(self) -> CDnsResult<Vec<QDnsQuery>>
306 {
307 let ok = self.collect_ok();
308
309 if ok.is_empty() == true
310 {
311 internal_error!(CDnsErrorType::DnsNotAvailable, "network error");
312 }
313
314 return Ok(ok);
315 }
316
317 pub
318 fn get_ok_or_error(self) ->CDnsResult<Vec<QDnsQuery>>
319 {
320 return
321 self
322 .queries
323 .into_iter()
324 .map(|e| e.1)
325 .collect::<CDnsResult<Vec<QDnsQuery>>>();
326 }
327
328 pub
329 fn collect_ok(self) -> Vec<QDnsQuery>
330 {
331 return
332 self
333 .queries
334 .into_iter()
335 .filter(|(_k, v)|
336 v.is_ok()
337 )
338 .map(|(_, v)| v.unwrap())
339 .collect();
340 }
341
342 pub
344 fn collect_split(self) -> (Vec<(QDnsReq, Result<QDnsQuery, CDnsError>)>, Vec<(QDnsReq, Result<QDnsQuery, CDnsError>)>)
345
346 {
347 return
348 self
349 .queries
350 .into_iter()
351 .partition(|(_, v)|
352 v.is_ok()
353 );
354 }
355
356}
357
358impl fmt::Display for QDnsQueryResult
359{
360 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
361 {
362 if self.is_empty() == false
363 {
364 for (req, qr) in self.list_results()
365 {
366 match qr
367 {
368 Ok(r) =>
369 write!(f, "{}", r)?,
370 Err(e) =>
371 write!(f, "request: {}, error: {}", req, e)?
372 }
373
374 }
375 }
376 else
377 {
378 write!(f, "No DNS server available")?;
379 }
380
381 return Ok(());
382 }
383}
384
385#[derive(Clone, Debug)]
388pub struct QDnsQuery
389{
390 pub elapsed: Option<Duration>,
392 pub server: String,
394 pub aa: bool,
396 pub authoratives: Vec<DnsResponsePayload>,
398 pub resp: Vec<DnsResponsePayload>,
400 pub status: QDnsQueryRec,
402}
403
404impl fmt::Display for QDnsQuery
405{
406 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
407 {
408 write!(f, "Source: {} ", self.server)?;
409 if let Some(ref el) = self.elapsed
410 {
411 write!(f, "{:.2?} ", el)?;
412 }
413
414 if self.aa == true
415 {
416 writeln!(f, "Authoritative answer")?;
417 }
418 else
419 {
420 writeln!(f, "Non-Authoritative answer")?;
421 }
422
423
424 writeln!(f, "Authoritatives: {}", self.authoratives.len())?;
425
426 if self.authoratives.len() > 0
427 {
428 for a in self.authoratives.iter()
429 {
430 writeln!(f, "{}", a)?;
431 }
432
433 writeln!(f, "")?;
434 }
435
436 writeln!(f, "Status: {}", self.status)?;
437
438 writeln!(f, "Answers: {}", self.resp.len())?;
439
440 if self.resp.len() > 0
441 {
442 for r in self.resp.iter()
443 {
444 writeln!(f, "{}", r)?;
445 }
446
447 writeln!(f, "")?;
448 }
449
450 return Ok(());
451 }
452}
453
454impl IntoIterator for QDnsQuery
455{
456 type Item = DnsResponsePayload;
457 type IntoIter = std::vec::IntoIter<Self::Item>;
458
459 fn into_iter(self) -> Self::IntoIter
460 {
461 self.resp.into_iter()
462 }
463}
464
465impl QDnsQuery
466{
467 pub
469 fn is_ok(&self) -> bool
470 {
471 return self.status == QDnsQueryRec::Ok;
472 }
473
474 pub
475 fn is_authorative(&self) -> bool
476 {
477 return self.aa;
478 }
479
480 pub
481 fn get_elapsed_time(&self) -> Option<&Duration>
482 {
483 return self.elapsed.as_ref();
484 }
485
486 pub
487 fn get_server(&self) -> &String
488 {
489 return &self.server;
490 }
491
492 pub
494 fn get_authoratives(&self) -> &[DnsResponsePayload]
495 {
496 return self.authoratives.as_slice();
497 }
498
499 pub
501 fn get_responses(&self) -> &[DnsResponsePayload]
502 {
503 return self.resp.as_slice();
504 }
505
506 pub
508 fn move_responses(self) -> Vec<DnsResponsePayload>
509 {
510 return self.resp;
511 }
512
513 pub
514 fn get_status(&self) -> QDnsQueryRec
515 {
516 return self.status;
517 }
518
519 pub
520 fn should_check_next_ns(&self) -> bool
521 {
522 return self.status.try_next_nameserver(self.aa);
523 }
524}
525
526impl QDnsQuery
527{
528 pub
530 fn from_local(req_pl: Vec<DnsResponsePayload>, now: Option<&Instant>) -> QDnsQuery
531 {
532 let elapsed = now.map(|n| n.elapsed());
533
534 return
535 Self
536 {
537 elapsed: elapsed,
538 server: HOST_CFG_PATH.to_string(),
539 aa: true,
540 authoratives: Vec::new(),
541 status: QDnsQueryRec::Ok,
542 resp: req_pl
543 };
544 }
545
546 pub
548 fn from_response(server: &SocketAddr, ans: DnsRequestAnswer, now: Option<&Instant>) -> CDnsResult<Self>
549 {
550 return Ok(
551 Self
552 {
553 elapsed: now.map_or(None, |n| Some(n.elapsed())),
554 server: server.to_string(),
555 aa: ans.req_header.header.status.contains(StatusBits::AUTH_ANSWER),
556 authoratives: ans.authoratives,
557 status: ans.req_header.header.status.try_into()?,
558 resp: ans.response,
559 }
560 );
561 }
562}