1use std::collections::LinkedList;
25use std::convert::{TryFrom, TryInto};
26use std::net::SocketAddr;
27use std::fmt;
28use std::time::Duration;
29use std::time::Instant;
30
31
32use crate::error::*;
33use crate::internal_error;
34
35use super::common::*;
36
37
38#[derive(Debug, Clone)]
40pub struct QuerySetup
41{
42 pub(crate) measure_time: bool,
44
45 pub(crate) ign_hosts: bool,
47
48 pub(crate) timeout: Option<u32>,
50}
51
52impl Default for QuerySetup
53{
54 fn default() -> Self
55 {
56 return Self { measure_time: false, ign_hosts: false, timeout: None };
57 }
58}
59
60impl QuerySetup
61{
62 pub
65 fn set_measure_time(&mut self, flag: bool) -> &mut Self
66 {
67 self.measure_time = flag;
68
69 return self;
70 }
71
72 pub
75 fn set_ign_hosts(&mut self, flag: bool) -> &mut Self
76 {
77 self.ign_hosts = flag;
78
79 return self;
80 }
81
82 pub
84 fn set_override_timeout(&mut self, timeout: u32) -> &mut Self
85 {
86 if timeout == 0
87 {
88 return self;
89 }
90
91 self.timeout = Some(timeout);
92
93 return self;
94 }
95
96 pub
98 fn reset_override_timeout(&mut self) -> &mut Self
99 {
100 self.timeout = None;
101
102 return self;
103 }
104
105}
106
107#[derive(Clone, Copy, Debug, PartialEq, Eq)]
109pub enum QDnsQueryRec
110{
111 Ok,
113 ServFail,
115 NxDomain,
117 Refused,
119 NotImpl,
121 FormError,
123}
124
125impl QDnsQueryRec
126{
127 pub(crate)
131 fn try_next_nameserver(&self, aa: bool) -> bool
132 {
133 match *self
134 {
135 Self::NxDomain =>
136 {
137 if aa == true
138 {
139 return false;
141 }
142
143 return true;
144 },
145 Self::Ok | Self::Refused | Self::ServFail | Self::NotImpl | Self::FormError =>
146 {
147 return true;
148 }
149 }
150 }
151}
152
153impl TryFrom<StatusBits> for QDnsQueryRec
154{
155 type Error = CDnsError;
156
157 fn try_from(value: StatusBits) -> Result<Self, Self::Error>
158 {
159 if value.contains(StatusBits::RESP_NOERROR) == true
160 {
161 return Ok(QDnsQueryRec::Ok);
165 }
166 else if value.contains(StatusBits::RESP_FORMERR) == true
167 {
168 return Ok(QDnsQueryRec::FormError);
169 }
170 else if value.contains(StatusBits::RESP_NOT_IMPL) == true
171 {
172 return Ok(QDnsQueryRec::NotImpl);
173 }
174 else if value.contains(StatusBits::RESP_NXDOMAIN) == true
175 {
176 return Ok(QDnsQueryRec::NxDomain);
177 }
178 else if value.contains(StatusBits::RESP_REFUSED) == true
179 {
180 return Ok(QDnsQueryRec::Refused);
181 }
182 else if value.contains(StatusBits::RESP_SERVFAIL) == true
183 {
184 return Ok(QDnsQueryRec::ServFail);
185 }
186 else
187 {
188 internal_error!(CDnsErrorType::DnsResponse, "response status bits unknwon result: '{}'", value.bits());
189 };
190 }
191}
192
193
194impl fmt::Display for QDnsQueryRec
195{
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
197 {
198 match *self
199 {
200 Self::Ok =>
201 {
202 writeln!(f, "OK")?;
203 },
204 Self::ServFail =>
205 {
206 writeln!(f, "SERVFAIL")?;
207 },
208 Self::NxDomain =>
209 {
210 writeln!(f, "NXDOMAIN")?;
211 },
212 Self::Refused =>
213 {
214 writeln!(f, "REFUSED")?;
215 },
216 Self::NotImpl =>
217 {
218 writeln!(f, "NOT IMPLEMENTED")?;
219 },
220 Self::FormError =>
221 {
222 writeln!(f, "FORMAT ERROR")?;
223 }
224 }
225
226 return Ok(());
227 }
228}
229
230#[derive(Clone, Debug)]
233pub struct QDnsQuery
234{
235 pub elapsed: Option<Duration>,
237 pub server: String,
239 pub aa: bool,
241 pub authoratives: Vec<DnsResponsePayload>,
243 pub resp: Vec<DnsResponsePayload>,
245 pub status: QDnsQueryRec,
247}
248
249impl fmt::Display for QDnsQuery
250{
251 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
252 {
253 write!(f, "Source: {} ", self.server)?;
254 if let Some(ref el) = self.elapsed
255 {
256 write!(f, "{:.2?} ", el)?;
257 }
258
259 if self.aa == true
260 {
261 writeln!(f, "Authoritative answer")?;
262 }
263 else
264 {
265 writeln!(f, "Non-Authoritative answer")?;
266 }
267
268 writeln!(f, "Authoritatives: {}", self.authoratives.len())?;
269
270 if self.authoratives.len() > 0
271 {
272 for a in self.authoratives.iter()
273 {
274 writeln!(f, "{}", a)?;
275 }
276
277 writeln!(f, "")?;
278 }
279
280 writeln!(f, "Status: {}", self.status)?;
281
282 writeln!(f, "Answers: {}", self.resp.len())?;
283
284 if self.resp.len() > 0
285 {
286 for r in self.resp.iter()
287 {
288 writeln!(f, "{}", r)?;
289 }
290
291 writeln!(f, "")?;
292 }
293
294 return Ok(());
295 }
296}
297
298impl QDnsQuery
299{
300 pub
302 fn is_ok(&self) -> bool
303 {
304 return self.status == QDnsQueryRec::Ok;
305 }
306
307 pub
308 fn is_authorative(&self) -> bool
309 {
310 return self.aa;
311 }
312
313 pub
314 fn get_elapsed_time(&self) -> Option<&Duration>
315 {
316 return self.elapsed.as_ref();
317 }
318
319 pub
320 fn get_server(&self) -> &String
321 {
322 return &self.server;
323 }
324
325 pub
327 fn get_authoratives(&self) -> &[DnsResponsePayload]
328 {
329 return self.authoratives.as_slice();
330 }
331
332 pub
334 fn get_responses(&self) -> &[DnsResponsePayload]
335 {
336 return self.resp.as_slice();
337 }
338
339 pub
341 fn move_responses(self) -> Vec<DnsResponsePayload>
342 {
343 return self.resp;
344 }
345}
346
347impl QDnsQuery
348{
349 pub
351 fn from_local(req_pl: Vec<DnsResponsePayload>, now: Option<&Instant>) -> QDnsQuery
352 {
353 let elapsed =
354 match now
355 {
356 Some(n) => Some(n.elapsed()),
357 None => None
358 };
359
360 return
361 Self
362 {
363 elapsed: elapsed,
364 server: HOST_CFG_PATH.to_string(),
365 aa: true,
366 authoratives: Vec::new(),
367 status: QDnsQueryRec::Ok,
368 resp: req_pl
369 };
370 }
371
372 pub
374 fn from_response(server: &SocketAddr, ans: DnsRequestAnswer, now: Option<&Instant>) -> CDnsResult<Self>
375 {
376 return Ok(
377 Self
378 {
379 elapsed: now.map_or(None, |n| Some(n.elapsed())),
380 server: server.to_string(),
381 aa: ans.header.status.contains(StatusBits::AUTH_ANSWER),
382 authoratives: ans.authoratives,
383 status: ans.header.status.try_into()?,
384 resp: ans.response,
385 }
386 );
387 }
388}
389
390#[derive(Debug)]
392pub enum QDnsQueriesRes
393{
394 DnsOk
396 {
397 res: Vec<QDnsQuery>,
398 },
399 DnsNotAvailable,
401}
402
403impl QDnsQueriesRes
404{
405 pub(crate)
406 fn extend(&mut self, other: Self)
407 {
408 if other.is_results() == false
409 {
410 return;
411 }
412
413 match *self
414 {
415 Self::DnsOk{ ref mut res } =>
416 {
417 res.extend(other.into_inner().unwrap());
418 },
419 Self::DnsNotAvailable =>
420 {
421 *self = Self::DnsOk{ res: other.into_inner().unwrap() };
422 }
423 }
424 }
425
426 pub
428 fn into_inner(self) -> Option<Vec<QDnsQuery>>
429 {
430 match self
431 {
432 Self::DnsNotAvailable => None,
433 Self::DnsOk{ res } => return Some(res),
434 }
435 }
436
437 pub
442 fn is_results(&self) -> bool
443 {
444 match *self
445 {
446 Self::DnsNotAvailable => return false,
447 _ => return true,
448 }
449 }
450
451 pub
454 fn len(&self) -> usize
455 {
456 if let Self::DnsOk{res} = self
457 {
458 return res.len();
459 }
460 else
461 {
462 return 0;
463 }
464 }
465
466 pub
468 fn list_results(&self) -> Option<std::slice::Iter<'_, QDnsQuery>>
469 {
470 if let Self::DnsOk{res} = self
471 {
472 return Some(res.iter());
473 }
474 else
475 {
476 return None;
477 }
478 }
479}
480
481impl From<QDnsQuery> for QDnsQueriesRes
482{
483 fn from(query: QDnsQuery) -> Self
484 {
485 return QDnsQueriesRes::DnsOk{ res: vec![query] };
486 }
487}
488
489impl From<LinkedList<QDnsQuery>> for QDnsQueriesRes
490{
491 fn from(responses: LinkedList<QDnsQuery>) -> Self
492 {
493 if responses.len() > 0
494 {
495 return QDnsQueriesRes::DnsOk{ res: responses.into_iter().map(|h| h).collect() };
496 }
497 else
498 {
499 return QDnsQueriesRes::DnsNotAvailable;
500 }
501 }
502}
503
504impl fmt::Display for QDnsQueriesRes
505{
506 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
507 {
508 match *self
509 {
510 Self::DnsOk{ ref res } =>
511 {
512 for r in res.iter()
513 {
514 write!(f, "{}", r)?;
515 }
516 },
517 Self::DnsNotAvailable => write!(f, "No DNS server available")?
518 }
519
520 return Ok(());
521 }
522}
523
524