1use std::{cmp::Ordering, fmt::{self}, io::{Cursor, Read, Write}, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, path::Path, sync::{Arc, LazyLock, OnceLock}, time::Duration};
59use std::borrow::Borrow;
60use std::hash::{Hash, Hasher};
61
62use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
63
64use crate::{cfg_host_parser::HostnameEntry, error::*, internal_error_map, query_private::QDnsReq};
65use crate::internal_error;
66
67pub const RESOLV_CFG_PATH: &'static str = "/etc/resolv.conf";
69
70pub const HOST_CFG_PATH: &'static str = "/etc/hosts";
72
73pub static RESOLV_CFG_PATH_P: LazyLock<&'static Path> = LazyLock::new(|| {Path::new(RESOLV_CFG_PATH)});
74pub static HOST_CFG_PATH_P: LazyLock<&'static Path> = LazyLock::new(|| {Path::new(HOST_CFG_PATH)});
75
76pub static GLOBALS: OnceLock<CDdnsGlobals> = OnceLock::new();
77
78pub const NSSWITCH_CFG_PATH: &'static str = "/etc/nsswitch.conf";
80
81const IN_ADDR_ARPA: &[u8] = b"\x07in-addr\x04arpa\x00";
82const IN_ADDR6_ARPA: &[u8] = b"\x03ip6\x04arpa\x00";
83
84pub const DEF_USERAGENT: &'static str = concat!("CDNS-RS/", env!("CARGO_PKG_VERSION"));
85pub const DEF_TLS_PORT: u16 = 853;
86pub const DEF_HTTPS_PORT: u16 = 443;
87
88pub const IPV4_BIND_ALL: IpAddr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
90pub const IPV6_BIND_ALL: IpAddr = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
92
93#[derive(Debug)]
94pub struct CDdnsGlobals
95{
96 pub tcp_timeout: Option<Duration>,
97}
98
99impl CDdnsGlobals
100{
101 pub
104 fn init_once(globals: CDdnsGlobals)
105 {
106 GLOBALS.get_or_init(|| globals);
107
108 return;
109 }
110
111 pub
112 fn get_tcp_conn_timeout() -> Option<Duration>
113 {
114 return GLOBALS.get().map_or(None, |f| f.tcp_timeout);
115 }
116}
117
118#[inline]
119pub
120fn bind_all(ip_addr: IpAddr) -> SocketAddr
121{
122 match ip_addr
123 {
124 IpAddr::V4(_) =>
125 SocketAddr::from((IPV4_BIND_ALL, 0)),
126 IpAddr::V6(_) =>
127 SocketAddr::from((IPV6_BIND_ALL, 0)),
128 }
129}
130
131pub
132fn pkt2string_exact(pkt: &mut Cursor<&[u8]>, rdlen: u16) -> CDnsResult<String>
133{
134 let mut new_string = vec![0_u8; rdlen as usize];
135
136
137 pkt.read_exact(&mut new_string).map_err(map_read_err)?;
138
139
140 return
141 String::from_utf8(new_string)
142 .map_err(|e|
143 internal_error_map!(CDnsErrorType::InternalError, "UTF-8 decode error, {}", e)
144 );
145}
146
147pub
148fn pkt2vec(pkt: &mut Cursor<&[u8]>, rdlen: Option<u16>) -> CDnsResult<Vec<u8>>
149{
150 if let Some(rdl) = rdlen
151 {
152 let mut new_buf = vec![0_u8; rdl as usize];
153
154
155 pkt.read_exact(&mut new_buf).map_err(map_read_err)?;
156
157
158 return Ok(new_buf);
159 }
160 else
161 {
162 let mut new_buf = Vec::new();
163
164 pkt.read_to_end(&mut new_buf).map_err(map_read_err)?;
165
166 return Ok(new_buf);
167 }
168}
169
170pub
181fn pkt2name(pkt: &mut Cursor<&[u8]>) -> CDnsResult<Vec<u8>>
182{
183 let qname_s = pkt.position() as usize;
184
185 loop
186 {
187 let cnt = pkt.read_u8().map_err(map_read_err)?;
188
189 if cnt == 0
190 {
191 break;
192 }
193 else
194 {
195 for _ in 0..cnt
196 {
197 let c = pkt.read_u8().map_err(map_read_err)?;
198 if c == 0
199 {
200 internal_error!(
201 CDnsErrorType::DnsResponse,
202 "incorrectly encoded QNAME in response, found '0' at offset: '{}'",
203 pkt.position()
204 );
205 }
206 }
207 }
208 }
209
210 let cur_pos = pkt.position() as usize;
212
213 if (cur_pos - qname_s) <= 1
214 {
215 internal_error!(
216 CDnsErrorType::DnsResponse,
217 "read name is too short"
218 );
219 }
220
221 return Ok(pkt.get_ref()[qname_s..cur_pos].to_vec());
232}
233
234
235pub
237fn name2str(pkt: &mut Cursor<&[u8]>, mut opt_rdlen: Option<u16>) -> CDnsResult<String>
238{
239 let cur_in_pos = pkt.position();
240 let mut comp: u8;
242 let mut output: Vec<String> = Vec::with_capacity(6);
243
244 loop
245 {
246 if let Some(rdlen) = opt_rdlen
247 {
248 if pkt.position() - cur_in_pos >= rdlen as u64
249 {
250 return Ok(output.join("."));
251 }
252 }
253
254 comp = pkt.read_u8().map_err(map_read_err)?;
257
258 let msb = comp & 0xC0;
264
265 if msb == 0xC0
266 {
267 if opt_rdlen.is_none() == true
268 {
269 opt_rdlen = Some(2);
270 }
271
272 let offset1: u16 = ((comp & !0xC0) as u16) << 8;let offset2: u16 = pkt.read_u8().map_err(map_read_err)? as u16;
274
275 let offset = offset1 | offset2;
276
277 if offset as usize >= pkt.get_ref().len()
281 {
282 internal_error!(
283 CDnsErrorType::DnsResponse,
284 "incoreclty formated packet: offset: '{}' > len: '{}'",
285 offset, pkt.get_ref().len()
286 );
287 }
288
289 let cur_pos = pkt.position();
291 pkt.set_position(offset as u64);
292
293 output.push(name2str(pkt, None)?);
295 pkt.set_position(cur_pos);
299 }
300 else if msb == 0x00
301 {
302 if comp == 0
303 {
304 if let Some(rdlen) = opt_rdlen
305 {
306 let dif = pkt.position() - cur_in_pos;
307
308 if rdlen as u64 != dif
309 {
310 internal_error!(CDnsErrorType::DnsResponse, "incorrect rdlen: '{}', exp: '{}'", rdlen, dif);
311 }
312 }
313
314 return Ok(output.join("."));
315 }
316 else
317 {
318 let mut tmp: Vec<u8> = Vec::with_capacity(comp as usize);
319
320 for _ in 0..comp
321 {
322 let c = pkt.read_u8().map_err(map_read_err)?;
323 if c == 0
324 {
325 internal_error!(CDnsErrorType::DnsResponse, "protocol violation, incorrectly encoded QNAME in response");
326 }
327
328 tmp.push(c);
329 }
330
331 output
332 .push(
333 String::from_utf8(tmp)
334 .map_err(|e|
335 internal_error_map!(CDnsErrorType::InternalError, "UTF-8 decode error, {}", e)
336 )?
337 );
338 }
339 }
340 else
341 {
342 internal_error!(CDnsErrorType::DnsResponse, "incorrect compression: {:x}", msb);
343 }
344
345 } }
347
348
349pub
364fn byte2hexchar(b: u8) -> u8
365{
366 match b
367 {
368 0..=9 => return '0' as u8 + b,
369 10..=15 => return 'a' as u8 + (b - 10),
370 _ => panic!("out of hex range!")
371 }
372}
373
374pub
385fn ip2pkt(ip: &IpAddr) -> CDnsResult<Vec<u8>>
386{
387 match *ip
388 {
389 IpAddr::V4(ref ipv4) =>
390 return ipv4_pkt(ipv4),
391 IpAddr::V6(ref ipv6) =>
392 return ipv6_pkt(ipv6)
393 };
394}
395
396const MAX_NAME_LEN: usize = 63;
397
398pub
399fn ipv4_pkt(ip: &Ipv4Addr) -> CDnsResult<Vec<u8>>
400{
401
402 let mut out: Vec<u8> = Vec::with_capacity(16 + IN_ADDR_ARPA.len());
404
405
406 ip
407 .octets()
408 .into_iter()
409 .rev()
410 .for_each(|v|
411 {
412 let st = v.to_string();
413 out.push(st.len() as u8);
414 out.extend(st.as_bytes());
415 }
416 );
417
418 out.extend_from_slice(IN_ADDR_ARPA);
419
420 return Ok(out);
421}
422
423pub
424fn ipv6_pkt(ip: &Ipv6Addr) -> CDnsResult<Vec<u8>>
425{
426 let mut out: Vec<u8> = Vec::with_capacity(32 + IN_ADDR6_ARPA.len());
428
429 let mut octets = ip.octets();
430 octets.reverse();
431
432 for oct in octets
433 {
434 let h_oct = byte2hexchar((oct & 0xF0) >> 4);
435 let l_oct = byte2hexchar(oct & 0x0F);
437 out.push(1);
442 out.push(l_oct);
443 out.push(1);
445 out.push(h_oct);
446 }
447
448 out.extend(IN_ADDR6_ARPA);
449
450 return Ok(out);
451}
452
453pub
454fn name2pkt(name: &str) -> CDnsResult<Vec<u8>>
455{
456 let mut out: Vec<u8> = Vec::with_capacity(name.len() + 2);
458
459 for n in name.split(".")
460 {
461 if n.len() >= MAX_NAME_LEN
462 {
463 internal_error!(CDnsErrorType::InternalError, "name too long: '{}' in: '{}'", n.len(), name);
464 }
465
466 out.push((n.len() & 0xFF) as u8);
467 out.extend(n.as_bytes());
468 }
469
470 out.push(0);
471
472 return Ok(out);
473}
474
475
476#[repr(u16)]
482#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
483pub enum QType
484{
485 A = 1,
487 NS = 2,
489 MD = 3,
491 MF = 4,
493 CNAME = 5,
495 SOA = 6,
497 MB = 7,
499 MG = 8,
501 MR = 9,
503 NULL = 10,
505 WKS = 11,
507 PTR = 12,
509 HINFO = 13,
511 MINFO = 14,
513 MX = 15,
515 TXT = 16,
517 AFSDB = 18,
519 KEY = 25,
521 AAAA = 28,
523 SRV = 33,
525 CERT = 37,
527 DS = 43,
529 RRSIG = 46,
531 NSEC = 47,
533 DNSKEY = 48,
535 NSEC3 = 50,
537 NSEC3PARAM = 51,
539 CDS = 59,
541 CDNSKEY = 60,
543 OPENPGPKEY = 61,
545 AXFR = 252,
548 MAILB = 253,
550 MAILA = 254,
552 URI = 256,
554 CAA = 257,
556 ALL = 255,
558 DLV = 32769,
560}
561
562impl Default for QType
563{
564 fn default() -> Self
565 {
566 return Self::A;
567 }
568}
569
570
571impl Into<u16> for QType
572{
573 fn into(self) -> u16
574 {
575 return self as u16;
576 }
577}
578
579impl fmt::Display for QType
580{
581 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
582 {
583 match *self
584 {
585 Self::A => write!(f, "A"),
586 Self::NS => write!(f, "NS"),
587 Self::MD => write!(f, "MD"),
588 Self::MF => write!(f, "MF"),
589 Self::CNAME => write!(f, "CNAME"),
590 Self::SOA => write!(f, "SOA"),
591 Self::MB => write!(f, "MB"),
592 Self::MG => write!(f, "MG"),
593 Self::MR => write!(f, "MR"),
594 Self::NULL => write!(f, "NULL"),
595 Self::WKS => write!(f, "WKS"),
596 Self::PTR => write!(f, "PTR"),
597 Self::HINFO => write!(f, "HINFO"),
598 Self::MINFO => write!(f, "MINFO"),
599 Self::MX => write!(f, "MX"),
600 Self::TXT => write!(f, "TXT"),
601 Self::AFSDB => write!(f, "AFSDB"),
602 Self::KEY => write!(f, "KEY"),
603 Self::AAAA => write!(f, "AAAA"),
604 Self::SRV => write!(f, "SRV"),
605 Self::CERT => write!(f, "CERT"),
606 Self::DS => write!(f, "DS"),
607 Self::RRSIG => write!(f, "RRSIG"),
608 Self::NSEC => write!(f, "NSEC"),
609 Self::DNSKEY => write!(f, "DNSKEY"),
610 Self::NSEC3 => write!(f, "NSEC"),
611 Self::NSEC3PARAM => write!(f, "NSEC3PARAM"),
612 Self::CDS => write!(f, "CDS"),
613 Self::CDNSKEY => write!(f, "CDNSKEY"),
614 Self::OPENPGPKEY => write!(f, "OPENPGPKEY"),
615 Self::AXFR => write!(f, "AXFR"),
616 Self::MAILB => write!(f, "MAILB"),
617 Self::MAILA => write!(f, "MAILA"),
618 Self::CAA => write!(f, "CAA"),
619 Self::ALL => write!(f, "ALL"),
620 Self::DLV => write!(f, "DLV"),
621 Self::URI => write!(f, "URI"),
622 }
623 }
624}
625
626
627impl QType
628{
629 pub
630 fn ipaddr_match(&self, ip: &IpAddr) -> bool
631 {
632 match *self
633 {
634 Self::A => return ip.is_ipv4(),
635 Self::AAAA => return ip.is_ipv6(),
636 _ => false,
637 }
638 }
639
640 pub
641 fn u16_to_qtype(value: u16) -> CDnsResult<QType>
642 {
643 match value
644 {
645 x if x == Self::AXFR as u16 => return Ok(Self::AXFR),
646 x if x == Self::MAILB as u16 => return Ok(Self::MAILB),
647 x if x == Self::MAILA as u16 => return Ok(Self::MAILA),
648 x if x == Self::ALL as u16 => return Ok(Self::ALL),
649 x if x == Self::DLV as u16 => return Ok(Self::DLV),
650 _ => return Self::u16_to_type(value),
651 }
652 }
653
654 pub
655 fn u16_to_type(value: u16) -> CDnsResult<QType>
656 {
657
658 match value
659 {
660 x if x == Self::A as u16 => return Ok(Self::A),
661 x if x == Self::NS as u16 => return Ok(Self::NS),
662 x if x == Self::MD as u16 => return Ok(Self::MD),
663 x if x == Self::MF as u16 => return Ok(Self::MF),
664 x if x == Self::CNAME as u16 => return Ok(Self::CNAME),
665 x if x == Self::SOA as u16 => return Ok(Self::SOA),
666 x if x == Self::MB as u16 => return Ok(Self::MB),
667 x if x == Self::MG as u16 => return Ok(Self::MG),
668 x if x == Self::MR as u16 => return Ok(Self::MR),
669 x if x == Self::NULL as u16 => return Ok(Self::NULL),
670 x if x == Self::WKS as u16 => return Ok(Self::WKS),
671 x if x == Self::PTR as u16 => return Ok(Self::PTR),
672 x if x == Self::HINFO as u16 => return Ok(Self::HINFO),
673 x if x == Self::MINFO as u16 => return Ok(Self::MINFO),
674 x if x == Self::MX as u16 => return Ok(Self::MX),
675 x if x == Self::TXT as u16 => return Ok(Self::TXT),
676 x if x == Self::AFSDB as u16 => return Ok(Self::AFSDB),
677 x if x == Self::KEY as u16 => return Ok(Self::KEY),
678 x if x == Self::AAAA as u16 => return Ok(Self::AAAA),
679 x if x == Self::CERT as u16 => return Ok(Self::CERT),
680 x if x == Self::DS as u16 => return Ok(Self::DS),
681 x if x == Self::RRSIG as u16 => return Ok(Self::RRSIG),
682 x if x == Self::NSEC as u16 => return Ok(Self::NSEC),
683 x if x == Self::DNSKEY as u16 => return Ok(Self::DNSKEY),
684 x if x == Self::NSEC3 as u16 => return Ok(Self::NSEC3),
685 x if x == Self::NSEC3PARAM as u16 => return Ok(Self::NSEC3PARAM),
686 x if x == Self::CDS as u16 => return Ok(Self::CDS),
687 x if x == Self::CDNSKEY as u16 => return Ok(Self::CDNSKEY),
688 x if x == Self::OPENPGPKEY as u16 => return Ok(Self::OPENPGPKEY),
689 _ => internal_error!(CDnsErrorType::DnsResponse, "unknown request record type: '{}'", value),
690 }
691 }
692}
693
694
695#[repr(u16)]
699#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
700pub enum QClass
701{
702 IN = 1,
704 CS = 2,
706 CH = 3,
708 HS = 4,
710
711 ALL = 255,
714}
715
716impl fmt::Display for QClass
717{
718 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
719 {
720 match *self
721 {
722 Self::IN => write!(f, "IN"),
723 Self::CS => write!(f, "CS"),
724 Self::CH => write!(f, "CH"),
725 Self::HS => write!(f, "HS"),
726 Self::ALL => write!(f, "ALL"),
727 }
728 }
729}
730
731impl Default for QClass
732{
733 fn default() -> Self
734 {
735 return Self::IN;
736 }
737}
738
739impl Into<u16> for QClass
740{
741 fn into(self) -> u16
742 {
743 return self as u16;
744 }
745}
746
747impl QClass
748{
749 pub
754 fn u16_to_qclass(value: u16) -> CDnsResult<QClass>
755 {
756 match value
757 {
758 x if x == QClass::ALL as u16 => return Ok(QClass::ALL),
759 _ => Self::u16_to_class(value),
760 }
761 }
762
763 pub
765 fn u16_to_class(value: u16) -> CDnsResult<QClass>
766 {
767 match value
768 {
769 x if x == QClass::IN as u16 => return Ok(QClass::IN),
770 x if x == QClass::CS as u16 => return Ok(QClass::CS),
771 x if x == QClass::CH as u16 => return Ok(QClass::CH),
772 x if x == QClass::HS as u16 => return Ok(QClass::HS),
773 _ => internal_error!(CDnsErrorType::DnsResponse, "unknown QCLASS type: '{}'", value),
774 }
775 }
776}
777
778bitflags! {
782 #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
784 pub struct StatusBits: u16
785 {
786 const QR_RESP = 0x8000;
789
790 const OPCODE_STANDARD = 0x87FF;
793 const OPCODE_IQUERY = 0x0040;
795 const OPCODE_STATUS = 0x0020;
797 const AUTH_ANSWER = 0x0400;
805
806 const TRUN_CATION = 0x0200;
810
811 const RECURSION_DESIRED = 0x0100;
817
818 const RECURSION_AVAIL = 0x0080;
823
824 const RSERVER0 = 0x0040;
828
829 const ANSWER_AUTHN = 0x0020;
830 const NON_AUTH_DATA = 0x0010;
831
832 const RESP_NOERROR = 0x0000;
836 const RESP_FORMERR = 0x0001;
838 const RESP_SERVFAIL = 0x0002;
841 const RESP_NXDOMAIN = 0x0003;
845 const RESP_NOT_IMPL = 0x0004;
847 const RESP_REFUSED = 0x0005;
850 }
852}
853
854#[derive(Clone, Debug, Hash, PartialEq, Eq)]
860pub enum QDnsName
861{
862 IpV4(Ipv4Addr),
863 IpV6(Ipv6Addr),
864 Name(Arc<String>),
865}
866
867impl fmt::Display for QDnsName
868{
869 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
870 {
871 match self
872 {
873 QDnsName::IpV4(ipv4_addr) =>
874 write!(f, "{}", ipv4_addr),
875 QDnsName::IpV6(ipv6_addr) =>
876 write!(f, "{}", ipv6_addr),
877 QDnsName::Name(name) =>
878 write!(f, "{}", name),
879 }
880 }
881}
882
883impl QDnsName
884{
885 pub
888 fn is_ipv4(&self) -> bool
889 {
890 match *self
891 {
892 Self::IpV4(_) => return true,
893 _ => return false,
894 }
895 }
896
897 pub
900 fn is_ipv6(&self) -> bool
901 {
902 match *self
903 {
904 Self::IpV6(_) => return true,
905 _ => return false,
906 }
907 }
908
909 pub
912 fn is_ip(&self) -> bool
913 {
914 match *self
915 {
916 Self::IpV4(_) => return true,
917 Self::IpV6(_) => return true,
918 _ => return false,
919 }
920 }
921
922 pub
924 fn get_ip_qtype(&self) -> Option<QType>
925 {
926 match *self
927 {
928 Self::IpV4(_) => return Some(QType::A),
929 Self::IpV6(_) => return Some(QType::AAAA),
930 Self::Name(_) =>
931 {
932 return None;
933 }
934 }
935 }
936}
937
938
939impl PartialEq<str> for QDnsName
940{
941 fn eq(&self, other: &str) -> bool
942 {
943 match *self
944 {
945 Self::Name(ref name) =>
946 return name.as_str() == other,
947 Self::IpV4(ref ip) =>
948 {
949 if let Ok(other_ip) = other.parse::<Ipv4Addr>()
950 {
951 return &other_ip == ip;
952 }
953
954 return false;
955 },
956 Self::IpV6(ref ip) =>
957 {
958 if let Ok(other_ip) = other.parse::<Ipv6Addr>()
959 {
960 return &other_ip == ip;
961 }
962
963 return false;
964 }
965 }
966 }
967}
968
969impl From<&IpAddr> for QDnsName
986{
987 fn from(ip: &IpAddr) -> Self
988 {
989 match *ip
990 {
991 IpAddr::V4(ref ip) =>
992 return Self::IpV4(ip.clone()),
993 IpAddr::V6(ref ip) =>
994 return Self::IpV6(ip.clone()),
995 }
996 }
997}
998
999impl From<IpAddr> for QDnsName
1000{
1001 fn from(ip: IpAddr) -> Self
1002 {
1003 match ip
1004 {
1005 IpAddr::V4(ip) =>
1006 return Self::IpV4(ip),
1007 IpAddr::V6(ip) =>
1008 return Self::IpV6(ip),
1009 }
1010 }
1011}
1012
1013impl From<&Ipv4Addr> for QDnsName
1014{
1015 fn from(ip: &Ipv4Addr) -> Self
1016 {
1017 return Self::IpV4(ip.clone());
1018 }
1019}
1020
1021impl From<Ipv4Addr> for QDnsName
1022{
1023 fn from(ip: Ipv4Addr) -> Self
1024 {
1025 return Self::IpV4(ip);
1026 }
1027}
1028
1029impl From<&Ipv6Addr> for QDnsName
1030{
1031 fn from(ip: &Ipv6Addr) -> Self
1032 {
1033 return Self::IpV6(ip.clone());
1034 }
1035}
1036
1037impl From<Ipv6Addr> for QDnsName
1038{
1039 fn from(ip: Ipv6Addr) -> Self
1040 {
1041 return Self::IpV6(ip);
1042 }
1043}
1044
1045impl From<&str> for QDnsName
1046{
1047 fn from(name: &str) -> Self
1048 {
1049 let ipp = name.parse::<IpAddr>();
1050 if ipp.is_err()
1051 {
1052 return Self::Name(Arc::new(name.to_string()));
1053 }
1054 else
1055 {
1056 return QDnsName::from(ipp.unwrap());
1057 }
1058 }
1059}
1060
1061impl TryFrom<QDnsName> for Vec<u8>
1062{
1063 type Error = CDnsError;
1064
1065 fn try_from(qns: QDnsName) -> Result<Self, Self::Error>
1066 {
1067 match qns
1068 {
1069 QDnsName::IpV4(ref ip) =>
1070 {
1071 return ipv4_pkt(ip);
1072 },
1073 QDnsName::IpV6(ref ip) =>
1074 {
1075 return ipv6_pkt(ip);
1076 },
1077 QDnsName::Name(ref name) =>
1078 {
1079 if let Ok(ip) = name.parse::<Ipv4Addr>()
1080 {
1081 return ipv4_pkt(&ip);
1082 }
1083 else if let Ok(ip) = name.parse::<Ipv6Addr>()
1084 {
1085 return ipv6_pkt(&ip);
1086 }
1087 else
1088 {
1089 return name2pkt(name);
1090 }
1091 }
1092 }
1093 }
1094}
1095
1096impl TryFrom<&QDnsName> for Vec<u8>
1097{
1098 type Error = CDnsError;
1099
1100 fn try_from(qns: &QDnsName) -> Result<Self, Self::Error>
1101 {
1102 match qns
1103 {
1104 QDnsName::IpV4(ip) =>
1105 {
1106 return ipv4_pkt(ip);
1107 },
1108 QDnsName::IpV6(ip) =>
1109 {
1110 return ipv6_pkt(ip);
1111 },
1112 QDnsName::Name(name) =>
1113 {
1114 if let Ok(ip) = name.parse::<Ipv4Addr>()
1115 {
1116 return ipv4_pkt(&ip);
1117 }
1118 else if let Ok(ip) = name.parse::<Ipv6Addr>()
1119 {
1120 return ipv6_pkt(&ip);
1121 }
1122 else
1123 {
1124 return name2pkt(name);
1125 }
1126 }
1127 }
1128 }
1129}
1130
1131impl From<&QDnsName> for String
1132{
1133 fn from(dnsname: &QDnsName) -> Self
1134 {
1135 match *dnsname
1136 {
1137 QDnsName::IpV4(ref ip) =>
1138 {
1139 return ip.to_string();
1140 },
1141 QDnsName::IpV6(ref ip) =>
1142 {
1143 return ip.to_string();
1144 },
1145 QDnsName::Name(ref name) =>
1146 {
1147 return name.to_string();
1148 }
1149 }
1150 }
1151}
1152
1153
1154impl TryFrom<&QDnsName> for IpAddr
1155{
1156 type Error = CDnsError;
1157 fn try_from(value: &QDnsName) -> Result<Self, Self::Error>
1158 {
1159 match *value
1160 {
1161 QDnsName::IpV4(ref ip) =>
1162 {
1163 return Ok(IpAddr::V4(ip.clone()));
1164 },
1165 QDnsName::IpV6(ref ip) =>
1166 {
1167 return Ok(IpAddr::V6(ip.clone()));
1168 },
1169 QDnsName::Name(ref name) =>
1170 {
1171 if let Ok(ip) = name.parse::<Ipv4Addr>()
1172 {
1173 return Ok(IpAddr::V4(ip.clone()));
1174 }
1175 else if let Ok(ip) = name.parse::<Ipv6Addr>()
1176 {
1177 return Ok(IpAddr::V6(ip.clone()));
1178 }
1179 else
1180 {
1181 internal_error!(CDnsErrorType::InternalError, "not ip address!")
1182 }
1183 }
1184 }
1185 }
1186}
1187
1188
1189impl TryFrom<QDnsName> for IpAddr
1190{
1191 type Error = CDnsError;
1192 fn try_from(value: QDnsName) -> Result<Self, Self::Error>
1193 {
1194 match value
1195 {
1196 QDnsName::IpV4(ip) =>
1197 {
1198 return Ok(IpAddr::V4(ip));
1199 },
1200 QDnsName::IpV6(ip) =>
1201 {
1202 return Ok(IpAddr::V6(ip));
1203 },
1204 QDnsName::Name(ref name) =>
1205 {
1206 if let Ok(ip) = name.parse::<Ipv4Addr>()
1207 {
1208 return Ok(IpAddr::V4(ip));
1209 }
1210 else if let Ok(ip) = name.parse::<Ipv6Addr>()
1211 {
1212 return Ok(IpAddr::V6(ip));
1213 }
1214 else
1215 {
1216 internal_error!(CDnsErrorType::InternalError, "not ip address!")
1217 }
1218 }
1219 }
1220 }
1221}
1222
1223#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1224pub struct DnsHeader
1225{
1226 pub id: u16,
1229
1230 pub status: StatusBits,
1232
1233 pub qdcount: u16,
1236
1237 pub ancount: u16,
1240
1241 pub nscount: u16,
1245
1246 pub arcount: u16,
1249}
1250
1251impl fmt::Display for DnsHeader
1252{
1253 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1254 {
1255 write!(f, "ID:{} Status:{:?}, qdcnt:{}, ancnt:{}, nscnt:{}, arcnt:{}",
1256 self.id, self.status, self.qdcount, self.ancount, self.nscount, self.arcount)
1257 }
1258}
1259
1260
1261#[derive(Clone, Debug, Default, PartialEq, Eq)]
1262pub struct DnsRequestAnswer
1263{
1264 pub req_header: DnsRequestHeader,
1266 pub response: Vec<DnsResponsePayload>,
1268 pub additional: Vec<DnsResponsePayload>,
1270 pub authoratives: Vec<DnsResponsePayload>,
1272}
1273
1274impl DnsRequestAnswer
1275{
1276 #[inline]
1277 pub
1278 fn get_req_id(&self) -> u16
1279 {
1280 return self.req_header.get_id();
1281 }
1282
1283 pub
1289 fn verify(&self, req: &DnsRequestHeader) -> CDnsResult<()>
1290 {
1291 if self.get_req_id() != req.get_id()
1292 {
1293 internal_error!(
1294 CDnsErrorType::DnsResponse,
1295 "request and response ID did not match: '{}' != '{}'",
1296 req.header.id, self.get_req_id()
1297 );
1298 }
1299
1300 if self.req_header.payload != req.payload
1302 {
1303 internal_error!(CDnsErrorType::DnsResponse,
1304 "received request section is different from sent");
1305 }
1306 else if req.payload.qtype != QType::ALL
1307 {
1308 if req.payload.qtype != self.req_header.payload.qtype
1310 {
1311 internal_error!(
1312 CDnsErrorType::DnsResponse,
1313 "requested QTYPE differ received TYPE: '{}' != '{}'",
1314 req.payload.qtype,
1315 self.req_header.payload.qtype
1316 );
1317 }
1318 }
1319 else if self.req_header.header.status.contains(StatusBits::TRUN_CATION) == true
1320 {
1321 internal_error!(CDnsErrorType::MessageTruncated,
1322 "DNS response was truncated, aborting processing");
1323 }
1324
1325 return Ok(());
1326 }
1327
1328 pub(crate)
1334 fn parse(ans: &[u8]) -> CDnsResult<Self>
1335 {
1336 let mut pkt = Cursor::new(ans);
1338
1339 let id = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
1341
1342 let status = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
1343
1344 let header =
1345 DnsHeader
1346 {
1347 id: id,
1348 status: StatusBits::from_bits(status).ok_or_else(||
1349 internal_error_map!(CDnsErrorType::DnsResponse, "unknown status bits: '{}'", status)
1350 )?,
1351 qdcount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1352 ancount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1353 nscount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1354 arcount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1355 };
1356
1357 if header.status.contains(StatusBits::QR_RESP) == false
1361 {
1362 internal_error!(
1363 CDnsErrorType::DnsResponse,
1364 "incorret QR flag in STATUS register of response, expected 1 got 0"
1365 );
1366 }
1367 let request =
1384 DnsRequestPayload
1385 {
1386 qname: pkt2name(&mut pkt)?,
1387 qtype: QType::u16_to_qtype(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?,
1388 qclass: QClass::u16_to_qclass(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?,
1389 };
1390
1391 let mut an_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.ancount as usize);
1392 let mut rr_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.arcount as usize);
1393 let mut ns_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.nscount as usize);
1394
1395 for _ in 0..header.ancount
1396 {
1397 an_list.push(DnsResponsePayload::new(&mut pkt)?);
1398 }
1399
1400 for _ in 0..header.nscount
1402 {
1403 ns_list.push(DnsResponsePayload::new(&mut pkt)?);
1404 }
1405
1406 for _ in 0..header.arcount
1408 {
1409 rr_list.push(DnsResponsePayload::new(&mut pkt)?);
1410 }
1411
1412 return Ok(
1413 DnsRequestAnswer
1414 {
1415 req_header: DnsRequestHeader{ header, payload: request },
1416 response: an_list,
1417 additional: rr_list,
1418 authoratives: ns_list,
1419 }
1420 );
1421 }
1422
1423}
1424
1425#[derive(Clone, Debug, Default)]
1426pub struct DnsRequestHeader
1427{
1428 pub header: DnsHeader,
1430 pub payload: DnsRequestPayload,
1432}
1433
1434impl Eq for DnsRequestHeader {}
1435
1436impl PartialEq for DnsRequestHeader
1437{
1438 fn eq(&self, other: &DnsRequestHeader) -> bool
1439 {
1440 return self.header.id == other.header.id && self.payload == other.payload;
1441 }
1442}
1443
1444impl Ord for DnsRequestHeader
1445{
1446 fn cmp(&self, other: &Self) -> Ordering
1447 {
1448 return self.header.id.cmp(&other.header.id);
1450 }
1451}
1452
1453impl PartialOrd for DnsRequestHeader
1454{
1455 fn partial_cmp(&self, other: &Self) -> Option<Ordering>
1456 {
1457 return Some(self.cmp(other));
1458 }
1459}
1460
1461impl Hash for DnsRequestHeader
1462{
1463 fn hash<H: Hasher>(&self, state: &mut H)
1464 {
1465 self.header.id.hash(state);
1466 self.payload.hash(state);
1467 }
1468}
1469
1470impl Borrow<u16> for DnsRequestHeader
1471{
1472 fn borrow(&self) -> &u16
1473 {
1474 return &self.header.id;
1475 }
1476}
1477
1478impl TryFrom<&QDnsReq> for DnsRequestHeader
1479{
1480 type Error = CDnsError;
1481
1482 fn try_from(value: &QDnsReq) -> Result<Self, Self::Error>
1483 {
1484 return DnsRequestHeader::construct_lookup(value);}
1486}
1487
1488impl fmt::Display for DnsRequestHeader
1489{
1490 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1491 {
1492 write!(f, "Header: {}, Status: {}", self.header, self.payload)
1493 }
1494}
1495
1496
1497impl DnsRequestHeader
1498{
1499 pub
1500 fn regenerate_id(&mut self)
1501 {
1502 self.header.id = rand::random();
1503 }
1504
1505 pub
1506 fn get_id(&self) -> u16
1507 {
1508 return self.header.id;
1509 }
1510
1511 pub
1519 fn derive(&self) -> Self
1520 {
1521 let header =
1522 DnsHeader
1523 {
1524 id: rand::random(),
1525 status: self.header.status,
1526 qdcount: self.header.qdcount,
1527 ancount: self.header.ancount,
1528 nscount: self.header.nscount,
1529 arcount: self.header.arcount,
1530 };
1531
1532 return DnsRequestHeader{ header: header, payload: self.payload.clone() };
1533 }
1534
1535 pub
1537 fn construct_lookup(qreq: &QDnsReq) -> CDnsResult<DnsRequestHeader>
1538 {
1539 let mut status: StatusBits = StatusBits::empty();
1541 status = (status & !StatusBits::OPCODE_STANDARD) | StatusBits::RECURSION_DESIRED;
1542
1543 let mut req: DnsRequestHeader = DnsRequestHeader{ ..Default::default() };
1545
1546 req.header.id = rand::random();
1547 req.header.status = status;
1548 req.header.qdcount = 1;
1549
1550 req.payload = DnsRequestPayload::new(qreq.get_req_name().try_into()?, *qreq.get_type(), QClass::IN);
1552
1553 return Ok(req);
1554 }
1555
1556 pub
1557 fn to_bytes(&self, append_len: bool) -> CDnsResult<Vec<u8>>
1558 {
1559 let mut pkt_size: usize = size_of::<DnsHeader>() + self.payload.qname.len() + 4;
1560
1561 if append_len == true
1562 {
1563 pkt_size += 2;
1564 }
1565
1566 let mut pkt = Cursor::new(vec![0_u8; pkt_size]);
1567
1568 if append_len == true
1569 {
1570 pkt.write_u16::<BigEndian>((pkt_size-2) as u16).map_err(map_read_err)?;
1571 }
1572
1573 pkt.write_u16::<BigEndian>(self.header.id).map_err(map_read_err)?;
1574 pkt.write_u16::<BigEndian>(self.header.status.bits()).map_err(map_read_err)?;
1575 pkt.write_u16::<BigEndian>(self.header.qdcount).map_err(map_read_err)?;
1576 pkt.write_u16::<BigEndian>(self.header.ancount).map_err(map_read_err)?;
1577 pkt.write_u16::<BigEndian>(self.header.nscount).map_err(map_read_err)?;
1578 pkt.write_u16::<BigEndian>(self.header.arcount).map_err(map_read_err)?;
1579
1580 pkt.write(self.payload.qname.as_slice()).map_err(map_read_err)?;
1583 pkt.write_u16::<BigEndian>(self.payload.qtype.into()).map_err(map_read_err)?;
1584 pkt.write_u16::<BigEndian>(self.payload.qclass.into()).map_err(map_read_err)?;
1585 return Ok(pkt.into_inner());
1588 }
1589}
1590
1591#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
1593pub struct DnsRequestPayload
1594{
1595 pub qname: Vec<u8>,
1597
1598 pub qtype: QType,
1600
1601 pub qclass: QClass,
1603}
1604
1605impl fmt::Display for DnsRequestPayload
1606{
1607 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1608 {
1609 write!(f, "qname:{:?} qtype:{}, qclass:{}", self.qname, self.qtype, self.qclass)
1610 }
1611}
1612
1613impl DnsRequestPayload
1614{
1615 pub
1616 fn new(qname: Vec<u8>, qtype: QType, qclass: QClass) -> Self
1617 {
1618 return DnsRequestPayload{ qname: qname, qtype: qtype.into(), qclass: qclass.into() };
1619 }
1620}
1621
1622#[derive(Clone, Debug, Default, Eq, PartialEq)]
1624pub struct DnsResponsePayload
1625{
1626 pub name: String,
1628 pub dtype: QType,
1630 pub class: QClass,
1632 pub ttl: i32,
1635 pub rdlength: u16,
1637 pub rdata: DnsRdata,
1639}
1640
1641impl DnsResponsePayload
1642{
1643 pub(crate)
1646 fn new_local(dtype: QType, data: &HostnameEntry) -> Option<Vec<Self>>
1647 {
1648 match dtype
1649 {
1650 QType::A =>
1651 {
1652 let mut out: Vec<Self> = Vec::with_capacity(1);
1653
1654 let IpAddr::V4(ipv4) = data.get_ip()
1655 else { return None; };
1656
1657 out.push(
1658 DnsResponsePayload
1659 {
1660 name: data.get_hostnames()[0].to_string(),
1661 dtype: dtype,
1662 class: QClass::IN,
1663 ttl: i32::MAX,
1664 rdlength: 0,
1665 rdata: RecordA::wrap(RecordA{ ip: ipv4.clone()}),
1666 }
1667 );
1668
1669 return Some(out);
1670 },
1671 QType::AAAA =>
1672 {
1673 let mut out: Vec<Self> = Vec::with_capacity(1);
1674
1675 let IpAddr::V6(ipv6) = data.get_ip()
1676 else { return None };
1677
1678 out.push(
1679 DnsResponsePayload
1680 {
1681 name: data.get_hostnames()[0].to_string(),
1682 dtype: dtype,
1683 class: QClass::IN,
1684 ttl: i32::MAX,
1685 rdlength: 0,
1686 rdata: RecordAAAA::wrap(RecordAAAA{ ip: ipv6.clone() }),
1687 }
1688 );
1689
1690 return Some(out);
1691 },
1692 QType::PTR =>
1693 {
1694 let mut out: Vec<Self> = Vec::with_capacity(data.get_hostnames().len());
1695
1696 for h in data.get_hostnames_iter()
1698 {
1699 out.push(
1700 DnsResponsePayload
1701 {
1702 name: [data.get_ip().to_string().as_str(), ".in-addr.arpa"].concat(),
1703 dtype: dtype,
1704 class: QClass::IN,
1705 ttl: i32::MAX,
1706 rdlength: 0,
1707 rdata: RecordPTR::wrap( RecordPTR { fqdn: h.clone() }),
1708 }
1709 );
1710 }
1711
1712 return Some(out);
1713 },
1714 _ =>
1715 return None
1716 }
1717
1718 }
1719
1720 fn new(pkt: &mut Cursor<&[u8]>) -> CDnsResult<Self>
1721 {
1722 let name = name2str(pkt, None)?;
1723 let qtype = QType::u16_to_type(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?;
1724 let qclass = QClass::u16_to_class(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?;
1725 let ttl = pkt.read_i32::<BigEndian>().map_err(map_read_err)?;
1726 let rdlength = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
1727 let rdata = DnsRdata::convert(pkt, rdlength, qtype)?;
1728
1729 return Ok(
1730 DnsResponsePayload
1731 {
1732 name: name,
1733 dtype: qtype,
1734 class: qclass,
1735 ttl: ttl,
1736 rdlength: rdlength,
1737 rdata: rdata,
1738 }
1739 );
1740 }
1741
1742 pub
1743 fn get_rdata(&self) -> &DnsRdata
1744 {
1745 return &self.rdata;
1746 }
1747
1748 pub
1749 fn borrow_rdata(self) -> DnsRdata
1750 {
1751 return self.rdata;
1752 }
1753}
1754
1755impl fmt::Display for DnsResponsePayload
1764{
1765 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1766 {
1767 write!(f, "{} {} {} {} {}",
1768 self.name, self.dtype, self.class, self.ttl, self.rdata)
1769 }
1770}
1771
1772
1773pub trait RecordReader: Sized
1775{
1776
1777 const REC_TYPE: QType;
1779
1780 const RLEN: u16;
1782
1783 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>;
1787
1788 fn wrap(self) -> DnsRdata;
1789}
1790
1791#[derive(Clone, Debug, Eq, PartialEq)]
1792pub struct RecordA
1793{
1794 pub ip: Ipv4Addr
1795}
1796
1797impl RecordReader for RecordA
1798{
1799 const REC_TYPE: QType = QType::A;
1800
1801 const RLEN: u16 = 4;
1802
1803 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
1804 {
1805 if rlen != Self::RLEN
1807 {
1808 internal_error!(CDnsErrorType::DnsResponse, "RecordA len expected: '4', got: '{}'", rlen);
1809 }
1810 else if qtype != Self::REC_TYPE
1811 {
1812 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1813 }
1814
1815 let ip = pkt.read_u32::<BigEndian>().map_err(map_read_err)?;
1816
1817 return Ok(Self{ip: Ipv4Addr::from(ip) });
1818 }
1819
1820 fn wrap(self) -> DnsRdata
1821 {
1822 return DnsRdata::A(self);
1823 }
1824}
1825
1826impl fmt::Display for RecordA
1827{
1828 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1829 {
1830 write!(f, "{} {}", Self::REC_TYPE, self.ip)
1831 }
1832}
1833
1834
1835#[derive(Clone, Debug, Eq, PartialEq)]
1836pub struct RecordAAAA
1837{
1838 pub ip: Ipv6Addr
1839}
1840
1841impl RecordReader for RecordAAAA
1842{
1843 const REC_TYPE: QType = QType::AAAA;
1844
1845 const RLEN: u16 = 16;
1846
1847 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
1848 {
1849 if rlen != Self::RLEN
1850 {
1851 internal_error!(CDnsErrorType::DnsResponse, "RecordAAAA len expected: '{}', got: '{}'", Self::RLEN, rlen);
1852 }
1853 else if qtype != Self::REC_TYPE
1854 {
1855 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1856 }
1857
1858 let ip = pkt.read_u128::<BigEndian>().map_err(map_read_err)?;
1859
1860 return Ok(Self{ ip: Ipv6Addr::from(ip) });
1861 }
1862
1863 fn wrap(self) -> DnsRdata
1864 {
1865 return DnsRdata::AAAA(self);
1866 }
1867}
1868
1869impl fmt::Display for RecordAAAA
1870{
1871 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1872 {
1873 write!(f, "{} {}", Self::REC_TYPE, self.ip)
1874 }
1875}
1876
1877#[derive(Clone, Debug, Eq, PartialEq)]
1878pub struct RecordPTR
1879{
1880 pub fqdn: String
1881}
1882
1883impl RecordReader for RecordPTR
1884{
1885 const REC_TYPE: QType = QType::PTR;
1886
1887 const RLEN: u16 = 0;
1888
1889 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
1890 {
1891 if qtype != Self::REC_TYPE
1892 {
1893 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1894 }
1895
1896 return Ok(
1897 Self{ fqdn: name2str(pkt, Some(rlen))? }
1898 );
1899 }
1900
1901 fn wrap(self) -> DnsRdata
1902 {
1903 return DnsRdata::PTR(self);
1904 }
1905}
1906
1907impl fmt::Display for RecordPTR
1908{
1909 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1910 {
1911 write!(f, "{} {}", Self::REC_TYPE, self.fqdn)
1912 }
1913}
1914
1915#[derive(Clone, Debug, Eq, PartialEq)]
1916pub struct RecordMX
1917{
1918 pub preference: u16,
1919 pub exchange: String
1920}
1921
1922impl RecordReader for RecordMX
1923{
1924 const REC_TYPE: QType = QType::MX;
1925
1926 const RLEN: u16 = 2;
1927
1928 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
1929 {
1930 if rlen <= Self::RLEN
1931 {
1932 internal_error!(CDnsErrorType::DnsResponse, "RecordMX len expected: '{}', got: '{}'", Self::RLEN, rlen);
1933 }
1934 else if qtype != Self::REC_TYPE
1935 {
1936 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1937 }
1938
1939 return Ok(
1940 Self
1941 {
1942 preference: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1943 exchange: name2str(pkt, Some(rlen - 2))?,
1944 }
1945 );
1946 }
1947
1948 fn wrap(self) -> DnsRdata
1949 {
1950 return DnsRdata::MX(self);
1951 }
1952}
1953
1954impl fmt::Display for RecordMX
1955{
1956 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1957 {
1958 write!(f, "{} {} {}", Self::REC_TYPE, self.preference, self.exchange)
1959 }
1960}
1961
1962#[derive(Clone, Debug, Eq, PartialEq)]
1963pub struct RecordCNAME
1964{
1965 pub fqdn: String
1966}
1967
1968impl RecordReader for RecordCNAME
1969{
1970 const REC_TYPE: QType = QType::CNAME;
1971
1972 const RLEN: u16 = 0;
1973
1974 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
1975 {
1976 if qtype != Self::REC_TYPE
1977 {
1978 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1979 }
1980
1981 return Ok(
1982 Self{ fqdn: name2str(pkt, Some(rlen))? }
1983 );
1984 }
1985
1986 fn wrap(self) -> DnsRdata
1987 {
1988 return DnsRdata::CNAME(self);
1989 }
1990}
1991
1992impl fmt::Display for RecordCNAME
1993{
1994 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1995 {
1996 write!(f, "{} {}", Self::REC_TYPE, self.fqdn)
1997 }
1998}
1999
2000#[derive(Clone, Debug, Eq, PartialEq)]
2001pub struct RecordNS
2002{
2003 pub fqdn: String
2004}
2005
2006impl RecordReader for RecordNS
2007{
2008 const REC_TYPE: QType = QType::NS;
2009
2010 const RLEN: u16 = 0;
2011
2012 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2013 {
2014 if qtype != Self::REC_TYPE
2015 {
2016 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2017 }
2018
2019 return Ok(
2020 Self{ fqdn: name2str(pkt, Some(rlen))? }
2021 );
2022 }
2023
2024 fn wrap(self) -> DnsRdata
2025 {
2026 return DnsRdata::NS(self);
2027 }
2028}
2029
2030impl fmt::Display for RecordNS
2031{
2032 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2033 {
2034 write!(f, "{} {}", Self::REC_TYPE, self.fqdn)
2035 }
2036}
2037
2038#[derive(Clone, Debug, Eq, PartialEq)]
2039pub struct RecordSOA
2040{
2041 pub pnm: String,
2043 pub ram: String,
2045 pub serial: u32,
2047 pub interv_refr: u32,
2049 pub interv_retry: u32,
2051 pub expire_limit: u32,
2053 pub min_ttl: u32,
2055}
2056
2057impl RecordReader for RecordSOA
2058{
2059 const REC_TYPE: QType = QType::SOA;
2060
2061 const RLEN: u16 = 0;
2062
2063 fn read(pkt: &mut Cursor<&[u8]>, _rlen: u16, qtype: QType) -> CDnsResult<Self>
2064 {
2065 if qtype != Self::REC_TYPE
2066 {
2067 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2068 }
2069
2070 return Ok(
2071 Self
2072 {
2073 pnm: name2str(pkt, None)?,
2075 ram: name2str(pkt, None)?,
2077 serial: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2079 interv_refr: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2081 interv_retry: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2083 expire_limit: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2085 min_ttl: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2087 }
2088 );
2089 }
2090
2091 fn wrap(self) -> DnsRdata
2092 {
2093 return DnsRdata::SOA(self);
2094 }
2095}
2096
2097impl fmt::Display for RecordSOA
2098{
2099 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2100 {
2101 write!(f, "{} {} {} {} {} {} {} {}", Self::REC_TYPE, self.pnm, self.ram, self.serial,
2102 self.interv_refr, self.interv_retry, self.expire_limit, self.min_ttl)
2103 }
2104}
2105
2106#[derive(Clone, Debug, Eq, PartialEq)]
2107pub struct RecordSRV
2108{
2109 pub priority: u16,
2111
2112 pub weight: u16,
2115
2116 pub port: u16,
2118
2119 pub target: String,
2121}
2122
2123impl RecordReader for RecordSRV
2124{
2125 const REC_TYPE: QType = QType::SRV;
2126
2127 const RLEN: u16 = 0;
2128
2129 fn read(pkt: &mut Cursor<&[u8]>, _rlen: u16, qtype: QType) -> CDnsResult<Self>
2130 {
2131 if qtype != Self::REC_TYPE
2132 {
2133 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2134 }
2135
2136 return Ok(
2137 Self
2138 {
2139 priority: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2140 weight: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2141 port: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2142 target: name2str(pkt, None)?,
2143 }
2144 );
2145 }
2146
2147 fn wrap(self) -> DnsRdata
2148 {
2149 return DnsRdata::SRV(self);
2150 }
2151}
2152
2153impl fmt::Display for RecordSRV
2154{
2155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2156 {
2157 write!(f, "{} {} {} {} \"{}\"", Self::REC_TYPE, self.priority, self.weight, self.port, self.target)
2158 }
2159}
2160
2161#[derive(Clone, Debug, Eq, PartialEq)]
2162pub struct RecordTXT
2163{
2164 pub txt_strings: String,
2166}
2167
2168impl RecordReader for RecordTXT
2169{
2170 const REC_TYPE: QType = QType::TXT;
2171
2172 const RLEN: u16 = 2;
2173
2174 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2175 {
2176 if rlen <= Self::RLEN
2177 {
2178 internal_error!(CDnsErrorType::DnsResponse, "RecordTXT len expected: '{}' >, got: '{}'", Self::RLEN, rlen);
2179 }
2180 else if qtype != Self::REC_TYPE
2181 {
2182 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2183 }
2184
2185 let mut read_length = 0;
2186
2187
2188 let dmod = ((rlen % 255) > 0) as u16;
2189 let cap = rlen / 255 + dmod;
2190
2191 let mut txt_datas = Vec::<String>::with_capacity(cap as usize);
2192
2193 while read_length < rlen
2194 {
2195 let mut txt_data = Vec::new();
2196
2197 loop
2198 {
2199 let blk_size = pkt.read_u8().map_err(map_read_err)?;
2200
2201 read_length += blk_size as u16 + 1;
2202
2203 let mut new_txt = Vec::with_capacity(blk_size as usize);unsafe { new_txt.set_len(blk_size as usize); }
2205
2206 pkt.read_exact(&mut new_txt).map_err(map_read_err)?;
2207
2208 txt_data.push(new_txt);
2209
2210 if blk_size < 255
2211 {
2212 break;
2213 }
2214 }
2215
2216 if txt_data.is_empty() == true
2217 {
2218 internal_error!(
2219 CDnsErrorType::DnsResponse,
2220 "unexpected EOF in TXT rec cur position: '{}', data_length: '{}', read: '{}'",
2221 pkt.position(), rlen, read_length
2222 );
2223 }
2224
2225 let data = txt_data.concat();
2226
2227 txt_datas.push(
2228 String::from_utf8(data)
2229 .map_err(|e|
2230 internal_error_map!(CDnsErrorType::InternalError, "UTF-8 decode error, {}", e)
2231 )?
2232 );
2233 }
2234
2235 return Ok(
2236 Self
2237 {
2238 txt_strings: txt_datas.concat()
2239 }
2240 );
2241 }
2242
2243 fn wrap(self) -> DnsRdata
2244 {
2245 return DnsRdata::TXT(self);
2246 }
2247}
2248
2249impl fmt::Display for RecordTXT
2250{
2251 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2252 {
2253 write!(f, "{} {}", Self::REC_TYPE, self.txt_strings)
2254 }
2255}
2256
2257#[derive(Clone, Debug, Eq, PartialEq)]
2258pub struct RecordURI
2259{
2260 pub priority: u16,
2262
2263 pub weight: u16,
2266
2267 pub target: String,
2270}
2271
2272impl RecordReader for RecordURI
2273{
2274 const REC_TYPE: QType = QType::URI;
2275
2276 const RLEN: u16 = 4;
2277
2278 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2279 {
2280 if rlen <= Self::RLEN
2281 {
2282 internal_error!(CDnsErrorType::DnsResponse, "RecordURI len expected: '{}' >, got: '{}'", Self::RLEN, rlen);
2283 }
2284 else if qtype != Self::REC_TYPE
2285 {
2286 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2287 }
2288
2289 return Ok(
2290 Self
2291 {
2292 priority: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2293 weight: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2294 target: pkt2string_exact(pkt, rlen - 4)?,
2295 }
2296 );
2297 }
2298
2299 fn wrap(self) -> DnsRdata
2300 {
2301 return DnsRdata::URI(self);
2302 }
2303}
2304
2305impl fmt::Display for RecordURI
2306{
2307 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2308 {
2309 write!(f, "{} {} {} \"{}\"", Self::REC_TYPE, self.priority, self.weight, self.target)
2310 }
2311}
2312
2313#[derive(Clone, Debug, Eq, PartialEq)]
2316pub struct RecordRRSIG
2317{
2318 type_cov: u16,
2319 alg: u8,
2320 labels: u8,
2321 orig_ttl: u32,
2322 sig_exp: u32,
2323 sig_inc: u32,
2324 keytag: u16,
2325 sig_name: String,
2326 key: Vec<u8>,
2327}
2328
2329impl RecordReader for RecordRRSIG
2330{
2331 const REC_TYPE: QType = QType::RRSIG;
2332
2333 const RLEN: u16 = 19;
2334
2335 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, _qtype: QType) -> CDnsResult<Self>
2336 {
2337 let data = vec![0_u8; rlen as usize];
2338
2339 let pos = pkt.position();
2340
2341 let mut res =
2342 Self
2343 {
2344 type_cov: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2345 alg: pkt.read_u8().map_err(map_read_err)?,
2346 labels: pkt.read_u8().map_err(map_read_err)?,
2347 orig_ttl: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2348 sig_exp: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2349 sig_inc: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2350 keytag: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2351 sig_name: name2str(pkt,None)?,
2352 key: Vec::new(),
2353 };
2354
2355 let left_rdlen = rlen - (pkt.position() - pos) as u16;
2356 res.key = pkt2vec(pkt, Some(left_rdlen))?;
2357
2358 return Ok(res);
2359 }
2360
2361 fn wrap(self) -> DnsRdata
2362 {
2363 return DnsRdata::RRSIG(self);
2364 }
2365}
2366
2367impl fmt::Display for RecordRRSIG
2368{
2369 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2370 {
2371 write!(f, "{} {} {} {} {} {} {} {} {} {}",
2372 Self::REC_TYPE, self.type_cov, self.alg, self.labels, self.orig_ttl,
2373 self.sig_exp, self.sig_inc, self.keytag, self.sig_name,
2374 self.key.iter().map(|k| format!("{:02X}", k)).collect::<Vec<String>>().concat()
2375 )
2376 }
2377}
2378
2379#[derive(Clone, Debug, Eq, PartialEq)]
2380pub struct RecordOther
2381{
2382 pub qtype: QType,
2384
2385 pub data: Vec<u8>
2387}
2388
2389impl RecordReader for RecordOther
2390{
2391 const REC_TYPE: QType = QType::ALL;
2392
2393 const RLEN: u16 = 0;
2394
2395 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2396 {
2397 let mut data = vec![0_u8; rlen as usize];
2398
2399 pkt.read_exact(&mut data).map_err(map_read_err)?;
2400
2401 return Ok(
2402 Self
2403 {
2404 qtype: qtype,
2405 data: data,
2406 }
2407 );
2408 }
2409
2410 fn wrap(self) -> DnsRdata
2411 {
2412 return DnsRdata::OTHER(self);
2413 }
2414}
2415
2416impl fmt::Display for RecordOther
2417{
2418 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2419 {
2420 write!(f, "{} RAW:", self.qtype)?;
2421
2422 for d in self.data.iter()
2423 {
2424 write!(f, "{:X}", d)?;
2425 }
2426
2427 return Ok(());
2428 }
2429}
2430
2431pub(crate)
2432fn sanitize_str_unicode(st: &str) -> String
2433{
2434 let mut out = String::with_capacity(st.len());
2435
2436 for c in st.chars()
2437 {
2438 if c.is_alphanumeric() == true ||
2439 c.is_ascii_punctuation() == true ||
2440 c == ' '
2441 {
2442 out.push(c);
2443 }
2444 else
2445 {
2446 let mut buf = [0_u8; 4];
2447 c.encode_utf8(&mut buf);
2448
2449 let formatted: String =
2450 buf[0..c.len_utf8()].into_iter()
2451 .map(|c| format!("\\x{:02x}", c))
2452 .collect();
2453
2454 out.push_str(&formatted);
2455 }
2456 }
2457
2458 return out;
2459}
2460
2461#[derive(Clone, Debug, Eq, PartialEq)]
2462pub enum DnsRdata
2463{
2464 None,
2465 A(RecordA),
2466 NS(RecordNS),
2467 CNAME(RecordCNAME),
2468 SOA(RecordSOA),
2469 PTR(RecordPTR),
2470 MX(RecordMX),
2471 TXT(RecordTXT),
2472 AAAA(RecordAAAA),
2473 SRV(RecordSRV),
2474 URI(RecordURI),
2475 RRSIG(RecordRRSIG),
2476 OTHER(RecordOther),
2477}
2478
2479impl fmt::Display for DnsRdata
2480{
2481 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2482 {
2483 match self
2484 {
2485 Self::None =>
2486 write!(f, "No record"),
2487 Self::A(ip) =>
2488 write!(f, "{}", ip),
2489 Self::NS(ns) =>
2490 write!(f, "{}", ns),
2491 Self::AAAA(aaaa) =>
2492 write!(f, "{}", aaaa),
2493 Self::MX(mx) =>
2494 write!(f, "{}", mx),
2495 Self::CNAME(cname) =>
2496 write!(f, "{}", cname),
2497 Self::PTR(ptr) =>
2498 write!(f, "{}", ptr),
2499 Self::SOA(soa) =>
2500 write!(f, "{}", soa),
2501 Self::TXT(txt) =>
2502 write!(f, "{}", txt),
2503 Self::SRV(srv) =>
2504 write!(f, "{}", srv),
2505 Self::URI(uri) =>
2506 write!(f, "{}", uri),
2507 Self::RRSIG(rrsig) =>
2508 write!(f, "{}", rrsig),
2509 Self::OTHER(other) =>
2510 write!(f, "{}", other),
2511 }
2512 }
2513}
2514
2515impl Default for DnsRdata
2516{
2517 fn default() -> Self
2518 {
2519 return Self::None;
2520 }
2521}
2522
2523impl DnsRdata
2524{
2525 #[inline]
2526 pub
2527 fn is_some(&self) -> bool
2528 {
2529 return *self != Self::None;
2530 }
2531}
2532
2533
2534impl DnsRdata
2535{
2536 pub
2550 fn convert(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2551 {
2552 match qtype
2553 {
2554 RecordA::REC_TYPE =>
2555 return Ok(RecordA::wrap(RecordA::read(pkt, rlen, qtype)?)),
2556 RecordAAAA::REC_TYPE =>
2557 return Ok(RecordAAAA::wrap(RecordAAAA::read(pkt, rlen, qtype)?)),
2558 RecordPTR::REC_TYPE =>
2559 return Ok(RecordPTR::wrap(RecordPTR::read(pkt, rlen, qtype)?)),
2560 RecordMX::REC_TYPE =>
2561 return Ok(RecordMX::wrap(RecordMX::read(pkt, rlen, qtype)?)),
2562 RecordCNAME::REC_TYPE =>
2563 return Ok(RecordCNAME::wrap(RecordCNAME::read(pkt, rlen, qtype)?)),
2564 RecordSOA::REC_TYPE =>
2565 return Ok(RecordSOA::wrap(RecordSOA::read(pkt, rlen, qtype)?)),
2566 RecordSRV::REC_TYPE =>
2567 return Ok(RecordSRV::wrap(RecordSRV::read(pkt, rlen, qtype)?)),
2568 RecordTXT::REC_TYPE =>
2569 return Ok(RecordTXT::wrap(RecordTXT::read(pkt, rlen, qtype)?)),
2570 RecordURI::REC_TYPE =>
2571 return Ok(RecordURI::wrap(RecordURI::read(pkt, rlen, qtype)?)),
2572 RecordNS::REC_TYPE =>
2573 return Ok(RecordNS::wrap(RecordNS::read(pkt, rlen, qtype)?)),
2574 RecordRRSIG::REC_TYPE =>
2575 return Ok(RecordRRSIG::wrap(RecordRRSIG::read(pkt, rlen, qtype)?)),
2576 _ =>
2577 return Ok(RecordOther::wrap(RecordOther::read(pkt, rlen, qtype)?)),
2578 }
2579 }
2580
2581 pub
2582 fn get_ip(&self) -> Option<IpAddr>
2583 {
2584 match self
2585 {
2586 Self::A(a) => return Some(IpAddr::V4(a.ip)),
2587 Self::AAAA(a) => return Some(IpAddr::V6(a.ip)),
2588 _ => return None
2589 }
2590 }
2591}
2592
2593#[cfg(test)]
2594mod tests
2595{
2596 use std::io::Cursor;
2597
2598 use crate::common::*;
2599
2600
2601
2602 #[test]
2603 fn test_pkt2name()
2604 {
2605 use std::time::Instant;
2606
2607 fn prepare(d: &[u8]) -> Cursor<&[u8]>
2608 {
2609 return Cursor::new(d);
2612 }
2613
2614 let t1 = b"\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00";
2615
2616 let mut cur1 = prepare(t1);
2617
2618 let now = Instant::now();
2619 let r1 = pkt2name(&mut cur1);
2620 let elapsed = now.elapsed();
2621 println!("Elapsed: {:.2?}", elapsed);
2622
2623 assert_eq!(r1.is_ok(), true);
2624 assert_eq!(r1.as_ref().unwrap(), t1);
2625
2626 let t2 =
2627 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2628 \x30\x30\x03\x6e\x65\x74\x00";
2629
2630 let mut cur2 = prepare(t2);
2631 let now = Instant::now();
2632 let r2 = pkt2name(&mut cur2);
2633 let elapsed = now.elapsed();
2634 println!("Elapsed: {:.2?}", elapsed);
2635
2636 assert_eq!(r2.is_ok(), true);
2637 assert_eq!(r2.as_ref().unwrap(), t2);
2638
2639 let t3 =
2640 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2641 \x30\x30\x03\x6e\x65\x74";
2642
2643 let r3 = pkt2name(&mut prepare(t3));
2644
2645 assert_eq!(r3.is_ok(), false);
2646
2647 let t4 =
2648 b"\x10\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2649 \x30\x30\x03\x6e\x65\x74";
2650
2651 let r4 = pkt2name(&mut prepare(t4));
2652
2653 assert_eq!(r4.is_ok(), false);
2654 }
2655
2656 #[test]
2657 fn test_qname2str()
2658 {
2659 use std::time::Instant;
2660
2661 fn prepare(d: &[u8]) -> Cursor<&[u8]>
2662 {
2663 return Cursor::new(d);
2666 }
2667
2668 let t1 = b"\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00";
2669
2670 let mut cur1 = prepare(t1);
2671 let now = Instant::now();
2672 let r1 = name2str(&mut cur1, None);
2673 let elapsed = now.elapsed();
2674 println!("Elapsed: {:.2?}", elapsed);
2675
2676 assert_eq!(r1.is_ok(), true);
2677 assert_eq!(r1.as_ref().unwrap(), "dns.google");
2678
2679 let t2 =
2680 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2681 \x30\x30\x03\x6e\x65\x74\x00";
2682
2683 let mut cur2 = prepare(t2);
2684
2685 let now = Instant::now();
2686 let r2 = name2str(&mut cur2, None);
2687 let elapsed = now.elapsed();
2688 println!("Elapsed: {:.2?}", elapsed);
2689
2690 assert_eq!(r2.is_ok(), true);
2691 assert_eq!(r2.as_ref().unwrap(), "mad07s09-in-x0e.1e100.net");
2692
2693 let t3 =
2694 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2695 \x30\x30\x03\x6e\x65\x74";
2696
2697 let r3 = name2str(&mut prepare(t3), None);
2698
2699 assert_eq!(r3.is_ok(), false);
2700
2701 let t4 =
2702 b"\x10\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2703 \x30\x30\x03\x6e\x65\x74";
2704
2705 let r4 = name2str(&mut prepare(t4), None);
2706
2707 assert_eq!(r4.is_ok(), false);
2708 }
2709
2710 #[test]
2711 fn test_response_parser()
2712 {
2713 use std::time::Instant;
2714
2715 let pkt =
2716 b"\x15\xc8\x81\x80\x00\x01\x00\x01\x00\x00\x00\x02\x01\x38\x01\x38\
2717 \x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\
2718 \x61\x00\x00\x0c\x00\x01\xc0\x0c\x00\x0c\x00\x01\x00\x01\x35\xf0\
2719 \x00\x0c\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00\xc0\x32\
2720 \x00\x01\x00\x01\x00\x00\x00\xe8\x00\x04\x08\x08\x08\x08\xc0\x32\
2721 \x00\x01\x00\x01\x00\x00\x00\xe8\x00\x04\x08\x08\x04\x04";
2722
2723 let dummy =
2724 DnsRequestHeader
2725 {
2726 header: DnsHeader {id: 0x15c8, ..Default::default()},
2727 payload: DnsRequestPayload
2728 {
2729 qname: b"\x01\x38\x01\x38\x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\x61\x00".to_vec(),
2730 qtype: QType::PTR,
2731 qclass: QClass::IN,
2732 }
2733 };
2734
2735 let now = Instant::now();
2736 let ans = DnsRequestAnswer::parse(pkt.as_slice());
2737 let elapsed = now.elapsed();
2738 println!("Elapsed: {:.2?}", elapsed);
2739
2740 assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
2741
2742 let ans = ans.unwrap();
2743
2744 let verif = ans.verify(&dummy);
2745 assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
2746
2747 assert_eq!(ans.req_header.header.id, 0x15c8);
2748 assert_eq!(ans.req_header.header.ancount, 1);
2749 assert_eq!(ans.req_header.header.arcount, 2);
2750 assert_eq!(ans.req_header.header.nscount, 0);
2751 assert_eq!(ans.req_header.header.qdcount, 1);
2752
2753 assert_eq!(ans.response[0].rdata, RecordPTR::wrap(RecordPTR { fqdn: "dns.google".to_string() }) );
2754 assert_eq!(ans.response[0].name, "8.8.8.8.in-addr.arpa".to_string());
2755 assert_eq!(ans.response[0].dtype, QType::PTR);
2756 assert_eq!(ans.response[0].class, QClass::IN);
2757 assert_eq!(ans.response[0].ttl, 79344);
2758 assert_eq!(ans.response[0].rdlength, 12);
2759
2760 assert_eq!(ans.additional[0].rdata, RecordA::wrap(RecordA { ip: "8.8.8.8".parse().unwrap() }) );
2761 assert_eq!(ans.additional[0].name, "dns.google".to_string());
2762 assert_eq!(ans.additional[0].ttl, 232);
2763 assert_eq!(ans.additional[0].dtype, QType::A);
2764 assert_eq!(ans.additional[0].class, QClass::IN);
2765
2766 assert_eq!(ans.additional[1].rdata, RecordA::wrap(RecordA { ip: "8.8.4.4".parse().unwrap() }) );
2767 assert_eq!(ans.additional[1].name, "dns.google".to_string());
2768 assert_eq!(ans.additional[1].ttl, 232);
2769 assert_eq!(ans.additional[1].dtype, QType::A);
2770 assert_eq!(ans.additional[1].class, QClass::IN);
2771 }
2772
2773 #[test]
2774 fn test_response2()
2775 {
2776 use std::time::Instant;
2777
2778 let pkt =
2779 b"\x4b\x38\x81\x80\x00\x01\x00\x05\x00\x00\x00\x00\x05\x67\x6d\x61\
2780 \x69\x6c\x03\x63\x6f\x6d\x00\x00\x0f\x00\x01\xc0\x0c\x00\x0f\x00\
2781 \x01\x00\x00\x0b\x55\x00\x1b\x00\x05\x0d\x67\x6d\x61\x69\x6c\x2d\
2782 \x73\x6d\x74\x70\x2d\x69\x6e\x01\x6c\x06\x67\x6f\x6f\x67\x6c\x65\
2783 \xc0\x12\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\x55\x00\x09\x00\x0a\
2784 \x04\x61\x6c\x74\x31\xc0\x29\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\
2785 \x55\x00\x09\x00\x1e\x04\x61\x6c\x74\x33\xc0\x29\xc0\x0c\x00\x0f\
2786 \x00\x01\x00\x00\x0b\x55\x00\x09\x00\x14\x04\x61\x6c\x74\x32\xc0\
2787 \x29\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\x55\x00\x09\x00\x28\x04\
2788 \x61\x6c\x74\x34\xc0\x29";
2789
2790 let dummy =
2791 DnsRequestHeader
2792 {
2793 header: DnsHeader {id: 0x4b38, ..Default::default()},
2794 payload: DnsRequestPayload
2795 {
2796 qname: b"\x05\x67\x6d\x61\x69\x6c\x03\x63\x6f\x6d\x00".to_vec(),
2797 qtype: QType::MX,
2798 qclass: QClass::IN,
2799 }
2800 };
2801
2802 let now = Instant::now();
2803 let ans = DnsRequestAnswer::parse(pkt.as_slice());
2804 let elapsed = now.elapsed();
2805 println!("Elapsed: {:.2?}", elapsed);
2806
2807 assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
2808 let ans = ans.unwrap();
2809
2810 let verif = ans.verify(&dummy);
2811 assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
2812
2813 assert_eq!(ans.req_header.header.id, 0x4b38);
2814 assert_eq!(ans.req_header.header.ancount, 5);
2815 assert_eq!(ans.req_header.header.arcount, 0);
2816 assert_eq!(ans.req_header.header.nscount, 0);
2817 assert_eq!(ans.req_header.header.qdcount, 1);
2818
2819 assert_eq!(ans.response[0].rdata, RecordMX::wrap(RecordMX { preference: 5, exchange: "gmail-smtp-in.l.google.com".to_string() }) );
2820 assert_eq!(ans.response[0].name, "gmail.com".to_string());
2821 assert_eq!(ans.response[0].dtype, QType::MX);
2822 assert_eq!(ans.response[0].class, QClass::IN);
2823 assert_eq!(ans.response[0].ttl, 2901);
2824 assert_eq!(ans.response[0].rdlength, 27);
2825
2826 assert_eq!(ans.response[1].rdata, RecordMX::wrap(RecordMX { preference: 10, exchange: "alt1.gmail-smtp-in.l.google.com".to_string() }) );
2827 assert_eq!(ans.response[1].name, "gmail.com".to_string());
2828 assert_eq!(ans.response[1].dtype, QType::MX);
2829 assert_eq!(ans.response[1].class, QClass::IN);
2830 assert_eq!(ans.response[1].ttl, 2901);
2831 assert_eq!(ans.response[1].rdlength, 9);
2832
2833 assert_eq!(ans.response[2].rdata, RecordMX::wrap(RecordMX { preference: 30, exchange: "alt3.gmail-smtp-in.l.google.com".to_string() }) );
2834 assert_eq!(ans.response[2].name, "gmail.com".to_string());
2835 assert_eq!(ans.response[2].dtype, QType::MX);
2836 assert_eq!(ans.response[2].class, QClass::IN);
2837 assert_eq!(ans.response[2].ttl, 2901);
2838 assert_eq!(ans.response[2].rdlength, 9);
2839
2840 assert_eq!(ans.response[3].rdata, RecordMX::wrap(RecordMX { preference: 20, exchange: "alt2.gmail-smtp-in.l.google.com".to_string() }) );
2841 assert_eq!(ans.response[3].name, "gmail.com".to_string());
2842 assert_eq!(ans.response[3].dtype, QType::MX);
2843 assert_eq!(ans.response[3].class, QClass::IN);
2844 assert_eq!(ans.response[3].ttl, 2901);
2845 assert_eq!(ans.response[3].rdlength, 9);
2846
2847 assert_eq!(ans.response[4].rdata, RecordMX::wrap(RecordMX { preference: 40, exchange: "alt4.gmail-smtp-in.l.google.com".to_string() }) );
2848 assert_eq!(ans.response[4].name, "gmail.com".to_string());
2849 assert_eq!(ans.response[4].dtype, QType::MX);
2850 assert_eq!(ans.response[4].class, QClass::IN);
2851 assert_eq!(ans.response[4].ttl, 2901);
2852 assert_eq!(ans.response[4].rdlength, 9);
2853 }
2854
2855
2856 #[test]
2857 fn test_response3()
2858 {
2859 use std::time::Instant;
2860
2861 let pkt =
2862 b"\xd0\x79\x81\x80\x00\x01\x00\x17\x00\x00\x00\x00\x06\x72\
2863 \x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x00\xff\x00\x01\xc0\x0c\x00\
2864 \x06\x00\x01\x00\x00\x0e\x10\x00\x30\x04\x6e\x73\x32\x31\x07\x63\
2865 \x6c\x6f\x75\x64\x6e\x73\x03\x6e\x65\x74\x00\x07\x73\x75\x70\x70\
2866 \x6f\x72\x74\xc0\x2c\x78\x77\xe2\xf1\x00\x00\x1c\x20\x00\x00\x07\
2867 \x08\x00\x12\x75\x00\x00\x00\x0e\x10\xc0\x0c\x00\x2e\x00\x01\x00\
2868 \x00\x0e\x10\x00\x5d\x00\x06\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\
2869 \x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\
2870 \x6b\x00\x2f\x79\xed\x73\xd0\x75\xc8\xa9\xa2\x2a\x08\x3c\x78\xb9\
2871 \xfb\x43\xc5\x8e\x62\x4c\xbc\x36\xeb\x22\x96\x45\x59\x36\x1f\x69\
2872 \x3a\x7a\x5e\x67\xd0\x54\x1e\xf0\xf2\x11\x1a\x72\x00\x56\x89\x26\
2873 \x79\xf4\x06\x1a\x0c\x59\x41\x32\x60\x68\x75\x05\x3d\x90\xed\x1e\
2874 \x0f\xfc\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x02\xc0\x27\
2875 \xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x08\x05\x70\x6e\x73\
2876 \x32\x33\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x07\
2877 \x04\x6e\x73\x32\x33\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\
2878 \x10\x00\x08\x05\x70\x6e\x73\x32\x32\xc0\x2c\xc0\x0c\x00\x02\x00\
2879 \x01\x00\x00\x0e\x10\x00\x08\x05\x70\x6e\x73\x32\x34\xc0\x2c\xc0\
2880 \x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x07\x04\x6e\x73\x32\x34\
2881 \xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x08\x05\x70\
2882 \x6e\x73\x32\x31\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\
2883 \x00\x07\x04\x6e\x73\x32\x32\xc0\x2c\xc0\x0c\x00\x2e\x00\x01\x00\
2884 \x00\x0e\x10\x00\x5d\x00\x02\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\
2885 \x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\
2886 \x6b\x00\xd1\xc5\x6c\xf1\xfb\xd0\x75\xf1\x38\x20\x28\x80\x4c\xe0\
2887 \x59\xa5\xa8\xab\x84\x79\xd8\x37\x48\xa7\xa5\x3f\x08\x9b\x4c\xca\
2888 \x40\x2b\xcb\x2c\xda\xcc\xc2\x18\xad\x07\x9e\xf8\x4e\x17\x8d\xb1\
2889 \x2b\x2d\xa2\xa6\x17\xdb\x55\x30\xbc\xa2\xb9\xa0\x01\x71\x01\xe5\
2890 \xdc\x4f\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xd9\x14\
2891 \x70\xd0\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\x01\
2892 \x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\
2893 \x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xf8\x57\x68\xf0\xad\
2894 \x9e\xfb\x3a\x0f\x66\xbd\xcc\x48\xe7\x29\x0a\xf4\xd8\xf6\xbe\xbc\
2895 \x04\x76\x02\x27\x64\xf2\xc9\x42\x6d\x75\x54\x83\x0a\x11\xda\x0a\
2896 \x02\x6b\x8c\xf1\x65\xc4\x21\x44\xea\x89\x09\x01\xc8\xa1\xe2\x11\
2897 \x8f\xed\x67\x39\x69\x33\xdd\x97\x22\x1a\xd3\xc0\x0c\x00\x0f\x00\
2898 \x01\x00\x00\x0e\x10\x00\x11\x00\x0a\x04\x6d\x61\x69\x6c\x04\x6e\
2899 \x69\x78\x64\x03\x6f\x72\x67\x00\xc0\x0c\x00\x2e\x00\x01\x00\x00\
2900 \x0e\x10\x00\x5d\x00\x0f\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\
2901 \x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\
2902 \x00\xd4\xdd\x07\xd9\xb6\xb2\xba\x57\xa9\x1d\x3b\xaa\x6c\x55\xc4\
2903 \x3d\x73\x79\xea\x74\xfe\xd7\x23\x0c\xb4\xab\x8f\x4b\x1f\xd9\x8a\
2904 \xb2\x4a\x5c\xad\x3e\x8e\x4a\x85\xbb\xbd\x75\xf2\x47\x2c\xa8\x89\
2905 \x21\x75\x89\xb1\x12\xc4\xd2\xf7\x40\x06\x52\x57\x83\x8a\xaa\x7b\
2906 \x75\xc0\x0c\x00\x10\x00\x01\x00\x00\x0e\x10\x00\x34\x33\x76\x3d\
2907 \x73\x70\x66\x31\x20\x2b\x6d\x78\x20\x2b\x61\x3a\x6d\x61\x69\x6c\
2908 \x2e\x6e\x69\x78\x64\x2e\x6f\x72\x67\x20\x69\x70\x34\x3a\x32\x31\
2909 \x37\x2e\x32\x30\x2e\x31\x31\x32\x2e\x32\x30\x38\x20\x2d\x61\x6c\
2910 \x6c\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\x10\x0d\
2911 \x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\
2912 \x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xd1\x6c\xd1\xf4\x3b\xe0\
2913 \x44\xba\xfe\xe9\xdb\x82\xbd\x89\x5f\xa1\x07\x72\xdd\x47\xad\x4e\
2914 \x91\xd5\xc3\xfe\x3e\x39\x74\xdb\x50\x50\x19\x6c\x3f\x6c\xb7\xa8\
2915 \x01\x03\x6a\xf5\xa7\xf3\x9b\xf7\x76\xd4\xff\xa3\xd5\x43\xfc\xec\
2916 \xa9\x89\x24\xf8\xd2\xb6\x76\xd4\x20\xbc\xc0\x0c\x00\x30\x00\x01\
2917 \x00\x00\x0e\x10\x00\x44\x01\x01\x03\x0d\xf3\x87\xe2\x7c\x2b\x82\
2918 \x40\x72\x7c\xfd\xc9\x2b\xe8\x22\xd6\xa9\x40\xc0\xab\x03\x25\x7d\
2919 \x92\xae\xf3\x17\x71\x82\x67\xc6\xcd\xb6\x4b\x11\x62\xc6\xfa\x06\
2920 \xec\x4c\x9f\xd9\xe6\xaf\x5c\x3d\xe4\x32\xde\x11\x1b\x09\x13\xe3\
2921 \xd0\xba\x66\xd1\xbc\x32\xdb\x13\xd7\x1d\xc0\x0c\x00\x30\x00\x01\
2922 \x00\x00\x0e\x10\x00\x44\x01\x00\x03\x0d\xd4\x43\xde\x96\xe5\xea\
2923 \x0a\xf9\x5d\x4f\x72\x88\x9c\xd9\x9c\xf7\xa6\x3f\x12\xd7\xf3\xea\
2924 \x8a\x6b\x44\x4c\x79\x23\x81\x94\x43\xa3\xbd\x9e\xb8\xde\xfe\x8c\
2925 \xe6\x21\xe3\x8a\x71\xba\x05\xd2\x0f\x98\x5b\xfc\x7e\x72\x8c\xe9\
2926 \x9a\xc0\x49\x00\xca\xd5\x62\x93\x7f\x03\xc0\x0c\x00\x2e\x00\x01\
2927 \x00\x00\x0e\x10\x00\x5d\x00\x30\x0d\x02\x00\x00\x0e\x10\x61\xf2\
2928 \xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\
2929 \x73\x6b\x00\xc0\x93\x23\x1d\xcb\x1e\x79\xfe\x7c\x40\x3e\xd4\x33\
2930 \x5f\xed\x69\x8e\x7d\x75\xff\x73\x6b\x24\x71\x8f\x50\xf8\xe0\x49\
2931 \xce\x5f\x62\x0c\x8c\xb3\x06\x8f\x26\xea\x20\xa0\xe3\x71\xe0\xa1\
2932 \x8b\xe0\x4a\x2f\x1d\x4b\x79\x2c\x52\x6b\xa4\x43\xb5\x70\x27\x01\
2933 \xb0\x63\x47\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\
2934 \x30\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x97\
2935 \x18\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x41\x87\x75\x1d\
2936 \x30\x44\xd1\x94\x40\xd4\xe6\x40\x98\x62\x94\x53\xad\x53\xe2\xed\
2937 \xc0\xc0\xb7\xa3\x20\x15\xae\x59\xbb\x97\x45\xfb\x0e\xbf\x70\xf3\
2938 \xb1\x24\x79\xe8\x85\x6c\x2a\x66\x10\xb6\x75\x99\x7b\x77\x78\x65\
2939 \xa6\x67\x8d\x59\xa6\x14\xf7\xe6\x77\xab\x53\x9c\xc0\x0c\x00\x33\
2940 \x00\x01\x00\x00\x02\x58\x00\x0d\x01\x00\x00\x0a\x08\x90\xc7\xf1\
2941 \x74\x0b\x0c\xfb\x34\xc0\x0c\x00\x2e\x00\x01\x00\x00\x02\x58\x00\
2942 \x5d\x00\x33\x0d\x02\x00\x00\x00\x00\x61\xf2\xaf\x39\x61\xcb\x22\
2943 \x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xc4\x4d\
2944 \x00\x48\x9c\x86\x49\xac\x8d\x03\x28\x23\xac\xec\xf5\x5b\xb6\xe5\
2945 \x2f\xf6\xae\xaa\x01\x5a\x66\x52\xf7\x43\xc3\xb1\xe5\xef\xe5\xbf\
2946 \x5f\x71\x5d\xa1\x57\x64\x66\x5e\xa1\x6f\x96\xa8\xcd\x48\x85\xe4\
2947 \x20\xe2\xfb\xb0\xc1\x00\x47\x72\xc8\x72\x98\xc7\x41\xd9";
2948
2949 let dummy =
2950 DnsRequestHeader
2951 {
2952 header: DnsHeader {id: 0xd079, ..Default::default()},
2953 payload: DnsRequestPayload
2954 {
2955 qname: b"\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00".to_vec(),
2956 qtype: QType::ALL,
2957 qclass: QClass::IN,
2958 }
2959 };
2960
2961 let now = Instant::now();
2962 let ans = DnsRequestAnswer::parse(pkt.as_slice());
2963 let elapsed = now.elapsed();
2964 println!("Elapsed: {:.2?}", elapsed);
2965
2966 assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
2967 let ans = ans.unwrap();
2968
2969 let verif = ans.verify(&dummy);
2970 assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
2971
2972 assert_eq!(ans.req_header.header.id, 0xd079);
2973 assert_eq!(ans.req_header.header.ancount, 23);
2974 assert_eq!(ans.req_header.header.arcount, 0);
2975 assert_eq!(ans.req_header.header.nscount, 0);
2976 assert_eq!(ans.req_header.header.qdcount, 1);
2977
2978 let ansord = &ans.response[0];
2979 assert_eq!(
2980 ansord.rdata,
2981 RecordSOA::wrap(
2982 RecordSOA
2983 {
2984 pnm: "ns21.cloudns.net".to_string(),
2985 ram: "support.cloudns.net".to_string(),
2986 serial: 2021122801,
2987 interv_refr: 7200,
2988 interv_retry: 1800,
2989 expire_limit: 1209600,
2990 min_ttl: 3600
2991 }
2992 )
2993 );
2994 assert_eq!(ansord.name, "relkom.sk".to_string());
2995 assert_eq!(ansord.dtype, QType::SOA);
2996 assert_eq!(ansord.class, QClass::IN);
2997 assert_eq!(ansord.ttl, 3600);
2998 assert_eq!(ansord.rdlength, 48);
2999
3000 let a1 =
3001 b"\x00\x06\x0d\x02\
3002 \x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\x72\
3003 \x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x2f\x79\xed\x73\xd0\x75\xc8\
3004 \xa9\xa2\x2a\x08\x3c\x78\xb9\xfb\x43\xc5\x8e\x62\x4c\xbc\x36\xeb\
3005 \x22\x96\x45\x59\x36\x1f\x69\x3a\x7a\x5e\x67\xd0\x54\x1e\xf0\xf2\
3006 \x11\x1a\x72\x00\x56\x89\x26\x79\xf4\x06\x1a\x0c\x59\x41\x32\x60\
3007 \x68\x75\x05\x3d\x90\xed\x1e\x0f\xfc";
3008 let mut a1curs = Cursor::new(a1.as_slice());
3009 let a1len = a1.len();
3010
3011 let ansord = &ans.response[1];
3012 assert_eq!(ansord.rdata, RecordRRSIG::wrap( RecordRRSIG::read(&mut a1curs, a1len as u16, QType::RRSIG).unwrap() ));
3013 assert_eq!(ansord.name, "relkom.sk".to_string());
3014 assert_eq!(ansord.dtype, QType::RRSIG);
3015 assert_eq!(ansord.class, QClass::IN);
3016 assert_eq!(ansord.ttl, 3600);
3017 assert_eq!(ansord.rdlength, a1len as u16);
3018
3019 let ansord = &ans.response[2];
3020 assert_eq!(ansord.rdata, RecordNS::wrap( RecordNS{ fqdn: "ns21.cloudns.net".to_string() }));
3021 assert_eq!(ansord.name, "relkom.sk".to_string());
3022 assert_eq!(ansord.dtype, QType::NS);
3023 assert_eq!(ansord.class, QClass::IN);
3024 assert_eq!(ansord.ttl, 3600);
3025 assert_eq!(ansord.rdlength, 2);
3026 }
3027
3028
3029 #[test]
3030 fn test_request()
3031 {
3032 use std::time::Instant;
3033 use std::net::IpAddr;
3034
3035 let ipp = IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8));
3036 let qdnsreq = QDnsReq::new_into(&ipp, QType::PTR);
3037
3038 let now = Instant::now();
3039
3040 let req = DnsRequestHeader::construct_lookup(&qdnsreq);
3041
3042 let elapsed = now.elapsed();
3043 println!("Elapsed: {:.2?}", elapsed);
3044
3045 assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
3046
3047 let pkt = req.unwrap().to_bytes(false);
3048 assert_eq!(pkt.is_ok(), true);
3049 let pkt = pkt.unwrap();
3050
3051 let ctrl =
3052 b"\x15\xc8\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x38\x01\x38\
3053 \x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\
3054 \x61\x00\x00\x0c\x00\x01";
3055
3056 assert_eq!(&pkt[2..], &ctrl[2..]);
3057 }
3058
3059 #[test]
3060 fn test_request_1()
3061 {
3062 use std::time::Instant;
3063 use std::net::IpAddr;
3064
3065 let ipp = IpAddr::V4("100.150.111.80".parse().unwrap());
3066 let qdnsreq = QDnsReq::new_into(&ipp, QType::PTR);
3067
3068 let now = Instant::now();
3069
3070 let req = DnsRequestHeader::construct_lookup(&qdnsreq);
3071
3072 let elapsed = now.elapsed();
3073 println!("Elapsed: {:.2?}", elapsed);
3074
3075 assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
3076
3077 let pkt = req.unwrap().to_bytes(false);
3078 assert_eq!(pkt.is_ok(), true);
3079 let pkt = pkt.unwrap();
3080
3081 let ctrl =
3082 b"\x74\xa1\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x02\x38\x30\x03\
3083 \x31\x31\x31\x03\x31\x35\x30\x03\x31\x30\x30\x07\x69\x6e\x2d\x61\
3084 \x64\x64\x72\x04\x61\x72\x70\x61\x00\x00\x0c\x00\x01";
3085
3086 assert_eq!(&pkt[2..], &ctrl[2..]);
3087 }
3088
3089 #[test]
3090 fn test_request6()
3091 {
3092 use std::time::Instant;
3093 use std::net::IpAddr;
3094
3095 let ipp = IpAddr::V6("2a00:1450:4003:802::200e".parse().unwrap());
3096 let qdnsreq = QDnsReq::new_into(&ipp, QType::PTR);
3097
3098 let now = Instant::now();
3099
3100 let req = DnsRequestHeader::construct_lookup(&qdnsreq);
3101
3102 let elapsed = now.elapsed();
3103 println!("Elapsed: {:.2?}", elapsed);
3104
3105 assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
3106
3107 let pkt = req.unwrap().to_bytes(false);
3108 assert_eq!(pkt.is_ok(), true);
3109 let pkt = pkt.unwrap();
3110
3111 let ctrl =
3112 b"\xee\xec\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x65\x01\x30\
3113 \x01\x30\x01\x32\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\
3114 \x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x32\x01\x30\
3115 \x01\x38\x01\x30\x01\x33\x01\x30\x01\x30\x01\x34\x01\x30\x01\x35\
3116 \x01\x34\x01\x31\x01\x30\x01\x30\x01\x61\x01\x32\x03\x69\x70\x36\
3117 \x04\x61\x72\x70\x61\x00\x00\x0c\x00\x01";
3118
3119 assert_eq!(&pkt[2..], &ctrl[2..]);
3120 }
3121
3122
3123}