1use std::{borrow::Cow, cmp::Ordering, fmt::{self}, io::{Cursor, Read, Write}, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, path::Path, sync::{LazyLock, OnceLock}, time::Duration};
51use std::borrow::Borrow;
52use std::hash::{Hash, Hasher};
53
54use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
55
56use crate::{cfg_host_parser::HostnameEntry, common, error::*, internal_error_map, query_private::QDnsReq};
57use crate::internal_error;
58
59pub const RESOLV_CFG_PATH: &'static str = "/etc/resolv.conf";
61
62pub const HOST_CFG_PATH: &'static str = "/etc/hosts";
64
65pub static RESOLV_CFG_PATH_P: LazyLock<&'static Path> = LazyLock::new(|| {Path::new(RESOLV_CFG_PATH)});
66pub static HOST_CFG_PATH_P: LazyLock<&'static Path> = LazyLock::new(|| {Path::new(HOST_CFG_PATH)});
67
68pub static GLOBALS: OnceLock<CDdnsGlobals> = OnceLock::new();
69
70pub const NSSWITCH_CFG_PATH: &'static str = "/etc/nsswitch.conf";
72
73const IN_ADDR_ARPA: &[u8] = b"\x07in-addr\x04arpa\x00";
74const IN_ADDR6_ARPA: &[u8] = b"\x03ip6\x04arpa\x00";
75
76pub const DEF_USERAGENT: &'static str = concat!("CDNS-RS/", env!("CARGO_PKG_VERSION"));
77pub const DEF_TLS_PORT: u16 = 853;
78pub const DEF_HTTPS_PORT: u16 = 443;
79
80pub const IPV4_BIND_ALL: IpAddr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
82pub const IPV6_BIND_ALL: IpAddr = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
84
85#[derive(Debug)]
86pub struct CDdnsGlobals
87{
88 pub tcp_timeout: Option<Duration>,
89}
90
91impl CDdnsGlobals
92{
93 pub
96 fn init_once(globals: CDdnsGlobals)
97 {
98 GLOBALS.get_or_init(|| globals);
99
100 return;
101 }
102
103 pub
104 fn get_tcp_conn_timeout() -> Option<Duration>
105 {
106 return GLOBALS.get().map_or(None, |f| f.tcp_timeout);
107 }
108}
109
110#[inline]
111pub
112fn bind_all(ip_addr: IpAddr) -> SocketAddr
113{
114 match ip_addr
115 {
116 IpAddr::V4(_) =>
117 SocketAddr::from((IPV4_BIND_ALL, 0)),
118 IpAddr::V6(_) =>
119 SocketAddr::from((IPV6_BIND_ALL, 0)),
120 }
121}
122
123pub
124fn pkt2string_exact(pkt: &mut Cursor<&[u8]>, rdlen: u16) -> CDnsResult<String>
125{
126 let mut new_string = vec![0_u8; rdlen as usize];
127
128
129 pkt.read_exact(&mut new_string).map_err(map_read_err)?;
130
131
132 return
133 String::from_utf8(new_string)
134 .map_err(|e|
135 internal_error_map!(CDnsErrorType::InternalError, "UTF-8 decode error, {}", e)
136 );
137}
138
139pub
140fn pkt2vec(pkt: &mut Cursor<&[u8]>, rdlen: Option<u16>) -> CDnsResult<Vec<u8>>
141{
142 if let Some(rdl) = rdlen
143 {
144 let mut new_buf = vec![0_u8; rdl as usize];
145
146
147 pkt.read_exact(&mut new_buf).map_err(map_read_err)?;
148
149
150 return Ok(new_buf);
151 }
152 else
153 {
154 let mut new_buf = Vec::new();
155
156 pkt.read_to_end(&mut new_buf).map_err(map_read_err)?;
157
158 return Ok(new_buf);
159 }
160}
161
162pub
173fn pkt2name(pkt: &mut Cursor<&[u8]>) -> CDnsResult<Vec<u8>>
174{
175 let qname_s = pkt.position() as usize;
176
177 loop
180 {
181 let cnt = pkt.read_u8().map_err(map_read_err)? as usize;
182
183
184
185 if cnt == 0
186 {
187 break;
188 }
189 else
190 {
191 for _ in 0..cnt
217 {
218 let c = pkt.read_u8().map_err(map_read_err)?;
219 if c == 0
220 {
221 internal_error!(
222 CDnsErrorType::DnsResponse,
223 "incorrectly encoded QNAME in response, found '0' at offset: '{}'",
224 pkt.position()
225 );
226 }
227 }
228 }
229 } let cur_pos = pkt.position() as usize;
233
234 if (cur_pos - qname_s) <= 1
235 {
236 internal_error!(
237 CDnsErrorType::DnsResponse,
238 "read name is too short"
239 );
240 }
241
242 return Ok(pkt.get_ref()[qname_s..cur_pos].to_vec());
253}
254
255
256pub
258fn name2str(pkt: &mut Cursor<&[u8]>, mut opt_rdlen: Option<u16>) -> CDnsResult<String>
259{
260 let cur_in_pos = pkt.position();
261 let mut comp: u8;
263 let mut output: Vec<String> = Vec::with_capacity(6);
264
265 loop
266 {
267 if let Some(rdlen) = opt_rdlen
268 {
269 if pkt.position() - cur_in_pos >= rdlen as u64
270 {
271 return Ok(output.join("."));
272 }
273 }
274
275 comp = pkt.read_u8().map_err(map_read_err)?;
278
279 let msb = comp & 0xC0;
285
286 if msb == 0xC0
287 {
288 if opt_rdlen.is_none() == true
289 {
290 opt_rdlen = Some(2);
291 }
292
293 let offset1: u16 = ((comp & !0xC0) as u16) << 8;let offset2: u16 = pkt.read_u8().map_err(map_read_err)? as u16;
295
296 let offset = offset1 | offset2;
297
298 if offset as usize >= pkt.get_ref().len()
302 {
303 internal_error!(
304 CDnsErrorType::DnsResponse,
305 "incoreclty formated packet: offset: '{}' > len: '{}'",
306 offset, pkt.get_ref().len()
307 );
308 }
309
310 let cur_pos = pkt.position();
312 pkt.set_position(offset as u64);
313
314 output.push(name2str(pkt, None)?);
316
317 pkt.set_position(cur_pos);
319 }
320 else if msb == 0x00
321 {
322 if comp == 0
323 {
324 if let Some(rdlen) = opt_rdlen
325 {
326 let dif = pkt.position() - cur_in_pos;
327
328 if rdlen as u64 != dif
329 {
330 internal_error!(CDnsErrorType::DnsResponse, "incorrect rdlen: '{}', exp: '{}'", rdlen, dif);
331 }
332 }
333
334 return Ok(output.join("."));
335 }
336 else
337 {
338 let mut tmp = String::with_capacity(comp as usize);
339
340 for _ in 0..comp
341 {
342 let Some(c) = char::from_u32( pkt.read_u8().map_err(map_read_err)? as u32 )
343 else
344 {
345 internal_error!(CDnsErrorType::DnsResponse, "protocol violation, invalid character received");
346 };
347
348 if c.is_ascii_alphanumeric() == false && c != '-'
349 {
350 internal_error!(CDnsErrorType::DnsResponse, "protocol violation, forbidden characters in QNAME response");
351 }
352
353 tmp.push(c);
354 }
355
356 output.push(tmp);
357 }
358 }
359 else
360 {
361 internal_error!(CDnsErrorType::DnsResponse, "incorrect compression: {:x}", msb);
362 }
363
364 } }
366
367
368pub
383fn byte2hexchar(b: u8) -> u8
384{
385 match b
386 {
387 0..=9 => return '0' as u8 + b,
388 10..=15 => return 'a' as u8 + (b - 10),
389 _ => panic!("out of hex range!")
390 }
391}
392
393pub
404fn ip2pkt(ip: &IpAddr) -> Vec<u8>
405{
406 match *ip
407 {
408 IpAddr::V4(ref ipv4) =>
409 return ipv4_pkt(ipv4),
410 IpAddr::V6(ref ipv6) =>
411 return ipv6_pkt(ipv6)
412 };
413}
414
415const MAX_NAME_LEN: usize = 63;
416
417pub
418fn ipv4_pkt(ip: &Ipv4Addr) -> Vec<u8>
419{
420
421 let mut out: Vec<u8> = Vec::with_capacity(16 + IN_ADDR_ARPA.len());
423
424 ip
425 .octets()
426 .into_iter()
427 .rev()
428 .for_each(|v|
429 {
430 let st = v.to_string();
431 out.push(st.len() as u8);
432 out.extend(st.as_bytes());
433 }
434 );
435
436 out.extend_from_slice(IN_ADDR_ARPA);
437
438 return out;
439}
440
441pub
442fn ipv6_pkt(ip: &Ipv6Addr) -> Vec<u8>
443{
444 let mut out: Vec<u8> = Vec::with_capacity(32 + IN_ADDR6_ARPA.len());
446
447 let mut octets = ip.octets();
448 octets.reverse();
449
450 for oct in octets
451 {
452 let h_oct = byte2hexchar((oct & 0xF0) >> 4);
453 let l_oct = byte2hexchar(oct & 0x0F);
455 out.push(1);
460 out.push(l_oct);
461 out.push(1);
463 out.push(h_oct);
464 }
465
466 out.extend(IN_ADDR6_ARPA);
467
468 return out;
469}
470
471
472#[cfg(feature = "enable_IDN_support")]
473pub mod with_punycode
474{
475 use crate::external::rust_punycode;
476
477 use super::*;
478
479 pub
480 fn name2pkt(name: &str) -> CDnsResult<Vec<u8>>
481 {
482 let mut out: Vec<u8> = Vec::with_capacity(MAX_NAME_LEN);
484
485 for n in name.split(".")
486 {
487 let dom =
488 if n.chars().any(|c| c.is_ascii() == false) == true
489 {
490 rust_punycode::encode(n, true)?
491 }
492 else
493 {
494 n.to_string()
495 };
496
497 common::check_domain_ascii(&dom)?;
498
499
500 out.push((dom.len() & 0xFF) as u8);
501 out.extend(dom.as_bytes());
502 }
503
504 out.push(0);
505
506 if out.len() > 255
507 {
508 internal_error!(CDnsErrorType::InternalError,
509 "DNS name '{}' too long: {}", sanitize_str_unicode(name), out.len());
510 }
511
512 return Ok(out);
513 }
514}
515
516#[cfg(feature = "enable_IDN_support")]
517pub use self::with_punycode::*;
518
519
520#[cfg(not(feature = "enable_IDN_support"))]
521pub mod with_punycode
522{
523 use super::*;
524
525 pub
526 fn name2pkt(name: &str) -> CDnsResult<Vec<u8>>
527 {
528 let mut out: Vec<u8> = Vec::with_capacity(MAX_NAME_LEN);
530
531 for n in name.split(".")
532 {
533 let dom =
534 if n.chars().any(|c| c.is_ascii() == false) == true
535 {
536 internal_error!(CDnsErrorType::InternalError,
537 "DNS name '{}' contains non-ascii charactes, the IDN is disbaled",
538 sanitize_str_unicode(name));
539 }
540 else
541 {
542 n.to_string()
543 };
544
545 common::check_domain_ascii(&dom)?;
546
547
548 out.push((dom.len() & 0xFF) as u8);
549 out.extend(dom.as_bytes());
550 }
551
552 out.push(0);
553
554 if out.len() > 255
555 {
556 internal_error!(CDnsErrorType::InternalError,
557 "DNS name '{}' too long: {}", sanitize_str_unicode(name), out.len());
558 }
559
560 return Ok(out);
561 }
562}
563
564#[cfg(not(feature = "enable_IDN_support"))]
565pub use self::with_punycode::*;
566
567
568
569
570#[repr(u16)]
576#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
577pub enum QType
578{
579 A = 1,
581 NS = 2,
583 MD = 3,
585 MF = 4,
587 CNAME = 5,
589 SOA = 6,
591 MB = 7,
593 MG = 8,
595 MR = 9,
597 NULL = 10,
599 WKS = 11,
601 PTR = 12,
603 HINFO = 13,
605 MINFO = 14,
607 MX = 15,
609 TXT = 16,
611 AFSDB = 18,
613 KEY = 25,
615 AAAA = 28,
617 SRV = 33,
619 CERT = 37,
621 DS = 43,
623 RRSIG = 46,
625 NSEC = 47,
627 DNSKEY = 48,
629 NSEC3 = 50,
631 NSEC3PARAM = 51,
633 CDS = 59,
635 CDNSKEY = 60,
637 OPENPGPKEY = 61,
639 AXFR = 252,
642 MAILB = 253,
644 MAILA = 254,
646 URI = 256,
648 CAA = 257,
650 ALL = 255,
652 DLV = 32769,
654}
655
656impl Default for QType
657{
658 fn default() -> Self
659 {
660 return Self::A;
661 }
662}
663
664
665impl Into<u16> for QType
666{
667 fn into(self) -> u16
668 {
669 return self as u16;
670 }
671}
672
673impl fmt::Display for QType
674{
675 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
676 {
677 match *self
678 {
679 Self::A => write!(f, "A"),
680 Self::NS => write!(f, "NS"),
681 Self::MD => write!(f, "MD"),
682 Self::MF => write!(f, "MF"),
683 Self::CNAME => write!(f, "CNAME"),
684 Self::SOA => write!(f, "SOA"),
685 Self::MB => write!(f, "MB"),
686 Self::MG => write!(f, "MG"),
687 Self::MR => write!(f, "MR"),
688 Self::NULL => write!(f, "NULL"),
689 Self::WKS => write!(f, "WKS"),
690 Self::PTR => write!(f, "PTR"),
691 Self::HINFO => write!(f, "HINFO"),
692 Self::MINFO => write!(f, "MINFO"),
693 Self::MX => write!(f, "MX"),
694 Self::TXT => write!(f, "TXT"),
695 Self::AFSDB => write!(f, "AFSDB"),
696 Self::KEY => write!(f, "KEY"),
697 Self::AAAA => write!(f, "AAAA"),
698 Self::SRV => write!(f, "SRV"),
699 Self::CERT => write!(f, "CERT"),
700 Self::DS => write!(f, "DS"),
701 Self::RRSIG => write!(f, "RRSIG"),
702 Self::NSEC => write!(f, "NSEC"),
703 Self::DNSKEY => write!(f, "DNSKEY"),
704 Self::NSEC3 => write!(f, "NSEC"),
705 Self::NSEC3PARAM => write!(f, "NSEC3PARAM"),
706 Self::CDS => write!(f, "CDS"),
707 Self::CDNSKEY => write!(f, "CDNSKEY"),
708 Self::OPENPGPKEY => write!(f, "OPENPGPKEY"),
709 Self::AXFR => write!(f, "AXFR"),
710 Self::MAILB => write!(f, "MAILB"),
711 Self::MAILA => write!(f, "MAILA"),
712 Self::CAA => write!(f, "CAA"),
713 Self::ALL => write!(f, "ALL"),
714 Self::DLV => write!(f, "DLV"),
715 Self::URI => write!(f, "URI"),
716 }
717 }
718}
719
720
721impl QType
722{
723 pub
724 fn ipaddr_match(&self, ip: &IpAddr) -> bool
725 {
726 match *self
727 {
728 Self::A => return ip.is_ipv4(),
729 Self::AAAA => return ip.is_ipv6(),
730 _ => false,
731 }
732 }
733
734 pub
735 fn u16_to_qtype(value: u16) -> CDnsResult<QType>
736 {
737 match value
738 {
739 x if x == Self::AXFR as u16 => return Ok(Self::AXFR),
740 x if x == Self::MAILB as u16 => return Ok(Self::MAILB),
741 x if x == Self::MAILA as u16 => return Ok(Self::MAILA),
742 x if x == Self::ALL as u16 => return Ok(Self::ALL),
743 x if x == Self::DLV as u16 => return Ok(Self::DLV),
744 _ => return Self::u16_to_type(value),
745 }
746 }
747
748 pub
749 fn u16_to_type(value: u16) -> CDnsResult<QType>
750 {
751
752 match value
753 {
754 x if x == Self::A as u16 => return Ok(Self::A),
755 x if x == Self::NS as u16 => return Ok(Self::NS),
756 x if x == Self::MD as u16 => return Ok(Self::MD),
757 x if x == Self::MF as u16 => return Ok(Self::MF),
758 x if x == Self::CNAME as u16 => return Ok(Self::CNAME),
759 x if x == Self::SOA as u16 => return Ok(Self::SOA),
760 x if x == Self::MB as u16 => return Ok(Self::MB),
761 x if x == Self::MG as u16 => return Ok(Self::MG),
762 x if x == Self::MR as u16 => return Ok(Self::MR),
763 x if x == Self::NULL as u16 => return Ok(Self::NULL),
764 x if x == Self::WKS as u16 => return Ok(Self::WKS),
765 x if x == Self::PTR as u16 => return Ok(Self::PTR),
766 x if x == Self::HINFO as u16 => return Ok(Self::HINFO),
767 x if x == Self::MINFO as u16 => return Ok(Self::MINFO),
768 x if x == Self::MX as u16 => return Ok(Self::MX),
769 x if x == Self::TXT as u16 => return Ok(Self::TXT),
770 x if x == Self::AFSDB as u16 => return Ok(Self::AFSDB),
771 x if x == Self::KEY as u16 => return Ok(Self::KEY),
772 x if x == Self::AAAA as u16 => return Ok(Self::AAAA),
773 x if x == Self::CERT as u16 => return Ok(Self::CERT),
774 x if x == Self::DS as u16 => return Ok(Self::DS),
775 x if x == Self::RRSIG as u16 => return Ok(Self::RRSIG),
776 x if x == Self::NSEC as u16 => return Ok(Self::NSEC),
777 x if x == Self::DNSKEY as u16 => return Ok(Self::DNSKEY),
778 x if x == Self::NSEC3 as u16 => return Ok(Self::NSEC3),
779 x if x == Self::NSEC3PARAM as u16 => return Ok(Self::NSEC3PARAM),
780 x if x == Self::CDS as u16 => return Ok(Self::CDS),
781 x if x == Self::CDNSKEY as u16 => return Ok(Self::CDNSKEY),
782 x if x == Self::OPENPGPKEY as u16 => return Ok(Self::OPENPGPKEY),
783 _ => internal_error!(CDnsErrorType::DnsResponse, "unknown request record type: '{}'", value),
784 }
785 }
786}
787
788
789#[repr(u16)]
793#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
794pub enum QClass
795{
796 IN = 1,
798 CS = 2,
800 CH = 3,
802 HS = 4,
804
805 ALL = 255,
808}
809
810impl fmt::Display for QClass
811{
812 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
813 {
814 match *self
815 {
816 Self::IN => write!(f, "IN"),
817 Self::CS => write!(f, "CS"),
818 Self::CH => write!(f, "CH"),
819 Self::HS => write!(f, "HS"),
820 Self::ALL => write!(f, "ALL"),
821 }
822 }
823}
824
825impl Default for QClass
826{
827 fn default() -> Self
828 {
829 return Self::IN;
830 }
831}
832
833impl Into<u16> for QClass
834{
835 fn into(self) -> u16
836 {
837 return self as u16;
838 }
839}
840
841impl QClass
842{
843 pub
848 fn u16_to_qclass(value: u16) -> CDnsResult<QClass>
849 {
850 match value
851 {
852 x if x == QClass::ALL as u16 => return Ok(QClass::ALL),
853 _ => Self::u16_to_class(value),
854 }
855 }
856
857 pub
859 fn u16_to_class(value: u16) -> CDnsResult<QClass>
860 {
861 match value
862 {
863 x if x == QClass::IN as u16 => return Ok(QClass::IN),
864 x if x == QClass::CS as u16 => return Ok(QClass::CS),
865 x if x == QClass::CH as u16 => return Ok(QClass::CH),
866 x if x == QClass::HS as u16 => return Ok(QClass::HS),
867 _ => internal_error!(CDnsErrorType::DnsResponse, "unknown QCLASS type: '{}'", value),
868 }
869 }
870}
871
872bitflags! {
876 #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
878 pub struct StatusBits: u16
879 {
880 const QR_RESP = 0x8000;
883
884 const OPCODE_STANDARD = 0x87FF;
887 const OPCODE_IQUERY = 0x0040;
889 const OPCODE_STATUS = 0x0020;
891 const AUTH_ANSWER = 0x0400;
899
900 const TRUN_CATION = 0x0200;
904
905 const RECURSION_DESIRED = 0x0100;
911
912 const RECURSION_AVAIL = 0x0080;
917
918 const RSERVER0 = 0x0040;
922
923 const ANSWER_AUTHN = 0x0020;
924 const NON_AUTH_DATA = 0x0010;
925
926 const RESP_NOERROR = 0x0000;
930 const RESP_FORMERR = 0x0001;
932 const RESP_SERVFAIL = 0x0002;
935 const RESP_NXDOMAIN = 0x0003;
939 const RESP_NOT_IMPL = 0x0004;
941 const RESP_REFUSED = 0x0005;
944 }
946}
947
948#[derive(Clone, Debug, PartialEq, Eq)]
954pub enum QDnsName
955{
956 IpV4
957 {
958 query: Ipv4Addr,
959 encoded: Vec<u8>
960 },
961 IpV6
962 {
963 query: Ipv6Addr,
964 encoded: Vec<u8>
965 },
966 Name
967 {
968 query: String,
969 encoded: Vec<u8>
970 },
971}
972
973impl PartialEq<&[u8]> for QDnsName
974{
975 fn eq(&self, other: &&[u8]) -> bool
976 {
977 match self
978 {
979 Self::IpV4{ encoded, .. } |
980 Self::IpV6{ encoded, .. } |
981 Self::Name{ encoded, .. } =>
982 return encoded.as_slice() == *other
983 }
984 }
985}
986
987impl Default for QDnsName
988{
989 fn default() -> Self
990 {
991 let def = Ipv4Addr::new(0, 0, 0, 0);
992
993 return
994 Self::IpV4
995 {
996 query: def,
997 encoded: ipv4_pkt(&def)
998 };
999 }
1000}
1001
1002impl fmt::Display for QDnsName
1003{
1004 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1005 {
1006 match self
1007 {
1008 Self::IpV4 { query, .. } =>
1009 write!(f, "{}", query),
1010 Self::IpV6 { query, .. } =>
1011 write!(f, "{}", query),
1012 Self::Name { query, .. } =>
1013 write!(f, "{}", query)
1014 }
1015 }
1016}
1017
1018impl QDnsName
1019{
1020 pub
1023 fn is_ipv4(&self) -> bool
1024 {
1025 let Self::IpV4 { .. } = self
1026 else { return false };
1027
1028 return true;
1029 }
1030
1031 pub
1034 fn is_ipv6(&self) -> bool
1035 {
1036 let Self::IpV6 { .. } = self
1037 else { return false };
1038
1039 return true;
1040 }
1041
1042 pub
1045 fn is_ip(&self) -> bool
1046 {
1047 match *self
1048 {
1049 Self::IpV4{ .. } => return true,
1050 Self::IpV6{ .. } => return true,
1051 _ => return false,
1052 }
1053 }
1054
1055 pub
1057 fn get_ip_qtype(&self) -> Option<QType>
1058 {
1059 match *self
1060 {
1061 Self::IpV4{ .. } => return Some(QType::A),
1062 Self::IpV6{ .. } => return Some(QType::AAAA),
1063 Self::Name{ .. } => return None,
1064 }
1065 }
1066
1067 pub
1068 fn get_encoded_len(&self) -> usize
1069 {
1070 match self
1071 {
1072 Self::IpV4{ encoded, .. } |
1073 Self::IpV6{ encoded, .. } |
1074 Self::Name{ encoded, .. } =>
1075 return encoded.len()
1076 }
1077 }
1078}
1079
1080impl Hash for QDnsName
1081{
1082 fn hash<H: Hasher>(&self, state: &mut H)
1083 {
1084 core::mem::discriminant(self).hash(state);
1085
1086 match self
1087 {
1088 Self::IpV4{ query, .. } =>
1089 query.hash(state),
1090 Self::IpV6{ query, .. } =>
1091 query.hash(state),
1092 Self::Name{ query, .. } =>
1093 query.hash(state),
1094 }
1095 }
1096}
1097
1098impl PartialEq<str> for QDnsName
1099{
1100 fn eq(&self, other: &str) -> bool
1101 {
1102 match *self
1103 {
1104 Self::Name{ ref query, .. } =>
1105 return query.as_str() == other,
1106 Self::IpV4{ ref query, .. } =>
1107 {
1108 if let Ok(other_ip) = other.parse::<Ipv4Addr>()
1109 {
1110 return &other_ip == query;
1111 }
1112
1113 return false;
1114 },
1115 Self::IpV6{ ref query, .. } =>
1116 {
1117 if let Ok(other_ip) = other.parse::<Ipv6Addr>()
1118 {
1119 return &other_ip == query;
1120 }
1121
1122 return false;
1123 }
1124 }
1125 }
1126}
1127
1128
1129impl TryFrom<&IpAddr> for QDnsName
1130{
1131 type Error = CDnsError;
1132
1133 fn try_from(ip: &IpAddr) -> Result<Self, Self::Error>
1134 {
1135 let encoded = ip2pkt(ip);
1136
1137 match *ip
1138 {
1139 IpAddr::V4(ref ip) =>
1140 return Ok( Self::IpV4{ query: ip.clone(), encoded: encoded } ),
1141 IpAddr::V6(ref ip) =>
1142 return Ok( Self::IpV6{ query: ip.clone(), encoded: encoded } ),
1143 }
1144 }
1145}
1146
1147
1148impl TryFrom<IpAddr> for QDnsName
1149{
1150 type Error = CDnsError;
1151
1152 fn try_from(ip: IpAddr) -> Result<Self, Self::Error>
1153 {
1154 return Self::try_from(&ip);
1155 }
1156}
1157
1158
1159impl TryFrom<&Ipv4Addr> for QDnsName
1160{
1161 type Error = CDnsError;
1162
1163 fn try_from(ip: &Ipv4Addr) -> Result<Self, Self::Error>
1164 {
1165 return Ok(Self::IpV4{ query: ip.clone(), encoded: ipv4_pkt(ip) });
1166 }
1167}
1168
1169impl TryFrom<Ipv4Addr> for QDnsName
1170{
1171 type Error = CDnsError;
1172
1173 fn try_from(ip: Ipv4Addr) -> Result<Self, Self::Error>
1174 {
1175 return Self::try_from(&ip);
1176 }
1177}
1178
1179impl TryFrom<&Ipv6Addr> for QDnsName
1180{
1181 type Error = CDnsError;
1182
1183 fn try_from(ip: &Ipv6Addr) -> Result<Self, Self::Error>
1184 {
1185 return Ok( Self::IpV6{ query: ip.clone(), encoded: ipv6_pkt(ip) } );
1186 }
1187}
1188
1189impl TryFrom<Ipv6Addr> for QDnsName
1190{
1191 type Error = CDnsError;
1192
1193 fn try_from(ip: Ipv6Addr) -> Result<Self, Self::Error>
1194 {
1195 return Self::try_from(&ip);
1196 }
1197}
1198
1199impl TryFrom<&str> for QDnsName
1200{
1201 type Error = CDnsError;
1202
1203 fn try_from(name: &str) -> Result<Self, Self::Error>
1204 {
1205 return Self::try_from(name.to_string());
1206 }
1207}
1208
1209impl TryFrom<String> for QDnsName
1210{
1211 type Error = CDnsError;
1212
1213 fn try_from(name: String) -> Result<Self, Self::Error>
1214 {
1215 let Ok(ipp) = name.parse::<IpAddr>()
1216 else
1217 {
1218 let enc_name = name2pkt(&name)?;
1219
1220 return Ok( Self::Name{ query: name, encoded: enc_name} );
1221 };
1222
1223 return QDnsName::try_from(ipp);
1224 }
1225}
1226
1227impl From<QDnsName> for Vec<u8>
1228{
1229 fn from(qns: QDnsName) -> Self
1230 {
1231 match qns
1232 {
1233 QDnsName::IpV4{ encoded, .. } |
1234 QDnsName::IpV6{ encoded, .. } |
1235 QDnsName::Name{ encoded, .. } =>
1236 return encoded
1237 }
1238 }
1239}
1240
1241impl<'t> From<&'t QDnsName> for &'t [u8]
1242{
1243 fn from(qns: &'t QDnsName) -> Self
1244 {
1245 match qns
1246 {
1247 QDnsName::IpV4{ encoded, .. } |
1248 QDnsName::IpV6{ encoded, .. } |
1249 QDnsName::Name{ encoded, .. } =>
1250 return encoded.as_slice()
1251 }
1252 }
1253}
1254
1255impl<'t> From<&'t QDnsName> for Cow<'t, [u8]>
1256{
1257 fn from(qns: &'t QDnsName) -> Self
1258 {
1259 match qns
1260 {
1261 QDnsName::IpV4{ encoded, .. } |
1262 QDnsName::IpV6{ encoded, .. } |
1263 QDnsName::Name{ encoded, .. } =>
1264 return Cow::Borrowed(encoded.as_slice())
1265 }
1266 }
1267}
1268
1269
1270
1271impl From<&QDnsName> for String
1272{
1273 fn from(dnsname: &QDnsName) -> Self
1274 {
1275 match *dnsname
1276 {
1277 QDnsName::IpV4{ ref query, .. } =>
1278 {
1279 return query.to_string();
1280 },
1281 QDnsName::IpV6{ ref query, .. } =>
1282 {
1283 return query.to_string();
1284 },
1285 QDnsName::Name{ ref query, .. } =>
1286 {
1287 return query.to_string();
1288 }
1289 }
1290 }
1291}
1292
1293
1294impl TryFrom<&QDnsName> for IpAddr
1295{
1296 type Error = CDnsError;
1297 fn try_from(value: &QDnsName) -> Result<Self, Self::Error>
1298 {
1299 match value
1300 {
1301 QDnsName::IpV4{ query, .. } =>
1302 {
1303 return Ok(IpAddr::V4(query.clone()));
1304 },
1305 QDnsName::IpV6{ query, .. } =>
1306 {
1307 return Ok(IpAddr::V6(query.clone()));
1308 },
1309 QDnsName::Name{ query, .. } =>
1310 {
1311 if let Ok(ip) = query.parse::<Ipv4Addr>()
1312 {
1313 return Ok(IpAddr::V4(ip.clone()));
1314 }
1315 else if let Ok(ip) = query.parse::<Ipv6Addr>()
1316 {
1317 return Ok(IpAddr::V6(ip.clone()));
1318 }
1319 else
1320 {
1321 internal_error!(CDnsErrorType::InternalError, "not ip address!")
1322 }
1323 }
1324 }
1325 }
1326}
1327
1328
1329impl TryFrom<QDnsName> for IpAddr
1330{
1331 type Error = CDnsError;
1332 fn try_from(value: QDnsName) -> Result<Self, Self::Error>
1333 {
1334 match value
1335 {
1336 QDnsName::IpV4{ query, .. } =>
1337 {
1338 return Ok(IpAddr::V4(query));
1339 },
1340 QDnsName::IpV6{ query, .. } =>
1341 {
1342 return Ok(IpAddr::V6(query));
1343 },
1344 QDnsName::Name{ query, .. } =>
1345 {
1346 if let Ok(ip) = query.parse::<Ipv4Addr>()
1347 {
1348 return Ok(IpAddr::V4(ip));
1349 }
1350 else if let Ok(ip) = query.parse::<Ipv6Addr>()
1351 {
1352 return Ok(IpAddr::V6(ip));
1353 }
1354 else
1355 {
1356 internal_error!(CDnsErrorType::InternalError, "not ip address!")
1357 }
1358 }
1359 }
1360 }
1361}
1362
1363#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1364pub struct DnsHeader
1365{
1366 pub id: u16,
1369
1370 pub status: StatusBits,
1372
1373 pub qdcount: u16,
1376
1377 pub ancount: u16,
1380
1381 pub nscount: u16,
1385
1386 pub arcount: u16,
1389}
1390
1391impl fmt::Display for DnsHeader
1392{
1393 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1394 {
1395 write!(f, "ID:{} Status:{:?}, qdcnt:{}, ancnt:{}, nscnt:{}, arcnt:{}",
1396 self.id, self.status, self.qdcount, self.ancount, self.nscount, self.arcount)
1397 }
1398}
1399
1400
1401#[derive(Clone, Debug, PartialEq, Eq)]
1402pub struct DnsRequestAnswer<'temp>
1403{
1404 pub req_header: DnsRequestHeader<'temp>,
1406 pub response: Vec<DnsResponsePayload>,
1408 pub additional: Vec<DnsResponsePayload>,
1410 pub authoratives: Vec<DnsResponsePayload>,
1412}
1413
1414impl<'temp> DnsRequestAnswer<'temp>
1415{
1416 #[inline]
1417 pub
1418 fn get_req_id(&self) -> u16
1419 {
1420 return self.req_header.get_id();
1421 }
1422
1423 pub
1429 fn verify(&self, req: &DnsRequestHeader<'_>) -> CDnsResult<()>
1430 {
1431 if self.get_req_id() != req.get_id()
1432 {
1433 internal_error!(
1434 CDnsErrorType::DnsResponse,
1435 "request and response ID did not match: '{}' != '{}'",
1436 req.header.id, self.get_req_id()
1437 );
1438 }
1439
1440 if self.req_header.payload != req.payload
1442 {
1443 internal_error!(CDnsErrorType::DnsResponse,
1444 "received request section is different from sent");
1445 }
1446 else if req.payload.qtype != QType::ALL
1447 {
1448 if req.payload.qtype != self.req_header.payload.qtype
1450 {
1451 internal_error!(
1452 CDnsErrorType::DnsResponse,
1453 "requested QTYPE differ received TYPE: '{}' != '{}'",
1454 req.payload.qtype,
1455 self.req_header.payload.qtype
1456 );
1457 }
1458 }
1459 else if self.req_header.header.status.contains(StatusBits::TRUN_CATION) == true
1460 {
1461 internal_error!(CDnsErrorType::MessageTruncated,
1462 "DNS response was truncated, aborting processing");
1463 }
1464
1465 return Ok(());
1466 }
1467
1468 pub(crate)
1474 fn parse(ans: &[u8]) -> CDnsResult<Self>
1475 {
1476 let mut pkt = Cursor::new(ans);
1478
1479 let id = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
1481
1482 let status = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
1483
1484 let header =
1485 DnsHeader
1486 {
1487 id: id,
1488 status: StatusBits::from_bits(status).ok_or_else(||
1489 internal_error_map!(CDnsErrorType::DnsResponse, "unknown status bits: '{}'", status)
1490 )?,
1491 qdcount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1492 ancount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1493 nscount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1494 arcount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1495 };
1496
1497 if header.status.contains(StatusBits::QR_RESP) == false
1501 {
1502 internal_error!(
1503 CDnsErrorType::DnsResponse,
1504 "incorret QR flag in STATUS register of response, expected 1 got 0"
1505 );
1506 }
1507 let request =
1524 DnsRequestPayload
1525 {
1526 qname: Cow::Owned(pkt2name(&mut pkt)?),
1527 qtype: QType::u16_to_qtype(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?,
1528 qclass: QClass::u16_to_qclass(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?,
1529 };
1530
1531 let mut an_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.ancount as usize);
1532 let mut rr_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.arcount as usize);
1533 let mut ns_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.nscount as usize);
1534
1535 for _ in 0..header.ancount
1536 {
1537 an_list.push(DnsResponsePayload::new(&mut pkt)?);
1538 }
1539
1540 for _ in 0..header.nscount
1542 {
1543 ns_list.push(DnsResponsePayload::new(&mut pkt)?);
1544 }
1545
1546 for _ in 0..header.arcount
1548 {
1549 rr_list.push(DnsResponsePayload::new(&mut pkt)?);
1550 }
1551
1552 return Ok(
1553 DnsRequestAnswer
1554 {
1555 req_header:
1556 DnsRequestHeader
1557 {
1558 header,
1559 payload: request
1560 },
1561 response: an_list,
1562 additional: rr_list,
1563 authoratives: ns_list,
1564 }
1565 );
1566 }
1567
1568}
1569
1570#[derive(Clone, Debug)]
1571pub struct DnsRequestHeader<'temp>
1572{
1573 pub header: DnsHeader,
1575 pub payload: DnsRequestPayload<'temp>,
1577}
1578
1579impl<'temp> Eq for DnsRequestHeader<'temp> {}
1580
1581impl<'temp> PartialEq for DnsRequestHeader<'temp>
1582{
1583 fn eq(&self, other: &DnsRequestHeader<'temp>) -> bool
1584 {
1585 return self.header.id == other.header.id && self.payload == other.payload;
1586 }
1587}
1588
1589impl<'temp> Ord for DnsRequestHeader<'temp>
1590{
1591 fn cmp(&self, other: &Self) -> Ordering
1592 {
1593 return self.header.id.cmp(&other.header.id);
1595 }
1596}
1597
1598impl<'temp> PartialOrd for DnsRequestHeader<'temp>
1599{
1600 fn partial_cmp(&self, other: &Self) -> Option<Ordering>
1601 {
1602 return Some(self.cmp(other));
1603 }
1604}
1605
1606impl<'temp> Hash for DnsRequestHeader<'temp>
1607{
1608 fn hash<H: Hasher>(&self, state: &mut H)
1609 {
1610 self.header.id.hash(state);
1611 self.payload.hash(state);
1612 }
1613}
1614
1615impl<'temp> Borrow<u16> for DnsRequestHeader<'temp>
1616{
1617 fn borrow(&self) -> &u16
1618 {
1619 return &self.header.id;
1620 }
1621}
1622
1623impl<'temp> TryFrom<&'temp QDnsReq> for DnsRequestHeader<'temp>
1624{
1625 type Error = CDnsError;
1626
1627 fn try_from(value: &'temp QDnsReq) -> Result<Self, Self::Error>
1628 {
1629 return DnsRequestHeader::construct_lookup(value);}
1631}
1632
1633impl<'temp> fmt::Display for DnsRequestHeader<'temp>
1634{
1635 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1636 {
1637 write!(f, "Header: {}, Status: {}", self.header, self.payload)
1638 }
1639}
1640
1641impl<'temp> DnsRequestHeader<'temp>
1642{
1643 pub
1644 fn get_id(&self) -> u16
1645 {
1646 return self.header.id;
1647 }
1648}
1649
1650
1651impl<'temp> DnsRequestHeader<'temp>
1652{
1653 pub
1654 fn regenerate_id(&mut self)
1655 {
1656 self.header.id = rand::random();
1657 }
1658
1659
1660 pub
1668 fn derive(&self) -> Self
1669 {
1670 let header =
1671 DnsHeader
1672 {
1673 id: rand::random(),
1674 status: self.header.status,
1675 qdcount: self.header.qdcount,
1676 ancount: self.header.ancount,
1677 nscount: self.header.nscount,
1678 arcount: self.header.arcount,
1679 };
1680
1681 return DnsRequestHeader{ header: header, payload: self.payload.clone() };
1682 }
1683
1684 pub
1686 fn construct_lookup(qreq: &'temp QDnsReq) -> CDnsResult<DnsRequestHeader<'_>>
1687 {
1688 let mut status: StatusBits = StatusBits::empty();
1690 status = (status & !StatusBits::OPCODE_STANDARD) | StatusBits::RECURSION_DESIRED;
1691
1692 let req =
1694 DnsRequestHeader
1695 {
1696 header:
1697 DnsHeader
1698 {
1699 id: rand::random(),
1700 status: status,
1701 qdcount: 1,
1702 ancount: 0,
1703 nscount: 0,
1704 arcount: 0,
1705 },
1706 payload:
1707 DnsRequestPayload
1708 ::new(qreq.get_req_name().into(), *qreq.get_type(), QClass::IN)
1709 };
1710
1711 return Ok(req);
1712 }
1713
1714 pub
1715 fn to_bytes(&self, append_len: bool) -> CDnsResult<Vec<u8>>
1716 {
1717 let mut pkt_size: usize = size_of::<DnsHeader>() + self.payload.qname.len() + 4;
1718
1719 if append_len == true
1720 {
1721 pkt_size += 2;
1722 }
1723
1724 let mut pkt = Cursor::new(vec![0_u8; pkt_size]);
1725
1726 if append_len == true
1727 {
1728 pkt.write_u16::<BigEndian>((pkt_size-2) as u16).map_err(map_read_err)?;
1729 }
1730
1731 pkt.write_u16::<BigEndian>(self.header.id).map_err(map_read_err)?;
1732 pkt.write_u16::<BigEndian>(self.header.status.bits()).map_err(map_read_err)?;
1733 pkt.write_u16::<BigEndian>(self.header.qdcount).map_err(map_read_err)?;
1734 pkt.write_u16::<BigEndian>(self.header.ancount).map_err(map_read_err)?;
1735 pkt.write_u16::<BigEndian>(self.header.nscount).map_err(map_read_err)?;
1736 pkt.write_u16::<BigEndian>(self.header.arcount).map_err(map_read_err)?;
1737
1738
1739 pkt.write(&self.payload.qname).map_err(map_read_err)?;
1740 pkt.write_u16::<BigEndian>(self.payload.qtype.into()).map_err(map_read_err)?;
1741 pkt.write_u16::<BigEndian>(self.payload.qclass.into()).map_err(map_read_err)?;
1742
1743
1744 return Ok(pkt.into_inner());
1745 }
1746}
1747
1748#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1750pub struct DnsRequestPayload<'temp>
1751{
1752 pub qname: Cow<'temp, [u8]>,
1754
1755 pub qtype: QType,
1757
1758 pub qclass: QClass,
1760}
1761
1762
1763impl<'temp> fmt::Display for DnsRequestPayload<'temp>
1764{
1765 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1766 {
1767 write!(f, "qname:{:?} qtype:{}, qclass:{}", self.qname, self.qtype, self.qclass)
1768 }
1769}
1770
1771impl<'temp> DnsRequestPayload<'temp>
1772{
1773 pub
1774 fn new(qname: Cow<'temp, [u8]>, qtype: QType, qclass: QClass) -> Self
1775 {
1776 return DnsRequestPayload{ qname: qname, qtype: qtype.into(), qclass: qclass.into() };
1777 }
1778}
1779
1780
1781#[derive(Clone, Debug, Default, Eq, PartialEq)]
1783pub struct DnsResponsePayload
1784{
1785 pub name: String,
1787 pub dtype: QType,
1789 pub class: QClass,
1791 pub ttl: i32,
1794 pub rdlength: u16,
1796 pub rdata: DnsRdata,
1798}
1799
1800impl DnsResponsePayload
1801{
1802 pub(crate)
1805 fn new_local(dtype: QType, data: &HostnameEntry) -> Option<Vec<Self>>
1806 {
1807 match dtype
1808 {
1809 QType::A =>
1810 {
1811 let mut out: Vec<Self> = Vec::with_capacity(1);
1812
1813 let IpAddr::V4(ipv4) = data.get_ip()
1814 else { return None; };
1815
1816 out.push(
1817 DnsResponsePayload
1818 {
1819 name: data.get_hostnames()[0].to_string(),
1820 dtype: dtype,
1821 class: QClass::IN,
1822 ttl: i32::MAX,
1823 rdlength: 0,
1824 rdata: RecordA::wrap(RecordA{ ip: ipv4.clone()}),
1825 }
1826 );
1827
1828 return Some(out);
1829 },
1830 QType::AAAA =>
1831 {
1832 let mut out: Vec<Self> = Vec::with_capacity(1);
1833
1834 let IpAddr::V6(ipv6) = data.get_ip()
1835 else { return None };
1836
1837 out.push(
1838 DnsResponsePayload
1839 {
1840 name: data.get_hostnames()[0].to_string(),
1841 dtype: dtype,
1842 class: QClass::IN,
1843 ttl: i32::MAX,
1844 rdlength: 0,
1845 rdata: RecordAAAA::wrap(RecordAAAA{ ip: ipv6.clone() }),
1846 }
1847 );
1848
1849 return Some(out);
1850 },
1851 QType::PTR =>
1852 {
1853 let mut out: Vec<Self> = Vec::with_capacity(data.get_hostnames().len());
1854
1855 for h in data.get_hostnames_iter()
1857 {
1858 out.push(
1859 DnsResponsePayload
1860 {
1861 name: [data.get_ip().to_string().as_str(), ".in-addr.arpa"].concat(),
1862 dtype: dtype,
1863 class: QClass::IN,
1864 ttl: i32::MAX,
1865 rdlength: 0,
1866 rdata: RecordPTR::wrap( RecordPTR { fqdn: h.clone() }),
1867 }
1868 );
1869 }
1870
1871 return Some(out);
1872 },
1873 _ =>
1874 return None
1875 }
1876
1877 }
1878
1879 fn new(pkt: &mut Cursor<&[u8]>) -> CDnsResult<Self>
1880 {
1881 let name = name2str(pkt, None)?;
1882 let qtype = QType::u16_to_type(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?;
1883 let qclass = QClass::u16_to_class(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?;
1884 let ttl = pkt.read_i32::<BigEndian>().map_err(map_read_err)?;
1885 let rdlength = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
1886 let rdata = DnsRdata::convert(pkt, rdlength, qtype)?;
1887
1888 return Ok(
1889 DnsResponsePayload
1890 {
1891 name: name,
1892 dtype: qtype,
1893 class: qclass,
1894 ttl: ttl,
1895 rdlength: rdlength,
1896 rdata: rdata,
1897 }
1898 );
1899 }
1900
1901 pub
1904 fn get_rdata(&self) -> &DnsRdata
1905 {
1906 return &self.rdata;
1907 }
1908
1909 pub
1912 fn borrow_rdata(self) -> DnsRdata
1913 {
1914 return self.rdata;
1915 }
1916
1917 #[cfg(feature = "enable_IDN_support")]
1924 pub
1925 fn get_full_domain_name_with_idn_decode(&self) -> CDnsResult<String>
1926 {
1927 use crate::external::rust_punycode;
1928
1929 return Ok(
1930 self
1931 .name
1932 .split(".")
1933 .map(|v|
1934 rust_punycode::decode(&v)
1935 )
1936 .collect::<CDnsResult<Vec<String>>>()?
1937 .join(".")
1938 );
1939 }
1940
1941 pub
1943 fn get_full_domain_name(&self) -> &str
1944 {
1945 return self.name.as_str();
1946 }
1947
1948 pub
1949 fn get_domain_name_iter(&self) -> std::str::Split<'_, &str>
1950 {
1951 return self.name.split(".");
1952 }
1953
1954 #[cfg(feature = "enable_IDN_support")]
1962 pub
1963 fn get_domain_name_iter_with_idn_decode(&self) -> CDnsResult<std::vec::IntoIter<String>>
1964 {
1965 use crate::external::rust_punycode;
1966
1967 return
1968 self
1969 .name
1970 .split(".")
1971 .map(|v| rust_punycode::decode(&v))
1972 .collect::<CDnsResult<Vec<String>>>()
1973 .map(|v| v.into_iter());
1974 }
1975}
1976
1977#[cfg(feature = "enable_IDN_support")]
1986impl fmt::Display for DnsResponsePayload
1987{
1988 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1989 {
1990 if self.name.starts_with("xn-") == true
1991 {
1992 let idn =
1993 self.get_full_domain_name_with_idn_decode().unwrap_or_else(|_| "decode_error".into());
1994
1995 write!(f, "{}({}) ", self.name, idn)?;
1996 }
1997 else
1998 {
1999 write!(f, "{} ", self.name)?;
2000 }
2001
2002 write!(f, "{} {} {} {}",
2003 self.dtype, self.class, self.ttl, self.rdata)
2004 }
2005}
2006
2007#[cfg(not(feature = "enable_IDN_support"))]
2008impl fmt::Display for DnsResponsePayload
2009{
2010 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2011 {
2012 if self.name.starts_with("xn-") == true
2013 {
2014 let idn = self.get_full_domain_name();
2015
2016 write!(f, "{}({}) ", self.name, idn)?;
2017 }
2018 else
2019 {
2020 write!(f, "{} ", self.name)?;
2021 }
2022
2023 write!(f, "{} {} {} {}",
2024 self.dtype, self.class, self.ttl, self.rdata)
2025 }
2026}
2027
2028
2029pub trait RecordReader: Sized
2031{
2032
2033 const REC_TYPE: QType;
2035
2036 const RLEN: u16;
2038
2039 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>;
2043
2044 fn wrap(self) -> DnsRdata;
2045}
2046
2047#[derive(Clone, Debug, Eq, PartialEq)]
2048pub struct RecordA
2049{
2050 pub ip: Ipv4Addr
2051}
2052
2053impl RecordReader for RecordA
2054{
2055 const REC_TYPE: QType = QType::A;
2056
2057 const RLEN: u16 = 4;
2058
2059 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2060 {
2061 if rlen != Self::RLEN
2063 {
2064 internal_error!(CDnsErrorType::DnsResponse, "RecordA len expected: '4', got: '{}'", rlen);
2065 }
2066 else if qtype != Self::REC_TYPE
2067 {
2068 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2069 }
2070
2071 let ip = pkt.read_u32::<BigEndian>().map_err(map_read_err)?;
2072
2073 return Ok(Self{ip: Ipv4Addr::from(ip) });
2074 }
2075
2076 fn wrap(self) -> DnsRdata
2077 {
2078 return DnsRdata::A(self);
2079 }
2080}
2081
2082impl fmt::Display for RecordA
2083{
2084 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2085 {
2086 write!(f, "{} {}", Self::REC_TYPE, self.ip)
2087 }
2088}
2089
2090
2091#[derive(Clone, Debug, Eq, PartialEq)]
2092pub struct RecordAAAA
2093{
2094 pub ip: Ipv6Addr
2095}
2096
2097impl RecordReader for RecordAAAA
2098{
2099 const REC_TYPE: QType = QType::AAAA;
2100
2101 const RLEN: u16 = 16;
2102
2103 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2104 {
2105 if rlen != Self::RLEN
2106 {
2107 internal_error!(CDnsErrorType::DnsResponse, "RecordAAAA len expected: '{}', got: '{}'", Self::RLEN, rlen);
2108 }
2109 else if qtype != Self::REC_TYPE
2110 {
2111 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2112 }
2113
2114 let ip = pkt.read_u128::<BigEndian>().map_err(map_read_err)?;
2115
2116 return Ok(Self{ ip: Ipv6Addr::from(ip) });
2117 }
2118
2119 fn wrap(self) -> DnsRdata
2120 {
2121 return DnsRdata::AAAA(self);
2122 }
2123}
2124
2125impl fmt::Display for RecordAAAA
2126{
2127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2128 {
2129 write!(f, "{} {}", Self::REC_TYPE, self.ip)
2130 }
2131}
2132
2133#[derive(Clone, Debug, Eq, PartialEq)]
2134pub struct RecordPTR
2135{
2136 pub fqdn: String
2137}
2138
2139impl RecordReader for RecordPTR
2140{
2141 const REC_TYPE: QType = QType::PTR;
2142
2143 const RLEN: u16 = 0;
2144
2145 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2146 {
2147 if qtype != Self::REC_TYPE
2148 {
2149 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2150 }
2151
2152 return Ok(
2153 Self{ fqdn: name2str(pkt, Some(rlen))? }
2154 );
2155 }
2156
2157 fn wrap(self) -> DnsRdata
2158 {
2159 return DnsRdata::PTR(self);
2160 }
2161}
2162
2163impl fmt::Display for RecordPTR
2164{
2165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2166 {
2167 write!(f, "{} {}", Self::REC_TYPE, self.fqdn)
2168 }
2169}
2170
2171#[derive(Clone, Debug, Eq, PartialEq)]
2172pub struct RecordMX
2173{
2174 pub preference: u16,
2175 pub exchange: String
2176}
2177
2178impl RecordReader for RecordMX
2179{
2180 const REC_TYPE: QType = QType::MX;
2181
2182 const RLEN: u16 = 2;
2183
2184 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2185 {
2186 if rlen <= Self::RLEN
2187 {
2188 internal_error!(CDnsErrorType::DnsResponse, "RecordMX len expected: '{}', got: '{}'", Self::RLEN, rlen);
2189 }
2190 else if qtype != Self::REC_TYPE
2191 {
2192 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2193 }
2194
2195 return Ok(
2196 Self
2197 {
2198 preference: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2199 exchange: name2str(pkt, Some(rlen - 2))?,
2200 }
2201 );
2202 }
2203
2204 fn wrap(self) -> DnsRdata
2205 {
2206 return DnsRdata::MX(self);
2207 }
2208}
2209
2210impl fmt::Display for RecordMX
2211{
2212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2213 {
2214 write!(f, "{} {} {}", Self::REC_TYPE, self.preference, self.exchange)
2215 }
2216}
2217
2218#[derive(Clone, Debug, Eq, PartialEq)]
2219pub struct RecordCNAME
2220{
2221 pub fqdn: String
2222}
2223
2224impl RecordReader for RecordCNAME
2225{
2226 const REC_TYPE: QType = QType::CNAME;
2227
2228 const RLEN: u16 = 0;
2229
2230 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2231 {
2232 if qtype != Self::REC_TYPE
2233 {
2234 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2235 }
2236
2237 return Ok(
2238 Self{ fqdn: name2str(pkt, Some(rlen))? }
2239 );
2240 }
2241
2242 fn wrap(self) -> DnsRdata
2243 {
2244 return DnsRdata::CNAME(self);
2245 }
2246}
2247
2248impl fmt::Display for RecordCNAME
2249{
2250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2251 {
2252 write!(f, "{} {}", Self::REC_TYPE, self.fqdn)
2253 }
2254}
2255
2256#[derive(Clone, Debug, Eq, PartialEq)]
2257pub struct RecordNS
2258{
2259 pub fqdn: String
2260}
2261
2262impl RecordReader for RecordNS
2263{
2264 const REC_TYPE: QType = QType::NS;
2265
2266 const RLEN: u16 = 0;
2267
2268 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2269 {
2270 if qtype != Self::REC_TYPE
2271 {
2272 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2273 }
2274
2275 return Ok(
2276 Self{ fqdn: name2str(pkt, Some(rlen))? }
2277 );
2278 }
2279
2280 fn wrap(self) -> DnsRdata
2281 {
2282 return DnsRdata::NS(self);
2283 }
2284}
2285
2286impl fmt::Display for RecordNS
2287{
2288 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2289 {
2290 write!(f, "{} {}", Self::REC_TYPE, self.fqdn)
2291 }
2292}
2293
2294#[derive(Clone, Debug, Eq, PartialEq)]
2295pub struct RecordSOA
2296{
2297 pub pnm: String,
2299 pub ram: String,
2301 pub serial: u32,
2303 pub interv_refr: u32,
2305 pub interv_retry: u32,
2307 pub expire_limit: u32,
2309 pub min_ttl: u32,
2311}
2312
2313impl RecordReader for RecordSOA
2314{
2315 const REC_TYPE: QType = QType::SOA;
2316
2317 const RLEN: u16 = 0;
2318
2319 fn read(pkt: &mut Cursor<&[u8]>, _rlen: u16, qtype: QType) -> CDnsResult<Self>
2320 {
2321 if qtype != Self::REC_TYPE
2322 {
2323 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2324 }
2325
2326 return Ok(
2327 Self
2328 {
2329 pnm: name2str(pkt, None)?,
2331 ram: name2str(pkt, None)?,
2333 serial: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2335 interv_refr: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2337 interv_retry: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2339 expire_limit: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2341 min_ttl: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2343 }
2344 );
2345 }
2346
2347 fn wrap(self) -> DnsRdata
2348 {
2349 return DnsRdata::SOA(self);
2350 }
2351}
2352
2353impl fmt::Display for RecordSOA
2354{
2355 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2356 {
2357 write!(f, "{} {} {} {} {} {} {} {}", Self::REC_TYPE, self.pnm, self.ram, self.serial,
2358 self.interv_refr, self.interv_retry, self.expire_limit, self.min_ttl)
2359 }
2360}
2361
2362#[derive(Clone, Debug, Eq, PartialEq)]
2363pub struct RecordSRV
2364{
2365 pub priority: u16,
2367
2368 pub weight: u16,
2371
2372 pub port: u16,
2374
2375 pub target: String,
2377}
2378
2379impl RecordReader for RecordSRV
2380{
2381 const REC_TYPE: QType = QType::SRV;
2382
2383 const RLEN: u16 = 0;
2384
2385 fn read(pkt: &mut Cursor<&[u8]>, _rlen: u16, qtype: QType) -> CDnsResult<Self>
2386 {
2387 if qtype != Self::REC_TYPE
2388 {
2389 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2390 }
2391
2392 return Ok(
2393 Self
2394 {
2395 priority: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2396 weight: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2397 port: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2398 target: name2str(pkt, None)?,
2399 }
2400 );
2401 }
2402
2403 fn wrap(self) -> DnsRdata
2404 {
2405 return DnsRdata::SRV(self);
2406 }
2407}
2408
2409impl fmt::Display for RecordSRV
2410{
2411 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2412 {
2413 write!(f, "{} {} {} {} \"{}\"", Self::REC_TYPE, self.priority, self.weight, self.port, self.target)
2414 }
2415}
2416
2417#[derive(Clone, Debug, Eq, PartialEq)]
2418pub struct RecordTXT
2419{
2420 pub txt_strings: String,
2422}
2423
2424impl RecordReader for RecordTXT
2425{
2426 const REC_TYPE: QType = QType::TXT;
2427
2428 const RLEN: u16 = 2;
2429
2430 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2431 {
2432 if rlen <= Self::RLEN
2433 {
2434 internal_error!(CDnsErrorType::DnsResponse, "RecordTXT len expected: '{}' >, got: '{}'", Self::RLEN, rlen);
2435 }
2436 else if qtype != Self::REC_TYPE
2437 {
2438 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2439 }
2440
2441 let mut read_length = 0;
2442
2443
2444 let dmod = ((rlen % 255) > 0) as u16;
2445 let cap = rlen / 255 + dmod;
2446
2447 let mut txt_datas = Vec::<String>::with_capacity(cap as usize);
2448
2449 while read_length < rlen
2450 {
2451 let mut txt_data = Vec::new();
2452
2453 loop
2454 {
2455 let blk_size = pkt.read_u8().map_err(map_read_err)?;
2456
2457 read_length += blk_size as u16 + 1;
2458
2459 let mut new_txt = Vec::with_capacity(blk_size as usize);unsafe { new_txt.set_len(blk_size as usize); }
2461
2462 pkt.read_exact(&mut new_txt).map_err(map_read_err)?;
2463
2464 txt_data.push(new_txt);
2465
2466 if blk_size < 255
2467 {
2468 break;
2469 }
2470 }
2471
2472 if txt_data.is_empty() == true
2473 {
2474 internal_error!(
2475 CDnsErrorType::DnsResponse,
2476 "unexpected EOF in TXT rec cur position: '{}', data_length: '{}', read: '{}'",
2477 pkt.position(), rlen, read_length
2478 );
2479 }
2480
2481 let data = txt_data.concat();
2482
2483 txt_datas.push(
2484 String::from_utf8(data)
2485 .map_err(|e|
2486 internal_error_map!(CDnsErrorType::InternalError, "UTF-8 decode error, {}", e)
2487 )?
2488 );
2489 }
2490
2491 return Ok(
2492 Self
2493 {
2494 txt_strings: txt_datas.concat()
2495 }
2496 );
2497 }
2498
2499 fn wrap(self) -> DnsRdata
2500 {
2501 return DnsRdata::TXT(self);
2502 }
2503}
2504
2505impl fmt::Display for RecordTXT
2506{
2507 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2508 {
2509 write!(f, "{} {}", Self::REC_TYPE, self.txt_strings)
2510 }
2511}
2512
2513#[derive(Clone, Debug, Eq, PartialEq)]
2514pub struct RecordURI
2515{
2516 pub priority: u16,
2518
2519 pub weight: u16,
2522
2523 pub target: String,
2526}
2527
2528impl RecordReader for RecordURI
2529{
2530 const REC_TYPE: QType = QType::URI;
2531
2532 const RLEN: u16 = 4;
2533
2534 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2535 {
2536 if rlen <= Self::RLEN
2537 {
2538 internal_error!(CDnsErrorType::DnsResponse, "RecordURI len expected: '{}' >, got: '{}'", Self::RLEN, rlen);
2539 }
2540 else if qtype != Self::REC_TYPE
2541 {
2542 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2543 }
2544
2545 return Ok(
2546 Self
2547 {
2548 priority: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2549 weight: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2550 target: pkt2string_exact(pkt, rlen - 4)?,
2551 }
2552 );
2553 }
2554
2555 fn wrap(self) -> DnsRdata
2556 {
2557 return DnsRdata::URI(self);
2558 }
2559}
2560
2561impl fmt::Display for RecordURI
2562{
2563 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2564 {
2565 write!(f, "{} {} {} \"{}\"", Self::REC_TYPE, self.priority, self.weight, self.target)
2566 }
2567}
2568
2569#[derive(Clone, Debug, Eq, PartialEq)]
2572pub struct RecordRRSIG
2573{
2574 type_cov: u16,
2575 alg: u8,
2576 labels: u8,
2577 orig_ttl: u32,
2578 sig_exp: u32,
2579 sig_inc: u32,
2580 keytag: u16,
2581 sig_name: String,
2582 key: Vec<u8>,
2583}
2584
2585impl RecordReader for RecordRRSIG
2586{
2587 const REC_TYPE: QType = QType::RRSIG;
2588
2589 const RLEN: u16 = 19;
2590
2591 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, _qtype: QType) -> CDnsResult<Self>
2592 {
2593 let data = vec![0_u8; rlen as usize];
2594
2595 let pos = pkt.position();
2596
2597 let mut res =
2598 Self
2599 {
2600 type_cov: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2601 alg: pkt.read_u8().map_err(map_read_err)?,
2602 labels: pkt.read_u8().map_err(map_read_err)?,
2603 orig_ttl: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2604 sig_exp: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2605 sig_inc: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2606 keytag: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2607 sig_name: name2str(pkt,None)?,
2608 key: Vec::new(),
2609 };
2610
2611 let left_rdlen = rlen - (pkt.position() - pos) as u16;
2612 res.key = pkt2vec(pkt, Some(left_rdlen))?;
2613
2614 return Ok(res);
2615 }
2616
2617 fn wrap(self) -> DnsRdata
2618 {
2619 return DnsRdata::RRSIG(self);
2620 }
2621}
2622
2623impl fmt::Display for RecordRRSIG
2624{
2625 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2626 {
2627 write!(f, "{} {} {} {} {} {} {} {} {} {}",
2628 Self::REC_TYPE, self.type_cov, self.alg, self.labels, self.orig_ttl,
2629 self.sig_exp, self.sig_inc, self.keytag, self.sig_name,
2630 self.key.iter().map(|k| format!("{:02X}", k)).collect::<Vec<String>>().concat()
2631 )
2632 }
2633}
2634
2635#[derive(Clone, Debug, Eq, PartialEq)]
2636pub struct RecordOther
2637{
2638 pub qtype: QType,
2640
2641 pub data: Vec<u8>
2643}
2644
2645impl RecordReader for RecordOther
2646{
2647 const REC_TYPE: QType = QType::ALL;
2648
2649 const RLEN: u16 = 0;
2650
2651 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2652 {
2653 let mut data = vec![0_u8; rlen as usize];
2654
2655 pkt.read_exact(&mut data).map_err(map_read_err)?;
2656
2657 return Ok(
2658 Self
2659 {
2660 qtype: qtype,
2661 data: data,
2662 }
2663 );
2664 }
2665
2666 fn wrap(self) -> DnsRdata
2667 {
2668 return DnsRdata::OTHER(self);
2669 }
2670}
2671
2672impl fmt::Display for RecordOther
2673{
2674 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2675 {
2676 write!(f, "{} RAW:", self.qtype)?;
2677
2678 for d in self.data.iter()
2679 {
2680 write!(f, "{:X}", d)?;
2681 }
2682
2683 return Ok(());
2684 }
2685}
2686
2687pub(crate)
2688fn sanitize_str_unicode(st: &str) -> String
2689{
2690 let mut out = String::with_capacity(st.len());
2691
2692 for c in st.chars()
2693 {
2694 if c.is_alphanumeric() == true ||
2695 c.is_ascii_punctuation() == true ||
2696 c == ' '
2697 {
2698 out.push(c);
2699 }
2700 else
2701 {
2702 let mut buf = [0_u8; 4];
2703 c.encode_utf8(&mut buf);
2704
2705 let formatted: String =
2706 buf[0..c.len_utf8()].into_iter()
2707 .map(|c| format!("\\x{:02x}", c))
2708 .collect();
2709
2710 out.push_str(&formatted);
2711 }
2712 }
2713
2714 return out;
2715}
2716
2717pub(crate)
2718fn check_domain_ascii(st: &str) -> CDnsResult<()>
2719{
2720 if st.len() == 0
2721 {
2722 internal_error!(CDnsErrorType::InternalError,
2723 "name empty: '{}' in: '{}'", st.len(), sanitize_str_unicode(st));
2724 }
2725 else if st.starts_with("-") == true
2726 {
2727 internal_error!(CDnsErrorType::InternalError,
2728 "cannot start from '-' in: '{}'", sanitize_str_unicode(st));
2729 }
2730 else if st.ends_with("-") == true
2731 {
2732 internal_error!(CDnsErrorType::InternalError,
2733 "cannot start from '-' in: '{}'", sanitize_str_unicode(st));
2734 }
2735 else if st.len() >= MAX_NAME_LEN
2736 {
2737 internal_error!(CDnsErrorType::InternalError,
2738 "name too long: '{}' in: '{}'", st.len(), sanitize_str_unicode(st));
2739 }
2740 else if st.chars().any(|v| v.is_alphanumeric() == false && v != '-') == true
2741 {
2742 internal_error!(CDnsErrorType::InternalError,
2743 "contains non-valid ASCII chars in: '{}'", sanitize_str_unicode(st));
2744 }
2745
2746 return Ok(());
2747}
2748
2749#[derive(Clone, Debug, Eq, PartialEq)]
2750pub enum DnsRdata
2751{
2752 None,
2753 A(RecordA),
2754 NS(RecordNS),
2755 CNAME(RecordCNAME),
2756 SOA(RecordSOA),
2757 PTR(RecordPTR),
2758 MX(RecordMX),
2759 TXT(RecordTXT),
2760 AAAA(RecordAAAA),
2761 SRV(RecordSRV),
2762 URI(RecordURI),
2763 RRSIG(RecordRRSIG),
2764 OTHER(RecordOther),
2765}
2766
2767impl fmt::Display for DnsRdata
2768{
2769 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2770 {
2771 match self
2772 {
2773 Self::None =>
2774 write!(f, "No record"),
2775 Self::A(ip) =>
2776 write!(f, "{}", ip),
2777 Self::NS(ns) =>
2778 write!(f, "{}", ns),
2779 Self::AAAA(aaaa) =>
2780 write!(f, "{}", aaaa),
2781 Self::MX(mx) =>
2782 write!(f, "{}", mx),
2783 Self::CNAME(cname) =>
2784 write!(f, "{}", cname),
2785 Self::PTR(ptr) =>
2786 write!(f, "{}", ptr),
2787 Self::SOA(soa) =>
2788 write!(f, "{}", soa),
2789 Self::TXT(txt) =>
2790 write!(f, "{}", txt),
2791 Self::SRV(srv) =>
2792 write!(f, "{}", srv),
2793 Self::URI(uri) =>
2794 write!(f, "{}", uri),
2795 Self::RRSIG(rrsig) =>
2796 write!(f, "{}", rrsig),
2797 Self::OTHER(other) =>
2798 write!(f, "{}", other),
2799 }
2800 }
2801}
2802
2803impl Default for DnsRdata
2804{
2805 fn default() -> Self
2806 {
2807 return Self::None;
2808 }
2809}
2810
2811impl DnsRdata
2812{
2813 #[inline]
2814 pub
2815 fn is_some(&self) -> bool
2816 {
2817 return *self != Self::None;
2818 }
2819}
2820
2821
2822impl DnsRdata
2823{
2824 pub
2838 fn convert(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2839 {
2840 match qtype
2841 {
2842 RecordA::REC_TYPE =>
2843 return Ok(RecordA::wrap(RecordA::read(pkt, rlen, qtype)?)),
2844 RecordAAAA::REC_TYPE =>
2845 return Ok(RecordAAAA::wrap(RecordAAAA::read(pkt, rlen, qtype)?)),
2846 RecordPTR::REC_TYPE =>
2847 return Ok(RecordPTR::wrap(RecordPTR::read(pkt, rlen, qtype)?)),
2848 RecordMX::REC_TYPE =>
2849 return Ok(RecordMX::wrap(RecordMX::read(pkt, rlen, qtype)?)),
2850 RecordCNAME::REC_TYPE =>
2851 return Ok(RecordCNAME::wrap(RecordCNAME::read(pkt, rlen, qtype)?)),
2852 RecordSOA::REC_TYPE =>
2853 return Ok(RecordSOA::wrap(RecordSOA::read(pkt, rlen, qtype)?)),
2854 RecordSRV::REC_TYPE =>
2855 return Ok(RecordSRV::wrap(RecordSRV::read(pkt, rlen, qtype)?)),
2856 RecordTXT::REC_TYPE =>
2857 return Ok(RecordTXT::wrap(RecordTXT::read(pkt, rlen, qtype)?)),
2858 RecordURI::REC_TYPE =>
2859 return Ok(RecordURI::wrap(RecordURI::read(pkt, rlen, qtype)?)),
2860 RecordNS::REC_TYPE =>
2861 return Ok(RecordNS::wrap(RecordNS::read(pkt, rlen, qtype)?)),
2862 RecordRRSIG::REC_TYPE =>
2863 return Ok(RecordRRSIG::wrap(RecordRRSIG::read(pkt, rlen, qtype)?)),
2864 _ =>
2865 return Ok(RecordOther::wrap(RecordOther::read(pkt, rlen, qtype)?)),
2866 }
2867 }
2868
2869 pub
2870 fn get_ip(&self) -> Option<IpAddr>
2871 {
2872 match self
2873 {
2874 Self::A(a) => return Some(IpAddr::V4(a.ip)),
2875 Self::AAAA(a) => return Some(IpAddr::V6(a.ip)),
2876 _ => return None
2877 }
2878 }
2879}
2880
2881#[cfg(test)]
2882mod tests
2883{
2884 use std::io::Cursor;
2885
2886 use crate::common::*;
2887
2888
2889
2890 #[test]
2891 fn test_pkt2name()
2892 {
2893 use std::time::Instant;
2894
2895 fn prepare(d: &[u8]) -> Cursor<&[u8]>
2896 {
2897 return Cursor::new(d);
2900 }
2901
2902 let t1 = b"\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00";
2903
2904 let mut cur1 = prepare(t1);
2905
2906 let now = Instant::now();
2907 let r1 = pkt2name(&mut cur1);
2908 let elapsed = now.elapsed();
2909 println!("Elapsed: {:.2?}", elapsed);
2910
2911 assert_eq!(r1.is_ok(), true);
2912 assert_eq!(r1.as_ref().unwrap(), t1);
2913
2914 let t2 =
2915 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2916 \x30\x30\x03\x6e\x65\x74\x00";
2917
2918 let mut cur2 = prepare(t2);
2919 let now = Instant::now();
2920 let r2 = pkt2name(&mut cur2);
2921 let elapsed = now.elapsed();
2922 println!("Elapsed: {:.2?}", elapsed);
2923
2924 assert_eq!(r2.is_ok(), true);
2925 assert_eq!(r2.as_ref().unwrap(), t2);
2926
2927 let t3 =
2928 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2929 \x30\x30\x03\x6e\x65\x74";
2930
2931 let r3 = pkt2name(&mut prepare(t3));
2932
2933 assert_eq!(r3.is_ok(), false);
2934
2935 let t4 =
2936 b"\x10\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2937 \x30\x30\x03\x6e\x65\x74";
2938
2939 let r4 = pkt2name(&mut prepare(t4));
2940
2941 assert_eq!(r4.is_ok(), false);
2942 }
2943
2944 #[test]
2945 fn test_qname2str()
2946 {
2947 use std::time::Instant;
2948
2949 fn prepare(d: &[u8]) -> Cursor<&[u8]>
2950 {
2951 return Cursor::new(d);
2954 }
2955
2956 let t1 = b"\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00";
2957
2958 let mut cur1 = prepare(t1);
2959 let now = Instant::now();
2960 let r1 = name2str(&mut cur1, None);
2961 let elapsed = now.elapsed();
2962 println!("Elapsed: {:.2?}", elapsed);
2963
2964 assert_eq!(r1.is_ok(), true);
2965 assert_eq!(r1.as_ref().unwrap(), "dns.google");
2966
2967 let t2 =
2968 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2969 \x30\x30\x03\x6e\x65\x74\x00";
2970
2971 let mut cur2 = prepare(t2);
2972
2973 let now = Instant::now();
2974 let r2 = name2str(&mut cur2, None);
2975 let elapsed = now.elapsed();
2976 println!("Elapsed: {:.2?}", elapsed);
2977
2978 assert_eq!(r2.is_ok(), true);
2979 assert_eq!(r2.as_ref().unwrap(), "mad07s09-in-x0e.1e100.net");
2980
2981 let t3 =
2982 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2983 \x30\x30\x03\x6e\x65\x74";
2984
2985 let r3 = name2str(&mut prepare(t3), None);
2986
2987 assert_eq!(r3.is_ok(), false);
2988
2989 let t4 =
2990 b"\x10\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2991 \x30\x30\x03\x6e\x65\x74";
2992
2993 let r4 = name2str(&mut prepare(t4), None);
2994
2995 assert_eq!(r4.is_ok(), false);
2996 }
2997
2998 #[test]
2999 fn test_response_parser()
3000 {
3001 use std::time::Instant;
3002
3003 let pkt =
3004 b"\x15\xc8\x81\x80\x00\x01\x00\x01\x00\x00\x00\x02\x01\x38\x01\x38\
3005 \x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\
3006 \x61\x00\x00\x0c\x00\x01\xc0\x0c\x00\x0c\x00\x01\x00\x01\x35\xf0\
3007 \x00\x0c\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00\xc0\x32\
3008 \x00\x01\x00\x01\x00\x00\x00\xe8\x00\x04\x08\x08\x08\x08\xc0\x32\
3009 \x00\x01\x00\x01\x00\x00\x00\xe8\x00\x04\x08\x08\x04\x04";
3010
3011 let dummy =
3012 DnsRequestHeader
3013 {
3014 header: DnsHeader {id: 0x15c8, ..Default::default()},
3015 payload: DnsRequestPayload
3016 {
3017 qname: Cow::Borrowed(b"\x01\x38\x01\x38\x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\x61\x00"),
3018 qtype: QType::PTR,
3019 qclass: QClass::IN,
3020 }
3021 };
3022
3023 let now = Instant::now();
3024 let ans = DnsRequestAnswer::parse(pkt.as_slice());
3025 let elapsed = now.elapsed();
3026 println!("Elapsed: {:.2?}", elapsed);
3027
3028 assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
3029
3030 let ans = ans.unwrap();
3031
3032 let verif = ans.verify(&dummy);
3033 assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
3034
3035 assert_eq!(ans.req_header.header.id, 0x15c8);
3036 assert_eq!(ans.req_header.header.ancount, 1);
3037 assert_eq!(ans.req_header.header.arcount, 2);
3038 assert_eq!(ans.req_header.header.nscount, 0);
3039 assert_eq!(ans.req_header.header.qdcount, 1);
3040
3041 assert_eq!(ans.response[0].rdata, RecordPTR::wrap(RecordPTR { fqdn: "dns.google".to_string() }) );
3042 assert_eq!(ans.response[0].name, "8.8.8.8.in-addr.arpa".to_string());
3043 assert_eq!(ans.response[0].dtype, QType::PTR);
3044 assert_eq!(ans.response[0].class, QClass::IN);
3045 assert_eq!(ans.response[0].ttl, 79344);
3046 assert_eq!(ans.response[0].rdlength, 12);
3047
3048 assert_eq!(ans.additional[0].rdata, RecordA::wrap(RecordA { ip: "8.8.8.8".parse().unwrap() }) );
3049 assert_eq!(ans.additional[0].name, "dns.google".to_string());
3050 assert_eq!(ans.additional[0].ttl, 232);
3051 assert_eq!(ans.additional[0].dtype, QType::A);
3052 assert_eq!(ans.additional[0].class, QClass::IN);
3053
3054 assert_eq!(ans.additional[1].rdata, RecordA::wrap(RecordA { ip: "8.8.4.4".parse().unwrap() }) );
3055 assert_eq!(ans.additional[1].name, "dns.google".to_string());
3056 assert_eq!(ans.additional[1].ttl, 232);
3057 assert_eq!(ans.additional[1].dtype, QType::A);
3058 assert_eq!(ans.additional[1].class, QClass::IN);
3059 }
3060
3061 #[test]
3062 fn test_response2()
3063 {
3064 use std::time::Instant;
3065
3066 let pkt =
3067 b"\x4b\x38\x81\x80\x00\x01\x00\x05\x00\x00\x00\x00\x05\x67\x6d\x61\
3068 \x69\x6c\x03\x63\x6f\x6d\x00\x00\x0f\x00\x01\xc0\x0c\x00\x0f\x00\
3069 \x01\x00\x00\x0b\x55\x00\x1b\x00\x05\x0d\x67\x6d\x61\x69\x6c\x2d\
3070 \x73\x6d\x74\x70\x2d\x69\x6e\x01\x6c\x06\x67\x6f\x6f\x67\x6c\x65\
3071 \xc0\x12\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\x55\x00\x09\x00\x0a\
3072 \x04\x61\x6c\x74\x31\xc0\x29\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\
3073 \x55\x00\x09\x00\x1e\x04\x61\x6c\x74\x33\xc0\x29\xc0\x0c\x00\x0f\
3074 \x00\x01\x00\x00\x0b\x55\x00\x09\x00\x14\x04\x61\x6c\x74\x32\xc0\
3075 \x29\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\x55\x00\x09\x00\x28\x04\
3076 \x61\x6c\x74\x34\xc0\x29";
3077
3078 let dummy =
3079 DnsRequestHeader
3080 {
3081 header: DnsHeader {id: 0x4b38, ..Default::default()},
3082 payload: DnsRequestPayload
3083 {
3084 qname: Cow::Borrowed(b"\x05\x67\x6d\x61\x69\x6c\x03\x63\x6f\x6d\x00"),
3085 qtype: QType::MX,
3086 qclass: QClass::IN,
3087 }
3088 };
3089
3090 let now = Instant::now();
3091 let ans = DnsRequestAnswer::parse(pkt.as_slice());
3092 let elapsed = now.elapsed();
3093 println!("Elapsed: {:.2?}", elapsed);
3094
3095 assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
3096 let ans = ans.unwrap();
3097
3098 let verif = ans.verify(&dummy);
3099 assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
3100
3101 assert_eq!(ans.req_header.header.id, 0x4b38);
3102 assert_eq!(ans.req_header.header.ancount, 5);
3103 assert_eq!(ans.req_header.header.arcount, 0);
3104 assert_eq!(ans.req_header.header.nscount, 0);
3105 assert_eq!(ans.req_header.header.qdcount, 1);
3106
3107 assert_eq!(ans.response[0].rdata, RecordMX::wrap(RecordMX { preference: 5, exchange: "gmail-smtp-in.l.google.com".to_string() }) );
3108 assert_eq!(ans.response[0].name, "gmail.com".to_string());
3109 assert_eq!(ans.response[0].dtype, QType::MX);
3110 assert_eq!(ans.response[0].class, QClass::IN);
3111 assert_eq!(ans.response[0].ttl, 2901);
3112 assert_eq!(ans.response[0].rdlength, 27);
3113
3114 assert_eq!(ans.response[1].rdata, RecordMX::wrap(RecordMX { preference: 10, exchange: "alt1.gmail-smtp-in.l.google.com".to_string() }) );
3115 assert_eq!(ans.response[1].name, "gmail.com".to_string());
3116 assert_eq!(ans.response[1].dtype, QType::MX);
3117 assert_eq!(ans.response[1].class, QClass::IN);
3118 assert_eq!(ans.response[1].ttl, 2901);
3119 assert_eq!(ans.response[1].rdlength, 9);
3120
3121 assert_eq!(ans.response[2].rdata, RecordMX::wrap(RecordMX { preference: 30, exchange: "alt3.gmail-smtp-in.l.google.com".to_string() }) );
3122 assert_eq!(ans.response[2].name, "gmail.com".to_string());
3123 assert_eq!(ans.response[2].dtype, QType::MX);
3124 assert_eq!(ans.response[2].class, QClass::IN);
3125 assert_eq!(ans.response[2].ttl, 2901);
3126 assert_eq!(ans.response[2].rdlength, 9);
3127
3128 assert_eq!(ans.response[3].rdata, RecordMX::wrap(RecordMX { preference: 20, exchange: "alt2.gmail-smtp-in.l.google.com".to_string() }) );
3129 assert_eq!(ans.response[3].name, "gmail.com".to_string());
3130 assert_eq!(ans.response[3].dtype, QType::MX);
3131 assert_eq!(ans.response[3].class, QClass::IN);
3132 assert_eq!(ans.response[3].ttl, 2901);
3133 assert_eq!(ans.response[3].rdlength, 9);
3134
3135 assert_eq!(ans.response[4].rdata, RecordMX::wrap(RecordMX { preference: 40, exchange: "alt4.gmail-smtp-in.l.google.com".to_string() }) );
3136 assert_eq!(ans.response[4].name, "gmail.com".to_string());
3137 assert_eq!(ans.response[4].dtype, QType::MX);
3138 assert_eq!(ans.response[4].class, QClass::IN);
3139 assert_eq!(ans.response[4].ttl, 2901);
3140 assert_eq!(ans.response[4].rdlength, 9);
3141 }
3142
3143
3144 #[test]
3145 fn test_response3()
3146 {
3147 use std::time::Instant;
3148
3149 let pkt =
3150 b"\xd0\x79\x81\x80\x00\x01\x00\x17\x00\x00\x00\x00\x06\x72\
3151 \x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x00\xff\x00\x01\xc0\x0c\x00\
3152 \x06\x00\x01\x00\x00\x0e\x10\x00\x30\x04\x6e\x73\x32\x31\x07\x63\
3153 \x6c\x6f\x75\x64\x6e\x73\x03\x6e\x65\x74\x00\x07\x73\x75\x70\x70\
3154 \x6f\x72\x74\xc0\x2c\x78\x77\xe2\xf1\x00\x00\x1c\x20\x00\x00\x07\
3155 \x08\x00\x12\x75\x00\x00\x00\x0e\x10\xc0\x0c\x00\x2e\x00\x01\x00\
3156 \x00\x0e\x10\x00\x5d\x00\x06\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\
3157 \x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\
3158 \x6b\x00\x2f\x79\xed\x73\xd0\x75\xc8\xa9\xa2\x2a\x08\x3c\x78\xb9\
3159 \xfb\x43\xc5\x8e\x62\x4c\xbc\x36\xeb\x22\x96\x45\x59\x36\x1f\x69\
3160 \x3a\x7a\x5e\x67\xd0\x54\x1e\xf0\xf2\x11\x1a\x72\x00\x56\x89\x26\
3161 \x79\xf4\x06\x1a\x0c\x59\x41\x32\x60\x68\x75\x05\x3d\x90\xed\x1e\
3162 \x0f\xfc\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x02\xc0\x27\
3163 \xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x08\x05\x70\x6e\x73\
3164 \x32\x33\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x07\
3165 \x04\x6e\x73\x32\x33\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\
3166 \x10\x00\x08\x05\x70\x6e\x73\x32\x32\xc0\x2c\xc0\x0c\x00\x02\x00\
3167 \x01\x00\x00\x0e\x10\x00\x08\x05\x70\x6e\x73\x32\x34\xc0\x2c\xc0\
3168 \x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x07\x04\x6e\x73\x32\x34\
3169 \xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x08\x05\x70\
3170 \x6e\x73\x32\x31\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\
3171 \x00\x07\x04\x6e\x73\x32\x32\xc0\x2c\xc0\x0c\x00\x2e\x00\x01\x00\
3172 \x00\x0e\x10\x00\x5d\x00\x02\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\
3173 \x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\
3174 \x6b\x00\xd1\xc5\x6c\xf1\xfb\xd0\x75\xf1\x38\x20\x28\x80\x4c\xe0\
3175 \x59\xa5\xa8\xab\x84\x79\xd8\x37\x48\xa7\xa5\x3f\x08\x9b\x4c\xca\
3176 \x40\x2b\xcb\x2c\xda\xcc\xc2\x18\xad\x07\x9e\xf8\x4e\x17\x8d\xb1\
3177 \x2b\x2d\xa2\xa6\x17\xdb\x55\x30\xbc\xa2\xb9\xa0\x01\x71\x01\xe5\
3178 \xdc\x4f\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xd9\x14\
3179 \x70\xd0\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\x01\
3180 \x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\
3181 \x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xf8\x57\x68\xf0\xad\
3182 \x9e\xfb\x3a\x0f\x66\xbd\xcc\x48\xe7\x29\x0a\xf4\xd8\xf6\xbe\xbc\
3183 \x04\x76\x02\x27\x64\xf2\xc9\x42\x6d\x75\x54\x83\x0a\x11\xda\x0a\
3184 \x02\x6b\x8c\xf1\x65\xc4\x21\x44\xea\x89\x09\x01\xc8\xa1\xe2\x11\
3185 \x8f\xed\x67\x39\x69\x33\xdd\x97\x22\x1a\xd3\xc0\x0c\x00\x0f\x00\
3186 \x01\x00\x00\x0e\x10\x00\x11\x00\x0a\x04\x6d\x61\x69\x6c\x04\x6e\
3187 \x69\x78\x64\x03\x6f\x72\x67\x00\xc0\x0c\x00\x2e\x00\x01\x00\x00\
3188 \x0e\x10\x00\x5d\x00\x0f\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\
3189 \x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\
3190 \x00\xd4\xdd\x07\xd9\xb6\xb2\xba\x57\xa9\x1d\x3b\xaa\x6c\x55\xc4\
3191 \x3d\x73\x79\xea\x74\xfe\xd7\x23\x0c\xb4\xab\x8f\x4b\x1f\xd9\x8a\
3192 \xb2\x4a\x5c\xad\x3e\x8e\x4a\x85\xbb\xbd\x75\xf2\x47\x2c\xa8\x89\
3193 \x21\x75\x89\xb1\x12\xc4\xd2\xf7\x40\x06\x52\x57\x83\x8a\xaa\x7b\
3194 \x75\xc0\x0c\x00\x10\x00\x01\x00\x00\x0e\x10\x00\x34\x33\x76\x3d\
3195 \x73\x70\x66\x31\x20\x2b\x6d\x78\x20\x2b\x61\x3a\x6d\x61\x69\x6c\
3196 \x2e\x6e\x69\x78\x64\x2e\x6f\x72\x67\x20\x69\x70\x34\x3a\x32\x31\
3197 \x37\x2e\x32\x30\x2e\x31\x31\x32\x2e\x32\x30\x38\x20\x2d\x61\x6c\
3198 \x6c\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\x10\x0d\
3199 \x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\
3200 \x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xd1\x6c\xd1\xf4\x3b\xe0\
3201 \x44\xba\xfe\xe9\xdb\x82\xbd\x89\x5f\xa1\x07\x72\xdd\x47\xad\x4e\
3202 \x91\xd5\xc3\xfe\x3e\x39\x74\xdb\x50\x50\x19\x6c\x3f\x6c\xb7\xa8\
3203 \x01\x03\x6a\xf5\xa7\xf3\x9b\xf7\x76\xd4\xff\xa3\xd5\x43\xfc\xec\
3204 \xa9\x89\x24\xf8\xd2\xb6\x76\xd4\x20\xbc\xc0\x0c\x00\x30\x00\x01\
3205 \x00\x00\x0e\x10\x00\x44\x01\x01\x03\x0d\xf3\x87\xe2\x7c\x2b\x82\
3206 \x40\x72\x7c\xfd\xc9\x2b\xe8\x22\xd6\xa9\x40\xc0\xab\x03\x25\x7d\
3207 \x92\xae\xf3\x17\x71\x82\x67\xc6\xcd\xb6\x4b\x11\x62\xc6\xfa\x06\
3208 \xec\x4c\x9f\xd9\xe6\xaf\x5c\x3d\xe4\x32\xde\x11\x1b\x09\x13\xe3\
3209 \xd0\xba\x66\xd1\xbc\x32\xdb\x13\xd7\x1d\xc0\x0c\x00\x30\x00\x01\
3210 \x00\x00\x0e\x10\x00\x44\x01\x00\x03\x0d\xd4\x43\xde\x96\xe5\xea\
3211 \x0a\xf9\x5d\x4f\x72\x88\x9c\xd9\x9c\xf7\xa6\x3f\x12\xd7\xf3\xea\
3212 \x8a\x6b\x44\x4c\x79\x23\x81\x94\x43\xa3\xbd\x9e\xb8\xde\xfe\x8c\
3213 \xe6\x21\xe3\x8a\x71\xba\x05\xd2\x0f\x98\x5b\xfc\x7e\x72\x8c\xe9\
3214 \x9a\xc0\x49\x00\xca\xd5\x62\x93\x7f\x03\xc0\x0c\x00\x2e\x00\x01\
3215 \x00\x00\x0e\x10\x00\x5d\x00\x30\x0d\x02\x00\x00\x0e\x10\x61\xf2\
3216 \xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\
3217 \x73\x6b\x00\xc0\x93\x23\x1d\xcb\x1e\x79\xfe\x7c\x40\x3e\xd4\x33\
3218 \x5f\xed\x69\x8e\x7d\x75\xff\x73\x6b\x24\x71\x8f\x50\xf8\xe0\x49\
3219 \xce\x5f\x62\x0c\x8c\xb3\x06\x8f\x26\xea\x20\xa0\xe3\x71\xe0\xa1\
3220 \x8b\xe0\x4a\x2f\x1d\x4b\x79\x2c\x52\x6b\xa4\x43\xb5\x70\x27\x01\
3221 \xb0\x63\x47\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\
3222 \x30\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x97\
3223 \x18\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x41\x87\x75\x1d\
3224 \x30\x44\xd1\x94\x40\xd4\xe6\x40\x98\x62\x94\x53\xad\x53\xe2\xed\
3225 \xc0\xc0\xb7\xa3\x20\x15\xae\x59\xbb\x97\x45\xfb\x0e\xbf\x70\xf3\
3226 \xb1\x24\x79\xe8\x85\x6c\x2a\x66\x10\xb6\x75\x99\x7b\x77\x78\x65\
3227 \xa6\x67\x8d\x59\xa6\x14\xf7\xe6\x77\xab\x53\x9c\xc0\x0c\x00\x33\
3228 \x00\x01\x00\x00\x02\x58\x00\x0d\x01\x00\x00\x0a\x08\x90\xc7\xf1\
3229 \x74\x0b\x0c\xfb\x34\xc0\x0c\x00\x2e\x00\x01\x00\x00\x02\x58\x00\
3230 \x5d\x00\x33\x0d\x02\x00\x00\x00\x00\x61\xf2\xaf\x39\x61\xcb\x22\
3231 \x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xc4\x4d\
3232 \x00\x48\x9c\x86\x49\xac\x8d\x03\x28\x23\xac\xec\xf5\x5b\xb6\xe5\
3233 \x2f\xf6\xae\xaa\x01\x5a\x66\x52\xf7\x43\xc3\xb1\xe5\xef\xe5\xbf\
3234 \x5f\x71\x5d\xa1\x57\x64\x66\x5e\xa1\x6f\x96\xa8\xcd\x48\x85\xe4\
3235 \x20\xe2\xfb\xb0\xc1\x00\x47\x72\xc8\x72\x98\xc7\x41\xd9";
3236
3237 let dummy =
3238 DnsRequestHeader
3239 {
3240 header: DnsHeader {id: 0xd079, ..Default::default()},
3241 payload: DnsRequestPayload
3242 {
3243 qname: Cow::Borrowed(b"\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00"),
3244 qtype: QType::ALL,
3245 qclass: QClass::IN,
3246 }
3247 };
3248
3249 let now = Instant::now();
3250 let ans = DnsRequestAnswer::parse(pkt.as_slice());
3251 let elapsed = now.elapsed();
3252 println!("Elapsed: {:.2?}", elapsed);
3253
3254 assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
3255 let ans = ans.unwrap();
3256
3257 let verif = ans.verify(&dummy);
3258 assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
3259
3260 assert_eq!(ans.req_header.header.id, 0xd079);
3261 assert_eq!(ans.req_header.header.ancount, 23);
3262 assert_eq!(ans.req_header.header.arcount, 0);
3263 assert_eq!(ans.req_header.header.nscount, 0);
3264 assert_eq!(ans.req_header.header.qdcount, 1);
3265
3266 let ansord = &ans.response[0];
3267 assert_eq!(
3268 ansord.rdata,
3269 RecordSOA::wrap(
3270 RecordSOA
3271 {
3272 pnm: "ns21.cloudns.net".to_string(),
3273 ram: "support.cloudns.net".to_string(),
3274 serial: 2021122801,
3275 interv_refr: 7200,
3276 interv_retry: 1800,
3277 expire_limit: 1209600,
3278 min_ttl: 3600
3279 }
3280 )
3281 );
3282 assert_eq!(ansord.name, "relkom.sk".to_string());
3283 assert_eq!(ansord.dtype, QType::SOA);
3284 assert_eq!(ansord.class, QClass::IN);
3285 assert_eq!(ansord.ttl, 3600);
3286 assert_eq!(ansord.rdlength, 48);
3287
3288 let a1 =
3289 b"\x00\x06\x0d\x02\
3290 \x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\x72\
3291 \x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x2f\x79\xed\x73\xd0\x75\xc8\
3292 \xa9\xa2\x2a\x08\x3c\x78\xb9\xfb\x43\xc5\x8e\x62\x4c\xbc\x36\xeb\
3293 \x22\x96\x45\x59\x36\x1f\x69\x3a\x7a\x5e\x67\xd0\x54\x1e\xf0\xf2\
3294 \x11\x1a\x72\x00\x56\x89\x26\x79\xf4\x06\x1a\x0c\x59\x41\x32\x60\
3295 \x68\x75\x05\x3d\x90\xed\x1e\x0f\xfc";
3296 let mut a1curs = Cursor::new(a1.as_slice());
3297 let a1len = a1.len();
3298
3299 let ansord = &ans.response[1];
3300 assert_eq!(ansord.rdata, RecordRRSIG::wrap( RecordRRSIG::read(&mut a1curs, a1len as u16, QType::RRSIG).unwrap() ));
3301 assert_eq!(ansord.name, "relkom.sk".to_string());
3302 assert_eq!(ansord.dtype, QType::RRSIG);
3303 assert_eq!(ansord.class, QClass::IN);
3304 assert_eq!(ansord.ttl, 3600);
3305 assert_eq!(ansord.rdlength, a1len as u16);
3306
3307 let ansord = &ans.response[2];
3308 assert_eq!(ansord.rdata, RecordNS::wrap( RecordNS{ fqdn: "ns21.cloudns.net".to_string() }));
3309 assert_eq!(ansord.name, "relkom.sk".to_string());
3310 assert_eq!(ansord.dtype, QType::NS);
3311 assert_eq!(ansord.class, QClass::IN);
3312 assert_eq!(ansord.ttl, 3600);
3313 assert_eq!(ansord.rdlength, 2);
3314 }
3315
3316
3317 #[test]
3318 fn test_request()
3319 {
3320 use std::time::Instant;
3321 use std::net::IpAddr;
3322
3323 let ipp = IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8));
3324 let qdnsreq =
3325 QDnsReq::new_into(&ipp, QType::PTR)
3326 .unwrap();
3327
3328 let now = Instant::now();
3329
3330 let req = DnsRequestHeader::construct_lookup(&qdnsreq);
3331
3332 let elapsed = now.elapsed();
3333 println!("Elapsed: {:.2?}", elapsed);
3334
3335 assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
3336
3337 let pkt = req.unwrap().to_bytes(false);
3338 assert_eq!(pkt.is_ok(), true);
3339 let pkt = pkt.unwrap();
3340
3341 let ctrl =
3342 b"\x15\xc8\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x38\x01\x38\
3343 \x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\
3344 \x61\x00\x00\x0c\x00\x01";
3345
3346 assert_eq!(&pkt[2..], &ctrl[2..]);
3347 }
3348
3349 #[test]
3350 fn test_request_1()
3351 {
3352 use std::time::Instant;
3353 use std::net::IpAddr;
3354
3355 let ipp = IpAddr::V4("100.150.111.80".parse().unwrap());
3356 let qdnsreq =
3357 QDnsReq::new_into(&ipp, QType::PTR)
3358 .unwrap();
3359
3360 let now = Instant::now();
3361
3362 let req = DnsRequestHeader::construct_lookup(&qdnsreq);
3363
3364 let elapsed = now.elapsed();
3365 println!("Elapsed: {:.2?}", elapsed);
3366
3367 assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
3368
3369 let pkt = req.unwrap().to_bytes(false);
3370 assert_eq!(pkt.is_ok(), true);
3371 let pkt = pkt.unwrap();
3372
3373 let ctrl =
3374 b"\x74\xa1\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x02\x38\x30\x03\
3375 \x31\x31\x31\x03\x31\x35\x30\x03\x31\x30\x30\x07\x69\x6e\x2d\x61\
3376 \x64\x64\x72\x04\x61\x72\x70\x61\x00\x00\x0c\x00\x01";
3377
3378 assert_eq!(&pkt[2..], &ctrl[2..]);
3379 }
3380
3381 #[test]
3382 fn test_request6()
3383 {
3384 use std::time::Instant;
3385 use std::net::IpAddr;
3386
3387 let ipp = IpAddr::V6("2a00:1450:4003:802::200e".parse().unwrap());
3388 let qdnsreq =
3389 QDnsReq::new_into(&ipp, QType::PTR)
3390 .unwrap();
3391
3392 let now = Instant::now();
3393
3394 let req = DnsRequestHeader::construct_lookup(&qdnsreq);
3395
3396 let elapsed = now.elapsed();
3397 println!("Elapsed: {:.2?}", elapsed);
3398
3399 assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
3400
3401 let pkt = req.unwrap().to_bytes(false);
3402 assert_eq!(pkt.is_ok(), true);
3403 let pkt = pkt.unwrap();
3404
3405 let ctrl =
3406 b"\xee\xec\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x65\x01\x30\
3407 \x01\x30\x01\x32\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\
3408 \x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x32\x01\x30\
3409 \x01\x38\x01\x30\x01\x33\x01\x30\x01\x30\x01\x34\x01\x30\x01\x35\
3410 \x01\x34\x01\x31\x01\x30\x01\x30\x01\x61\x01\x32\x03\x69\x70\x36\
3411 \x04\x61\x72\x70\x61\x00\x00\x0c\x00\x01";
3412
3413 assert_eq!(&pkt[2..], &ctrl[2..]);
3414 }
3415
3416}