1use std::{cmp::Ordering, fmt, net::{IpAddr, Ipv4Addr, Ipv6Addr}, path::Path, sync::LazyLock};
25use std::borrow::Borrow;
26use std::hash::{Hash, Hasher};
27
28use crate::{error::*, query_private::QDnsReq, cfg_resolv_parser::ResolveConfigLookup, cfg_host_parser::HostnameEntry};
29use crate::internal_error;
30
31use super::cfg_resolv_parser::ResolveConfig;
32
33pub const RESOLV_CFG_PATH: &'static str = "/etc/resolv.conf";
35
36pub const HOST_CFG_PATH: &'static str = "/etc/hosts";
38
39pub static RESOLV_CFG_PATH_P: LazyLock<&'static Path> = LazyLock::new(|| {Path::new(RESOLV_CFG_PATH)});
40pub static HOST_CFG_PATH_P: LazyLock<&'static Path> = LazyLock::new(|| {Path::new(HOST_CFG_PATH)});
41
42pub const NSSWITCH_CFG_PATH: &'static str = "/etc/nsswitch.conf";
44
45const IN_ADDR_ARPA: &[u8] = b"\x07in-addr\x04arpa\x00";
46const IN_ADDR6_ARPA: &[u8] = b"\x03ip6\x04arpa\x00";
47
48pub const IPV4_BIND_ALL: IpAddr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
50pub const IPV6_BIND_ALL: IpAddr = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
52
53
54pub
69fn byte2hexchar(b: u8) -> u8
70{
71 match b
72 {
73 0..=9 => return '0' as u8 + b,
74 10..=15 => return 'a' as u8 + (b - 10),
75 _ => panic!("out of hex range!")
76 }
77}
78
79pub
90fn ip2pkt(ip: &IpAddr) -> CDnsResult<Vec<u8>>
91{
92 match *ip
93 {
94 IpAddr::V4(ref ipv4) =>
95 return ipv4_pkt(ipv4),
96 IpAddr::V6(ref ipv6) =>
97 return ipv6_pkt(ipv6)
98 };
99}
100
101const MAX_NAME_LEN: usize = 63;
102
103pub
104fn ipv4_pkt(ip: &Ipv4Addr) -> CDnsResult<Vec<u8>>
105{
106
107 let mut out: Vec<u8> = Vec::with_capacity(16 + IN_ADDR_ARPA.len());
109
110 let mut octets = ip.octets();
111 octets.reverse();
112
113 for oct in octets
114 {
115 let str_oct = oct.to_string();
116
117 if str_oct.len() > 3
118 {
119 internal_error!(
120 CDnsErrorType::InternalError,
121 "domain component too long, len: '{}' oct: '{}'",
122 str_oct.len(), str_oct
123 );
124 }
125
126 let ln: u8 = str_oct.len() as u8;
127
128 out.push(ln);
129 out.extend(str_oct.as_bytes());
130 }
131
132 out.extend(IN_ADDR_ARPA);
133
134 return Ok(out);
135}
136
137pub
138fn ipv6_pkt(ip: &Ipv6Addr) -> CDnsResult<Vec<u8>>
139{
140 let mut out: Vec<u8> = Vec::with_capacity(32 + IN_ADDR6_ARPA.len());
142
143 let mut octets = ip.octets();
144 octets.reverse();
145
146 for oct in octets
147 {
148 let h_oct = byte2hexchar((oct & 0xF0) >> 4);
149 let l_oct = byte2hexchar(oct & 0x0F);
151 out.push(1);
156 out.push(l_oct);
157 out.push(1);
159 out.push(h_oct);
160 }
161
162 out.extend(IN_ADDR6_ARPA);
163
164 return Ok(out);
165}
166
167pub
168fn name2pkt(name: &str) -> CDnsResult<Vec<u8>>
169{
170 let mut out: Vec<u8> = Vec::with_capacity(name.len() + 2);
172
173 for n in name.split(".")
174 {
175 if n.len() >= MAX_NAME_LEN
176 {
177 internal_error!(CDnsErrorType::InternalError, "name too long: '{}' in: '{}'", n.len(), name);
178 }
179
180 out.push((n.len() & 0xFF) as u8);
181 out.extend(n.as_bytes());
182 }
183
184 out.push(0);
185
186 return Ok(out);
187}
188
189
190#[repr(u16)]
196#[derive(Clone, Copy, Debug, PartialEq, Eq)]
197pub enum QType
198{
199 A = 1,
201 NS = 2,
203 MD = 3,
205 MF = 4,
207 CNAME = 5,
209 SOA = 6,
211 MB = 7,
213 MG = 8,
215 MR = 9,
217 NULL = 10,
219 WKS = 11,
221 PTR = 12,
223 HINFO = 13,
225 MINFO = 14,
227 MX = 15,
229 TXT = 16,
231 AFSDB = 18,
233 KEY = 25,
235 AAAA = 28,
237 CERT = 37,
239 DS = 43,
241 RRSIG = 46,
243 NSEC = 47,
245 DNSKEY = 48,
247 NSEC3 = 50,
249 NSEC3PARAM = 51,
251 CDS = 59,
253 CDNSKEY = 60,
255 OPENPGPKEY = 61,
257 AXFR = 252,
260 MAILB = 253,
262 MAILA = 254,
264 CAA = 257,
266 ALL = 255,
268 DLV = 32769,
270}
271
272impl Default for QType
273{
274 fn default() -> Self
275 {
276 return Self::A;
277 }
278}
279
280
281impl Into<u16> for QType
282{
283 fn into(self) -> u16
284 {
285 return self as u16;
286 }
287}
288
289impl fmt::Display for QType
290{
291 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
292 {
293 match *self
294 {
295 Self::A => write!(f, "A"),
296 Self::NS => write!(f, "NS"),
297 Self::MD => write!(f, "MD"),
298 Self::MF => write!(f, "MF"),
299 Self::CNAME => write!(f, "CNAME"),
300 Self::SOA => write!(f, "SOA"),
301 Self::MB => write!(f, "MB"),
302 Self::MG => write!(f, "MG"),
303 Self::MR => write!(f, "MR"),
304 Self::NULL => write!(f, "NULL"),
305 Self::WKS => write!(f, "WKS"),
306 Self::PTR => write!(f, "PTR"),
307 Self::HINFO => write!(f, "HINFO"),
308 Self::MINFO => write!(f, "MINFO"),
309 Self::MX => write!(f, "MX"),
310 Self::TXT => write!(f, "TXT"),
311 Self::AFSDB => write!(f, "AFSDB"),
312 Self::KEY => write!(f, "KEY"),
313 Self::AAAA => write!(f, "AAAA"),
314 Self::CERT => write!(f, "CERT"),
315 Self::DS => write!(f, "DS"),
316 Self::RRSIG => write!(f, "RRSIG"),
317 Self::NSEC => write!(f, "NSEC"),
318 Self::DNSKEY => write!(f, "DNSKEY"),
319 Self::NSEC3 => write!(f, "NSEC"),
320 Self::NSEC3PARAM => write!(f, "NSEC3PARAM"),
321 Self::CDS => write!(f, "CDS"),
322 Self::CDNSKEY => write!(f, "CDNSKEY"),
323 Self::OPENPGPKEY => write!(f, "OPENPGPKEY"),
324 Self::AXFR => write!(f, "AXFR"),
325 Self::MAILB => write!(f, "MAILB"),
326 Self::MAILA => write!(f, "MAILA"),
327 Self::CAA => write!(f, "CAA"),
328 Self::ALL => write!(f, "ALL"),
329 Self::DLV => write!(f, "DLV"),
330 }
331 }
332}
333
334
335impl QType
336{
337 pub
338 fn ipaddr_match(&self, ip: &IpAddr) -> bool
339 {
340 match *self
341 {
342 Self::A => return ip.is_ipv4(),
343 Self::AAAA => return ip.is_ipv6(),
344 _ => false,
345 }
346 }
347
348 pub
349 fn u16_to_qtype(value: u16) -> CDnsResult<QType>
350 {
351 match value
352 {
353 x if x == Self::AXFR as u16 => return Ok(Self::AXFR),
354 x if x == Self::MAILB as u16 => return Ok(Self::MAILB),
355 x if x == Self::MAILA as u16 => return Ok(Self::MAILA),
356 x if x == Self::ALL as u16 => return Ok(Self::ALL),
357 x if x == Self::DLV as u16 => return Ok(Self::DLV),
358 _ => return Self::u16_to_type(value),
359 }
360 }
361
362 pub
363 fn u16_to_type(value: u16) -> CDnsResult<QType>
364 {
365
366 match value
367 {
368 x if x == Self::A as u16 => return Ok(Self::A),
369 x if x == Self::NS as u16 => return Ok(Self::NS),
370 x if x == Self::MD as u16 => return Ok(Self::MD),
371 x if x == Self::MF as u16 => return Ok(Self::MF),
372 x if x == Self::CNAME as u16 => return Ok(Self::CNAME),
373 x if x == Self::SOA as u16 => return Ok(Self::SOA),
374 x if x == Self::MB as u16 => return Ok(Self::MB),
375 x if x == Self::MG as u16 => return Ok(Self::MG),
376 x if x == Self::MR as u16 => return Ok(Self::MR),
377 x if x == Self::NULL as u16 => return Ok(Self::NULL),
378 x if x == Self::WKS as u16 => return Ok(Self::WKS),
379 x if x == Self::PTR as u16 => return Ok(Self::PTR),
380 x if x == Self::HINFO as u16 => return Ok(Self::HINFO),
381 x if x == Self::MINFO as u16 => return Ok(Self::MINFO),
382 x if x == Self::MX as u16 => return Ok(Self::MX),
383 x if x == Self::TXT as u16 => return Ok(Self::TXT),
384 x if x == Self::AFSDB as u16 => return Ok(Self::AFSDB),
385 x if x == Self::KEY as u16 => return Ok(Self::KEY),
386 x if x == Self::AAAA as u16 => return Ok(Self::AAAA),
387 x if x == Self::CERT as u16 => return Ok(Self::CERT),
388 x if x == Self::DS as u16 => return Ok(Self::DS),
389 x if x == Self::RRSIG as u16 => return Ok(Self::RRSIG),
390 x if x == Self::NSEC as u16 => return Ok(Self::NSEC),
391 x if x == Self::DNSKEY as u16 => return Ok(Self::DNSKEY),
392 x if x == Self::NSEC3 as u16 => return Ok(Self::NSEC3),
393 x if x == Self::NSEC3PARAM as u16 => return Ok(Self::NSEC3PARAM),
394 x if x == Self::CDS as u16 => return Ok(Self::CDS),
395 x if x == Self::CDNSKEY as u16 => return Ok(Self::CDNSKEY),
396 x if x == Self::OPENPGPKEY as u16 => return Ok(Self::OPENPGPKEY),
397 _ => internal_error!(CDnsErrorType::DnsResponse, "unknown request record type: '{}'", value),
398 }
399 }
400}
401
402
403#[repr(u16)]
407#[derive(Clone, Copy, Debug, PartialEq, Eq)]
408pub enum QClass
409{
410 IN = 1,
412 CS = 2,
414 CH = 3,
416 HS = 4,
418
419 ALL = 255,
422}
423
424impl fmt::Display for QClass
425{
426 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
427 {
428 match *self
429 {
430 Self::IN => write!(f, "IN"),
431 Self::CS => write!(f, "CS"),
432 Self::CH => write!(f, "CH"),
433 Self::HS => write!(f, "HS"),
434 Self::ALL => write!(f, "ALL"),
435 }
436 }
437}
438
439impl Default for QClass
440{
441 fn default() -> Self
442 {
443 return Self::IN;
444 }
445}
446
447impl Into<u16> for QClass
448{
449 fn into(self) -> u16
450 {
451 return self as u16;
452 }
453}
454
455impl QClass
456{
457 pub
462 fn u16_to_qclass(value: u16) -> CDnsResult<QClass>
463 {
464 match value
465 {
466 x if x == QClass::ALL as u16 => return Ok(QClass::ALL),
467 _ => Self::u16_to_class(value),
468 }
469 }
470
471 pub
473 fn u16_to_class(value: u16) -> CDnsResult<QClass>
474 {
475 match value
476 {
477 x if x == QClass::IN as u16 => return Ok(QClass::IN),
478 x if x == QClass::CS as u16 => return Ok(QClass::CS),
479 x if x == QClass::CH as u16 => return Ok(QClass::CH),
480 x if x == QClass::HS as u16 => return Ok(QClass::HS),
481 _ => internal_error!(CDnsErrorType::DnsResponse, "unknown QCLASS type: '{}'", value),
482 }
483 }
484}
485
486bitflags! {
490 #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
492 pub struct StatusBits: u16
493 {
494 const QR_RESP = 0x8000;
497
498 const OPCODE_STANDARD = 0x87FF;
501 const OPCODE_IQUERY = 0x0040;
503 const OPCODE_STATUS = 0x0020;
505 const AUTH_ANSWER = 0x0400;
513
514 const TRUN_CATION = 0x0200;
518
519 const RECURSION_DESIRED = 0x0100;
525
526 const RECURSION_AVAIL = 0x0080;
531
532 const RSERVER0 = 0x0040;
536
537 const ANSWER_AUTHN = 0x0020;
538 const NON_AUTH_DATA = 0x0010;
539
540 const RESP_NOERROR = 0x0000;
544 const RESP_FORMERR = 0x0001;
546 const RESP_SERVFAIL = 0x0002;
549 const RESP_NXDOMAIN = 0x0003;
553 const RESP_NOT_IMPL = 0x0004;
555 const RESP_REFUSED = 0x0005;
558 }
560}
561
562#[derive(Clone, Debug, Hash)]
568pub enum QDnsName
569{
570 IpV4(Ipv4Addr),
572 IpV6(Ipv6Addr),
573 Name(String),
574}
575
576impl QDnsName
577{
578 pub
581 fn is_ipv4(&self) -> bool
582 {
583 match *self
584 {
585 Self::IpV4(_) => return true,
586 _ => return false,
587 }
588 }
589
590 pub
593 fn is_ipv6(&self) -> bool
594 {
595 match *self
596 {
597 Self::IpV6(_) => return true,
598 _ => return false,
599 }
600 }
601
602 pub
605 fn is_ip(&self) -> bool
606 {
607 match *self
608 {
609 Self::IpV4(_) => return true,
610 Self::IpV6(_) => return true,
611 _ => return false,
612 }
613 }
614
615 pub
617 fn get_ip_qtype(&self) -> Option<QType>
618 {
619 match *self
620 {
621 Self::IpV4(_) => return Some(QType::A),
622 Self::IpV6(_) => return Some(QType::AAAA),
623 Self::Name(_) =>
624 {
625 return None;
626 }
627 }
628 }
629}
630
631impl Eq for QDnsName {}
632
633impl PartialEq for QDnsName
634{
635 fn eq(&self, other: &Self) -> bool
636 {
637 return self == other;
638 }
639}
640
641impl PartialEq<str> for QDnsName
642{
643 fn eq(&self, other: &str) -> bool
644 {
645 match *self
646 {
647 Self::Name(ref name) => return name == other,
648 Self::IpV4(ref ip) =>
649 {
650 if let Ok(other_ip) = other.parse::<Ipv4Addr>()
651 {
652 return &other_ip == ip;
653 }
654
655 return false;
656 },
657 Self::IpV6(ref ip) =>
658 {
659 if let Ok(other_ip) = other.parse::<Ipv6Addr>()
660 {
661 return &other_ip == ip;
662 }
663
664 return false;
665 }
666 }
667 }
668}
669
670impl From<&IpAddr> for QDnsName
671{
672 fn from(ip: &IpAddr) -> Self
673 {
674 match *ip
675 {
676 IpAddr::V4(ref ip) =>
677 return Self::IpV4(ip.clone()),
678 IpAddr::V6(ref ip) =>
679 return Self::IpV6(ip.clone()),
680 }
681 }
682}
683
684impl From<IpAddr> for QDnsName
685{
686 fn from(ip: IpAddr) -> Self
687 {
688 match ip
689 {
690 IpAddr::V4(ip) =>
691 return Self::IpV4(ip),
692 IpAddr::V6(ip) =>
693 return Self::IpV6(ip),
694 }
695 }
696}
697
698impl From<&Ipv4Addr> for QDnsName
699{
700 fn from(ip: &Ipv4Addr) -> Self
701 {
702 return Self::IpV4(ip.clone());
703 }
704}
705
706impl From<Ipv4Addr> for QDnsName
707{
708 fn from(ip: Ipv4Addr) -> Self
709 {
710 return Self::IpV4(ip);
711 }
712}
713
714impl From<&Ipv6Addr> for QDnsName
715{
716 fn from(ip: &Ipv6Addr) -> Self
717 {
718 return Self::IpV6(ip.clone());
719 }
720}
721
722impl From<Ipv6Addr> for QDnsName
723{
724 fn from(ip: Ipv6Addr) -> Self
725 {
726 return Self::IpV6(ip);
727 }
728}
729
730impl From<&str> for QDnsName
731{
732 fn from(name: &str) -> Self
733 {
734 let ipp = name.parse::<IpAddr>();
735 if ipp.is_err()
736 {
737 return Self::Name(name.to_string());
738 }
739 else
740 {
741 return QDnsName::from(ipp.unwrap());
742 }
743 }
744}
745
746impl TryInto<Vec<u8>> for QDnsName
747{
748 type Error = CDnsError;
749 fn try_into(self) -> Result<Vec<u8>, Self::Error>
750 {
751 match self
752 {
753 Self::IpV4(ref ip) =>
754 {
755 return ipv4_pkt(ip);
756 },
757 Self::IpV6(ref ip) =>
758 {
759 return ipv6_pkt(ip);
760 },
761 Self::Name(ref name) =>
762 {
763 if let Ok(ip) = name.parse::<Ipv4Addr>()
764 {
765 return ipv4_pkt(&ip);
766 }
767 else if let Ok(ip) = name.parse::<Ipv6Addr>()
768 {
769 return ipv6_pkt(&ip);
770 }
771 else
772 {
773 return name2pkt(name);
774 }
775 }
776 }
777 }
778}
779
780impl From<&QDnsName> for String
781{
782 fn from(dnsname: &QDnsName) -> Self
783 {
784 match *dnsname
785 {
786 QDnsName::IpV4(ref ip) =>
787 {
788 return ip.to_string();
789 },
790 QDnsName::IpV6(ref ip) =>
791 {
792 return ip.to_string();
793 },
794 QDnsName::Name(ref name) =>
795 {
796 return name.to_string();
797 }
798 }
799 }
800}
801
802
803impl TryFrom<&QDnsName> for IpAddr
804{
805 type Error = CDnsError;
806 fn try_from(value: &QDnsName) -> Result<Self, Self::Error>
807 {
808 match *value
809 {
810 QDnsName::IpV4(ref ip) =>
811 {
812 return Ok(IpAddr::V4(ip.clone()));
813 },
814 QDnsName::IpV6(ref ip) =>
815 {
816 return Ok(IpAddr::V6(ip.clone()));
817 },
818 QDnsName::Name(ref name) =>
819 {
820 if let Ok(ip) = name.parse::<Ipv4Addr>()
821 {
822 return Ok(IpAddr::V4(ip.clone()));
823 }
824 else if let Ok(ip) = name.parse::<Ipv6Addr>()
825 {
826 return Ok(IpAddr::V6(ip.clone()));
827 }
828 else
829 {
830 internal_error!(CDnsErrorType::InternalError, "not ip address!")
831 }
832 }
833 }
834 }
835}
836
837
838impl TryFrom<QDnsName> for IpAddr
839{
840 type Error = CDnsError;
841 fn try_from(value: QDnsName) -> Result<Self, Self::Error>
842 {
843 match value
844 {
845 QDnsName::IpV4(ip) =>
846 {
847 return Ok(IpAddr::V4(ip));
848 },
849 QDnsName::IpV6(ip) =>
850 {
851 return Ok(IpAddr::V6(ip));
852 },
853 QDnsName::Name(ref name) =>
854 {
855 if let Ok(ip) = name.parse::<Ipv4Addr>()
856 {
857 return Ok(IpAddr::V4(ip));
858 }
859 else if let Ok(ip) = name.parse::<Ipv6Addr>()
860 {
861 return Ok(IpAddr::V6(ip));
862 }
863 else
864 {
865 internal_error!(CDnsErrorType::InternalError, "not ip address!")
866 }
867 }
868 }
869 }
870}
871
872#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
873pub struct DnsHeader
874{
875 pub id: u16,
878
879 pub status: StatusBits,
881
882 pub qdcount: u16,
885
886 pub ancount: u16,
889
890 pub nscount: u16,
894
895 pub arcount: u16,
898}
899
900
901#[derive(Clone, Debug, Default, PartialEq, Eq)]
902pub struct DnsRequestAnswer
903{
904 pub header: DnsHeader,
906 pub request: DnsRequestPayload,
908 pub response: Vec<DnsResponsePayload>,
910 pub additional: Vec<DnsResponsePayload>,
912 pub authoratives: Vec<DnsResponsePayload>,
914}
915
916impl DnsRequestAnswer
917{
918 pub
924 fn verify(&self, req: &DnsRequestHeader) -> CDnsResult<()>
925 {
926 if self.header.id != req.header.id
927 {
928 internal_error!(
929 CDnsErrorType::DnsResponse,
930 "request and response ID did not match: '{}' != '{}'",
931 req.header.id, self.header.id
932 );
933 }
934
935 if self.request != req.payload
937 {
938 internal_error!(CDnsErrorType::DnsResponse,
939 "received request section is different from sent");
940 }
941 else if req.payload.qtype != QType::ALL
942 {
943 if req.payload.qtype != self.request.qtype
945 {
946 internal_error!(
947 CDnsErrorType::DnsResponse,
948 "requested QTYPE differ received TYPE: '{}' != '{}'",
949 req.payload.qtype,
950 self.request.qtype
951 );
952 }
953 }
954 else if self.header.status.contains(StatusBits::TRUN_CATION) == true
955 {
956 internal_error!(CDnsErrorType::MessageTruncated,
957 "DNS response was truncated, aborting processing");
958 }
959
960 return Ok(());
961 }
962
963}
964
965#[derive(Clone, Debug, Default)]
966pub struct DnsRequestHeader
967{
968 pub header: DnsHeader,
970 pub payload: DnsRequestPayload,
972}
973
974impl Eq for DnsRequestHeader {}
975
976impl PartialEq for DnsRequestHeader
977{
978 fn eq(&self, other: &DnsRequestHeader) -> bool
979 {
980 return self.header.id == other.header.id;
981 }
982}
983
984impl Ord for DnsRequestHeader
985{
986 fn cmp(&self, other: &Self) -> Ordering
987 {
988 return self.header.id.cmp(&other.header.id);
990 }
991}
992
993impl PartialOrd for DnsRequestHeader
994{
995 fn partial_cmp(&self, other: &Self) -> Option<Ordering>
996 {
997 return Some(self.cmp(other));
998 }
999}
1000
1001impl Hash for DnsRequestHeader
1002{
1003 fn hash<H: Hasher>(&self, state: &mut H)
1004 {
1005 self.header.id.hash(state);
1006 }
1007}
1008
1009impl Borrow<u16> for DnsRequestHeader
1010{
1011 fn borrow(&self) -> &u16
1012 {
1013 return &self.header.id;
1014 }
1015}
1016
1017
1018
1019impl DnsRequestHeader
1020{
1021 pub
1022 fn regenerate_id(&mut self)
1023 {
1024 self.header.id = rand::random();
1025 }
1026
1027 pub
1028 fn get_id(&self) -> u16
1029 {
1030 return self.header.id;
1031 }
1032
1033 pub
1034 fn from_qdns_req(qrec: &QDnsReq, resolvers: &ResolveConfig) -> CDnsResult<Self>
1035 {
1036 if resolvers.lookup.contains(ResolveConfigLookup::BIND) == true
1037 {
1038 return DnsRequestHeader::construct_lookup(qrec.get_req_name().clone(), *qrec.get_type());
1039 }
1040 else
1041 {
1042 panic!("QDnsReq::get_header() misuse!");
1043 };
1044 }
1045
1046 pub
1047 fn derive(&self) -> Self
1048 {
1049 let header =
1050 DnsHeader
1051 {
1052 id: rand::random(),
1053 status: self.header.status,
1054 qdcount: self.header.qdcount,
1055 ancount: self.header.ancount,
1056 nscount: self.header.nscount,
1057 arcount: self.header.arcount,
1058 };
1059
1060 return DnsRequestHeader{ header: header, payload: self.payload.clone() };
1061 }
1062
1063 pub
1065 fn construct_lookup(name: QDnsName, qtype: QType) -> CDnsResult<DnsRequestHeader>
1066 {
1067 let mut status: StatusBits = StatusBits::empty();
1070 status = (status & !StatusBits::OPCODE_STANDARD) | StatusBits::RECURSION_DESIRED;
1071
1072 let mut req: DnsRequestHeader = DnsRequestHeader{ ..Default::default() };
1074
1075 req.header.id = rand::random();
1076 req.header.status = status;
1077 req.header.qdcount = 1;
1078
1079 req.payload = DnsRequestPayload::new(name.try_into()?, qtype, QClass::IN);
1081
1082
1083 return Ok(req);
1088 }
1089
1090}
1091
1092#[derive(Clone, Debug, Default, PartialEq, Eq)]
1094pub struct DnsRequestPayload
1095{
1096 pub qname: Vec<u8>,
1098
1099 pub qtype: QType,
1101
1102 pub qclass: QClass,
1104}
1105
1106impl DnsRequestPayload
1107{
1108 pub
1109 fn new(qname: Vec<u8>, qtype: QType, qclass: QClass) -> Self
1110 {
1111 return DnsRequestPayload{ qname: qname, qtype: qtype.into(), qclass: qclass.into() };
1112 }
1113}
1114
1115#[derive(Clone, Debug, Default, Eq, PartialEq)]
1117pub struct DnsResponsePayload
1118{
1119 pub name: String,
1121 pub dtype: QType,
1123 pub class: QClass,
1125 pub ttl: i32,
1128 pub rdlength: u16,
1130 pub rdata: DnsRdata,
1132}
1133
1134impl DnsResponsePayload
1135{
1136 pub(crate)
1139 fn new_local(dtype: QType, data: &HostnameEntry) -> CDnsResult<Vec<Self>>
1140 {
1141
1142 match dtype
1143 {
1144 QType::A =>
1145 {
1146 let mut out: Vec<Self> = Vec::with_capacity(1);
1147
1148 let IpAddr::V4(ipv4) = data.get_ip()
1149 else { internal_error!(CDnsErrorType::InternalError, "wrong data type") };
1150
1151 out.push(
1152 DnsResponsePayload
1153 {
1154 name: [data.get_hostnames()[0].as_str(), ".local"].concat(),
1155 dtype: dtype,
1156 class: QClass::IN,
1157 ttl: i32::MAX,
1158 rdlength: 0,
1159 rdata: DnsRdata::A{ ip: ipv4.clone() },
1160 }
1161 );
1162
1163 return Ok(out);
1164 },
1165 QType::AAAA =>
1166 {
1167 let mut out: Vec<Self> = Vec::with_capacity(1);
1168
1169 let IpAddr::V6(ipv6) = data.get_ip()
1170 else { internal_error!(CDnsErrorType::InternalError, "wrong data type") };
1171
1172 out.push(
1173 DnsResponsePayload
1174 {
1175 name: [data.get_hostnames()[0].as_str(), ".local"].concat(),
1176 dtype: dtype,
1177 class: QClass::IN,
1178 ttl: i32::MAX,
1179 rdlength: 0,
1180 rdata: DnsRdata::AAAA{ ip: ipv6.clone() },
1181 }
1182 );
1183
1184 return Ok(out);
1185 },
1186 QType::PTR =>
1187 {
1188 let mut out: Vec<Self> = Vec::with_capacity(data.get_hostnames().len());
1189
1190 for h in data.get_hostnames_iter()
1192 {
1193 out.push(
1194 DnsResponsePayload
1195 {
1196 name: [data.get_ip().to_string().as_str(), ".local"].concat(),
1197 dtype: dtype,
1198 class: QClass::IN,
1199 ttl: i32::MAX,
1200 rdlength: 0,
1201 rdata: DnsRdata::PTR{ fqdn: h.clone() },
1202 }
1203 );
1204 }
1205
1206 return Ok(out);
1207 },
1208 _ =>
1209 {
1210 internal_error!(CDnsErrorType::InternalError, "new_local can not be used for types except A, AAAA, PTR");
1211 }
1212 }
1213
1214 }
1215}
1216
1217impl fmt::Display for DnsResponsePayload
1226{
1227 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1228 {
1229 write!(f, "{} {} {} {} {}",
1230 self.name, self.dtype, self.class, self.ttl, self.rdata)
1231 }
1232}
1233
1234#[derive(Clone, Debug, Eq, PartialEq)]
1235pub struct DnsSoa
1236{
1237 pub pnm: String,
1239 pub ram: String,
1241 pub serial: u32,
1243 pub interv_refr: u32,
1245 pub interv_retry: u32,
1247 pub expire_limit: u32,
1249 pub min_ttl: u32,
1251}
1252
1253impl fmt::Display for DnsSoa
1254{
1255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1256 {
1257 writeln!(f, "{} {} {} {} {} {} {}",
1258 self.pnm, self.ram, self.serial, self.interv_refr,
1259 self.interv_retry, self.expire_limit, self.min_ttl)
1260 }
1261}
1262
1263#[derive(Clone, Debug, Eq, PartialEq)]
1264pub enum DnsRdata
1265{
1266 None,
1267 A{ ip: Ipv4Addr },
1268 NS{ fqdn: String },
1269 MD{ data: Vec<u8> },
1270 MF{ data: Vec<u8> },
1271 CNAME{ fqdn: String },
1272 SOA{ soa: DnsSoa },
1273 MB{ data: Vec<u8> },
1274 MG{ data: Vec<u8> },
1275 MR{ data: Vec<u8> },
1276 NULL{ data: Vec<u8> },
1277 WKS{ data: Vec<u8> },
1278 PTR{ fqdn: String },
1279 HINFO{ data: Vec<u8> },
1280 MX{ preference: u16, exchange: String },
1281 TXT{ data: Vec<u8> },
1282 AFSDB{ data: Vec<u8> },
1283 KEY{ data: Vec<u8> },
1284 AAAA{ ip: Ipv6Addr },
1285 CERT{ data: Vec<u8> },
1286 DS{ data: Vec<u8> },
1287 RRSIG{ data: Vec<u8> },
1288 NSEC{ data: Vec<u8> },
1289 DNSKEY{ data: Vec<u8> },
1290 NSEC3{ data: Vec<u8> },
1291 NSEC3PARAM{ data: Vec<u8> },
1292 CDS{ data: Vec<u8> },
1293 CDNSKEY{ data: Vec<u8> },
1294 OPENPGPKEY{ data: Vec<u8> },
1295 UNKNOWN{ data: Vec<u8> },
1296}
1297
1298impl fmt::Display for DnsRdata
1299{
1300 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1301 {
1302 match *self
1303 {
1304 Self::None =>
1305 write!(f, "No record"),
1306 Self::A{ ref ip } =>
1307 write!(f, "{}", ip),
1308 Self::NS{ ref fqdn } =>
1309 write!(f, "{}", fqdn),
1310 Self::AAAA{ ref ip} =>
1311 write!(f, "{}", ip),
1312 Self::MX{ preference, ref exchange } =>
1313 write!(f, "{} {}", preference, exchange),
1314 Self::CNAME{ ref fqdn } =>
1315 write!(f, "{}", fqdn),
1316 Self::PTR{ ref fqdn } =>
1317 write!(f, "{}", fqdn),
1318 Self::SOA{ ref soa } =>
1319 write!(f, "{}", soa),
1320 Self::UNKNOWN{ .. } =>
1321 write!(f, "UNKNOWN"),
1322 _ => write!(f, "RAW DATA"),
1323 }
1324 }
1325}
1326
1327impl Default for DnsRdata
1328{
1329 fn default() -> Self
1330 {
1331 return Self::None;
1332 }
1333}
1334
1335impl DnsRdata
1336{
1337 pub
1338 fn is_some(&self) -> bool
1339 {
1340 return *self != Self::None;
1341 }
1342}
1343