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 let mut octets = ip.octets();
406 octets.reverse();
407
408 for oct in octets
409 {
410 let str_oct = oct.to_string();
411
412 if str_oct.len() > 3
413 {
414 internal_error!(
415 CDnsErrorType::InternalError,
416 "domain component too long, len: '{}' oct: '{}'",
417 str_oct.len(), str_oct
418 );
419 }
420
421 let ln: u8 = str_oct.len() as u8;
422
423 out.push(ln);
424 out.extend(str_oct.as_bytes());
425 }
426
427 out.extend(IN_ADDR_ARPA);
428
429 return Ok(out);
430}
431
432pub
433fn ipv6_pkt(ip: &Ipv6Addr) -> CDnsResult<Vec<u8>>
434{
435 let mut out: Vec<u8> = Vec::with_capacity(32 + IN_ADDR6_ARPA.len());
437
438 let mut octets = ip.octets();
439 octets.reverse();
440
441 for oct in octets
442 {
443 let h_oct = byte2hexchar((oct & 0xF0) >> 4);
444 let l_oct = byte2hexchar(oct & 0x0F);
446 out.push(1);
451 out.push(l_oct);
452 out.push(1);
454 out.push(h_oct);
455 }
456
457 out.extend(IN_ADDR6_ARPA);
458
459 return Ok(out);
460}
461
462pub
463fn name2pkt(name: &str) -> CDnsResult<Vec<u8>>
464{
465 let mut out: Vec<u8> = Vec::with_capacity(name.len() + 2);
467
468 for n in name.split(".")
469 {
470 if n.len() >= MAX_NAME_LEN
471 {
472 internal_error!(CDnsErrorType::InternalError, "name too long: '{}' in: '{}'", n.len(), name);
473 }
474
475 out.push((n.len() & 0xFF) as u8);
476 out.extend(n.as_bytes());
477 }
478
479 out.push(0);
480
481 return Ok(out);
482}
483
484
485#[repr(u16)]
491#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
492pub enum QType
493{
494 A = 1,
496 NS = 2,
498 MD = 3,
500 MF = 4,
502 CNAME = 5,
504 SOA = 6,
506 MB = 7,
508 MG = 8,
510 MR = 9,
512 NULL = 10,
514 WKS = 11,
516 PTR = 12,
518 HINFO = 13,
520 MINFO = 14,
522 MX = 15,
524 TXT = 16,
526 AFSDB = 18,
528 KEY = 25,
530 AAAA = 28,
532 SRV = 33,
534 CERT = 37,
536 DS = 43,
538 RRSIG = 46,
540 NSEC = 47,
542 DNSKEY = 48,
544 NSEC3 = 50,
546 NSEC3PARAM = 51,
548 CDS = 59,
550 CDNSKEY = 60,
552 OPENPGPKEY = 61,
554 AXFR = 252,
557 MAILB = 253,
559 MAILA = 254,
561 URI = 256,
563 CAA = 257,
565 ALL = 255,
567 DLV = 32769,
569}
570
571impl Default for QType
572{
573 fn default() -> Self
574 {
575 return Self::A;
576 }
577}
578
579
580impl Into<u16> for QType
581{
582 fn into(self) -> u16
583 {
584 return self as u16;
585 }
586}
587
588impl fmt::Display for QType
589{
590 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
591 {
592 match *self
593 {
594 Self::A => write!(f, "A"),
595 Self::NS => write!(f, "NS"),
596 Self::MD => write!(f, "MD"),
597 Self::MF => write!(f, "MF"),
598 Self::CNAME => write!(f, "CNAME"),
599 Self::SOA => write!(f, "SOA"),
600 Self::MB => write!(f, "MB"),
601 Self::MG => write!(f, "MG"),
602 Self::MR => write!(f, "MR"),
603 Self::NULL => write!(f, "NULL"),
604 Self::WKS => write!(f, "WKS"),
605 Self::PTR => write!(f, "PTR"),
606 Self::HINFO => write!(f, "HINFO"),
607 Self::MINFO => write!(f, "MINFO"),
608 Self::MX => write!(f, "MX"),
609 Self::TXT => write!(f, "TXT"),
610 Self::AFSDB => write!(f, "AFSDB"),
611 Self::KEY => write!(f, "KEY"),
612 Self::AAAA => write!(f, "AAAA"),
613 Self::SRV => write!(f, "SRV"),
614 Self::CERT => write!(f, "CERT"),
615 Self::DS => write!(f, "DS"),
616 Self::RRSIG => write!(f, "RRSIG"),
617 Self::NSEC => write!(f, "NSEC"),
618 Self::DNSKEY => write!(f, "DNSKEY"),
619 Self::NSEC3 => write!(f, "NSEC"),
620 Self::NSEC3PARAM => write!(f, "NSEC3PARAM"),
621 Self::CDS => write!(f, "CDS"),
622 Self::CDNSKEY => write!(f, "CDNSKEY"),
623 Self::OPENPGPKEY => write!(f, "OPENPGPKEY"),
624 Self::AXFR => write!(f, "AXFR"),
625 Self::MAILB => write!(f, "MAILB"),
626 Self::MAILA => write!(f, "MAILA"),
627 Self::CAA => write!(f, "CAA"),
628 Self::ALL => write!(f, "ALL"),
629 Self::DLV => write!(f, "DLV"),
630 Self::URI => write!(f, "URI"),
631 }
632 }
633}
634
635
636impl QType
637{
638 pub
639 fn ipaddr_match(&self, ip: &IpAddr) -> bool
640 {
641 match *self
642 {
643 Self::A => return ip.is_ipv4(),
644 Self::AAAA => return ip.is_ipv6(),
645 _ => false,
646 }
647 }
648
649 pub
650 fn u16_to_qtype(value: u16) -> CDnsResult<QType>
651 {
652 match value
653 {
654 x if x == Self::AXFR as u16 => return Ok(Self::AXFR),
655 x if x == Self::MAILB as u16 => return Ok(Self::MAILB),
656 x if x == Self::MAILA as u16 => return Ok(Self::MAILA),
657 x if x == Self::ALL as u16 => return Ok(Self::ALL),
658 x if x == Self::DLV as u16 => return Ok(Self::DLV),
659 _ => return Self::u16_to_type(value),
660 }
661 }
662
663 pub
664 fn u16_to_type(value: u16) -> CDnsResult<QType>
665 {
666
667 match value
668 {
669 x if x == Self::A as u16 => return Ok(Self::A),
670 x if x == Self::NS as u16 => return Ok(Self::NS),
671 x if x == Self::MD as u16 => return Ok(Self::MD),
672 x if x == Self::MF as u16 => return Ok(Self::MF),
673 x if x == Self::CNAME as u16 => return Ok(Self::CNAME),
674 x if x == Self::SOA as u16 => return Ok(Self::SOA),
675 x if x == Self::MB as u16 => return Ok(Self::MB),
676 x if x == Self::MG as u16 => return Ok(Self::MG),
677 x if x == Self::MR as u16 => return Ok(Self::MR),
678 x if x == Self::NULL as u16 => return Ok(Self::NULL),
679 x if x == Self::WKS as u16 => return Ok(Self::WKS),
680 x if x == Self::PTR as u16 => return Ok(Self::PTR),
681 x if x == Self::HINFO as u16 => return Ok(Self::HINFO),
682 x if x == Self::MINFO as u16 => return Ok(Self::MINFO),
683 x if x == Self::MX as u16 => return Ok(Self::MX),
684 x if x == Self::TXT as u16 => return Ok(Self::TXT),
685 x if x == Self::AFSDB as u16 => return Ok(Self::AFSDB),
686 x if x == Self::KEY as u16 => return Ok(Self::KEY),
687 x if x == Self::AAAA as u16 => return Ok(Self::AAAA),
688 x if x == Self::CERT as u16 => return Ok(Self::CERT),
689 x if x == Self::DS as u16 => return Ok(Self::DS),
690 x if x == Self::RRSIG as u16 => return Ok(Self::RRSIG),
691 x if x == Self::NSEC as u16 => return Ok(Self::NSEC),
692 x if x == Self::DNSKEY as u16 => return Ok(Self::DNSKEY),
693 x if x == Self::NSEC3 as u16 => return Ok(Self::NSEC3),
694 x if x == Self::NSEC3PARAM as u16 => return Ok(Self::NSEC3PARAM),
695 x if x == Self::CDS as u16 => return Ok(Self::CDS),
696 x if x == Self::CDNSKEY as u16 => return Ok(Self::CDNSKEY),
697 x if x == Self::OPENPGPKEY as u16 => return Ok(Self::OPENPGPKEY),
698 _ => internal_error!(CDnsErrorType::DnsResponse, "unknown request record type: '{}'", value),
699 }
700 }
701}
702
703
704#[repr(u16)]
708#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
709pub enum QClass
710{
711 IN = 1,
713 CS = 2,
715 CH = 3,
717 HS = 4,
719
720 ALL = 255,
723}
724
725impl fmt::Display for QClass
726{
727 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
728 {
729 match *self
730 {
731 Self::IN => write!(f, "IN"),
732 Self::CS => write!(f, "CS"),
733 Self::CH => write!(f, "CH"),
734 Self::HS => write!(f, "HS"),
735 Self::ALL => write!(f, "ALL"),
736 }
737 }
738}
739
740impl Default for QClass
741{
742 fn default() -> Self
743 {
744 return Self::IN;
745 }
746}
747
748impl Into<u16> for QClass
749{
750 fn into(self) -> u16
751 {
752 return self as u16;
753 }
754}
755
756impl QClass
757{
758 pub
763 fn u16_to_qclass(value: u16) -> CDnsResult<QClass>
764 {
765 match value
766 {
767 x if x == QClass::ALL as u16 => return Ok(QClass::ALL),
768 _ => Self::u16_to_class(value),
769 }
770 }
771
772 pub
774 fn u16_to_class(value: u16) -> CDnsResult<QClass>
775 {
776 match value
777 {
778 x if x == QClass::IN as u16 => return Ok(QClass::IN),
779 x if x == QClass::CS as u16 => return Ok(QClass::CS),
780 x if x == QClass::CH as u16 => return Ok(QClass::CH),
781 x if x == QClass::HS as u16 => return Ok(QClass::HS),
782 _ => internal_error!(CDnsErrorType::DnsResponse, "unknown QCLASS type: '{}'", value),
783 }
784 }
785}
786
787bitflags! {
791 #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
793 pub struct StatusBits: u16
794 {
795 const QR_RESP = 0x8000;
798
799 const OPCODE_STANDARD = 0x87FF;
802 const OPCODE_IQUERY = 0x0040;
804 const OPCODE_STATUS = 0x0020;
806 const AUTH_ANSWER = 0x0400;
814
815 const TRUN_CATION = 0x0200;
819
820 const RECURSION_DESIRED = 0x0100;
826
827 const RECURSION_AVAIL = 0x0080;
832
833 const RSERVER0 = 0x0040;
837
838 const ANSWER_AUTHN = 0x0020;
839 const NON_AUTH_DATA = 0x0010;
840
841 const RESP_NOERROR = 0x0000;
845 const RESP_FORMERR = 0x0001;
847 const RESP_SERVFAIL = 0x0002;
850 const RESP_NXDOMAIN = 0x0003;
854 const RESP_NOT_IMPL = 0x0004;
856 const RESP_REFUSED = 0x0005;
859 }
861}
862
863#[derive(Clone, Debug, Hash, PartialEq, Eq)]
869pub enum QDnsName
870{
871 IpV4(Ipv4Addr),
872 IpV6(Ipv6Addr),
873 Name(Arc<String>),
874}
875
876impl fmt::Display for QDnsName
877{
878 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
879 {
880 match self
881 {
882 QDnsName::IpV4(ipv4_addr) =>
883 write!(f, "{}", ipv4_addr),
884 QDnsName::IpV6(ipv6_addr) =>
885 write!(f, "{}", ipv6_addr),
886 QDnsName::Name(name) =>
887 write!(f, "{}", name),
888 }
889 }
890}
891
892impl QDnsName
893{
894 pub
897 fn is_ipv4(&self) -> bool
898 {
899 match *self
900 {
901 Self::IpV4(_) => return true,
902 _ => return false,
903 }
904 }
905
906 pub
909 fn is_ipv6(&self) -> bool
910 {
911 match *self
912 {
913 Self::IpV6(_) => return true,
914 _ => return false,
915 }
916 }
917
918 pub
921 fn is_ip(&self) -> bool
922 {
923 match *self
924 {
925 Self::IpV4(_) => return true,
926 Self::IpV6(_) => return true,
927 _ => return false,
928 }
929 }
930
931 pub
933 fn get_ip_qtype(&self) -> Option<QType>
934 {
935 match *self
936 {
937 Self::IpV4(_) => return Some(QType::A),
938 Self::IpV6(_) => return Some(QType::AAAA),
939 Self::Name(_) =>
940 {
941 return None;
942 }
943 }
944 }
945}
946
947
948impl PartialEq<str> for QDnsName
949{
950 fn eq(&self, other: &str) -> bool
951 {
952 match *self
953 {
954 Self::Name(ref name) =>
955 return name.as_str() == other,
956 Self::IpV4(ref ip) =>
957 {
958 if let Ok(other_ip) = other.parse::<Ipv4Addr>()
959 {
960 return &other_ip == ip;
961 }
962
963 return false;
964 },
965 Self::IpV6(ref ip) =>
966 {
967 if let Ok(other_ip) = other.parse::<Ipv6Addr>()
968 {
969 return &other_ip == ip;
970 }
971
972 return false;
973 }
974 }
975 }
976}
977
978impl From<&IpAddr> for QDnsName
995{
996 fn from(ip: &IpAddr) -> Self
997 {
998 match *ip
999 {
1000 IpAddr::V4(ref ip) =>
1001 return Self::IpV4(ip.clone()),
1002 IpAddr::V6(ref ip) =>
1003 return Self::IpV6(ip.clone()),
1004 }
1005 }
1006}
1007
1008impl From<IpAddr> for QDnsName
1009{
1010 fn from(ip: IpAddr) -> Self
1011 {
1012 match ip
1013 {
1014 IpAddr::V4(ip) =>
1015 return Self::IpV4(ip),
1016 IpAddr::V6(ip) =>
1017 return Self::IpV6(ip),
1018 }
1019 }
1020}
1021
1022impl From<&Ipv4Addr> for QDnsName
1023{
1024 fn from(ip: &Ipv4Addr) -> Self
1025 {
1026 return Self::IpV4(ip.clone());
1027 }
1028}
1029
1030impl From<Ipv4Addr> for QDnsName
1031{
1032 fn from(ip: Ipv4Addr) -> Self
1033 {
1034 return Self::IpV4(ip);
1035 }
1036}
1037
1038impl From<&Ipv6Addr> for QDnsName
1039{
1040 fn from(ip: &Ipv6Addr) -> Self
1041 {
1042 return Self::IpV6(ip.clone());
1043 }
1044}
1045
1046impl From<Ipv6Addr> for QDnsName
1047{
1048 fn from(ip: Ipv6Addr) -> Self
1049 {
1050 return Self::IpV6(ip);
1051 }
1052}
1053
1054impl From<&str> for QDnsName
1055{
1056 fn from(name: &str) -> Self
1057 {
1058 let ipp = name.parse::<IpAddr>();
1059 if ipp.is_err()
1060 {
1061 return Self::Name(Arc::new(name.to_string()));
1062 }
1063 else
1064 {
1065 return QDnsName::from(ipp.unwrap());
1066 }
1067 }
1068}
1069
1070impl TryFrom<QDnsName> for Vec<u8>
1071{
1072 type Error = CDnsError;
1073
1074 fn try_from(qns: QDnsName) -> Result<Self, Self::Error>
1075 {
1076 match qns
1077 {
1078 QDnsName::IpV4(ref ip) =>
1079 {
1080 return ipv4_pkt(ip);
1081 },
1082 QDnsName::IpV6(ref ip) =>
1083 {
1084 return ipv6_pkt(ip);
1085 },
1086 QDnsName::Name(ref name) =>
1087 {
1088 if let Ok(ip) = name.parse::<Ipv4Addr>()
1089 {
1090 return ipv4_pkt(&ip);
1091 }
1092 else if let Ok(ip) = name.parse::<Ipv6Addr>()
1093 {
1094 return ipv6_pkt(&ip);
1095 }
1096 else
1097 {
1098 return name2pkt(name);
1099 }
1100 }
1101 }
1102 }
1103}
1104
1105impl TryFrom<&QDnsName> for Vec<u8>
1106{
1107 type Error = CDnsError;
1108
1109 fn try_from(qns: &QDnsName) -> Result<Self, Self::Error>
1110 {
1111 match qns
1112 {
1113 QDnsName::IpV4(ip) =>
1114 {
1115 return ipv4_pkt(ip);
1116 },
1117 QDnsName::IpV6(ip) =>
1118 {
1119 return ipv6_pkt(ip);
1120 },
1121 QDnsName::Name(name) =>
1122 {
1123 if let Ok(ip) = name.parse::<Ipv4Addr>()
1124 {
1125 return ipv4_pkt(&ip);
1126 }
1127 else if let Ok(ip) = name.parse::<Ipv6Addr>()
1128 {
1129 return ipv6_pkt(&ip);
1130 }
1131 else
1132 {
1133 return name2pkt(name);
1134 }
1135 }
1136 }
1137 }
1138}
1139
1140impl From<&QDnsName> for String
1141{
1142 fn from(dnsname: &QDnsName) -> Self
1143 {
1144 match *dnsname
1145 {
1146 QDnsName::IpV4(ref ip) =>
1147 {
1148 return ip.to_string();
1149 },
1150 QDnsName::IpV6(ref ip) =>
1151 {
1152 return ip.to_string();
1153 },
1154 QDnsName::Name(ref name) =>
1155 {
1156 return name.to_string();
1157 }
1158 }
1159 }
1160}
1161
1162
1163impl TryFrom<&QDnsName> for IpAddr
1164{
1165 type Error = CDnsError;
1166 fn try_from(value: &QDnsName) -> Result<Self, Self::Error>
1167 {
1168 match *value
1169 {
1170 QDnsName::IpV4(ref ip) =>
1171 {
1172 return Ok(IpAddr::V4(ip.clone()));
1173 },
1174 QDnsName::IpV6(ref ip) =>
1175 {
1176 return Ok(IpAddr::V6(ip.clone()));
1177 },
1178 QDnsName::Name(ref name) =>
1179 {
1180 if let Ok(ip) = name.parse::<Ipv4Addr>()
1181 {
1182 return Ok(IpAddr::V4(ip.clone()));
1183 }
1184 else if let Ok(ip) = name.parse::<Ipv6Addr>()
1185 {
1186 return Ok(IpAddr::V6(ip.clone()));
1187 }
1188 else
1189 {
1190 internal_error!(CDnsErrorType::InternalError, "not ip address!")
1191 }
1192 }
1193 }
1194 }
1195}
1196
1197
1198impl TryFrom<QDnsName> for IpAddr
1199{
1200 type Error = CDnsError;
1201 fn try_from(value: QDnsName) -> Result<Self, Self::Error>
1202 {
1203 match value
1204 {
1205 QDnsName::IpV4(ip) =>
1206 {
1207 return Ok(IpAddr::V4(ip));
1208 },
1209 QDnsName::IpV6(ip) =>
1210 {
1211 return Ok(IpAddr::V6(ip));
1212 },
1213 QDnsName::Name(ref name) =>
1214 {
1215 if let Ok(ip) = name.parse::<Ipv4Addr>()
1216 {
1217 return Ok(IpAddr::V4(ip));
1218 }
1219 else if let Ok(ip) = name.parse::<Ipv6Addr>()
1220 {
1221 return Ok(IpAddr::V6(ip));
1222 }
1223 else
1224 {
1225 internal_error!(CDnsErrorType::InternalError, "not ip address!")
1226 }
1227 }
1228 }
1229 }
1230}
1231
1232#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1233pub struct DnsHeader
1234{
1235 pub id: u16,
1238
1239 pub status: StatusBits,
1241
1242 pub qdcount: u16,
1245
1246 pub ancount: u16,
1249
1250 pub nscount: u16,
1254
1255 pub arcount: u16,
1258}
1259
1260impl fmt::Display for DnsHeader
1261{
1262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1263 {
1264 write!(f, "ID:{} Status:{:?}, qdcnt:{}, ancnt:{}, nscnt:{}, arcnt:{}",
1265 self.id, self.status, self.qdcount, self.ancount, self.nscount, self.arcount)
1266 }
1267}
1268
1269
1270#[derive(Clone, Debug, Default, PartialEq, Eq)]
1271pub struct DnsRequestAnswer
1272{
1273 pub req_header: DnsRequestHeader,
1275 pub response: Vec<DnsResponsePayload>,
1277 pub additional: Vec<DnsResponsePayload>,
1279 pub authoratives: Vec<DnsResponsePayload>,
1281}
1282
1283impl DnsRequestAnswer
1284{
1285 #[inline]
1286 pub
1287 fn get_req_id(&self) -> u16
1288 {
1289 return self.req_header.get_id();
1290 }
1291
1292 pub
1298 fn verify(&self, req: &DnsRequestHeader) -> CDnsResult<()>
1299 {
1300 if self.get_req_id() != req.get_id()
1301 {
1302 internal_error!(
1303 CDnsErrorType::DnsResponse,
1304 "request and response ID did not match: '{}' != '{}'",
1305 req.header.id, self.get_req_id()
1306 );
1307 }
1308
1309 if self.req_header.payload != req.payload
1311 {
1312 internal_error!(CDnsErrorType::DnsResponse,
1313 "received request section is different from sent");
1314 }
1315 else if req.payload.qtype != QType::ALL
1316 {
1317 if req.payload.qtype != self.req_header.payload.qtype
1319 {
1320 internal_error!(
1321 CDnsErrorType::DnsResponse,
1322 "requested QTYPE differ received TYPE: '{}' != '{}'",
1323 req.payload.qtype,
1324 self.req_header.payload.qtype
1325 );
1326 }
1327 }
1328 else if self.req_header.header.status.contains(StatusBits::TRUN_CATION) == true
1329 {
1330 internal_error!(CDnsErrorType::MessageTruncated,
1331 "DNS response was truncated, aborting processing");
1332 }
1333
1334 return Ok(());
1335 }
1336
1337 pub(crate)
1343 fn parse(ans: &[u8]) -> CDnsResult<Self>
1344 {
1345 let mut pkt = Cursor::new(ans);
1347
1348 let id = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
1350
1351 let status = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
1352
1353 let header =
1354 DnsHeader
1355 {
1356 id: id,
1357 status: StatusBits::from_bits(status).ok_or_else(||
1358 internal_error_map!(CDnsErrorType::DnsResponse, "unknown status bits: '{}'", status)
1359 )?,
1360 qdcount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1361 ancount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1362 nscount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1363 arcount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1364 };
1365
1366 if header.status.contains(StatusBits::QR_RESP) == false
1370 {
1371 internal_error!(
1372 CDnsErrorType::DnsResponse,
1373 "incorret QR flag in STATUS register of response, expected 1 got 0"
1374 );
1375 }
1376 let request =
1393 DnsRequestPayload
1394 {
1395 qname: pkt2name(&mut pkt)?,
1396 qtype: QType::u16_to_qtype(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?,
1397 qclass: QClass::u16_to_qclass(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?,
1398 };
1399
1400 let mut an_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.ancount as usize);
1401 let mut rr_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.arcount as usize);
1402 let mut ns_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.nscount as usize);
1403
1404 for _ in 0..header.ancount
1405 {
1406 an_list.push(DnsResponsePayload::new(&mut pkt)?);
1407 }
1408
1409 for _ in 0..header.nscount
1411 {
1412 ns_list.push(DnsResponsePayload::new(&mut pkt)?);
1413 }
1414
1415 for _ in 0..header.arcount
1417 {
1418 rr_list.push(DnsResponsePayload::new(&mut pkt)?);
1419 }
1420
1421 return Ok(
1422 DnsRequestAnswer
1423 {
1424 req_header: DnsRequestHeader{ header, payload: request },
1425 response: an_list,
1426 additional: rr_list,
1427 authoratives: ns_list,
1428 }
1429 );
1430 }
1431
1432}
1433
1434#[derive(Clone, Debug, Default)]
1435pub struct DnsRequestHeader
1436{
1437 pub header: DnsHeader,
1439 pub payload: DnsRequestPayload,
1441}
1442
1443impl Eq for DnsRequestHeader {}
1444
1445impl PartialEq for DnsRequestHeader
1446{
1447 fn eq(&self, other: &DnsRequestHeader) -> bool
1448 {
1449 return self.header.id == other.header.id && self.payload == other.payload;
1450 }
1451}
1452
1453impl Ord for DnsRequestHeader
1454{
1455 fn cmp(&self, other: &Self) -> Ordering
1456 {
1457 return self.header.id.cmp(&other.header.id);
1459 }
1460}
1461
1462impl PartialOrd for DnsRequestHeader
1463{
1464 fn partial_cmp(&self, other: &Self) -> Option<Ordering>
1465 {
1466 return Some(self.cmp(other));
1467 }
1468}
1469
1470impl Hash for DnsRequestHeader
1471{
1472 fn hash<H: Hasher>(&self, state: &mut H)
1473 {
1474 self.header.id.hash(state);
1475 self.payload.hash(state);
1476 }
1477}
1478
1479impl Borrow<u16> for DnsRequestHeader
1480{
1481 fn borrow(&self) -> &u16
1482 {
1483 return &self.header.id;
1484 }
1485}
1486
1487impl TryFrom<&QDnsReq> for DnsRequestHeader
1488{
1489 type Error = CDnsError;
1490
1491 fn try_from(value: &QDnsReq) -> Result<Self, Self::Error>
1492 {
1493 return DnsRequestHeader::construct_lookup(value);}
1495}
1496
1497impl fmt::Display for DnsRequestHeader
1498{
1499 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1500 {
1501 write!(f, "Header: {}, Status: {}", self.header, self.payload)
1502 }
1503}
1504
1505
1506impl DnsRequestHeader
1507{
1508 pub
1509 fn regenerate_id(&mut self)
1510 {
1511 self.header.id = rand::random();
1512 }
1513
1514 pub
1515 fn get_id(&self) -> u16
1516 {
1517 return self.header.id;
1518 }
1519
1520 pub
1528 fn derive(&self) -> Self
1529 {
1530 let header =
1531 DnsHeader
1532 {
1533 id: rand::random(),
1534 status: self.header.status,
1535 qdcount: self.header.qdcount,
1536 ancount: self.header.ancount,
1537 nscount: self.header.nscount,
1538 arcount: self.header.arcount,
1539 };
1540
1541 return DnsRequestHeader{ header: header, payload: self.payload.clone() };
1542 }
1543
1544 pub
1546 fn construct_lookup(qreq: &QDnsReq) -> CDnsResult<DnsRequestHeader>
1547 {
1548 let mut status: StatusBits = StatusBits::empty();
1550 status = (status & !StatusBits::OPCODE_STANDARD) | StatusBits::RECURSION_DESIRED;
1551
1552 let mut req: DnsRequestHeader = DnsRequestHeader{ ..Default::default() };
1554
1555 req.header.id = rand::random();
1556 req.header.status = status;
1557 req.header.qdcount = 1;
1558
1559 req.payload = DnsRequestPayload::new(qreq.get_req_name().try_into()?, *qreq.get_type(), QClass::IN);
1561
1562 return Ok(req);
1563 }
1564
1565 pub
1566 fn to_bytes(&self, append_len: bool) -> CDnsResult<Vec<u8>>
1567 {
1568 let mut pkt_size: usize = size_of::<DnsHeader>() + self.payload.qname.len() + 4;
1569
1570 if append_len == true
1571 {
1572 pkt_size += 2;
1573 }
1574
1575 let mut pkt = Cursor::new(vec![0_u8; pkt_size]);
1576
1577 if append_len == true
1578 {
1579 pkt.write_u16::<BigEndian>((pkt_size-2) as u16).map_err(map_read_err)?;
1580 }
1581
1582 pkt.write_u16::<BigEndian>(self.header.id).map_err(map_read_err)?;
1583 pkt.write_u16::<BigEndian>(self.header.status.bits()).map_err(map_read_err)?;
1584 pkt.write_u16::<BigEndian>(self.header.qdcount).map_err(map_read_err)?;
1585 pkt.write_u16::<BigEndian>(self.header.ancount).map_err(map_read_err)?;
1586 pkt.write_u16::<BigEndian>(self.header.nscount).map_err(map_read_err)?;
1587 pkt.write_u16::<BigEndian>(self.header.arcount).map_err(map_read_err)?;
1588
1589 pkt.write(self.payload.qname.as_slice()).map_err(map_read_err)?;
1592 pkt.write_u16::<BigEndian>(self.payload.qtype.into()).map_err(map_read_err)?;
1593 pkt.write_u16::<BigEndian>(self.payload.qclass.into()).map_err(map_read_err)?;
1594 return Ok(pkt.into_inner());
1597 }
1598}
1599
1600#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
1602pub struct DnsRequestPayload
1603{
1604 pub qname: Vec<u8>,
1606
1607 pub qtype: QType,
1609
1610 pub qclass: QClass,
1612}
1613
1614impl fmt::Display for DnsRequestPayload
1615{
1616 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1617 {
1618 write!(f, "qname:{:?} qtype:{}, qclass:{}", self.qname, self.qtype, self.qclass)
1619 }
1620}
1621
1622impl DnsRequestPayload
1623{
1624 pub
1625 fn new(qname: Vec<u8>, qtype: QType, qclass: QClass) -> Self
1626 {
1627 return DnsRequestPayload{ qname: qname, qtype: qtype.into(), qclass: qclass.into() };
1628 }
1629}
1630
1631#[derive(Clone, Debug, Default, Eq, PartialEq)]
1633pub struct DnsResponsePayload
1634{
1635 pub name: String,
1637 pub dtype: QType,
1639 pub class: QClass,
1641 pub ttl: i32,
1644 pub rdlength: u16,
1646 pub rdata: DnsRdata,
1648}
1649
1650impl DnsResponsePayload
1651{
1652 pub(crate)
1655 fn new_local(dtype: QType, data: &HostnameEntry) -> Option<Vec<Self>>
1656 {
1657 match dtype
1658 {
1659 QType::A =>
1660 {
1661 let mut out: Vec<Self> = Vec::with_capacity(1);
1662
1663 let IpAddr::V4(ipv4) = data.get_ip()
1664 else { return None; };
1665
1666 out.push(
1667 DnsResponsePayload
1668 {
1669 name: data.get_hostnames()[0].to_string(),
1670 dtype: dtype,
1671 class: QClass::IN,
1672 ttl: i32::MAX,
1673 rdlength: 0,
1674 rdata: RecordA::wrap(RecordA{ ip: ipv4.clone()}),
1675 }
1676 );
1677
1678 return Some(out);
1679 },
1680 QType::AAAA =>
1681 {
1682 let mut out: Vec<Self> = Vec::with_capacity(1);
1683
1684 let IpAddr::V6(ipv6) = data.get_ip()
1685 else { return None };
1686
1687 out.push(
1688 DnsResponsePayload
1689 {
1690 name: data.get_hostnames()[0].to_string(),
1691 dtype: dtype,
1692 class: QClass::IN,
1693 ttl: i32::MAX,
1694 rdlength: 0,
1695 rdata: RecordAAAA::wrap(RecordAAAA{ ip: ipv6.clone() }),
1696 }
1697 );
1698
1699 return Some(out);
1700 },
1701 QType::PTR =>
1702 {
1703 let mut out: Vec<Self> = Vec::with_capacity(data.get_hostnames().len());
1704
1705 for h in data.get_hostnames_iter()
1707 {
1708 out.push(
1709 DnsResponsePayload
1710 {
1711 name: [data.get_ip().to_string().as_str(), ".in-addr.arpa"].concat(),
1712 dtype: dtype,
1713 class: QClass::IN,
1714 ttl: i32::MAX,
1715 rdlength: 0,
1716 rdata: RecordPTR::wrap( RecordPTR { fqdn: h.clone() }),
1717 }
1718 );
1719 }
1720
1721 return Some(out);
1722 },
1723 _ =>
1724 return None
1725 }
1726
1727 }
1728
1729 fn new(pkt: &mut Cursor<&[u8]>) -> CDnsResult<Self>
1730 {
1731 let name = name2str(pkt, None)?;
1732 let qtype = QType::u16_to_type(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?;
1733 let qclass = QClass::u16_to_class(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?;
1734 let ttl = pkt.read_i32::<BigEndian>().map_err(map_read_err)?;
1735 let rdlength = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
1736 let rdata = DnsRdata::convert(pkt, rdlength, qtype)?;
1737
1738 return Ok(
1739 DnsResponsePayload
1740 {
1741 name: name,
1742 dtype: qtype,
1743 class: qclass,
1744 ttl: ttl,
1745 rdlength: rdlength,
1746 rdata: rdata,
1747 }
1748 );
1749 }
1750
1751 pub
1752 fn get_rdata(&self) -> &DnsRdata
1753 {
1754 return &self.rdata;
1755 }
1756
1757 pub
1758 fn borrow_rdata(self) -> DnsRdata
1759 {
1760 return self.rdata;
1761 }
1762}
1763
1764impl fmt::Display for DnsResponsePayload
1773{
1774 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1775 {
1776 write!(f, "{} {} {} {} {}",
1777 self.name, self.dtype, self.class, self.ttl, self.rdata)
1778 }
1779}
1780
1781
1782pub trait RecordReader: Sized
1784{
1785
1786 const REC_TYPE: QType;
1788
1789 const RLEN: u16;
1791
1792 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>;
1796
1797 fn wrap(self) -> DnsRdata;
1798}
1799
1800#[derive(Clone, Debug, Eq, PartialEq)]
1801pub struct RecordA
1802{
1803 pub ip: Ipv4Addr
1804}
1805
1806impl RecordReader for RecordA
1807{
1808 const REC_TYPE: QType = QType::A;
1809
1810 const RLEN: u16 = 4;
1811
1812 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
1813 {
1814 if rlen != Self::RLEN
1816 {
1817 internal_error!(CDnsErrorType::DnsResponse, "RecordA len expected: '4', got: '{}'", rlen);
1818 }
1819 else if qtype != Self::REC_TYPE
1820 {
1821 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1822 }
1823
1824 let ip = pkt.read_u32::<BigEndian>().map_err(map_read_err)?;
1825
1826 return Ok(Self{ip: Ipv4Addr::from(ip) });
1827 }
1828
1829 fn wrap(self) -> DnsRdata
1830 {
1831 return DnsRdata::A(self);
1832 }
1833}
1834
1835impl fmt::Display for RecordA
1836{
1837 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1838 {
1839 write!(f, "{} {}", Self::REC_TYPE, self.ip)
1840 }
1841}
1842
1843
1844#[derive(Clone, Debug, Eq, PartialEq)]
1845pub struct RecordAAAA
1846{
1847 pub ip: Ipv6Addr
1848}
1849
1850impl RecordReader for RecordAAAA
1851{
1852 const REC_TYPE: QType = QType::AAAA;
1853
1854 const RLEN: u16 = 16;
1855
1856 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
1857 {
1858 if rlen != Self::RLEN
1859 {
1860 internal_error!(CDnsErrorType::DnsResponse, "RecordAAAA len expected: '{}', got: '{}'", Self::RLEN, rlen);
1861 }
1862 else if qtype != Self::REC_TYPE
1863 {
1864 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1865 }
1866
1867 let ip = pkt.read_u128::<BigEndian>().map_err(map_read_err)?;
1868
1869 return Ok(Self{ ip: Ipv6Addr::from(ip) });
1870 }
1871
1872 fn wrap(self) -> DnsRdata
1873 {
1874 return DnsRdata::AAAA(self);
1875 }
1876}
1877
1878impl fmt::Display for RecordAAAA
1879{
1880 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1881 {
1882 write!(f, "{} {}", Self::REC_TYPE, self.ip)
1883 }
1884}
1885
1886#[derive(Clone, Debug, Eq, PartialEq)]
1887pub struct RecordPTR
1888{
1889 pub fqdn: String
1890}
1891
1892impl RecordReader for RecordPTR
1893{
1894 const REC_TYPE: QType = QType::PTR;
1895
1896 const RLEN: u16 = 0;
1897
1898 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
1899 {
1900 if qtype != Self::REC_TYPE
1901 {
1902 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1903 }
1904
1905 return Ok(
1906 Self{ fqdn: name2str(pkt, Some(rlen))? }
1907 );
1908 }
1909
1910 fn wrap(self) -> DnsRdata
1911 {
1912 return DnsRdata::PTR(self);
1913 }
1914}
1915
1916impl fmt::Display for RecordPTR
1917{
1918 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1919 {
1920 write!(f, "{} {}", Self::REC_TYPE, self.fqdn)
1921 }
1922}
1923
1924#[derive(Clone, Debug, Eq, PartialEq)]
1925pub struct RecordMX
1926{
1927 pub preference: u16,
1928 pub exchange: String
1929}
1930
1931impl RecordReader for RecordMX
1932{
1933 const REC_TYPE: QType = QType::MX;
1934
1935 const RLEN: u16 = 2;
1936
1937 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
1938 {
1939 if rlen <= Self::RLEN
1940 {
1941 internal_error!(CDnsErrorType::DnsResponse, "RecordMX len expected: '{}', got: '{}'", Self::RLEN, rlen);
1942 }
1943 else if qtype != Self::REC_TYPE
1944 {
1945 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1946 }
1947
1948 return Ok(
1949 Self
1950 {
1951 preference: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1952 exchange: name2str(pkt, Some(rlen - 2))?,
1953 }
1954 );
1955 }
1956
1957 fn wrap(self) -> DnsRdata
1958 {
1959 return DnsRdata::MX(self);
1960 }
1961}
1962
1963impl fmt::Display for RecordMX
1964{
1965 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1966 {
1967 write!(f, "{} {} {}", Self::REC_TYPE, self.preference, self.exchange)
1968 }
1969}
1970
1971#[derive(Clone, Debug, Eq, PartialEq)]
1972pub struct RecordCNAME
1973{
1974 pub fqdn: String
1975}
1976
1977impl RecordReader for RecordCNAME
1978{
1979 const REC_TYPE: QType = QType::CNAME;
1980
1981 const RLEN: u16 = 0;
1982
1983 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
1984 {
1985 if qtype != Self::REC_TYPE
1986 {
1987 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1988 }
1989
1990 return Ok(
1991 Self{ fqdn: name2str(pkt, Some(rlen))? }
1992 );
1993 }
1994
1995 fn wrap(self) -> DnsRdata
1996 {
1997 return DnsRdata::CNAME(self);
1998 }
1999}
2000
2001impl fmt::Display for RecordCNAME
2002{
2003 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2004 {
2005 write!(f, "{} {}", Self::REC_TYPE, self.fqdn)
2006 }
2007}
2008
2009#[derive(Clone, Debug, Eq, PartialEq)]
2010pub struct RecordNS
2011{
2012 pub fqdn: String
2013}
2014
2015impl RecordReader for RecordNS
2016{
2017 const REC_TYPE: QType = QType::NS;
2018
2019 const RLEN: u16 = 0;
2020
2021 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2022 {
2023 if qtype != Self::REC_TYPE
2024 {
2025 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2026 }
2027
2028 return Ok(
2029 Self{ fqdn: name2str(pkt, Some(rlen))? }
2030 );
2031 }
2032
2033 fn wrap(self) -> DnsRdata
2034 {
2035 return DnsRdata::NS(self);
2036 }
2037}
2038
2039impl fmt::Display for RecordNS
2040{
2041 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2042 {
2043 write!(f, "{} {}", Self::REC_TYPE, self.fqdn)
2044 }
2045}
2046
2047#[derive(Clone, Debug, Eq, PartialEq)]
2048pub struct RecordSOA
2049{
2050 pub pnm: String,
2052 pub ram: String,
2054 pub serial: u32,
2056 pub interv_refr: u32,
2058 pub interv_retry: u32,
2060 pub expire_limit: u32,
2062 pub min_ttl: u32,
2064}
2065
2066impl RecordReader for RecordSOA
2067{
2068 const REC_TYPE: QType = QType::SOA;
2069
2070 const RLEN: u16 = 0;
2071
2072 fn read(pkt: &mut Cursor<&[u8]>, _rlen: u16, qtype: QType) -> CDnsResult<Self>
2073 {
2074 if qtype != Self::REC_TYPE
2075 {
2076 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2077 }
2078
2079 return Ok(
2080 Self
2081 {
2082 pnm: name2str(pkt, None)?,
2084 ram: name2str(pkt, None)?,
2086 serial: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2088 interv_refr: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2090 interv_retry: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2092 expire_limit: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2094 min_ttl: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2096 }
2097 );
2098 }
2099
2100 fn wrap(self) -> DnsRdata
2101 {
2102 return DnsRdata::SOA(self);
2103 }
2104}
2105
2106impl fmt::Display for RecordSOA
2107{
2108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2109 {
2110 write!(f, "{} {} {} {} {} {} {} {}", Self::REC_TYPE, self.pnm, self.ram, self.serial,
2111 self.interv_refr, self.interv_retry, self.expire_limit, self.min_ttl)
2112 }
2113}
2114
2115#[derive(Clone, Debug, Eq, PartialEq)]
2116pub struct RecordSRV
2117{
2118 pub priority: u16,
2120
2121 pub weight: u16,
2124
2125 pub port: u16,
2127
2128 pub target: String,
2130}
2131
2132impl RecordReader for RecordSRV
2133{
2134 const REC_TYPE: QType = QType::SRV;
2135
2136 const RLEN: u16 = 0;
2137
2138 fn read(pkt: &mut Cursor<&[u8]>, _rlen: u16, qtype: QType) -> CDnsResult<Self>
2139 {
2140 if qtype != Self::REC_TYPE
2141 {
2142 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2143 }
2144
2145 return Ok(
2146 Self
2147 {
2148 priority: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2149 weight: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2150 port: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2151 target: name2str(pkt, None)?,
2152 }
2153 );
2154 }
2155
2156 fn wrap(self) -> DnsRdata
2157 {
2158 return DnsRdata::SRV(self);
2159 }
2160}
2161
2162impl fmt::Display for RecordSRV
2163{
2164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2165 {
2166 write!(f, "{} {} {} {} \"{}\"", Self::REC_TYPE, self.priority, self.weight, self.port, self.target)
2167 }
2168}
2169
2170#[derive(Clone, Debug, Eq, PartialEq)]
2171pub struct RecordTXT
2172{
2173 pub txt_strings: String,
2175}
2176
2177impl RecordReader for RecordTXT
2178{
2179 const REC_TYPE: QType = QType::TXT;
2180
2181 const RLEN: u16 = 2;
2182
2183 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2184 {
2185 if rlen <= Self::RLEN
2186 {
2187 internal_error!(CDnsErrorType::DnsResponse, "RecordTXT len expected: '{}' >, got: '{}'", Self::RLEN, rlen);
2188 }
2189 else if qtype != Self::REC_TYPE
2190 {
2191 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2192 }
2193
2194 let mut read_length = 0;
2195
2196
2197 let dmod = ((rlen % 255) > 0) as u16;
2198 let cap = rlen / 255 + dmod;
2199
2200 let mut txt_datas = Vec::<String>::with_capacity(cap as usize);
2201
2202 while read_length < rlen
2203 {
2204 let mut txt_data = Vec::new();
2205
2206 loop
2207 {
2208 let blk_size = pkt.read_u8().map_err(map_read_err)?;
2209
2210 read_length += blk_size as u16 + 1;
2211
2212 let mut new_txt = Vec::with_capacity(blk_size as usize);unsafe { new_txt.set_len(blk_size as usize); }
2214
2215 pkt.read_exact(&mut new_txt).map_err(map_read_err)?;
2216
2217 txt_data.push(new_txt);
2218
2219 if blk_size < 255
2220 {
2221 break;
2222 }
2223 }
2224
2225 if txt_data.is_empty() == true
2226 {
2227 internal_error!(
2228 CDnsErrorType::DnsResponse,
2229 "unexpected EOF in TXT rec cur position: '{}', data_length: '{}', read: '{}'",
2230 pkt.position(), rlen, read_length
2231 );
2232 }
2233
2234 let data = txt_data.concat();
2235
2236 txt_datas.push(
2237 String::from_utf8(data)
2238 .map_err(|e|
2239 internal_error_map!(CDnsErrorType::InternalError, "UTF-8 decode error, {}", e)
2240 )?
2241 );
2242 }
2243
2244 return Ok(
2245 Self
2246 {
2247 txt_strings: txt_datas.concat()
2248 }
2249 );
2250 }
2251
2252 fn wrap(self) -> DnsRdata
2253 {
2254 return DnsRdata::TXT(self);
2255 }
2256}
2257
2258impl fmt::Display for RecordTXT
2259{
2260 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2261 {
2262 write!(f, "{} {}", Self::REC_TYPE, self.txt_strings)
2263 }
2264}
2265
2266#[derive(Clone, Debug, Eq, PartialEq)]
2267pub struct RecordURI
2268{
2269 pub priority: u16,
2271
2272 pub weight: u16,
2275
2276 pub target: String,
2279}
2280
2281impl RecordReader for RecordURI
2282{
2283 const REC_TYPE: QType = QType::URI;
2284
2285 const RLEN: u16 = 4;
2286
2287 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2288 {
2289 if rlen <= Self::RLEN
2290 {
2291 internal_error!(CDnsErrorType::DnsResponse, "RecordURI len expected: '{}' >, got: '{}'", Self::RLEN, rlen);
2292 }
2293 else if qtype != Self::REC_TYPE
2294 {
2295 internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2296 }
2297
2298 return Ok(
2299 Self
2300 {
2301 priority: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2302 weight: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2303 target: pkt2string_exact(pkt, rlen - 4)?,
2304 }
2305 );
2306 }
2307
2308 fn wrap(self) -> DnsRdata
2309 {
2310 return DnsRdata::URI(self);
2311 }
2312}
2313
2314impl fmt::Display for RecordURI
2315{
2316 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2317 {
2318 write!(f, "{} {} {} \"{}\"", Self::REC_TYPE, self.priority, self.weight, self.target)
2319 }
2320}
2321
2322#[derive(Clone, Debug, Eq, PartialEq)]
2325pub struct RecordRRSIG
2326{
2327 type_cov: u16,
2328 alg: u8,
2329 labels: u8,
2330 orig_ttl: u32,
2331 sig_exp: u32,
2332 sig_inc: u32,
2333 keytag: u16,
2334 sig_name: String,
2335 key: Vec<u8>,
2336}
2337
2338impl RecordReader for RecordRRSIG
2339{
2340 const REC_TYPE: QType = QType::RRSIG;
2341
2342 const RLEN: u16 = 19;
2343
2344 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, _qtype: QType) -> CDnsResult<Self>
2345 {
2346 let data = vec![0_u8; rlen as usize];
2347
2348 let pos = pkt.position();
2349
2350 let mut res =
2351 Self
2352 {
2353 type_cov: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2354 alg: pkt.read_u8().map_err(map_read_err)?,
2355 labels: pkt.read_u8().map_err(map_read_err)?,
2356 orig_ttl: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2357 sig_exp: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2358 sig_inc: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2359 keytag: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2360 sig_name: name2str(pkt,None)?,
2361 key: Vec::new(),
2362 };
2363
2364 let left_rdlen = rlen - (pkt.position() - pos) as u16;
2365 res.key = pkt2vec(pkt, Some(left_rdlen))?;
2366
2367 return Ok(res);
2368 }
2369
2370 fn wrap(self) -> DnsRdata
2371 {
2372 return DnsRdata::RRSIG(self);
2373 }
2374}
2375
2376impl fmt::Display for RecordRRSIG
2377{
2378 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2379 {
2380 write!(f, "{} {} {} {} {} {} {} {} {} {}",
2381 Self::REC_TYPE, self.type_cov, self.alg, self.labels, self.orig_ttl,
2382 self.sig_exp, self.sig_inc, self.keytag, self.sig_name,
2383 self.key.iter().map(|k| format!("{:02X}", k)).collect::<Vec<String>>().concat()
2384 )
2385 }
2386}
2387
2388#[derive(Clone, Debug, Eq, PartialEq)]
2389pub struct RecordOther
2390{
2391 pub qtype: QType,
2393
2394 pub data: Vec<u8>
2396}
2397
2398impl RecordReader for RecordOther
2399{
2400 const REC_TYPE: QType = QType::ALL;
2401
2402 const RLEN: u16 = 0;
2403
2404 fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2405 {
2406 let mut data = vec![0_u8; rlen as usize];
2407
2408 pkt.read_exact(&mut data).map_err(map_read_err)?;
2409
2410 return Ok(
2411 Self
2412 {
2413 qtype: qtype,
2414 data: data,
2415 }
2416 );
2417 }
2418
2419 fn wrap(self) -> DnsRdata
2420 {
2421 return DnsRdata::OTHER(self);
2422 }
2423}
2424
2425impl fmt::Display for RecordOther
2426{
2427 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2428 {
2429 write!(f, "{} RAW:", self.qtype)?;
2430
2431 for d in self.data.iter()
2432 {
2433 write!(f, "{:X}", d)?;
2434 }
2435
2436 return Ok(());
2437 }
2438}
2439
2440pub(crate)
2441fn sanitize_str_unicode(st: &str) -> String
2442{
2443 let mut out = String::with_capacity(st.len());
2444
2445 for c in st.chars()
2446 {
2447 if c.is_alphanumeric() == true ||
2448 c.is_ascii_punctuation() == true ||
2449 c == ' '
2450 {
2451 out.push(c);
2452 }
2453 else
2454 {
2455 let mut buf = [0_u8; 4];
2456 c.encode_utf8(&mut buf);
2457
2458 let formatted: String =
2459 buf[0..c.len_utf8()].into_iter()
2460 .map(|c| format!("\\x{:02x}", c))
2461 .collect();
2462
2463 out.push_str(&formatted);
2464 }
2465 }
2466
2467 return out;
2468}
2469
2470#[derive(Clone, Debug, Eq, PartialEq)]
2471pub enum DnsRdata
2472{
2473 None,
2474 A(RecordA),
2475 NS(RecordNS),
2476 CNAME(RecordCNAME),
2477 SOA(RecordSOA),
2478 PTR(RecordPTR),
2479 MX(RecordMX),
2480 TXT(RecordTXT),
2481 AAAA(RecordAAAA),
2482 SRV(RecordSRV),
2483 URI(RecordURI),
2484 RRSIG(RecordRRSIG),
2485 OTHER(RecordOther),
2486}
2487
2488impl fmt::Display for DnsRdata
2489{
2490 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
2491 {
2492 match self
2493 {
2494 Self::None =>
2495 write!(f, "No record"),
2496 Self::A(ip) =>
2497 write!(f, "{}", ip),
2498 Self::NS(ns) =>
2499 write!(f, "{}", ns),
2500 Self::AAAA(aaaa) =>
2501 write!(f, "{}", aaaa),
2502 Self::MX(mx) =>
2503 write!(f, "{}", mx),
2504 Self::CNAME(cname) =>
2505 write!(f, "{}", cname),
2506 Self::PTR(ptr) =>
2507 write!(f, "{}", ptr),
2508 Self::SOA(soa) =>
2509 write!(f, "{}", soa),
2510 Self::TXT(txt) =>
2511 write!(f, "{}", txt),
2512 Self::SRV(srv) =>
2513 write!(f, "{}", srv),
2514 Self::URI(uri) =>
2515 write!(f, "{}", uri),
2516 Self::RRSIG(rrsig) =>
2517 write!(f, "{}", rrsig),
2518 Self::OTHER(other) =>
2519 write!(f, "{}", other),
2520 }
2521 }
2522}
2523
2524impl Default for DnsRdata
2525{
2526 fn default() -> Self
2527 {
2528 return Self::None;
2529 }
2530}
2531
2532impl DnsRdata
2533{
2534 #[inline]
2535 pub
2536 fn is_some(&self) -> bool
2537 {
2538 return *self != Self::None;
2539 }
2540}
2541
2542
2543impl DnsRdata
2544{
2545 pub
2559 fn convert(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2560 {
2561 match qtype
2562 {
2563 RecordA::REC_TYPE =>
2564 return Ok(RecordA::wrap(RecordA::read(pkt, rlen, qtype)?)),
2565 RecordAAAA::REC_TYPE =>
2566 return Ok(RecordAAAA::wrap(RecordAAAA::read(pkt, rlen, qtype)?)),
2567 RecordPTR::REC_TYPE =>
2568 return Ok(RecordPTR::wrap(RecordPTR::read(pkt, rlen, qtype)?)),
2569 RecordMX::REC_TYPE =>
2570 return Ok(RecordMX::wrap(RecordMX::read(pkt, rlen, qtype)?)),
2571 RecordCNAME::REC_TYPE =>
2572 return Ok(RecordCNAME::wrap(RecordCNAME::read(pkt, rlen, qtype)?)),
2573 RecordSOA::REC_TYPE =>
2574 return Ok(RecordSOA::wrap(RecordSOA::read(pkt, rlen, qtype)?)),
2575 RecordSRV::REC_TYPE =>
2576 return Ok(RecordSRV::wrap(RecordSRV::read(pkt, rlen, qtype)?)),
2577 RecordTXT::REC_TYPE =>
2578 return Ok(RecordTXT::wrap(RecordTXT::read(pkt, rlen, qtype)?)),
2579 RecordURI::REC_TYPE =>
2580 return Ok(RecordURI::wrap(RecordURI::read(pkt, rlen, qtype)?)),
2581 RecordNS::REC_TYPE =>
2582 return Ok(RecordNS::wrap(RecordNS::read(pkt, rlen, qtype)?)),
2583 RecordRRSIG::REC_TYPE =>
2584 return Ok(RecordRRSIG::wrap(RecordRRSIG::read(pkt, rlen, qtype)?)),
2585 _ =>
2586 return Ok(RecordOther::wrap(RecordOther::read(pkt, rlen, qtype)?)),
2587 }
2588 }
2589
2590 pub
2591 fn get_ip(&self) -> Option<IpAddr>
2592 {
2593 match self
2594 {
2595 Self::A(a) => return Some(IpAddr::V4(a.ip)),
2596 Self::AAAA(a) => return Some(IpAddr::V6(a.ip)),
2597 _ => return None
2598 }
2599 }
2600}
2601
2602#[cfg(test)]
2603mod tests
2604{
2605 use std::io::Cursor;
2606
2607 use crate::common::*;
2608
2609
2610
2611 #[test]
2612 fn test_pkt2name()
2613 {
2614 use std::time::Instant;
2615
2616 fn prepare(d: &[u8]) -> Cursor<&[u8]>
2617 {
2618 return Cursor::new(d);
2621 }
2622
2623 let t1 = b"\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00";
2624
2625 let mut cur1 = prepare(t1);
2626
2627 let now = Instant::now();
2628 let r1 = pkt2name(&mut cur1);
2629 let elapsed = now.elapsed();
2630 println!("Elapsed: {:.2?}", elapsed);
2631
2632 assert_eq!(r1.is_ok(), true);
2633 assert_eq!(r1.as_ref().unwrap(), t1);
2634
2635 let t2 =
2636 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2637 \x30\x30\x03\x6e\x65\x74\x00";
2638
2639 let mut cur2 = prepare(t2);
2640 let now = Instant::now();
2641 let r2 = pkt2name(&mut cur2);
2642 let elapsed = now.elapsed();
2643 println!("Elapsed: {:.2?}", elapsed);
2644
2645 assert_eq!(r2.is_ok(), true);
2646 assert_eq!(r2.as_ref().unwrap(), t2);
2647
2648 let t3 =
2649 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2650 \x30\x30\x03\x6e\x65\x74";
2651
2652 let r3 = pkt2name(&mut prepare(t3));
2653
2654 assert_eq!(r3.is_ok(), false);
2655
2656 let t4 =
2657 b"\x10\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2658 \x30\x30\x03\x6e\x65\x74";
2659
2660 let r4 = pkt2name(&mut prepare(t4));
2661
2662 assert_eq!(r4.is_ok(), false);
2663 }
2664
2665 #[test]
2666 fn test_qname2str()
2667 {
2668 use std::time::Instant;
2669
2670 fn prepare(d: &[u8]) -> Cursor<&[u8]>
2671 {
2672 return Cursor::new(d);
2675 }
2676
2677 let t1 = b"\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00";
2678
2679 let mut cur1 = prepare(t1);
2680 let now = Instant::now();
2681 let r1 = name2str(&mut cur1, None);
2682 let elapsed = now.elapsed();
2683 println!("Elapsed: {:.2?}", elapsed);
2684
2685 assert_eq!(r1.is_ok(), true);
2686 assert_eq!(r1.as_ref().unwrap(), "dns.google");
2687
2688 let t2 =
2689 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2690 \x30\x30\x03\x6e\x65\x74\x00";
2691
2692 let mut cur2 = prepare(t2);
2693
2694 let now = Instant::now();
2695 let r2 = name2str(&mut cur2, None);
2696 let elapsed = now.elapsed();
2697 println!("Elapsed: {:.2?}", elapsed);
2698
2699 assert_eq!(r2.is_ok(), true);
2700 assert_eq!(r2.as_ref().unwrap(), "mad07s09-in-x0e.1e100.net");
2701
2702 let t3 =
2703 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2704 \x30\x30\x03\x6e\x65\x74";
2705
2706 let r3 = name2str(&mut prepare(t3), None);
2707
2708 assert_eq!(r3.is_ok(), false);
2709
2710 let t4 =
2711 b"\x10\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2712 \x30\x30\x03\x6e\x65\x74";
2713
2714 let r4 = name2str(&mut prepare(t4), None);
2715
2716 assert_eq!(r4.is_ok(), false);
2717 }
2718
2719 #[test]
2720 fn test_response_parser()
2721 {
2722 use std::time::Instant;
2723
2724 let pkt =
2725 b"\x15\xc8\x81\x80\x00\x01\x00\x01\x00\x00\x00\x02\x01\x38\x01\x38\
2726 \x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\
2727 \x61\x00\x00\x0c\x00\x01\xc0\x0c\x00\x0c\x00\x01\x00\x01\x35\xf0\
2728 \x00\x0c\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00\xc0\x32\
2729 \x00\x01\x00\x01\x00\x00\x00\xe8\x00\x04\x08\x08\x08\x08\xc0\x32\
2730 \x00\x01\x00\x01\x00\x00\x00\xe8\x00\x04\x08\x08\x04\x04";
2731
2732 let dummy =
2733 DnsRequestHeader
2734 {
2735 header: DnsHeader {id: 0x15c8, ..Default::default()},
2736 payload: DnsRequestPayload
2737 {
2738 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(),
2739 qtype: QType::PTR,
2740 qclass: QClass::IN,
2741 }
2742 };
2743
2744 let now = Instant::now();
2745 let ans = DnsRequestAnswer::parse(pkt.as_slice());
2746 let elapsed = now.elapsed();
2747 println!("Elapsed: {:.2?}", elapsed);
2748
2749 assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
2750
2751 let ans = ans.unwrap();
2752
2753 let verif = ans.verify(&dummy);
2754 assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
2755
2756 assert_eq!(ans.req_header.header.id, 0x15c8);
2757 assert_eq!(ans.req_header.header.ancount, 1);
2758 assert_eq!(ans.req_header.header.arcount, 2);
2759 assert_eq!(ans.req_header.header.nscount, 0);
2760 assert_eq!(ans.req_header.header.qdcount, 1);
2761
2762 assert_eq!(ans.response[0].rdata, RecordPTR::wrap(RecordPTR { fqdn: "dns.google".to_string() }) );
2763 assert_eq!(ans.response[0].name, "8.8.8.8.in-addr.arpa".to_string());
2764 assert_eq!(ans.response[0].dtype, QType::PTR);
2765 assert_eq!(ans.response[0].class, QClass::IN);
2766 assert_eq!(ans.response[0].ttl, 79344);
2767 assert_eq!(ans.response[0].rdlength, 12);
2768
2769 assert_eq!(ans.additional[0].rdata, RecordA::wrap(RecordA { ip: "8.8.8.8".parse().unwrap() }) );
2770 assert_eq!(ans.additional[0].name, "dns.google".to_string());
2771 assert_eq!(ans.additional[0].ttl, 232);
2772 assert_eq!(ans.additional[0].dtype, QType::A);
2773 assert_eq!(ans.additional[0].class, QClass::IN);
2774
2775 assert_eq!(ans.additional[1].rdata, RecordA::wrap(RecordA { ip: "8.8.4.4".parse().unwrap() }) );
2776 assert_eq!(ans.additional[1].name, "dns.google".to_string());
2777 assert_eq!(ans.additional[1].ttl, 232);
2778 assert_eq!(ans.additional[1].dtype, QType::A);
2779 assert_eq!(ans.additional[1].class, QClass::IN);
2780 }
2781
2782 #[test]
2783 fn test_response2()
2784 {
2785 use std::time::Instant;
2786
2787 let pkt =
2788 b"\x4b\x38\x81\x80\x00\x01\x00\x05\x00\x00\x00\x00\x05\x67\x6d\x61\
2789 \x69\x6c\x03\x63\x6f\x6d\x00\x00\x0f\x00\x01\xc0\x0c\x00\x0f\x00\
2790 \x01\x00\x00\x0b\x55\x00\x1b\x00\x05\x0d\x67\x6d\x61\x69\x6c\x2d\
2791 \x73\x6d\x74\x70\x2d\x69\x6e\x01\x6c\x06\x67\x6f\x6f\x67\x6c\x65\
2792 \xc0\x12\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\x55\x00\x09\x00\x0a\
2793 \x04\x61\x6c\x74\x31\xc0\x29\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\
2794 \x55\x00\x09\x00\x1e\x04\x61\x6c\x74\x33\xc0\x29\xc0\x0c\x00\x0f\
2795 \x00\x01\x00\x00\x0b\x55\x00\x09\x00\x14\x04\x61\x6c\x74\x32\xc0\
2796 \x29\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\x55\x00\x09\x00\x28\x04\
2797 \x61\x6c\x74\x34\xc0\x29";
2798
2799 let dummy =
2800 DnsRequestHeader
2801 {
2802 header: DnsHeader {id: 0x4b38, ..Default::default()},
2803 payload: DnsRequestPayload
2804 {
2805 qname: b"\x05\x67\x6d\x61\x69\x6c\x03\x63\x6f\x6d\x00".to_vec(),
2806 qtype: QType::MX,
2807 qclass: QClass::IN,
2808 }
2809 };
2810
2811 let now = Instant::now();
2812 let ans = DnsRequestAnswer::parse(pkt.as_slice());
2813 let elapsed = now.elapsed();
2814 println!("Elapsed: {:.2?}", elapsed);
2815
2816 assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
2817 let ans = ans.unwrap();
2818
2819 let verif = ans.verify(&dummy);
2820 assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
2821
2822 assert_eq!(ans.req_header.header.id, 0x4b38);
2823 assert_eq!(ans.req_header.header.ancount, 5);
2824 assert_eq!(ans.req_header.header.arcount, 0);
2825 assert_eq!(ans.req_header.header.nscount, 0);
2826 assert_eq!(ans.req_header.header.qdcount, 1);
2827
2828 assert_eq!(ans.response[0].rdata, RecordMX::wrap(RecordMX { preference: 5, exchange: "gmail-smtp-in.l.google.com".to_string() }) );
2829 assert_eq!(ans.response[0].name, "gmail.com".to_string());
2830 assert_eq!(ans.response[0].dtype, QType::MX);
2831 assert_eq!(ans.response[0].class, QClass::IN);
2832 assert_eq!(ans.response[0].ttl, 2901);
2833 assert_eq!(ans.response[0].rdlength, 27);
2834
2835 assert_eq!(ans.response[1].rdata, RecordMX::wrap(RecordMX { preference: 10, exchange: "alt1.gmail-smtp-in.l.google.com".to_string() }) );
2836 assert_eq!(ans.response[1].name, "gmail.com".to_string());
2837 assert_eq!(ans.response[1].dtype, QType::MX);
2838 assert_eq!(ans.response[1].class, QClass::IN);
2839 assert_eq!(ans.response[1].ttl, 2901);
2840 assert_eq!(ans.response[1].rdlength, 9);
2841
2842 assert_eq!(ans.response[2].rdata, RecordMX::wrap(RecordMX { preference: 30, exchange: "alt3.gmail-smtp-in.l.google.com".to_string() }) );
2843 assert_eq!(ans.response[2].name, "gmail.com".to_string());
2844 assert_eq!(ans.response[2].dtype, QType::MX);
2845 assert_eq!(ans.response[2].class, QClass::IN);
2846 assert_eq!(ans.response[2].ttl, 2901);
2847 assert_eq!(ans.response[2].rdlength, 9);
2848
2849 assert_eq!(ans.response[3].rdata, RecordMX::wrap(RecordMX { preference: 20, exchange: "alt2.gmail-smtp-in.l.google.com".to_string() }) );
2850 assert_eq!(ans.response[3].name, "gmail.com".to_string());
2851 assert_eq!(ans.response[3].dtype, QType::MX);
2852 assert_eq!(ans.response[3].class, QClass::IN);
2853 assert_eq!(ans.response[3].ttl, 2901);
2854 assert_eq!(ans.response[3].rdlength, 9);
2855
2856 assert_eq!(ans.response[4].rdata, RecordMX::wrap(RecordMX { preference: 40, exchange: "alt4.gmail-smtp-in.l.google.com".to_string() }) );
2857 assert_eq!(ans.response[4].name, "gmail.com".to_string());
2858 assert_eq!(ans.response[4].dtype, QType::MX);
2859 assert_eq!(ans.response[4].class, QClass::IN);
2860 assert_eq!(ans.response[4].ttl, 2901);
2861 assert_eq!(ans.response[4].rdlength, 9);
2862 }
2863
2864
2865 #[test]
2866 fn test_response3()
2867 {
2868 use std::time::Instant;
2869
2870 let pkt =
2871 b"\xd0\x79\x81\x80\x00\x01\x00\x17\x00\x00\x00\x00\x06\x72\
2872 \x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x00\xff\x00\x01\xc0\x0c\x00\
2873 \x06\x00\x01\x00\x00\x0e\x10\x00\x30\x04\x6e\x73\x32\x31\x07\x63\
2874 \x6c\x6f\x75\x64\x6e\x73\x03\x6e\x65\x74\x00\x07\x73\x75\x70\x70\
2875 \x6f\x72\x74\xc0\x2c\x78\x77\xe2\xf1\x00\x00\x1c\x20\x00\x00\x07\
2876 \x08\x00\x12\x75\x00\x00\x00\x0e\x10\xc0\x0c\x00\x2e\x00\x01\x00\
2877 \x00\x0e\x10\x00\x5d\x00\x06\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\
2878 \x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\
2879 \x6b\x00\x2f\x79\xed\x73\xd0\x75\xc8\xa9\xa2\x2a\x08\x3c\x78\xb9\
2880 \xfb\x43\xc5\x8e\x62\x4c\xbc\x36\xeb\x22\x96\x45\x59\x36\x1f\x69\
2881 \x3a\x7a\x5e\x67\xd0\x54\x1e\xf0\xf2\x11\x1a\x72\x00\x56\x89\x26\
2882 \x79\xf4\x06\x1a\x0c\x59\x41\x32\x60\x68\x75\x05\x3d\x90\xed\x1e\
2883 \x0f\xfc\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x02\xc0\x27\
2884 \xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x08\x05\x70\x6e\x73\
2885 \x32\x33\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x07\
2886 \x04\x6e\x73\x32\x33\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\
2887 \x10\x00\x08\x05\x70\x6e\x73\x32\x32\xc0\x2c\xc0\x0c\x00\x02\x00\
2888 \x01\x00\x00\x0e\x10\x00\x08\x05\x70\x6e\x73\x32\x34\xc0\x2c\xc0\
2889 \x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x07\x04\x6e\x73\x32\x34\
2890 \xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x08\x05\x70\
2891 \x6e\x73\x32\x31\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\
2892 \x00\x07\x04\x6e\x73\x32\x32\xc0\x2c\xc0\x0c\x00\x2e\x00\x01\x00\
2893 \x00\x0e\x10\x00\x5d\x00\x02\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\
2894 \x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\
2895 \x6b\x00\xd1\xc5\x6c\xf1\xfb\xd0\x75\xf1\x38\x20\x28\x80\x4c\xe0\
2896 \x59\xa5\xa8\xab\x84\x79\xd8\x37\x48\xa7\xa5\x3f\x08\x9b\x4c\xca\
2897 \x40\x2b\xcb\x2c\xda\xcc\xc2\x18\xad\x07\x9e\xf8\x4e\x17\x8d\xb1\
2898 \x2b\x2d\xa2\xa6\x17\xdb\x55\x30\xbc\xa2\xb9\xa0\x01\x71\x01\xe5\
2899 \xdc\x4f\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xd9\x14\
2900 \x70\xd0\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\x01\
2901 \x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\
2902 \x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xf8\x57\x68\xf0\xad\
2903 \x9e\xfb\x3a\x0f\x66\xbd\xcc\x48\xe7\x29\x0a\xf4\xd8\xf6\xbe\xbc\
2904 \x04\x76\x02\x27\x64\xf2\xc9\x42\x6d\x75\x54\x83\x0a\x11\xda\x0a\
2905 \x02\x6b\x8c\xf1\x65\xc4\x21\x44\xea\x89\x09\x01\xc8\xa1\xe2\x11\
2906 \x8f\xed\x67\x39\x69\x33\xdd\x97\x22\x1a\xd3\xc0\x0c\x00\x0f\x00\
2907 \x01\x00\x00\x0e\x10\x00\x11\x00\x0a\x04\x6d\x61\x69\x6c\x04\x6e\
2908 \x69\x78\x64\x03\x6f\x72\x67\x00\xc0\x0c\x00\x2e\x00\x01\x00\x00\
2909 \x0e\x10\x00\x5d\x00\x0f\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\
2910 \x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\
2911 \x00\xd4\xdd\x07\xd9\xb6\xb2\xba\x57\xa9\x1d\x3b\xaa\x6c\x55\xc4\
2912 \x3d\x73\x79\xea\x74\xfe\xd7\x23\x0c\xb4\xab\x8f\x4b\x1f\xd9\x8a\
2913 \xb2\x4a\x5c\xad\x3e\x8e\x4a\x85\xbb\xbd\x75\xf2\x47\x2c\xa8\x89\
2914 \x21\x75\x89\xb1\x12\xc4\xd2\xf7\x40\x06\x52\x57\x83\x8a\xaa\x7b\
2915 \x75\xc0\x0c\x00\x10\x00\x01\x00\x00\x0e\x10\x00\x34\x33\x76\x3d\
2916 \x73\x70\x66\x31\x20\x2b\x6d\x78\x20\x2b\x61\x3a\x6d\x61\x69\x6c\
2917 \x2e\x6e\x69\x78\x64\x2e\x6f\x72\x67\x20\x69\x70\x34\x3a\x32\x31\
2918 \x37\x2e\x32\x30\x2e\x31\x31\x32\x2e\x32\x30\x38\x20\x2d\x61\x6c\
2919 \x6c\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\x10\x0d\
2920 \x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\
2921 \x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xd1\x6c\xd1\xf4\x3b\xe0\
2922 \x44\xba\xfe\xe9\xdb\x82\xbd\x89\x5f\xa1\x07\x72\xdd\x47\xad\x4e\
2923 \x91\xd5\xc3\xfe\x3e\x39\x74\xdb\x50\x50\x19\x6c\x3f\x6c\xb7\xa8\
2924 \x01\x03\x6a\xf5\xa7\xf3\x9b\xf7\x76\xd4\xff\xa3\xd5\x43\xfc\xec\
2925 \xa9\x89\x24\xf8\xd2\xb6\x76\xd4\x20\xbc\xc0\x0c\x00\x30\x00\x01\
2926 \x00\x00\x0e\x10\x00\x44\x01\x01\x03\x0d\xf3\x87\xe2\x7c\x2b\x82\
2927 \x40\x72\x7c\xfd\xc9\x2b\xe8\x22\xd6\xa9\x40\xc0\xab\x03\x25\x7d\
2928 \x92\xae\xf3\x17\x71\x82\x67\xc6\xcd\xb6\x4b\x11\x62\xc6\xfa\x06\
2929 \xec\x4c\x9f\xd9\xe6\xaf\x5c\x3d\xe4\x32\xde\x11\x1b\x09\x13\xe3\
2930 \xd0\xba\x66\xd1\xbc\x32\xdb\x13\xd7\x1d\xc0\x0c\x00\x30\x00\x01\
2931 \x00\x00\x0e\x10\x00\x44\x01\x00\x03\x0d\xd4\x43\xde\x96\xe5\xea\
2932 \x0a\xf9\x5d\x4f\x72\x88\x9c\xd9\x9c\xf7\xa6\x3f\x12\xd7\xf3\xea\
2933 \x8a\x6b\x44\x4c\x79\x23\x81\x94\x43\xa3\xbd\x9e\xb8\xde\xfe\x8c\
2934 \xe6\x21\xe3\x8a\x71\xba\x05\xd2\x0f\x98\x5b\xfc\x7e\x72\x8c\xe9\
2935 \x9a\xc0\x49\x00\xca\xd5\x62\x93\x7f\x03\xc0\x0c\x00\x2e\x00\x01\
2936 \x00\x00\x0e\x10\x00\x5d\x00\x30\x0d\x02\x00\x00\x0e\x10\x61\xf2\
2937 \xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\
2938 \x73\x6b\x00\xc0\x93\x23\x1d\xcb\x1e\x79\xfe\x7c\x40\x3e\xd4\x33\
2939 \x5f\xed\x69\x8e\x7d\x75\xff\x73\x6b\x24\x71\x8f\x50\xf8\xe0\x49\
2940 \xce\x5f\x62\x0c\x8c\xb3\x06\x8f\x26\xea\x20\xa0\xe3\x71\xe0\xa1\
2941 \x8b\xe0\x4a\x2f\x1d\x4b\x79\x2c\x52\x6b\xa4\x43\xb5\x70\x27\x01\
2942 \xb0\x63\x47\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\
2943 \x30\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x97\
2944 \x18\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x41\x87\x75\x1d\
2945 \x30\x44\xd1\x94\x40\xd4\xe6\x40\x98\x62\x94\x53\xad\x53\xe2\xed\
2946 \xc0\xc0\xb7\xa3\x20\x15\xae\x59\xbb\x97\x45\xfb\x0e\xbf\x70\xf3\
2947 \xb1\x24\x79\xe8\x85\x6c\x2a\x66\x10\xb6\x75\x99\x7b\x77\x78\x65\
2948 \xa6\x67\x8d\x59\xa6\x14\xf7\xe6\x77\xab\x53\x9c\xc0\x0c\x00\x33\
2949 \x00\x01\x00\x00\x02\x58\x00\x0d\x01\x00\x00\x0a\x08\x90\xc7\xf1\
2950 \x74\x0b\x0c\xfb\x34\xc0\x0c\x00\x2e\x00\x01\x00\x00\x02\x58\x00\
2951 \x5d\x00\x33\x0d\x02\x00\x00\x00\x00\x61\xf2\xaf\x39\x61\xcb\x22\
2952 \x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xc4\x4d\
2953 \x00\x48\x9c\x86\x49\xac\x8d\x03\x28\x23\xac\xec\xf5\x5b\xb6\xe5\
2954 \x2f\xf6\xae\xaa\x01\x5a\x66\x52\xf7\x43\xc3\xb1\xe5\xef\xe5\xbf\
2955 \x5f\x71\x5d\xa1\x57\x64\x66\x5e\xa1\x6f\x96\xa8\xcd\x48\x85\xe4\
2956 \x20\xe2\xfb\xb0\xc1\x00\x47\x72\xc8\x72\x98\xc7\x41\xd9";
2957
2958 let dummy =
2959 DnsRequestHeader
2960 {
2961 header: DnsHeader {id: 0xd079, ..Default::default()},
2962 payload: DnsRequestPayload
2963 {
2964 qname: b"\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00".to_vec(),
2965 qtype: QType::ALL,
2966 qclass: QClass::IN,
2967 }
2968 };
2969
2970 let now = Instant::now();
2971 let ans = DnsRequestAnswer::parse(pkt.as_slice());
2972 let elapsed = now.elapsed();
2973 println!("Elapsed: {:.2?}", elapsed);
2974
2975 assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
2976 let ans = ans.unwrap();
2977
2978 let verif = ans.verify(&dummy);
2979 assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
2980
2981 assert_eq!(ans.req_header.header.id, 0xd079);
2982 assert_eq!(ans.req_header.header.ancount, 23);
2983 assert_eq!(ans.req_header.header.arcount, 0);
2984 assert_eq!(ans.req_header.header.nscount, 0);
2985 assert_eq!(ans.req_header.header.qdcount, 1);
2986
2987 let ansord = &ans.response[0];
2988 assert_eq!(
2989 ansord.rdata,
2990 RecordSOA::wrap(
2991 RecordSOA
2992 {
2993 pnm: "ns21.cloudns.net".to_string(),
2994 ram: "support.cloudns.net".to_string(),
2995 serial: 2021122801,
2996 interv_refr: 7200,
2997 interv_retry: 1800,
2998 expire_limit: 1209600,
2999 min_ttl: 3600
3000 }
3001 )
3002 );
3003 assert_eq!(ansord.name, "relkom.sk".to_string());
3004 assert_eq!(ansord.dtype, QType::SOA);
3005 assert_eq!(ansord.class, QClass::IN);
3006 assert_eq!(ansord.ttl, 3600);
3007 assert_eq!(ansord.rdlength, 48);
3008
3009 let a1 =
3010 b"\x00\x06\x0d\x02\
3011 \x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\x72\
3012 \x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x2f\x79\xed\x73\xd0\x75\xc8\
3013 \xa9\xa2\x2a\x08\x3c\x78\xb9\xfb\x43\xc5\x8e\x62\x4c\xbc\x36\xeb\
3014 \x22\x96\x45\x59\x36\x1f\x69\x3a\x7a\x5e\x67\xd0\x54\x1e\xf0\xf2\
3015 \x11\x1a\x72\x00\x56\x89\x26\x79\xf4\x06\x1a\x0c\x59\x41\x32\x60\
3016 \x68\x75\x05\x3d\x90\xed\x1e\x0f\xfc";
3017 let mut a1curs = Cursor::new(a1.as_slice());
3018 let a1len = a1.len();
3019
3020 let ansord = &ans.response[1];
3021 assert_eq!(ansord.rdata, RecordRRSIG::wrap( RecordRRSIG::read(&mut a1curs, a1len as u16, QType::RRSIG).unwrap() ));
3022 assert_eq!(ansord.name, "relkom.sk".to_string());
3023 assert_eq!(ansord.dtype, QType::RRSIG);
3024 assert_eq!(ansord.class, QClass::IN);
3025 assert_eq!(ansord.ttl, 3600);
3026 assert_eq!(ansord.rdlength, a1len as u16);
3027
3028 let ansord = &ans.response[2];
3029 assert_eq!(ansord.rdata, RecordNS::wrap( RecordNS{ fqdn: "ns21.cloudns.net".to_string() }));
3030 assert_eq!(ansord.name, "relkom.sk".to_string());
3031 assert_eq!(ansord.dtype, QType::NS);
3032 assert_eq!(ansord.class, QClass::IN);
3033 assert_eq!(ansord.ttl, 3600);
3034 assert_eq!(ansord.rdlength, 2);
3035 }
3036
3037
3038 #[test]
3039 fn test_request()
3040 {
3041 use std::time::Instant;
3042 use std::net::IpAddr;
3043
3044 let ipp = IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8));
3045 let qdnsreq = QDnsReq::new_into(&ipp, QType::PTR);
3046
3047 let now = Instant::now();
3048
3049 let req = DnsRequestHeader::construct_lookup(&qdnsreq);
3050
3051 let elapsed = now.elapsed();
3052 println!("Elapsed: {:.2?}", elapsed);
3053
3054 assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
3055
3056 let pkt = req.unwrap().to_bytes(false);
3057 assert_eq!(pkt.is_ok(), true);
3058 let pkt = pkt.unwrap();
3059
3060 let ctrl =
3061 b"\x15\xc8\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x38\x01\x38\
3062 \x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\
3063 \x61\x00\x00\x0c\x00\x01";
3064
3065 assert_eq!(&pkt[2..], &ctrl[2..]);
3066 }
3067
3068 #[test]
3069 fn test_request_1()
3070 {
3071 use std::time::Instant;
3072 use std::net::IpAddr;
3073
3074 let ipp = IpAddr::V4("100.150.111.80".parse().unwrap());
3075 let qdnsreq = QDnsReq::new_into(&ipp, QType::PTR);
3076
3077 let now = Instant::now();
3078
3079 let req = DnsRequestHeader::construct_lookup(&qdnsreq);
3080
3081 let elapsed = now.elapsed();
3082 println!("Elapsed: {:.2?}", elapsed);
3083
3084 assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
3085
3086 let pkt = req.unwrap().to_bytes(false);
3087 assert_eq!(pkt.is_ok(), true);
3088 let pkt = pkt.unwrap();
3089
3090 let ctrl =
3091 b"\x74\xa1\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x02\x38\x30\x03\
3092 \x31\x31\x31\x03\x31\x35\x30\x03\x31\x30\x30\x07\x69\x6e\x2d\x61\
3093 \x64\x64\x72\x04\x61\x72\x70\x61\x00\x00\x0c\x00\x01";
3094
3095 assert_eq!(&pkt[2..], &ctrl[2..]);
3096 }
3097
3098 #[test]
3099 fn test_request6()
3100 {
3101 use std::time::Instant;
3102 use std::net::IpAddr;
3103
3104 let ipp = IpAddr::V6("2a00:1450:4003:802::200e".parse().unwrap());
3105 let qdnsreq = QDnsReq::new_into(&ipp, QType::PTR);
3106
3107 let now = Instant::now();
3108
3109 let req = DnsRequestHeader::construct_lookup(&qdnsreq);
3110
3111 let elapsed = now.elapsed();
3112 println!("Elapsed: {:.2?}", elapsed);
3113
3114 assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
3115
3116 let pkt = req.unwrap().to_bytes(false);
3117 assert_eq!(pkt.is_ok(), true);
3118 let pkt = pkt.unwrap();
3119
3120 let ctrl =
3121 b"\xee\xec\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x65\x01\x30\
3122 \x01\x30\x01\x32\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\
3123 \x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x32\x01\x30\
3124 \x01\x38\x01\x30\x01\x33\x01\x30\x01\x30\x01\x34\x01\x30\x01\x35\
3125 \x01\x34\x01\x31\x01\x30\x01\x30\x01\x61\x01\x32\x03\x69\x70\x36\
3126 \x04\x61\x72\x70\x61\x00\x00\x0c\x00\x01";
3127
3128 assert_eq!(&pkt[2..], &ctrl[2..]);
3129 }
3130
3131
3132}