1use std::collections::{LinkedList, HashSet};
26use std::convert::TryFrom;
27use std::net::IpAddr;
28use std::sync::Arc;
29use std::time::Duration;
30use std::time::Instant;
31
32use async_recursion::async_recursion;
33use tokio::task::JoinHandle;
34
35use crate::cfg_resolv_parser::{ResolveConfigFamily, ResolveConfEntry};
36use crate::error::*;
37use crate::query::{QDnsQuery, QDnsQueriesRes, QDnsQueryRec};
38use crate::sync::QuerySetup;
39use crate::{write_error, internal_error, internal_error_map};
40use crate::query_private::QDnsReq;
41
42use super::common::*;
43use super::caches::CACHE;
44use super::network::{new_udp, new_tcp, NetworkTapType};
45use super::query_async_taps::{AsyncTaps, Tap};
46use super::ResolveConfig;
47
48
49enum SpawnFutereRes
50{
51 Ok(QDnsQuery),
52 Truncated(DnsRequestHeader),
53}
54
55
56pub struct QDns
58{
59 resolvers: Arc<ResolveConfig>,
61 ordered_req_list: Vec<QDnsReq>,
63 opts: QuerySetup,
65}
66
67impl QDns
68{
69 pub
87 fn make_empty(resolvers: Arc<ResolveConfig>, planned_reqs_len: usize, opts: QuerySetup) -> QDns
88 {
89 return
90 Self
91 {
92 resolvers: resolvers,
93 ordered_req_list: Vec::with_capacity(planned_reqs_len),
94 opts: opts,
95 };
96 }
97
98 pub
112 fn add_request<R>(&mut self, qtype: QType, req_name: R)
113 where R: Into<QDnsName>
114 {
115 let qr = QDnsReq::new(req_name.into(), qtype);
116
117 self.ordered_req_list.push(qr);
118
119 return;
120 }
121
122 pub
142 fn make_a_aaaa_request<R>(resolvers: Arc<ResolveConfig>, req_name: R, opts: QuerySetup) -> QDns
143 where R: Into<QDnsName>
144 {
145 let reqs: Vec<QDnsReq> =
147 match resolvers.family
148 {
149 ResolveConfigFamily::INET4_INET6 =>
150 {
151 let req_n: QDnsName = req_name.into();
152
153 vec![
154 QDnsReq::new(req_n.clone(), QType::A),
155 QDnsReq::new(req_n, QType::AAAA),
156 ]
157 },
158 ResolveConfigFamily::INET6_INET4 =>
159 {
160 let req_n: QDnsName = req_name.into();
161
162 vec![
163 QDnsReq::new(req_n.clone(), QType::AAAA),
164 QDnsReq::new(req_n, QType::A),
165 ]
166 },
167 ResolveConfigFamily::INET6 =>
168 {
169 vec![
170 QDnsReq::new(req_name.into(), QType::AAAA),
171 ]
172 },
173 ResolveConfigFamily::INET4 =>
174 {
175 vec![
176 QDnsReq::new(req_name.into(), QType::A),
177 ]
178 }
179 _ =>
180 {
181 let req_n: QDnsName = req_name.into();
183
184 vec![
185 QDnsReq::new(req_n.clone(), QType::A),
186 QDnsReq::new(req_n, QType::AAAA),
187 ]
188 }
189 };
190
191
192
193 return
194 Self
195 {
196 resolvers: resolvers,
197 ordered_req_list: reqs,
198 opts: opts,
199 };
200 }
201
202 pub async
212 fn query(mut self) -> QDnsQueriesRes
213 {
214 let now =
216 if self.opts.measure_time == true
217 {
218 Some(Instant::now())
219 }
220 else
221 {
222 None
223 };
224
225 let mut qres: QDnsQueriesRes = QDnsQueriesRes::DnsNotAvailable;
226
227 if self.resolvers.lookup.is_file_first()
230 {
231 match self.lookup_file(now.clone()).await
232 {
233 Ok(r) =>
234 qres.extend(r),
235 Err(e) =>
236 write_error!("{}", e),
237 }
238
239 if self.ordered_req_list.is_empty() == false && self.resolvers.lookup.is_bind() == true
241 {
242 match self.process_request(now.clone()).await
243 {
244 Ok(r) =>
245 qres.extend(r),
246 Err(e) =>
247 write_error!("{}", e),
248 }
249 }
250 }
251 else
252 {
253 match self.process_request(now.clone()).await
254 {
255 Ok(r) =>
256 qres.extend(r),
257 Err(e) =>
258 write_error!("{}", e),
259 }
260
261
262 if self.ordered_req_list.is_empty() == false && self.resolvers.lookup.is_file() == true
263 {
264 match self.lookup_file(now.clone()).await
265 {
266 Ok(r) =>
267 qres.extend(r),
268 Err(e) =>
269 write_error!("{}", e),
270 }
271 }
272 }
273
274 return qres;
275 }
276
277 fn get_timeout(&self) -> Duration
279 {
280 if let Some(timeout) = self.opts.timeout
281 {
282 return Duration::from_secs(timeout as u64);
283 }
284 else
285 {
286 return Duration::from_secs(self.resolvers.timeout as u64);
287 }
288 }
289
290 async
292 fn lookup_file(&mut self, now: Option<Instant>) -> CDnsResult<QDnsQueriesRes>
293 {
294 if self.opts.ign_hosts == false
296 {
297 let hlist = CACHE.clone_host_list().await?;
298
299 let mut dnsquries: LinkedList<QDnsQuery> = LinkedList::new();
300
301 self.ordered_req_list.retain(|req|
302 {
303 match *req.get_type()
304 {
305 QType::A | QType::AAAA =>
306 {
307 let req_name = String::from(req.get_req_name());
308
309 if let Some(res) = hlist.search_by_fqdn(req.get_type(), req_name.as_str())
310 {
311 let drp =
313 match DnsResponsePayload::new_local(*req.get_type(), res)
314 {
315 Ok(r) => r,
316 Err(e) =>
317 {
318 write_error!("{}", e);
319
320 return true;
321 }
322 };
323
324 dnsquries.push_back(
326 QDnsQuery::from_local(drp, now.as_ref())
327 );
328
329 return false;
330 }
331 else
332 {
333 return true;
334 }
335 },
336 QType::PTR =>
337 {
338 let ip: IpAddr =
339 match IpAddr::try_from(req.get_req_name())
340 {
341 Ok(r) => r,
342 Err(e) =>
343 {
344 write_error!("{}", e);
346
347 return true;
348 }
349 };
350
351 if let Some(r) = hlist.search_by_ip(&ip)
352 {
353 let drp =
355 match DnsResponsePayload::new_local(QType::PTR, r)
356 {
357 Ok(r) => r,
358 Err(e) =>
359 {
360 write_error!("{}", e);
361
362 return true;
363 }
364 };
365
366 dnsquries.push_back(
368 QDnsQuery::from_local(drp, now.as_ref())
369 );
370
371 return false;
372 }
373 else
374 {
375 return true;
376 }
377 },
378 _ =>
379 {
380 return true;
382 }
383 }
384 }
385 );
386
387 return Ok( QDnsQueriesRes::from(dnsquries) );
392 }
393 else
394 {
395 return Ok(QDnsQueriesRes::DnsNotAvailable);
396 }
397 }
398
399 fn create_socket(
402 &self,
403 force_tcp: bool,
404 resolver: &ResolveConfEntry,
405 timeout: Duration
406 ) -> CDnsResult<Box<NetworkTapType>>
407 {
408 if self.resolvers.option_flags.is_force_tcp() == true || force_tcp == true
410 {
411 return new_tcp(resolver.get_resolver_ip(), 53, resolver.get_adapter_ip(), timeout);
412 }
413 else
414 {
415 return new_udp(resolver.get_resolver_ip(), 53, resolver.get_adapter_ip(), timeout);
416 };
417 }
418
419 fn create_sockets(
421 &self,
422 resolver: &ResolveConfEntry,
423 requery_list: Option<LinkedList<DnsRequestHeader>>,
424 timeout: Duration,
425 force_tcp: bool,
426 ) -> CDnsResult<AsyncTaps>
427 {
428 let mut taps: AsyncTaps = AsyncTaps::new_with_capacity(self.ordered_req_list.len());
429
430 let force_tcp: bool =
431 force_tcp == true || self.resolvers.option_flags.is_force_tcp() == true;
432
433 if let Some(requery) = requery_list
434 {
435 let mut ids: HashSet<u16> = HashSet::with_capacity(requery.len());
436
437 for mut req in requery
438 {
439 if self.resolvers.option_flags.is_reopen_socket() == true || taps.len() == 0
440 {
441 let tap =
443 self.create_socket(force_tcp, resolver, timeout)?;
444
445 loop
447 {
448 req.regenerate_id();
449
450 if ids.insert(req.get_id()) == true
451 {
452 break;
453 }
454 }
455
456 let t = Tap::new(tap, req);
457
458 taps.push(t);
459 }
460 else
461 {
462 taps.push_to_last(req);
463 }
464 }
465 }
466 else
467 {
468 let mut ids: HashSet<u16> = HashSet::with_capacity(self.ordered_req_list.len());
469
470 for req in self.ordered_req_list.iter()
472 {
473 let mut drh_req = DnsRequestHeader::from_qdns_req(req, self.resolvers.as_ref())?;
474
475 if self.resolvers.option_flags.is_reopen_socket() == true || taps.len() == 0
476 {
477 let tap =
479 self.create_socket(force_tcp, resolver, timeout)?;
480
481 loop
483 {
484 if ids.insert(drh_req.get_id()) == true
485 {
486 break;
487 }
488
489 drh_req.regenerate_id();
490 }
491
492 let t = Tap::new(tap, drh_req);
493
494 taps.push(t);
495 }
496 else
497 {
498 taps.push_to_last(drh_req);
499 }
500 } }
502
503 return Ok(taps);
504 }
505
506 fn get_result(responses: &LinkedList<QDnsQuery>) -> QDnsQueryRec
508 {
509 let mut resp = QDnsQueryRec::Ok;
510
511 for r in responses.iter()
512 {
513 if r.is_ok() == false
514 {
515 resp = r.status;
516
517 return resp;
518 }
519 }
520
521 return resp;
522 }
523
524 fn get_authorative(responses: &LinkedList<QDnsQuery>) -> bool
526 {
527 return responses.front().map_or(false, |r| r.aa);
528 }
529
530 async
532 fn process_request(&mut self, now: Option<Instant>) -> CDnsResult<QDnsQueriesRes>
533 {
534 let mut qresponses: LinkedList<QDnsQuery> = LinkedList::new();
535
536 for resolver in self.resolvers.get_resolvers_iter()
539 {
540 let qresp =
541 self.processing(now, resolver, None, false).await?;
542
543 let dnsres = Self::get_result(&qresp);
545 let aa = Self::get_authorative(&qresp);
546
547 qresponses.extend(qresp);
548
549 if dnsres.try_next_nameserver(aa) == false
550 {
551 break;
552 }
553
554 }
555
556 return Ok(QDnsQueriesRes::from(qresponses));
557 }
558
559 #[async_recursion]
561 async
562 fn processing(
563 &self,
564 now: Option<Instant>,
565 resolver: &ResolveConfEntry,
566 requery: Option<LinkedList<DnsRequestHeader>>,
567 force_tcp: bool
568 ) -> CDnsResult<LinkedList<QDnsQuery>>
569 {
570 let mut responses: LinkedList<QDnsQuery> = LinkedList::new();
571
572 let mut truncated_list: LinkedList<DnsRequestHeader> = LinkedList::new();
574
575 let sync_taps: AsyncTaps =
577 self.create_sockets(resolver, requery, self.get_timeout(), force_tcp)?;
578
579 let mut handles: Vec<JoinHandle<CDnsResult<Vec<SpawnFutereRes>>>> = Vec::with_capacity(sync_taps.len());
581
582 for stap in sync_taps.into_iter()
583 {
584 let (mut socktap, req_list) = stap.into_inner();
590
591 if self.resolvers.option_flags.is_no_parallel() == true
592 {
593 socktap.connect().await?;
596
597 for req in req_list
598 {
599 let res =
600 Self::spawn_future_single(
601 socktap.as_mut(),
602 req,
603 now.map_or(None, |n| Some(n.clone()))
604 ).await;
605
606 match res
607 {
608 Ok(SpawnFutereRes::Ok(dq)) =>
609 {
610 responses.push_back(dq);
611 },
612 Ok(SpawnFutereRes::Truncated(drh)) =>
613 {
614 if force_tcp == true || self.resolvers.option_flags.is_force_tcp() == true
615 {
616 internal_error!(CDnsErrorType::MessageTruncated, "Message is truncated even using TCP. Give up.");
618 }
619
620 truncated_list.push_back(drh);
621 },
622 Err(e) => return Err(e),
623 }
624 }
625 }
626 else
627 {
628 let res: JoinHandle<CDnsResult<Vec<SpawnFutereRes>>> =
630 tokio::spawn(
631 async move {
632 return
633 Self::spawn_future_multi(
634 socktap,
635 req_list,
636 now.map_or(None, |n| Some(n.clone()))
637 ).await;
638 }
639 );
640
641 handles.push(res);
643 }
644 }
645
646 for handle in handles
648 {
649
650 let res =
651 handle.await
652 .map_err(|e|
653 internal_error_map!(CDnsErrorType::InternalError, "{}", e)
654 )?;
655
656 let v_sfr =
657 match res
658 {
659 Ok(r) => r,
660 Err(e) => return Err(e),
661 };
662
663 for sft in v_sfr
664 {
665 match sft
666 {
667 SpawnFutereRes::Ok(dq) =>
668 {
669 responses.push_back(dq);
670 },
671 SpawnFutereRes::Truncated(drh) =>
672 {
673 if force_tcp == true || self.resolvers.option_flags.is_force_tcp() == true
674 {
675 internal_error!(CDnsErrorType::MessageTruncated, "Message is truncated even using TCP. Give up.");
677 }
678
679 truncated_list.push_back(drh);
680 },
681 }
682 }
683 }
684
685 if truncated_list.is_empty() == false
686 {
687 if force_tcp == true || self.resolvers.option_flags.is_force_tcp() == true
689 {
690 internal_error!(CDnsErrorType::MessageTruncated, "Message is truncated even using TCP. Give up.");
692 }
693
694 let res =
695 self.processing(now, resolver, Some(truncated_list), true).await?;
696
697 responses.extend(res);
698 }
699
700 return Ok(responses);
701 }
702
703 async
705 fn spawn_future_single(sock: &mut NetworkTapType, req: DnsRequestHeader, now: Option<Instant>) -> CDnsResult<SpawnFutereRes>
706 {
707 let pkt = req.async_to_bytes().await?;
709
710 sock.send(pkt.as_slice()).await?;
712
713 let mut rcvbuf = vec![0_u8; 1024];
715
716 sock.recv(rcvbuf.as_mut_slice()).await?;
718
719 let ans = DnsRequestAnswer::async_try_from(rcvbuf.as_slice()).await?;
721
722 match ans.verify(&req)
724 {
725 Ok(_) => {},
726 Err(ref e)
727 if e.err_code == CDnsErrorType::MessageTruncated =>
728 {
729 async_write_error!("{}", e);
732
733 return Ok(SpawnFutereRes::Truncated(req));
734 },
735 Err(e) =>
736 return Err(e),
737 }
738
739 let resp = QDnsQuery::from_response(sock.get_remote_addr(), ans, now.as_ref())?;
741
742 return Ok(SpawnFutereRes::Ok(resp));
743 }
744
745 async
746 fn spawn_future_multi(mut sock: Box<NetworkTapType>, req_list: Vec<DnsRequestHeader>, now: Option<Instant>) -> CDnsResult<Vec<SpawnFutereRes>>
747 {
748 let mut spawn_res: Vec<SpawnFutereRes> = Vec::with_capacity(req_list.len());
749
750 sock.connect().await?;
752
753 for req in req_list
754 {
755 let r = Self::spawn_future_single(sock.as_mut(), req, now.clone()).await?;
756
757 spawn_res.push(r);
758 }
759
760 return Ok(spawn_res);
761 }
762}
763
764#[cfg(test)]
765mod tests
766{
767 use std::net::IpAddr;
768
769 use crate::{a_sync::{caches::CACHE, common::{byte2hexchar, ip2pkt}, QDns, QDnsName}, DnsRdata, QDnsQueriesRes, QDnsQueryRec, QType, QuerySetup};
770
771 #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
772 async fn test_ip2pkt()
773 {
774 use tokio::time::Instant;
775 use std::net::{IpAddr, Ipv4Addr};
776
777 let test = IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8));
778
779 let now = Instant::now();
780
781 let res = ip2pkt(&test);
782
783 let elapsed = now.elapsed();
784 println!("Elapsed: {:.2?}", elapsed);
785
786 assert_eq!(res.is_ok(), true, "err: {}", res.err().unwrap());
787
788 let res = res.unwrap();
789 let ctrl = b"\x01\x38\x01\x38\x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\x61\x00";
790
791 assert_eq!(res.as_slice(), ctrl);
792 }
793
794
795 #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
796 async fn test_byte2hexchar()
797 {
798 assert_eq!(byte2hexchar(1), 0x31);
799 assert_eq!(byte2hexchar(9), 0x39);
800 assert_eq!(byte2hexchar(10), 'a' as u8);
801 assert_eq!(byte2hexchar(15), 'f' as u8);
802 }
803
804
805 #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
806 async fn reverse_lookup_test()
807 {
808 use tokio::time::Instant;
809
810 let ipp: IpAddr = "8.8.8.8".parse().unwrap();
811 let test = QDnsName::from(&ipp);
812
813 let resolvers = CACHE.clone_resolve_list().await.unwrap();
814
815 let mut query_setup = QuerySetup::default();
816 query_setup.set_measure_time(true);
817
818 let now = Instant::now();
819
820 let mut dns_req =
821 QDns::make_empty(resolvers, 1, query_setup);
822
823 dns_req.add_request(QType::PTR, test);
824
825 let res = dns_req.query().await;
826
827 let elapsed = now.elapsed();
828 println!("Elapsed: {:.2?}", elapsed);
829
830 assert_eq!(res.is_results(), true);
831
832 println!("{}", res);
833
834 match res
835 {
836 QDnsQueriesRes::DnsOk{ res } =>
837 {
838 let rec = &res[0];
839
840 assert_eq!(rec.status, QDnsQueryRec::Ok);
842
843 assert_eq!(rec.resp.len(), 1);
844 assert_eq!(rec.resp[0].rdata, DnsRdata::PTR{ fqdn: "dns.google".to_string() });
845
846 },
847 _ => assert_eq!(true, false, "expected DnsResultSingle"),
848 }
849 }
850
851 #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
852 async fn reverse_lookup_hosts_test()
853 {
854 use tokio::time::Instant;
855
856 let ipp: IpAddr = "127.0.0.1".parse().unwrap();
857 let test = QDnsName::from(&ipp);
858
859 let now = Instant::now();
860
861 let mut query_setup = QuerySetup::default();
862 query_setup.set_measure_time(true);
863
864 let resolvers = CACHE.clone_resolve_list().await.unwrap();
865
866 let mut dns_req =
867 QDns::make_empty(resolvers, 1, query_setup);
868
869 dns_req.add_request(QType::PTR, test);
870
871 let res = dns_req.query().await;
872
873 let elapsed = now.elapsed();
874 println!("Elapsed: {:.2?}", elapsed);
875
876 assert_eq!(res.is_results(), true);
877
878 println!("{}", res);
879
880 match res
881 {
882 QDnsQueriesRes::DnsOk{ res } =>
883 {
884 let rec = &res[0];
885
886 assert_eq!(rec.server.as_str(), "/etc/hosts");
887 assert_eq!(rec.status, QDnsQueryRec::Ok);
888
889 assert_eq!(rec.resp.len(), 1);
890 assert_eq!(rec.resp[0].rdata, DnsRdata::PTR{ fqdn: "localhost".to_string() });
891
892 },
893 _ => assert_eq!(true, false, "expected DnsResultSingle"),
894 }
895 }
896
897
898 #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
899 async fn reverse_lookup_a()
900 {
901 use tokio::time::Instant;
902
903 let test = QDnsName::from("dns.google");
904
905 let mut query_setup = QuerySetup::default();
906 query_setup.set_measure_time(true);
907
908
909 let resolvers = CACHE.clone_resolve_list().await.unwrap();
910
911 let res = QDns::make_a_aaaa_request(resolvers, test, query_setup);
912
913
914 let now = Instant::now();
915 let res = res.query().await;
916
917
918 let elapsed = now.elapsed();
919 println!("Elapsed: {:.2?}", elapsed);
920
921 println!("{}", res);
922 }
923}