1use std::fmt;
17use std::hash::Hash;
21use std::net::{IpAddr, SocketAddr};
22use std::str::FromStr;
23use std::sync::atomic::{AtomicUsize, Ordering};
24use std::sync::Arc;
25
26use bitflags::bitflags;
27
28use crate::common::{bind_all, DEF_HTTPS_PORT, DEF_TLS_PORT};
29use crate::{error::*, internal_error, internal_error_map, write_error};
30use crate::portable::*;
31use crate::tokenizer::*;
32
33static ROUND_ROBIN_CNT: AtomicUsize = AtomicUsize::new(0);
36
37
38
39pub struct RoundRobinIterator<'iterator, I>
42{
43 end_index: usize,
44 current_index: usize,
45 slice: &'iterator [I]
46}
47
48impl<'iterator, I> RoundRobinIterator<'iterator, I>
49{
50 pub
51 fn new(start_index: usize, slice: &'iterator [I]) -> RoundRobinIterator<'iterator, I>
52 {
53 return
54 RoundRobinIterator
55 {
56 end_index: start_index + slice.len(),
57 current_index: start_index,
58 slice: slice
59 };
60 }
61
62 pub
63 fn len(&self) -> usize
64 {
65 return self.slice.len();
66 }
67}
68
69impl<'iterator, I> Iterator for RoundRobinIterator<'iterator, I>
70{
71 type Item = &'iterator I;
72
73 fn next(&mut self) -> Option<Self::Item>
74 {
75 let temp_index = self.current_index;
76
77 self.current_index += 1;
78
79 if temp_index == self.end_index
80 {
81 return None;
82 }
83
84 let real_index = temp_index % self.slice.len();
86
87 return self.slice.get(real_index);
88 }
89}
90
91#[derive(Clone, Copy, Debug, PartialEq, Eq)]
92pub enum ConfigEntryTls
93{
94 None, Tls, Https
95}
96
97impl fmt::Display for ConfigEntryTls
98{
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
100 {
101 match self
102 {
103 Self::None => write!(f, "unencrypted"),
104 Self::Tls => write!(f, "TLS"),
105 Self::Https => write!(f, "HTTPS"),
106 }
107 }
108}
109
110#[derive(Clone, Debug, PartialEq, Eq)]
112pub struct ResolveConfEntry
113{
114 ip: SocketAddr,
115 tls_domain: Option<String>,
116 https_req_path: Option<String>,
117 adapter_ip: SocketAddr,
118 tls_type: ConfigEntryTls,
119}
120
121impl ResolveConfEntry
122{
123 pub
124 fn new(ip: SocketAddr, tls_url: Option<String>, adapter_ip: SocketAddr) -> CDnsResult<Self>
125 {
126 let (tls_type, https_domain, https_req_path) =
127 if let Some(tlsd) = tls_url.as_ref()
128 {
129 if let Some(domain_path_https) = tlsd.strip_prefix("https://")
130 {
131 let Some ((domain, path)) = domain_path_https.split_once("/")
132 else
133 {
134 internal_error!(CDnsErrorType::ConfigError,
135 "in /etc/resolv.conf - invalid TLS/HTTPS URL '{}'",
136 domain_path_https
137 )
138 };
139
140 (ConfigEntryTls::Https, Some(domain.to_string()), Some(path.to_string()))
141 }
142 else
143 {
144 let domain =
146 tlsd
147 .split_once("://")
148 .map_or(tlsd.as_str(), |(_, d)| d);
149
150
151 let domain =
152 domain
153 .split_once("/")
154 .map_or(domain, |(d, _)| d);
155
156
157 (ConfigEntryTls::Tls, Some(domain.to_string()), None)
158 }
159 }
160 else
161 {
162 if ip.port() == DEF_HTTPS_PORT
163 {
164 (ConfigEntryTls::Https, None, None)
165 }
166 else if ip.port() == DEF_TLS_PORT
167 {
168 (ConfigEntryTls::Tls, None, None)
169 }
170 else
171 {
172 (ConfigEntryTls::None, None, None)
173 }
174 };
175
176 return Ok(Self {ip, tls_domain: https_domain, https_req_path: https_req_path, adapter_ip, tls_type});
177 }
178
179 pub
180 fn get_resolver_ip(&self) -> IpAddr
181 {
182 return self.ip.ip();
183 }
184
185 pub
186 fn get_resolver_sa(&self) -> &SocketAddr
187 {
188 return &self.ip;
189 }
190
191 pub
192 fn get_tls_domain(&self) -> Option<&String>
193 {
194 return self.tls_domain.as_ref();
195 }
196
197 pub
198 fn get_adapter_ip(&self) -> &SocketAddr
199 {
200 return &self.adapter_ip;
201 }
202
203 pub
204 fn get_tls_type(&self) -> ConfigEntryTls
205 {
206 return self.tls_type;
207 }
208
209 pub
210 fn get_tls_path(&self) -> Option<&String>
211 {
212 return self.https_req_path.as_ref();
213 }
214}
215
216bitflags! {
224 #[derive(Clone, Debug, PartialEq, Eq, Copy)]
226 pub struct ResolveConfigLookup: u32
227 {
228 const FILE_BIND = 0x10;
230 const BIND_FILE = 0x20;
232 const FILE = 0x01;
234 const BIND = 0x02;
236 }
237}
238
239
240impl ResolveConfigLookup
241{
242 pub
243 fn is_file(&self) -> bool
244 {
245 return self.contains(Self::FILE);
246 }
247
248 pub
249 fn is_bind(&self) -> bool
250 {
251 return self.contains(Self::BIND);
252 }
253
254 pub
255 fn is_file_first(&self) -> bool
256 {
257 return self.contains(Self::FILE_BIND);
258 }
259}
260
261impl Default for ResolveConfigLookup
262{
263 fn default() -> Self
264 {
265 return Self::FILE_BIND | Self::FILE | Self::BIND;
266 }
267}
268
269const LOOKUP_FILE: &'static str = "file";
270const LOOKUP_BIND: &'static str = "bind";
271
272impl TryFrom<&[String]> for ResolveConfigLookup
273{
274 type Error = CDnsError;
275
276 fn try_from(value: &[String]) -> Result<Self, Self::Error>
277 {
278 if value.is_empty() == true
279 {
280 internal_error!(CDnsErrorType::ConfigError, "'lookup' is empty");
281 }
282 else if value.len() > 2
283 {
284 internal_error!(CDnsErrorType::ConfigError, "'lookup' is set with too many paramenters: '{:?}'", value);
285 }
286
287 let first =
290 if value[0] == LOOKUP_FILE
291 {
292 Self::FILE
293 }
294 else if value[0] == LOOKUP_BIND
295 {
296 Self::BIND
297 }
298 else
299 {
300 internal_error!(CDnsErrorType::ConfigError, "'lookup' is set with unknown parameter: '{}'", value[0]);
301 };
302
303 let second: Self =
304 if value.len() == 2
305 {
306 if value[1] == LOOKUP_FILE
307 {
308 if first.contains(Self::FILE) == true
309 {
310 internal_error!(CDnsErrorType::ConfigError, "'lookup' is set with duplicate parameter: '{}'", value[1]);
311 }
312
313 Self::BIND_FILE | Self::FILE
314 }
315 else if value[1] == LOOKUP_BIND
316 {
317 if first.contains(Self::BIND) == true
318 {
319 internal_error!(CDnsErrorType::ConfigError, "'lookup' is set with duplicate parameter: '{}'", value[1]);
320 }
321
322 Self::FILE_BIND | Self::BIND
323 }
324 else
325 {
326 internal_error!(CDnsErrorType::ConfigError, "'lookup' is set with unknown parameter: '{}'", value[0]);
327 }
328 }
329 else
330 {
331 Self::empty()
332 };
333
334 return Ok(Self::from(first | second));
335
336 }
337}
338
339bitflags! {
340 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
342 pub struct ResolveConfigFamily: u32
343 {
344 const INET4_INET6 = 0x10;
346 const INET6_INET4 = 0x20;
348 const INET4 = 0x01;
350 const INET6 = 0x02;
352 }
353}
354
355impl ResolveConfigFamily
356{
357 pub
358 fn is_inet4(&self) -> bool
359 {
360 return self.contains(Self::INET4);
361 }
362
363 pub
364 fn is_inet6(&self) -> bool
365 {
366 return self.contains(Self::INET6);
367 }
368
369 pub
370 fn is_inet4_first(&self) -> bool
371 {
372 return self.contains(Self::INET4_INET6);
373 }
374
375 fn inverted_default() -> Self
376 {
377 return Self::INET6_INET4 | Self::INET4 | Self::INET6;
378 }
379}
380
381impl Default for ResolveConfigFamily
382{
383 fn default() -> Self
384 {
385 return Self::INET4_INET6 | Self::INET4 | Self::INET6;
386 }
387}
388
389const FAMILY_INET4: &'static str = "inet4";
390const FAMILY_INET6: &'static str = "inet6";
391
392impl TryFrom<&[String]> for ResolveConfigFamily
393{
394 type Error = CDnsError;
395
396 fn try_from(value: &[String]) -> Result<Self, Self::Error>
397 {
398 if value.is_empty() == true
399 {
400 internal_error!(CDnsErrorType::ConfigError, "'family' is empty");
401 }
402 else if value.len() > 2
403 {
404 internal_error!(CDnsErrorType::ConfigError, "'family' is set with too many paramenters: '{:?}'", value);
405 }
406
407 let mut family =
408 if value[0] == FAMILY_INET4
409 {
410 Self::INET4_INET6 | Self::INET4
412 }
413 else if value[0] == FAMILY_INET6
414 {
415 Self::INET6_INET4 | Self::INET6
417 }
418 else
419 {
420 internal_error!(CDnsErrorType::ConfigError, "'family' is set with unknown parameter: '{}'", value[0]);
421 };
422
423 if value.len() == 2
424 {
425 if value[1] == FAMILY_INET4
426 {
427 if family.contains(Self::INET4) == true
428 {
429 internal_error!(CDnsErrorType::ConfigError, "'family' is set with duplicate parameter: '{}'", value[1]);
430 }
431
432 family |= Self::INET4
434 }
435 else if value[1] == FAMILY_INET6
436 {
437 if family.contains(Self::INET6) == true
438 {
439 internal_error!(CDnsErrorType::ConfigError, "'family' is set with duplicate parameter: '{}'", value[1]);
440 }
441
442 family |= Self::INET6
444 }
445 else
446 {
447 internal_error!(CDnsErrorType::ConfigError, "'family' is set with unknown parameter: '{}'", value[0]);
448 }
449 }
450
451 return Ok(family);
452 }
453}
454
455
456bitflags! {
457 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
459 pub struct OptionFlags: u16
460 {
461 const OPT_DEBUG = 0x0001;
463
464 const OPT_ROTATE = 0x0002;
466
467 const OPT_NO_CHECK_NAMES = 0x0004;
471
472 const OPT_INET6 = 0x0008;
474
475 const OPT_SINGLE_REQUEST = 0x0010;
478
479 const OPT_SINGLE_REQUEST_REOPEN = 0x0020;
482
483 const OPT_NO_RELOAD = 0x0040;
485
486 const OPT_TRUST_AD = 0x0080;
488
489 const OPT_USE_VC = 0x0100;
491 }
492}
493
494impl Default for OptionFlags
495{
496 fn default() -> Self
497 {
498 return Self::empty();
499 }
500}
501
502impl OptionFlags
503{
504 pub
505 fn is_debug(&self) -> bool
506 {
507 return self.contains(Self::OPT_DEBUG);
508 }
509
510 pub
511 fn is_rotate(&self) -> bool
512 {
513 return self.contains(Self::OPT_ROTATE);
514 }
515
516 pub
517 fn is_no_check_names(&self) -> bool
518 {
519 return self.contains(Self::OPT_NO_CHECK_NAMES);
520 }
521
522 pub
523 fn is_no_parallel(&self) -> bool
524 {
525 return self.contains(Self::OPT_SINGLE_REQUEST);
526 }
527
528 pub
529 fn is_reopen_socket(&self) -> bool
530 {
531 return self.contains(Self::OPT_SINGLE_REQUEST_REOPEN);
532 }
533
534 pub
535 fn is_force_tcp(&self) -> bool
536 {
537 return self.contains(Self::OPT_USE_VC);
538 }
539}
540
541
542#[derive(Clone, Debug, PartialEq, Eq)]
543pub struct ResolveConfig
544{
545 pub nameservers: Vec<Arc<ResolveConfEntry>>,
546 pub lookup: ResolveConfigLookup,
547 pub family: ResolveConfigFamily,
548 pub search_list: Vec<String>,
549 pub domain: Option<String>,
550 pub option_flags: OptionFlags,
551 pub ndots: usize,
552 pub timeout: u16,
553 pub attempts: usize,
554}
555
556impl Default for ResolveConfig
557{
558 fn default() -> Self
559 {
560 return
561 ResolveConfig
562 {
563 nameservers: vec![],
564 lookup: ResolveConfigLookup::default(),
565 family: ResolveConfigFamily::default(),
566 search_list: vec![],
567 domain: None,
568 option_flags: OptionFlags::default(),
569 ndots: 1,
570 timeout: 5,
571 attempts: 2,
572 };
573 }
574}
575
576impl ResolveConfig
577{
578 pub
587 fn get_resolvers_iter(&self) -> RoundRobinIterator<Arc<ResolveConfEntry>>
588 {
589 if self.option_flags.is_rotate() == true
590 {
591 let start_index = ROUND_ROBIN_CNT.fetch_add(1, Ordering::SeqCst);
592
593 return RoundRobinIterator::new(start_index, self.nameservers.as_slice());
594 }
595 else
596 {
597 return RoundRobinIterator::new(0, self.nameservers.as_slice());
598 };
599 }
600
601 fn split_ext(field_data: &str) -> CDnsResult<(&str, u16, Option<String>)>
604 {
605 let splited = field_data.split("#").collect::<Vec<&str>>();
606 let mut port: u16 = 53;
607 let mut domain: Option<String> = None;
608
609 if splited.is_empty() == true
610 {
611 return Ok((field_data, port, domain));
612 }
613
614 let mut splt_iter = splited.into_iter();
615 let without_ext = splt_iter.nth(0).unwrap();
616
617
618 for ext in splt_iter
619 {
620 if ext.starts_with("@") == true
621 {
622 port =
624 u16::from_str_radix(&ext[1..], 10).map_err(|e|
625 internal_error_map!(CDnsErrorType::InternalError, "can not parse port number, {}", e)
626 )?;
627 }
628 else
629 {
630 domain = Some(ext.to_string());
632 }
633 }
634
635 return Ok((without_ext, port, domain));
636 }
637
638 fn split_dns_ifr(field_data: &str, ifr: &IfInfo) -> CDnsResult<(IpAddr, SocketAddr)>
639 {
640 if let Some((ip, intf)) = field_data.split_once("%")
641 {
642 let ip_addr: IpAddr =
643 ip.parse().map_err(|e|
644 internal_error_map!(CDnsErrorType::InternalError, "parse IP: '{}' failed: '{}'", ip, e)
645 )?;
646
647
648 match unsafe { ifr.get_ifr_ip(intf, &ip_addr)? }
649 {
650 Some(ip_ifr) =>
651 return Ok( (ip_addr, SocketAddr::from((ip_ifr, 0))) ),
652 None =>
653 internal_error!(CDnsErrorType::InternalError, "interface: '{}' does not exist", intf),
654 }
655 }
656 else
657 {
658 let ip_addr: IpAddr =
659 field_data.parse().map_err(|e|
660 internal_error_map!(CDnsErrorType::InternalError, "parse IP: '{}' failed: '{}'", field_data, e)
661 )?;
662
663 let ip_ifr = bind_all(ip_addr);
664 return Ok((ip_addr, ip_ifr))
673 }
674 }
675
676 #[inline]
677 fn set_option(
678 optname: &'static str,
679 right: Option<&str>,
680 option_flags: &mut OptionFlags,
681 opt_flag: OptionFlags
682 ) -> CDnsResult<()>
683 {
684 if right.is_some() == true
685 {
686 internal_error!(CDnsErrorType::ConfigError,
687 "in /etc/resolv.conf - 'option' '{}' is defined \
688 with parameter: '{}', but it does not have parameters", optname, right.unwrap());
689 }
690
691 option_flags.set(opt_flag, true);
692
693 return Ok(());
694 }
695
696 #[inline]
697 fn read_parameter<P: FromStr>(optname: &'static str, right: Option<&str>) -> CDnsResult<P>
698 {
699 if right.is_none() == true
700 {
701 internal_error!(CDnsErrorType::ConfigError,
702 "in /etc/resolv.conf - 'option' '{}' is defined without parameter", optname);
703 }
704 else
705 {
706 return
707 right.unwrap()
708 .parse::<P>()
709 .map_err(|_|
710 internal_error_map!(
711 CDnsErrorType::ConfigError,
712 "in /etc/resolv.conf - 'option' '{}' is defined with invalid \
713 parameter: '{}'", optname, right.unwrap()
714 )
715 );
716 }
717 }
718
719 pub(crate)
725 fn parser_resolv_internal(file_content: &str) -> CDnsResult<Self>
726 {
727 let mut tk = ConfTokenizer::from_str(&file_content)?;
728
729 let mut dns_list: Vec<Arc<ResolveConfEntry>> = Vec::new();
730 let mut lookup_list: ResolveConfigLookup = ResolveConfigLookup::default();
731 let mut family_list: ResolveConfigFamily = ResolveConfigFamily::default();
732
733 let mut search_list: Vec<String> = Vec::new();
735
736 let mut domain: Option<String> = None;
737 let mut option_flags: OptionFlags = OptionFlags::empty();
738 let mut ndots: usize = 1;
739 let mut timeout: u16 = 5;
740 let mut attempts: usize = 2;
741
742 let if_info: IfInfo = unsafe { IfInfo::get_interfaces_info()? };
743
744 loop
745 {
746 let field_name = tk.read_next()?;
747
748 if field_name.is_none() == true
749 {
750 break;
752 }
753
754 let field_name = field_name.unwrap();
755
756 if field_name == "nameserver"
757 {
758 let Some(field_data) = tk.read_next()?
760 else
761 {
762 internal_error!(CDnsErrorType::ConfigError, "unexpected EOF near nameserver");
764 };
765
766 let ext_split_res = Self::split_ext(field_data);
768
769 let Ok((without_ext, port, domain)) = ext_split_res
770 else
771 {
772 internal_error!(CDnsErrorType::ConfigError, "{}", ext_split_res.err().unwrap());
773 };
774
775 let split = Self::split_dns_ifr(without_ext, &if_info);
776
777 let Ok((dns_ip, ifr_ip)) = split
778 else
779 {
780 internal_error!(CDnsErrorType::ConfigError, "{}", split.err().unwrap());
781 };
782
783
784 dns_list.push(
785 Arc::new(ResolveConfEntry::new(SocketAddr::new(dns_ip, port), domain, ifr_ip)?)
786 );
787
788
789 }
790 else if field_name == "lookup" {
792 let lookups = tk.read_upto_eol()?;
794
795 if lookups.len() == 0
796 {
797 write_error!(internal_error_map!(CDnsErrorType::ConfigError, "in /etc/resolv.conf - 'lookup' is set but no args provided, setting defaults file, bind"));
798
799 continue;
800 }
801
802 lookup_list =
803 match ResolveConfigLookup::try_from(lookups.as_slice())
804 {
805 Ok(r) => r,
806 Err(e) =>
807 {
808 write_error!(internal_error_map!(CDnsErrorType::ConfigError, "in /etc/resolv.conf - {}", e));
809
810 continue;
811 }
812 };
813 }
814 else if field_name == "family" {
816 let families = tk.read_upto_eol()?;
818
819 if families.len() == 0
820 {
821 write_error!(internal_error_map!(CDnsErrorType::ConfigError, "in /etc/resolv.conf - 'family' is set but no args provided, setting defaults inet4, inet6"));
822
823 continue;
824 }
825
826 family_list =
827 match ResolveConfigFamily::try_from(families.as_slice())
828 {
829 Ok(r) => r,
830 Err(e) =>
831 {
832 write_error!(internal_error_map!(CDnsErrorType::ConfigError, "in /etc/resolv.conf - {}", e));
833 continue;
834 }
835 };
836 }
837 else if field_name == "search"
838 {
839 let searches = tk.read_upto_eol()?;
841
842 if searches.len() == 0
843 {
844 write_error!(internal_error_map!(CDnsErrorType::ConfigError, "in /etc/resolv.conf - 'search' is defined but empty"));
845 }
846 else
847 {
848 search_list.extend(searches);
849 }
850 }
851 else if field_name == "domain"
852 {
853 let mut domains = tk.read_upto_eol()?;
854
855 if domain.is_some() == true
856 {
857 write_error!(internal_error_map!(CDnsErrorType::ConfigError, "in /etc/resolv.conf - 'domain' is defined more than once: {:?} {:?}", domain, domains));
858 }
859
860 if domains.len() > 1
861 {
862 write_error!(internal_error_map!(CDnsErrorType::ConfigError, "in /etc/resolv.conf - 'domain' is defined with more than 1 address: {:?}", domains));
863 }
864 else if domains.len() == 0
865 {
866 write_error!(internal_error_map!(CDnsErrorType::ConfigError, "in /etc/resolv.conf - 'domain' is defined but empty"));
867 }
868 else
869 {
870 domain = Some(domains.pop().unwrap());
871 }
872 }
873 else if field_name == "options"
874 {
875
876 let options_vec = tk.read_upto_eol()?;
877
878 if options_vec.is_empty() == true
879 {
880 write_error!(internal_error_map!(CDnsErrorType::ConfigError, "in /etc/resolv.conf - 'option' is empty!"));
881
882 continue;
884 }
885
886 for option in options_vec
887 {
888 let (left, right) =
889 match option.split_once(":")
890 {
891 Some((l, r)) => (l, Some(r)),
892 None => (option.as_str(), None),
893 };
894
895 match left
896 {
897 "use-vc" | "usevc" | "tcp" => {
900 match Self::set_option("usevc", right, &mut option_flags, OptionFlags::OPT_USE_VC)
901 {
902 Err(e) =>
903 write_error!(e),
904 Ok(_) => {}
905 }
906 },
907 "debug" =>
908 {
909 match Self::set_option("debug", right, &mut option_flags, OptionFlags::OPT_DEBUG)
910 {
911 Err(e) =>
912 write_error!(e),
913 Ok(_) => {}
914 }
915 },
916 "ndots" =>
917 {
918 match Self::read_parameter("ndots", right)
919 {
920 Ok(val) =>
921 {
922 ndots = if val > 15 { 15 } else { val };
923 },
924 Err(e) =>
925 {
926 write_error!(e);
927 }
928 }
929 },
930 "timeout" =>
931 {
932 match Self::read_parameter::<u16>("timeout", right)
933 {
934 Ok(val) =>
935 {
936 timeout = if val > 30 { 30 } else { val };
937 },
938 Err(e) =>
939 {
940 write_error!(e);
941 }
942 }
943 },
944 "attempts" =>
945 {
946 match Self::read_parameter("attempts", right)
947 {
948 Ok(val) =>
949 {
950 attempts = if val > 5 { 5 } else { val };
951 },
952 Err(e) =>
953 {
954 write_error!(e);
955 }
956 }
957 },
958 "rotate" =>
959 {
960 match Self::set_option("rotate", right, &mut option_flags, OptionFlags::OPT_ROTATE)
961 {
962 Err(e) =>
963 write_error!(e),
964 Ok(_) => {}
965 }
966 },
967 "no-check-names" =>
968 {
969 match Self::set_option("no-check-names", right, &mut option_flags, OptionFlags::OPT_NO_CHECK_NAMES)
970 {
971 Err(e) =>
972 write_error!(e),
973 Ok(_) => {}
974 }
975 },
976 "no-reload" =>
977 {
978 match Self::set_option("no-reload", right, &mut option_flags, OptionFlags::OPT_NO_RELOAD)
979 {
980 Err(e) =>
981 write_error!(e),
982 Ok(_) => {}
983 }
984 },
985 "inet6" =>
986 {
987 match Self::set_option("inet6", right, &mut option_flags, OptionFlags::OPT_INET6)
989 {
990 Err(e) =>
991 write_error!(e),
992 Ok(_) => {}
993 }
994 },
995 "edns0" =>
996 {
997 },
999 "single-request" =>
1000 {
1001 match Self::set_option("single-request", right, &mut option_flags, OptionFlags::OPT_SINGLE_REQUEST)
1002 {
1003 Err(e) =>
1004 write_error!(e),
1005 Ok(_) => {}
1006 }
1007 },
1008 "single-request-reopen" =>
1009 {
1010 match Self::set_option("single-request-reopen", right, &mut option_flags, OptionFlags::OPT_SINGLE_REQUEST_REOPEN)
1011 {
1012 Err(e) =>
1013 write_error!(e),
1014 Ok(_) => {}
1015 }
1016 },
1017 "trust-ad" =>
1018 {
1019 match Self::set_option("trust-ad", right, &mut option_flags, OptionFlags::OPT_TRUST_AD)
1020 {
1021 Err(e) =>
1022 write_error!(e),
1023 Ok(_) => {}
1024 }
1025 },
1026 _ =>
1027 {
1028 write_error!(internal_error_map!(CDnsErrorType::ConfigError, "in /etc/resolv.conf - 'option' '{}' is unknown \
1029 with parameter: '{:?}'", left, right));
1030 },
1031 }
1032
1033
1034 }
1035 }
1036 else
1037 {
1038 tk.skip_upto_eol();
1040 }
1041 }
1042
1043 if option_flags.contains(OptionFlags::OPT_INET6) == true
1044 {
1045 family_list = ResolveConfigFamily::inverted_default();
1046 }
1047
1048
1049 return Ok(
1050 Self
1051 {
1052 nameservers: dns_list,
1053 lookup: lookup_list,
1054 family: family_list,
1055 search_list: search_list,
1056 domain: domain,
1057 option_flags: option_flags,
1058 ndots: ndots,
1059 timeout: timeout,
1060 attempts: attempts,
1061 }
1062 );
1063 }
1064}
1065
1066#[cfg(feature = "use_sync")]
1067#[cfg(test)]
1068mod tests
1069{
1070 use std::{net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, str::FromStr};
1071
1072 use crate::{cfg_resolv_parser::{OptionFlags, ResolveConfigFamily, ResolveConfigLookup}, sync::ResolveConfig};
1073
1074 #[test]
1075 fn test_parser_resolv_tls_0()
1076 {
1077 let ip1 = SocketAddr::new("1.1.1.1".parse::<IpAddr>().unwrap(), 853);
1078 let tls_domain1 = Some(String::from("cloudflare-dns.com"));
1079 let ip2 = SocketAddr::new("2606:4700:4700::1001".parse::<IpAddr>().unwrap(), 853);
1080 let tls_domain2 = Some(String::from("cloudflare-dns.com"));
1081 let ip3 = SocketAddr::new("127.0.0.1".parse().unwrap(), 853);
1082 let tls_domain3 = Some(String::from("localdomain"));
1083 let ip3_if: SocketAddr = SocketAddr::from((Ipv4Addr::from_str("127.0.0.1").unwrap(), 0));
1084 let ip4 = SocketAddr::new("8.8.8.8".parse().unwrap(), 55);
1085 let ip5 = SocketAddr::new("1.0.0.2".parse().unwrap(), 53);
1086 let ip6 = SocketAddr::new("1.1.1.1".parse::<IpAddr>().unwrap(), 443);
1087
1088 let test =
1089 "nameserver 1.1.1.1#@853#cloudflare-dns.com\n\
1090 nameserver 2606:4700:4700::1001#@853#cloudflare-dns.com\n\
1091 nameserver 127.0.0.1%lo#@853#localdomain\n\
1092 nameserver 8.8.8.8#@55\n\
1093 nameserver 1.0.0.2 #@853\n\
1094 nameserver 1.1.1.1#@443#https://cloudflare-dns.com/dns-query\n";
1095
1096 let res = ResolveConfig::parser_resolv_internal(test);
1097
1098 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
1099 let res = res.unwrap();
1100
1101 assert_eq!(res.family, ResolveConfigFamily::INET4_INET6 | ResolveConfigFamily::INET6 | ResolveConfigFamily::INET4);
1102
1103 assert_eq!(res.nameservers[0].ip, ip1);
1104 assert_eq!(res.nameservers[0].tls_domain.as_ref(), tls_domain1.as_ref());
1105 assert_eq!(res.nameservers[0].https_req_path, None);
1106 assert_eq!(res.nameservers[1].ip, ip2);
1107 assert_eq!(res.nameservers[1].tls_domain.as_ref(), tls_domain2.as_ref());
1108 assert_eq!(res.nameservers[2].ip, ip3);
1109 assert_eq!(res.nameservers[2].tls_domain.as_ref(), tls_domain3.as_ref());
1110 assert_eq!(res.nameservers[2].adapter_ip, ip3_if);
1111 assert_eq!(res.nameservers[3].ip, ip4);
1112 assert_eq!(res.nameservers[4].ip, ip5);
1113 assert_eq!(res.nameservers[5].ip, ip6);
1114 assert_eq!(res.nameservers[5].tls_domain, Some("cloudflare-dns.com".to_string()));
1115 assert_eq!(res.nameservers[5].https_req_path, Some("dns-query".to_string()));
1116 }
1117
1118 #[test]
1119 fn test_parser_resolv_internal_0()
1120 {
1121 let ip1 = SocketAddr::new("192.168.2.1".parse().unwrap(), 53);
1122 let ip2 = SocketAddr::new("127.0.0.1".parse().unwrap(), 53);
1123 let ip3 = SocketAddr::new("8.8.8.8".parse().unwrap(), 53);
1124 let ip4 = SocketAddr::new("127.0.0.1".parse().unwrap(), 53);
1125 let ip4_if: SocketAddr = SocketAddr::from((Ipv4Addr::from_str("127.0.0.1").unwrap(), 0));
1126 let ip5 = SocketAddr::new("fe80::1".parse().unwrap(), 53);
1127 let ip5_if: SocketAddr = SocketAddr::from((Ipv6Addr::from_str("::1").unwrap(), 0));
1128
1129 let test =
1130 "nameserver 192.168.2.1\n\
1131 nameserver 127.0.0.1\n\
1132 lookup bind\n\
1133 nameserver 8.8.8.8\n
1134 nameserver 127.0.0.1%lo\n
1135 nameserver fe80::1%lo\n";
1136
1137
1138 let res = ResolveConfig::parser_resolv_internal(test);
1139
1140 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
1141 let res = res.unwrap();
1142
1143 assert_eq!(res.lookup, ResolveConfigLookup::BIND);
1144
1145 assert_eq!(res.family, ResolveConfigFamily::INET4_INET6 | ResolveConfigFamily::INET6 | ResolveConfigFamily::INET4);
1146
1147 assert_eq!(res.nameservers[0].ip, ip1);
1148 assert_eq!(res.nameservers[1].ip, ip2);
1149 assert_eq!(res.nameservers[2].ip, ip3);
1150 assert_eq!(res.nameservers[3].ip, ip4);
1151 assert_eq!(res.nameservers[3].adapter_ip, ip4_if);
1152 assert_eq!(res.nameservers[4].ip, ip5);
1153 assert_eq!(res.nameservers[4].adapter_ip, ip5_if);
1154 }
1155
1156 #[test]
1157 fn test_parser_resolv_internal()
1158 {
1159 let ip1 = SocketAddr::new("192.168.2.1".parse().unwrap(), 53);
1160 let ip2 = SocketAddr::new("127.0.0.1".parse().unwrap(), 53);
1161 let ip3 = SocketAddr::new("8.8.8.8".parse().unwrap(), 53);
1162
1163 let test =
1164 "nameserver 192.168.2.1\n\
1165 nameserver 127.0.0.1\n\
1166 lookup bind file\n\
1167 nameserver 8.8.8.8";
1168
1169 let res = ResolveConfig::parser_resolv_internal(test);
1170 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
1171 let res = res.unwrap();
1172
1173 assert_eq!(res.lookup, ResolveConfigLookup::BIND | ResolveConfigLookup::FILE | ResolveConfigLookup::BIND_FILE);
1174
1175 assert_eq!(res.family, ResolveConfigFamily::INET4_INET6 | ResolveConfigFamily::INET6 | ResolveConfigFamily::INET4);
1176
1177 assert_eq!(res.nameservers[0].ip, ip1);
1178 assert_eq!(res.nameservers[1].ip, ip2);
1179 assert_eq!(res.nameservers[2].ip, ip3);
1180 }
1181
1182 #[test]
1183 fn test_parser_resolv_internal2()
1184 {
1185 let ip1 = SocketAddr::new("192.168.2.1".parse().unwrap(), 53);
1186 let ip2 = SocketAddr::new("127.0.0.1".parse().unwrap(), 53);
1187 let ip3 = SocketAddr::new("8.8.8.8".parse().unwrap(), 53);
1188
1189 let test =
1190 "# test 12345\n\
1191 # nameserver 192.168.3.1
1192 nameserver 192.168.2.1 \n\
1193 nameserver 127.0.0.1 \n\
1194 lookup file\n\
1195 family inet4\n\
1196 nameserver 8.8.8.8\n";
1197
1198 let res = ResolveConfig::parser_resolv_internal(test);
1199 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
1200 let res = res.unwrap();
1201
1202 assert_eq!(res.lookup, ResolveConfigLookup::FILE);
1203
1204 assert_eq!(res.family, ResolveConfigFamily::INET4 | ResolveConfigFamily::INET4_INET6);
1205
1206 assert_eq!(res.nameservers.len(), 3);
1207 assert_eq!(res.nameservers[0].ip, ip1);
1208 assert_eq!(res.nameservers[1].ip, ip2);
1209 assert_eq!(res.nameservers[2].ip, ip3);
1210 }
1211
1212 #[test]
1213 fn test_parser_resolv_internal3()
1214 {
1215 let ip1 = SocketAddr::new("192.168.2.1".parse().unwrap(), 53);
1216 let ip2 = SocketAddr::new("127.0.0.1".parse().unwrap(), 53);
1217 let ip3 = SocketAddr::new("8.8.8.8".parse().unwrap(), 53);
1218
1219 let test =
1220 "# test 12345\n\
1221 # nameserver 192.168.3.1
1222 nameserver 192.168.2.1 \n\
1223 nameserver 127.0.0.1 \n\
1224 lookup file\n\
1225 family inet4\n\
1226 nameserver 8.8.8.8\n
1227 options attempts:1 timeout:3 debug use-vc single-request-reopen\n
1228 search localdomain";
1229
1230 let res = ResolveConfig::parser_resolv_internal(test);
1231 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
1232 let res = res.unwrap();
1233
1234 assert_eq!(res.lookup, ResolveConfigLookup::FILE);
1235
1236 assert_eq!(res.family, ResolveConfigFamily::INET4_INET6 | ResolveConfigFamily::INET4);
1237
1238 assert_eq!(res.nameservers.len(), 3);
1239 assert_eq!(res.nameservers[0].ip, ip1);
1240 assert_eq!(res.nameservers[1].ip, ip2);
1241 assert_eq!(res.nameservers[2].ip, ip3);
1242
1243 assert_eq!(res.search_list[0], "localdomain");
1244
1245 assert_eq!(res.timeout, 3);
1246 assert_eq!(res.attempts, 1);
1247
1248 assert_eq!(res.option_flags.contains(OptionFlags::OPT_DEBUG), true);
1249 assert_eq!(res.option_flags.contains(OptionFlags::OPT_USE_VC), true);
1250 assert_eq!(res.option_flags.contains(OptionFlags::OPT_SINGLE_REQUEST_REOPEN), true);
1251 }
1252
1253 #[test]
1254 fn test_parser_resolv_internal4()
1255 {
1256 let ip1 = SocketAddr::new("192.168.2.1".parse().unwrap(), 53);
1257 let ip2 = SocketAddr::new("127.0.0.1".parse().unwrap(), 53);
1258 let ip3 = SocketAddr::new("8.8.8.8".parse().unwrap(), 53);
1259
1260 let test =
1261 "\
1262 # test 12345\n\
1263 # nameserver 192.168.3.1\n\
1264 nameserver 192.168.2.1 \n\
1265 nameserver 127.0.0.1 \n\
1266 lookup file\n\
1267 family inet4 \n\
1268 nameserver 8.8.8.8\n\
1269 options attempts:1 timeout:3 debug use-vc single-request-reopen\n\
1270 search localdomain\n\
1271 ";
1272
1273
1274 let res = ResolveConfig::parser_resolv_internal(test);
1275 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
1276 let res = res.unwrap();
1277
1278 assert_eq!(res.lookup, ResolveConfigLookup::FILE);
1279
1280 assert_eq!(res.family, ResolveConfigFamily::INET4_INET6 | ResolveConfigFamily::INET4);
1281
1282 assert_eq!(res.nameservers.len(), 3);
1283 assert_eq!(res.nameservers[0].ip, ip1);
1284 assert_eq!(res.nameservers[1].ip, ip2);
1285 assert_eq!(res.nameservers[2].ip, ip3);
1286
1287 assert_eq!(res.search_list[0], "localdomain");
1288
1289 assert_eq!(res.timeout, 3);
1290 assert_eq!(res.attempts, 1);
1291
1292 assert_eq!(res.option_flags.contains(OptionFlags::OPT_DEBUG), true);
1293 assert_eq!(res.option_flags.contains(OptionFlags::OPT_USE_VC), true);
1294 assert_eq!(res.option_flags.contains(OptionFlags::OPT_SINGLE_REQUEST_REOPEN), true);
1295 }
1296
1297 #[test]
1298 fn test_roundrobin_iter_1()
1299 {
1300 use std::time::Instant;
1301
1302 fn check_order(res: &ResolveConfig, ipl: &[SocketAddr], indx: usize)
1303 {
1304 let mut i = indx;
1305 let assert_i = (indx + ipl.len()) % ipl.len();
1306 let now = Instant::now();
1307
1308 let itr = res.get_resolvers_iter();
1309
1310 assert_eq!(itr.len(), ipl.len());
1311
1312 for n in itr
1313 {
1314 assert_eq!(n.ip, ipl[i]);
1316
1317 i += 1;
1318
1319 i %= ipl.len();
1320
1321 }
1322
1323 assert_eq!(i, assert_i);
1324
1325 let elapsed = now.elapsed();
1326 println!("Iter Elapsed: {:.2?}", elapsed);
1327 }
1328
1329 let ip1 = SocketAddr::new("192.168.2.1".parse().unwrap(), 53);
1330
1331 let ip_list: Vec<SocketAddr> = vec![ip1];
1332
1333 let test =
1334 "\
1335 # test 12345\n\
1336 # nameserver 192.168.3.1\n\
1337 nameserver 192.168.2.1 \n\
1338 #nameserver 127.0.0.1 \n\
1339 lookup file\n\
1340 family inet4 \n\
1341 #nameserver 8.8.8.8\n\
1342 options attempts:1 rotate timeout:3 debug use-vc single-request-reopen\n\
1343 search localdomain\n\
1344 ";
1345
1346 let now = Instant::now();
1347
1348
1349 let res = ResolveConfig::parser_resolv_internal(test);
1350
1351 let elapsed = now.elapsed();
1352 println!("parser_resolv_internal elapsed: {:.2?}", elapsed);
1353
1354 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
1355 let res = res.unwrap();
1356
1357 check_order(&res, &ip_list, 0);
1358 check_order(&res, &ip_list, 0);
1359 check_order(&res, &ip_list, 0);
1360 check_order(&res, &ip_list, 0);
1361 check_order(&res, &ip_list, 0);
1362 check_order(&res, &ip_list, 0);
1363 check_order(&res, &ip_list, 0);
1364 check_order(&res, &ip_list, 0);
1365 check_order(&res, &ip_list, 0);
1366 }
1367
1368 #[test]
1369 fn test_roundrobin_iter()
1370 {
1371 use std::time::Instant;
1372
1373 fn check_order(res: &ResolveConfig, ipl: &[SocketAddr], indx: usize)
1374 {
1375 let mut i = indx;
1376 let assert_i = (indx + ipl.len()) % ipl.len();
1377 let now = Instant::now();
1378
1379 let itr = res.get_resolvers_iter();
1380
1381 assert_eq!(itr.len(), ipl.len());
1382
1383 for n in itr
1384 {
1385 assert_eq!(n.ip, ipl[i]);
1387
1388 i += 1;
1389
1390 i %= ipl.len();
1391
1392 }
1393
1394 assert_eq!(i, assert_i);
1395
1396 let elapsed = now.elapsed();
1397 println!("Iter Elapsed: {:.2?}", elapsed);
1398 }
1399
1400 let ip1 = SocketAddr::new("192.168.2.1".parse().unwrap(), 53);
1401 let ip2 = SocketAddr::new("127.0.0.1".parse().unwrap(), 53);
1402 let ip3 = SocketAddr::new("8.8.8.8".parse().unwrap(), 53);
1403
1404 let ip_list: Vec<SocketAddr> = vec![ip1, ip2, ip3];
1405
1406 let test =
1407 "\
1408 # test 12345\n\
1409 # nameserver 192.168.3.1\n\
1410 nameserver 192.168.2.1 \n\
1411 nameserver 127.0.0.1 \n\
1412 lookup file\n\
1413 family inet4 \n\
1414 nameserver 8.8.8.8\n\
1415 options attempts:1 rotate timeout:3 debug use-vc single-request-reopen\n\
1416 search localdomain\n\
1417 ";
1418
1419 let now = Instant::now();
1420
1421 let res = ResolveConfig::parser_resolv_internal(test);
1422
1423 let elapsed = now.elapsed();
1424 println!("parser_resolv_internal elapsed: {:.2?}", elapsed);
1425
1426 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
1427 let res = res.unwrap();
1428
1429 check_order(&res, &ip_list, 0);
1430 check_order(&res, &ip_list, 1);
1431 check_order(&res, &ip_list, 2);
1432 check_order(&res, &ip_list, 0);
1433 check_order(&res, &ip_list, 1);
1434 check_order(&res, &ip_list, 2);
1435 check_order(&res, &ip_list, 0);
1436 check_order(&res, &ip_list, 1);
1437 check_order(&res, &ip_list, 2);
1438 }
1439
1440 #[test]
1441 fn test_direct_iter()
1442 {
1443 use std::time::Instant;
1444
1445 let ip1 = SocketAddr::new("192.168.2.1".parse().unwrap(), 53);
1446 let ip2 = SocketAddr::new("192.168.2.2".parse().unwrap(), 53);
1447
1448 let test =
1449 "\
1450 # test 12345\n\
1451 # nameserver 192.168.3.1\n\
1452 nameserver 192.168.2.1 \n\
1453 nameserver 192.168.2.2 \n\
1454 lookup file\n\
1455 family inet4 \n\
1456 options attempts:1 timeout:3 debug use-vc single-request-reopen\n\
1457 search localdomain\n\
1458 ";
1459
1460 let now = Instant::now();
1461
1462
1463 let res = ResolveConfig::parser_resolv_internal(test);
1464
1465 let elapsed = now.elapsed();
1466 println!("Elapsed: {:.2?}", elapsed);
1467
1468 assert_eq!(res.is_ok(), true, "{}", res.err().unwrap());
1469 let res = res.unwrap();
1470
1471 let mut i: usize = 0;
1472
1473 let now = Instant::now();
1474
1475 for n in res.get_resolvers_iter()
1476 {
1477 match i
1478 {
1479 0 => { assert_eq!(n.ip, ip1); i += 1; },
1480 1 => { assert_eq!(n.ip, ip2); i += 1; },
1481 _ => panic!("!")
1482 }
1483 }
1484
1485 let elapsed = now.elapsed();
1486 println!("Iter Elapsed: {:.2?}", elapsed);
1487
1488 assert_eq!(i, 2);
1489
1490 i = 0;
1491 for n in res.get_resolvers_iter()
1492 {
1493 match i
1494 {
1495 0 => { assert_eq!(n.ip, ip1); i += 1; },
1496 1 => { assert_eq!(n.ip, ip2); i += 1; },
1497 _ => panic!("!")
1498 }
1499 }
1500
1501 assert_eq!(i, 2);
1502 }
1503
1504}